diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 9af84740ad8..9a687fb4421 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -#### Brief description of the issue +#### Brief description of the bug #### What you expected to happen diff --git a/code/ATMOSPHERICS/components/shutoff.dm b/code/ATMOSPHERICS/components/shutoff.dm new file mode 100644 index 00000000000..de69f5e395e --- /dev/null +++ b/code/ATMOSPHERICS/components/shutoff.dm @@ -0,0 +1,57 @@ +GLOBAL_LIST_EMPTY(shutoff_valves) + +/obj/machinery/atmospherics/valve/shutoff + icon = 'icons/atmos/clamp.dmi' + icon_state = "map_vclamp0" + pipe_state = "vclamp" + + name = "automatic shutoff valve" + desc = "An automatic valve with control circuitry and pipe integrity sensor, capable of automatically isolating damaged segments of the pipe network." + var/close_on_leaks = TRUE // If false it will be always open + level = 1 + +/obj/machinery/atmospherics/valve/shutoff/update_icon() + icon_state = "vclamp[open]" + +/obj/machinery/atmospherics/valve/shutoff/examine(var/mob/user) + ..() + to_chat(user, "The automatic shutoff circuit is [close_on_leaks ? "enabled" : "disabled"].") + +/obj/machinery/atmospherics/valve/shutoff/Initialize() + . = ..() + open() + GLOB.shutoff_valves += src + hide(1) + +/obj/machinery/atmospherics/valve/shutoff/Destroy() + GLOB.shutoff_valves -= src + ..() + +/obj/machinery/atmospherics/valve/shutoff/attack_ai(mob/user as mob) + return src.attack_hand(user) + +/obj/machinery/atmospherics/valve/shutoff/attack_hand(var/mob/user) + src.add_fingerprint(usr) + update_icon(1) + close_on_leaks = !close_on_leaks + to_chat(user, "You [close_on_leaks ? "enable" : "disable"] the automatic shutoff circuit.") + return TRUE + +/obj/machinery/atmospherics/valve/shutoff/process() + ..() + + if (!network_node1 || !network_node2) + if(open) + close() + return + + if (!close_on_leaks) + if (!open) + open() + return + + if (network_node1.leaks.len || network_node2.leaks.len) + if (open) + close() + else if (!open) + open() diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm index ee1379ac288..61ace40879b 100644 --- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm +++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm @@ -1,4 +1,4 @@ -//Basically a one way passive valve. If the pressure inside is greater than the environment then gas will flow passively, +//Basically a one way passive valve. If the pressure inside is greater than the environment then gas will flow passively, //but it does not permit gas to flow back from the environment into the injector. Can be turned off to prevent any gas flow. //When it receives the "inject" signal, it will try to pump it's entire contents into the environment regardless of pressure, using power. @@ -13,7 +13,7 @@ use_power = 0 idle_power_usage = 150 //internal circuitry, friction losses and stuff power_rating = 15000 //15000 W ~ 20 HP - + var/injecting = 0 var/volume_rate = 50 //flow rate limit @@ -26,7 +26,7 @@ /obj/machinery/atmospherics/unary/outlet_injector/New() ..() - air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //Give it a small reservoir for injecting. Also allows it to have a higher flow rate limit than vent pumps, to differentiate injectors a bit more. + air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //Give it a small reservoir for injecting. Also allows it to have a higher flow rate limit than vent pumps, to differentiate injectors a bit more. /obj/machinery/atmospherics/unary/outlet_injector/Destroy() unregister_radio(src, frequency) @@ -60,21 +60,21 @@ if((stat & (NOPOWER|BROKEN)) || !use_power) return - + var/power_draw = -1 var/datum/gas_mixture/environment = loc.return_air() - + if(environment && air_contents.temperature > 0) var/transfer_moles = (volume_rate/air_contents.volume)*air_contents.total_moles //apply flow rate limit power_draw = pump_gas(src, air_contents, environment, transfer_moles, power_rating) - + if (power_draw >= 0) last_power_draw = power_draw use_power(power_draw) - + if(network) network.update = 1 - + return 1 /obj/machinery/atmospherics/unary/outlet_injector/proc/inject() @@ -84,7 +84,7 @@ var/datum/gas_mixture/environment = loc.return_air() if (!environment) return 0 - + injecting = 1 if(air_contents.temperature > 0) @@ -155,4 +155,23 @@ update_icon() /obj/machinery/atmospherics/unary/outlet_injector/hide(var/i) - update_underlays() \ No newline at end of file + update_underlays() + +/obj/machinery/atmospherics/unary/outlet_injector/attack_hand(mob/user as mob) + to_chat(user, "You toggle \the [src].") + injecting = !injecting + use_power = injecting + update_icon() + +/obj/machinery/atmospherics/unary/outlet_injector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) + if (!W.is_wrench()) + return ..() + + playsound(src, W.usesound, 50, 1) + to_chat(user, "You begin to unfasten \the [src]...") + if (do_after(user, 40 * W.toolspeed)) + user.visible_message( \ + "\The [user] unfastens \the [src].", \ + "You have unfastened \the [src].", \ + "You hear a ratchet.") + deconstruct() \ No newline at end of file diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index ce2eb97e677..1f7414e17f1 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -16,7 +16,7 @@ desc = "Has a valve and pump attached to it" use_power = 0 idle_power_usage = 150 //internal circuitry, friction losses and stuff - power_rating = 7500 //7500 W ~ 10 HP + power_rating = 30000 //7500 W ~ 10 HP //VOREStation Edit - 30000 W connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY //connects to regular and supply pipes @@ -89,7 +89,7 @@ /obj/machinery/atmospherics/unary/vent_pump/high_volume name = "Large Air Vent" power_channel = EQUIP - power_rating = 15000 //15 kW ~ 20 HP + power_rating = 45000 //15 kW ~ 20 HP //VOREStation Edit - 45000 /obj/machinery/atmospherics/unary/vent_pump/high_volume/New() ..() diff --git a/code/ATMOSPHERICS/datum_pipe_network.dm b/code/ATMOSPHERICS/datum_pipe_network.dm index eb5e89276ef..a611e30a893 100644 --- a/code/ATMOSPHERICS/datum_pipe_network.dm +++ b/code/ATMOSPHERICS/datum_pipe_network.dm @@ -8,76 +8,83 @@ var/global/list/datum/pipe_network/pipe_networks = list() // TODO - Move into SS var/list/datum/pipeline/line_members = list() //membership roster to go through for updates and what not + var/list/leaks = list() + var/update = 1 //var/datum/gas_mixture/air_transient = null - Destroy() - STOP_PROCESSING_PIPENET(src) - for(var/datum/pipeline/line_member in line_members) - line_member.network = null - for(var/obj/machinery/atmospherics/normal_member in normal_members) - normal_member.reassign_network(src, null) - gases.Cut() // Do not qdel the gases, we don't own them - return ..() +/datum/pipe_network/Destroy() + STOP_PROCESSING_PIPENET(src) + for(var/datum/pipeline/line_member in line_members) + line_member.network = null + for(var/obj/machinery/atmospherics/normal_member in normal_members) + normal_member.reassign_network(src, null) + gases.Cut() // Do not qdel the gases, we don't own them + leaks.Cut() + return ..() - process() - //Equalize gases amongst pipe if called for - if(update) - update = 0 - reconcile_air() //equalize_gases(gases) +/datum/pipe_network/process() + //Equalize gases amongst pipe if called for + if(update) + update = 0 + reconcile_air() //equalize_gases(gases) - //Give pipelines their process call for pressure checking and what not. Have to remove pressure checks for the time being as pipes dont radiate heat - Mport - //for(var/datum/pipeline/line_member in line_members) - // line_member.process() + listclearnulls(leaks) // Let's not have forever-seals. - proc/build_network(obj/machinery/atmospherics/start_normal, obj/machinery/atmospherics/reference) - //Purpose: Generate membership roster - //Notes: Assuming that members will add themselves to appropriate roster in network_expand() + //Give pipelines their process call for pressure checking and what not. Have to remove pressure checks for the time being as pipes dont radiate heat - Mport + //for(var/datum/pipeline/line_member in line_members) + // line_member.process() - if(!start_normal) - qdel(src) - return +/datum/pipe_network/proc/build_network(obj/machinery/atmospherics/start_normal, obj/machinery/atmospherics/reference) + //Purpose: Generate membership roster + //Notes: Assuming that members will add themselves to appropriate roster in network_expand() - start_normal.network_expand(src, reference) + if(!start_normal) + qdel(src) + return - update_network_gases() + start_normal.network_expand(src, reference) - if((normal_members.len>0)||(line_members.len>0)) - START_PROCESSING_PIPENET(src) - else - qdel(src) + update_network_gases() - proc/merge(datum/pipe_network/giver) - if(giver==src) return 0 + if((normal_members.len>0)||(line_members.len>0)) + START_PROCESSING_PIPENET(src) + else + qdel(src) - normal_members |= giver.normal_members +/datum/pipe_network/proc/merge(datum/pipe_network/giver) + if(giver==src) return 0 - line_members |= giver.line_members + normal_members |= giver.normal_members - for(var/obj/machinery/atmospherics/normal_member in giver.normal_members) - normal_member.reassign_network(giver, src) + line_members |= giver.line_members - for(var/datum/pipeline/line_member in giver.line_members) - line_member.network = src + leaks |= giver.leaks - update_network_gases() - return 1 + for(var/obj/machinery/atmospherics/normal_member in giver.normal_members) + normal_member.reassign_network(giver, src) - proc/update_network_gases() - //Go through membership roster and make sure gases is up to date + for(var/datum/pipeline/line_member in giver.line_members) + line_member.network = src - gases = list() - volume = 0 + update_network_gases() + return 1 - for(var/obj/machinery/atmospherics/normal_member in normal_members) - var/result = normal_member.return_network_air(src) - if(result) gases += result +/datum/pipe_network/proc/update_network_gases() + //Go through membership roster and make sure gases is up to date - for(var/datum/pipeline/line_member in line_members) - gases += line_member.air + gases = list() + volume = 0 - for(var/datum/gas_mixture/air in gases) - volume += air.volume + for(var/obj/machinery/atmospherics/normal_member in normal_members) + var/result = normal_member.return_network_air(src) + if(result) gases += result - proc/reconcile_air() - equalize_gases(gases) + for(var/datum/pipeline/line_member in line_members) + gases += line_member.air + + for(var/datum/gas_mixture/air in gases) + volume += air.volume + +/datum/pipe_network/proc/reconcile_air() + equalize_gases(gases) diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm index fc47bca9381..b53d722458b 100644 --- a/code/ATMOSPHERICS/datum_pipeline.dm +++ b/code/ATMOSPHERICS/datum_pipeline.dm @@ -1,219 +1,234 @@ -datum/pipeline +/datum/pipeline var/datum/gas_mixture/air var/list/obj/machinery/atmospherics/pipe/members var/list/obj/machinery/atmospherics/pipe/edges //Used for building networks + // Nodes that are leaking. Used for A.S. Valves. + var/list/leaks = list() + var/datum/pipe_network/network var/alert_pressure = 0 - Destroy() - QDEL_NULL(network) +/datum/pipeline/Destroy() + QDEL_NULL(network) - if(air && air.volume) - temporarily_store_air() - for(var/obj/machinery/atmospherics/pipe/P in members) - P.parent = null - members = null - edges = null - . = ..() + if(air && air.volume) + temporarily_store_air() + for(var/obj/machinery/atmospherics/pipe/P in members) + P.parent = null + members = null + edges = null + leaks = null + . = ..() - process()//This use to be called called from the pipe networks - - //Check to see if pressure is within acceptable limits - var/pressure = air.return_pressure() - if(pressure > alert_pressure) - for(var/obj/machinery/atmospherics/pipe/member in members) - if(!member.check_pressure(pressure)) - break //Only delete 1 pipe per process - - proc/temporarily_store_air() - //Update individual gas_mixtures by volume ratio +/datum/pipeline/process()//This use to be called called from the pipe networks + //Check to see if pressure is within acceptable limits + var/pressure = air.return_pressure() + if(pressure > alert_pressure) for(var/obj/machinery/atmospherics/pipe/member in members) - member.air_temporary = new - member.air_temporary.copy_from(air) - member.air_temporary.volume = member.volume - member.air_temporary.multiply(member.volume / air.volume) + if(!member.check_pressure(pressure)) + break //Only delete 1 pipe per process - proc/build_pipeline(obj/machinery/atmospherics/pipe/base) +/datum/pipeline/proc/temporarily_store_air() + //Update individual gas_mixtures by volume ratio + + for(var/obj/machinery/atmospherics/pipe/member in members) + member.air_temporary = new + member.air_temporary.copy_from(air) + member.air_temporary.volume = member.volume + member.air_temporary.multiply(member.volume / air.volume) + +/datum/pipeline/proc/build_pipeline(obj/machinery/atmospherics/pipe/base) + air = new + + var/list/possible_expansions = list(base) + members = list(base) + edges = list() + + var/volume = base.volume + base.parent = src + alert_pressure = base.alert_pressure + + if(base.air_temporary) + air = base.air_temporary + base.air_temporary = null + else air = new - var/list/possible_expansions = list(base) - members = list(base) - edges = list() + if(base.leaking) + leaks |= base - var/volume = base.volume - base.parent = src - alert_pressure = base.alert_pressure + while(possible_expansions.len>0) + for(var/obj/machinery/atmospherics/pipe/borderline in possible_expansions) - if(base.air_temporary) - air = base.air_temporary - base.air_temporary = null - else - air = new + var/list/result = borderline.pipeline_expansion() + var/edge_check = result.len - while(possible_expansions.len>0) - for(var/obj/machinery/atmospherics/pipe/borderline in possible_expansions) + if(result.len>0) + for(var/obj/machinery/atmospherics/pipe/item in result) - var/list/result = borderline.pipeline_expansion() - var/edge_check = result.len + if(item.in_stasis) + continue - if(result.len>0) - for(var/obj/machinery/atmospherics/pipe/item in result) - if(!members.Find(item)) - members += item - possible_expansions += item + if(!members.Find(item)) + members += item + possible_expansions += item - volume += item.volume - item.parent = src + volume += item.volume + item.parent = src - alert_pressure = min(alert_pressure, item.alert_pressure) + alert_pressure = min(alert_pressure, item.alert_pressure) - if(item.air_temporary) - air.merge(item.air_temporary) + if(item.air_temporary) + air.merge(item.air_temporary) - edge_check-- + if(item.leaking) + leaks |= item - if(edge_check>0) - edges += borderline + edge_check-- - possible_expansions -= borderline + if(edge_check>0) + edges += borderline - air.volume = volume + possible_expansions -= borderline - proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) + air.volume = volume - if(new_network.line_members.Find(src)) - return 0 +/datum/pipeline/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference) - new_network.line_members += src + if(new_network.line_members.Find(src)) + return 0 - network = new_network + new_network.line_members += src - for(var/obj/machinery/atmospherics/pipe/edge in edges) - for(var/obj/machinery/atmospherics/result in edge.pipeline_expansion()) - if(!istype(result,/obj/machinery/atmospherics/pipe) && (result!=reference)) - result.network_expand(new_network, edge) + network = new_network + network.leaks |= leaks - return 1 + for(var/obj/machinery/atmospherics/pipe/edge in edges) + for(var/obj/machinery/atmospherics/result in edge.pipeline_expansion()) + if(!istype(result,/obj/machinery/atmospherics/pipe) && (result!=reference)) + result.network_expand(new_network, edge) - proc/return_network(obj/machinery/atmospherics/reference) - if(!network) - network = new /datum/pipe_network() - network.build_network(src, null) - //technically passing these parameters should not be allowed - //however pipe_network.build_network(..) and pipeline.network_extend(...) - // were setup to properly handle this case + return 1 - return network +/datum/pipeline/proc/return_network(obj/machinery/atmospherics/reference) + if(!network) + network = new /datum/pipe_network() + network.build_network(src, null) + //technically passing these parameters should not be allowed + //however pipe_network.build_network(..) and pipeline.network_extend(...) + // were setup to properly handle this case - proc/mingle_with_turf(turf/simulated/target, mingle_volume) - var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume) - air_sample.volume = mingle_volume + return network - if(istype(target) && target.zone) - //Have to consider preservation of group statuses - var/datum/gas_mixture/turf_copy = new - var/datum/gas_mixture/turf_original = new +/datum/pipeline/proc/mingle_with_turf(turf/simulated/target, mingle_volume) + var/datum/gas_mixture/air_sample = air.remove_ratio(mingle_volume/air.volume) + air_sample.volume = mingle_volume - turf_copy.copy_from(target.zone.air) - turf_copy.volume = target.zone.air.volume //Copy a good representation of the turf from parent group - turf_original.copy_from(turf_copy) + if(istype(target) && target.zone) + //Have to consider preservation of group statuses + var/datum/gas_mixture/turf_copy = new + var/datum/gas_mixture/turf_original = new - equalize_gases(list(air_sample, turf_copy)) - air.merge(air_sample) + turf_copy.copy_from(target.zone.air) + turf_copy.volume = target.zone.air.volume //Copy a good representation of the turf from parent group + turf_original.copy_from(turf_copy) + + equalize_gases(list(air_sample, turf_copy)) + air.merge(air_sample) - target.zone.air.remove(turf_original.total_moles) - target.zone.air.merge(turf_copy) + target.zone.air.remove(turf_original.total_moles) + target.zone.air.merge(turf_copy) - else - var/datum/gas_mixture/turf_air = target.return_air() + else + var/datum/gas_mixture/turf_air = target.return_air() - equalize_gases(list(air_sample, turf_air)) - air.merge(air_sample) - //turf_air already modified by equalize_gases() + equalize_gases(list(air_sample, turf_air)) + air.merge(air_sample) + //turf_air already modified by equalize_gases() - if(network) - network.update = 1 + if(network) + network.update = 1 - proc/temperature_interact(turf/target, share_volume, thermal_conductivity) - var/total_heat_capacity = air.heat_capacity() - var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume) +/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity) + var/total_heat_capacity = air.heat_capacity() + var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume) - if(istype(target, /turf/simulated)) - var/turf/simulated/modeled_location = target + if(istype(target, /turf/simulated)) + var/turf/simulated/modeled_location = target - if(modeled_location.blocks_air) + if(modeled_location.blocks_air) - if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) - var/delta_temperature = air.temperature - modeled_location.temperature - - var/heat = thermal_conductivity*delta_temperature* \ - (partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity)) - - air.temperature -= heat/total_heat_capacity - modeled_location.temperature += heat/modeled_location.heat_capacity - - else - var/delta_temperature = 0 - var/sharer_heat_capacity = 0 - - if(modeled_location.zone) - delta_temperature = (air.temperature - modeled_location.zone.air.temperature) - sharer_heat_capacity = modeled_location.zone.air.heat_capacity() - else - delta_temperature = (air.temperature - modeled_location.air.temperature) - sharer_heat_capacity = modeled_location.air.heat_capacity() - - var/self_temperature_delta = 0 - var/sharer_temperature_delta = 0 - - if((sharer_heat_capacity>0) && (partial_heat_capacity>0)) - var/heat = thermal_conductivity*delta_temperature* \ - (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity)) - - self_temperature_delta = -heat/total_heat_capacity - sharer_temperature_delta = heat/sharer_heat_capacity - else - return 1 - - air.temperature += self_temperature_delta - - if(modeled_location.zone) - modeled_location.zone.air.temperature += sharer_temperature_delta/modeled_location.zone.air.group_multiplier - else - modeled_location.air.temperature += sharer_temperature_delta - - - else - if((target.heat_capacity>0) && (partial_heat_capacity>0)) - var/delta_temperature = air.temperature - target.temperature + if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) + var/delta_temperature = air.temperature - modeled_location.temperature var/heat = thermal_conductivity*delta_temperature* \ - (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) + (partial_heat_capacity*modeled_location.heat_capacity/(partial_heat_capacity+modeled_location.heat_capacity)) air.temperature -= heat/total_heat_capacity - if(network) - network.update = 1 + modeled_location.temperature += heat/modeled_location.heat_capacity - //surface must be the surface area in m^2 - proc/radiate_heat_to_space(surface, thermal_conductivity) - var/gas_density = air.total_moles/air.volume - thermal_conductivity *= min(gas_density / ( RADIATOR_OPTIMUM_PRESSURE/(R_IDEAL_GAS_EQUATION*GAS_CRITICAL_TEMPERATURE) ), 1) //mult by density ratio + else + var/delta_temperature = 0 + var/sharer_heat_capacity = 0 - // We only get heat from the star on the exposed surface area. - // If the HE pipes gain more energy from AVERAGE_SOLAR_RADIATION than they can radiate, then they have a net heat increase. - var/heat_gain = AVERAGE_SOLAR_RADIATION * (RADIATOR_EXPOSED_SURFACE_AREA_RATIO * surface) * thermal_conductivity + if(modeled_location.zone) + delta_temperature = (air.temperature - modeled_location.zone.air.temperature) + sharer_heat_capacity = modeled_location.zone.air.heat_capacity() + else + delta_temperature = (air.temperature - modeled_location.air.temperature) + sharer_heat_capacity = modeled_location.air.heat_capacity() - // Previously, the temperature would enter equilibrium at 26C or 294K. - // Only would happen if both sides (all 2 square meters of surface area) were exposed to sunlight. We now assume it aligned edge on. - // It currently should stabilise at 129.6K or -143.6C - heat_gain -= surface * STEFAN_BOLTZMANN_CONSTANT * thermal_conductivity * (air.temperature - COSMIC_RADIATION_TEMPERATURE) ** 4 + var/self_temperature_delta = 0 + var/sharer_temperature_delta = 0 - air.add_thermal_energy(heat_gain) - if(network) - network.update = 1 + if((sharer_heat_capacity>0) && (partial_heat_capacity>0)) + var/heat = thermal_conductivity*delta_temperature* \ + (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity)) + + self_temperature_delta = -heat/total_heat_capacity + sharer_temperature_delta = heat/sharer_heat_capacity + else + return 1 + + air.temperature += self_temperature_delta + + if(modeled_location.zone) + modeled_location.zone.air.temperature += sharer_temperature_delta/modeled_location.zone.air.group_multiplier + else + modeled_location.air.temperature += sharer_temperature_delta + + + else + if((target.heat_capacity>0) && (partial_heat_capacity>0)) + var/delta_temperature = air.temperature - target.temperature + + var/heat = thermal_conductivity*delta_temperature* \ + (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) + + air.temperature -= heat/total_heat_capacity + if(network) + network.update = 1 + +//surface must be the surface area in m^2 +/datum/pipeline/proc/radiate_heat_to_space(surface, thermal_conductivity) + var/gas_density = air.total_moles/air.volume + thermal_conductivity *= min(gas_density / ( RADIATOR_OPTIMUM_PRESSURE/(R_IDEAL_GAS_EQUATION*GAS_CRITICAL_TEMPERATURE) ), 1) //mult by density ratio + + // We only get heat from the star on the exposed surface area. + // If the HE pipes gain more energy from AVERAGE_SOLAR_RADIATION than they can radiate, then they have a net heat increase. + var/heat_gain = AVERAGE_SOLAR_RADIATION * (RADIATOR_EXPOSED_SURFACE_AREA_RATIO * surface) * thermal_conductivity + + // Previously, the temperature would enter equilibrium at 26C or 294K. + // Only would happen if both sides (all 2 square meters of surface area) were exposed to sunlight. We now assume it aligned edge on. + // It currently should stabilise at 129.6K or -143.6C + heat_gain -= surface * STEFAN_BOLTZMANN_CONSTANT * thermal_conductivity * (air.temperature - COSMIC_RADIATION_TEMPERATURE) ** 4 + + air.add_thermal_energy(heat_gain) + if(network) + network.update = 1 diff --git a/code/ATMOSPHERICS/pipes/cap.dm b/code/ATMOSPHERICS/pipes/cap.dm index a03ce16af55..1e32aa62952 100644 --- a/code/ATMOSPHERICS/pipes/cap.dm +++ b/code/ATMOSPHERICS/pipes/cap.dm @@ -54,7 +54,7 @@ alpha = 255 overlays.Cut() - overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "cap") + overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "cap[icon_connect_type]") /obj/machinery/atmospherics/pipe/cap/atmos_init() for(var/obj/machinery/atmospherics/target in get_step(src, dir)) diff --git a/code/ATMOSPHERICS/pipes/he_pipes.dm b/code/ATMOSPHERICS/pipes/he_pipes.dm index 2d77e3a4ca9..1b283e3ba4d 100644 --- a/code/ATMOSPHERICS/pipes/he_pipes.dm +++ b/code/ATMOSPHERICS/pipes/he_pipes.dm @@ -67,8 +67,22 @@ return update_icon() + handle_leaking() return +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/set_leaking(var/new_leaking) // They already process, no need for manual processing toggles. + if(new_leaking && !leaking) + leaking = TRUE + if(parent) + parent.leaks |= src + if(parent.network) + parent.network.leaks |= src + else if (!new_leaking && leaking) + leaking = FALSE + if(parent) + parent.leaks -= src + if(parent.network) + parent.network.leaks -= src /obj/machinery/atmospherics/pipe/simple/heat_exchanging/process() if(!parent) @@ -180,4 +194,5 @@ return update_icon() + handle_leaking() return diff --git a/code/ATMOSPHERICS/pipes/he_pipes_vr.dm b/code/ATMOSPHERICS/pipes/he_pipes_vr.dm new file mode 100644 index 00000000000..d763f75b74c --- /dev/null +++ b/code/ATMOSPHERICS/pipes/he_pipes_vr.dm @@ -0,0 +1,2 @@ +/obj/machinery/atmospherics/pipe/simple/heat_exchanging/set_leaking(var/new_leaking) + return //Nope \ No newline at end of file diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm index 524d420d392..f44bfc56866 100644 --- a/code/ATMOSPHERICS/pipes/manifold.dm +++ b/code/ATMOSPHERICS/pipes/manifold.dm @@ -68,9 +68,24 @@ node3 = null update_icon() + handle_leaking() ..() +/obj/machinery/atmospherics/pipe/manifold/handle_leaking() + if(node1 && node2 && node3) + set_leaking(FALSE) + else + set_leaking(TRUE) + +/obj/machinery/atmospherics/pipe/manifold/process() + if(!parent) + ..() + else if(leaking) + parent.mingle_with_turf(loc, volume) + else + . = PROCESS_KILL + /obj/machinery/atmospherics/pipe/manifold/change_color(var/new_color) ..() //for updating connected atmos device pipes (i.e. vents, manifolds, etc) @@ -154,6 +169,7 @@ var/turf/T = get_turf(src) if(level == 1 && !T.is_plating()) hide(1) update_icon() + handle_leaking() /obj/machinery/atmospherics/pipe/manifold/visible icon_state = "map" diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm index 0cc022423b1..197c1a090b7 100644 --- a/code/ATMOSPHERICS/pipes/manifold4w.dm +++ b/code/ATMOSPHERICS/pipes/manifold4w.dm @@ -66,9 +66,24 @@ node4 = null update_icon() + handle_leaking() ..() +/obj/machinery/atmospherics/pipe/manifold4w/handle_leaking() + if(node1 && node2 && node3 && node4) + set_leaking(FALSE) + else + set_leaking(TRUE) + +/obj/machinery/atmospherics/pipe/manifold4w/process() + if(!parent) + ..() + else if(leaking) + parent.mingle_with_turf(loc, volume) + else + . = PROCESS_KILL + /obj/machinery/atmospherics/pipe/manifold4w/change_color(var/new_color) ..() //for updating connected atmos device pipes (i.e. vents, manifolds, etc) @@ -156,6 +171,7 @@ var/turf/T = get_turf(src) if(level == 1 && !T.is_plating()) hide(1) update_icon() + handle_leaking() /obj/machinery/atmospherics/pipe/manifold4w/visible icon_state = "map_4way" diff --git a/code/ATMOSPHERICS/pipes/pipe_base.dm b/code/ATMOSPHERICS/pipes/pipe_base.dm index a035857e549..d1bb92fac77 100644 --- a/code/ATMOSPHERICS/pipes/pipe_base.dm +++ b/code/ATMOSPHERICS/pipes/pipe_base.dm @@ -6,6 +6,7 @@ var/datum/gas_mixture/air_temporary // used when reconstructing a pipeline that broke var/datum/pipeline/parent var/volume = 0 + var/leaking = FALSE // Do not set directly, use set_leaking(TRUE/FALSE) layer = PIPES_LAYER use_power = 0 @@ -13,6 +14,7 @@ pipe_flags = 0 // Does not have PIPING_DEFAULT_LAYER_ONLY flag. var/alert_pressure = 80*ONE_ATMOSPHERE + var/in_stasis = FALSE //minimum pressure before check_pressure(...) should be called can_buckle = 1 @@ -30,6 +32,31 @@ /obj/machinery/atmospherics/pipe/hides_under_flooring() return level != 2 +/obj/machinery/atmospherics/pipe/proc/set_leaking(var/new_leaking) + if(new_leaking && !leaking) + if(!speed_process) + START_MACHINE_PROCESSING(src) + else + START_PROCESSING(SSfastprocess, src) + leaking = TRUE + if(parent) + parent.leaks |= src + if(parent.network) + parent.network.leaks |= src + else if (!new_leaking && leaking) + if(!speed_process) + STOP_MACHINE_PROCESSING(src) + else + STOP_PROCESSING(SSfastprocess, src) + leaking = FALSE + if(parent) + parent.leaks -= src + if(parent.network) + parent.network.leaks -= src + +/obj/machinery/atmospherics/pipe/proc/handle_leaking() // Used specifically to update leaking status on different pipes. + return + /obj/machinery/atmospherics/pipe/proc/pipeline_expansion() return null diff --git a/code/ATMOSPHERICS/pipes/pipe_base_vr.dm b/code/ATMOSPHERICS/pipes/pipe_base_vr.dm new file mode 100644 index 00000000000..d20e73ae89f --- /dev/null +++ b/code/ATMOSPHERICS/pipes/pipe_base_vr.dm @@ -0,0 +1,2 @@ +/obj/machinery/atmospherics/pipe/set_leaking(var/new_leaking) + return // N O P E \ No newline at end of file diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm index 6aee81807e8..eb980c3b476 100644 --- a/code/ATMOSPHERICS/pipes/simple.dm +++ b/code/ATMOSPHERICS/pipes/simple.dm @@ -1,6 +1,6 @@ // // Simple Pipes - Just a tube, maybe bent -// +// /obj/machinery/atmospherics/pipe/simple icon = 'icons/atmos/pipes.dmi' icon_state = "" @@ -34,6 +34,14 @@ icon = null alpha = 255 +/obj/machinery/atmospherics/pipe/simple/process() + if(!parent) + ..() + else if(leaking) + parent.mingle_with_turf(loc, volume) + else + . = PROCESS_KILL + /obj/machinery/atmospherics/pipe/simple/check_pressure(pressure) var/datum/gas_mixture/environment = loc.return_air() @@ -147,6 +155,7 @@ var/turf/T = loc if(level == 1 && !T.is_plating()) hide(1) update_icon() + handle_leaking() /obj/machinery/atmospherics/pipe/simple/disconnect(obj/machinery/atmospherics/reference) if(reference == node1) @@ -160,9 +169,16 @@ node2 = null update_icon() + handle_leaking() return null +/obj/machinery/atmospherics/pipe/simple/handle_leaking() + if(node1 && node2) + set_leaking(FALSE) + else + set_leaking(TRUE) + /obj/machinery/atmospherics/pipe/simple/visible icon_state = "intact" level = 2 diff --git a/code/ATMOSPHERICS/pipes/universal.dm b/code/ATMOSPHERICS/pipes/universal.dm index 2d8bd09dff8..00d2746947a 100644 --- a/code/ATMOSPHERICS/pipes/universal.dm +++ b/code/ATMOSPHERICS/pipes/universal.dm @@ -48,7 +48,7 @@ construction_type = /obj/item/pipe/binary pipe_state = "universal" -/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(var/safety = 0) +/obj/machinery/atmospherics/pipe/simple/hidden/universal/update_icon(var/safety = 0) // Doesn't leak. It's a special pipe. if(!check_icon_cache()) return diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm index b7ab1999f03..6ffec0be995 100644 --- a/code/ZAS/Phoron.dm +++ b/code/ZAS/Phoron.dm @@ -47,6 +47,12 @@ obj/var/contaminated = 0 return 0 else if(istype(src,/obj/item/weapon/storage/backpack)) return 0 //Cannot be washed :( + //VOREStation Addition start + else if(isbelly(loc)) + return 0 + else if(ismob(loc) && isbelly(loc.loc)) + return 0 + //VOREStation Addition end else if(istype(src,/obj/item/clothing)) return 1 diff --git a/code/__defines/damage_organs.dm b/code/__defines/damage_organs.dm index 9692409d458..c87b9942dfc 100644 --- a/code/__defines/damage_organs.dm +++ b/code/__defines/damage_organs.dm @@ -8,6 +8,7 @@ #define HALLOSS "halloss" #define ELECTROCUTE "electrocute" #define BIOACID "bioacid" +#define SEARING "searing" #define CUT "cut" #define BRUISE "bruise" diff --git a/code/__defines/lighting_vr.dm b/code/__defines/lighting_vr.dm new file mode 100644 index 00000000000..0cd6b060a17 --- /dev/null +++ b/code/__defines/lighting_vr.dm @@ -0,0 +1,2 @@ +#define LIGHT_COLOR_INCANDESCENT_TUBE "#E0EFF0" +#define LIGHT_COLOR_INCANDESCENT_BULB "#FFFEB8" \ No newline at end of file diff --git a/code/__defines/machinery.dm b/code/__defines/machinery.dm index 48babcae96a..43937e0cbe5 100644 --- a/code/__defines/machinery.dm +++ b/code/__defines/machinery.dm @@ -34,6 +34,7 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called #define NETWORK_CRESCENT "Spaceport" // #define NETWORK_CAFE_DOCK "Cafe Dock" #define NETWORK_CARGO "Cargo" +#define NETWORK_CIRCUITS "Circuits" #define NETWORK_CIVILIAN "Civilian" // #define NETWORK_CIVILIAN_EAST "Civilian East" // #define NETWORK_CIVILIAN_WEST "Civilian West" @@ -54,7 +55,7 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called #define NETWORK_SECURITY "Security" #define NETWORK_INTERROGATION "Interrogation" #define NETWORK_TELECOM "Tcomms" -#define NETWORK_THUNDER "Thunderdome" +#define NETWORK_THUNDER "Entertainment" //VOREStation Edit: broader definition #define NETWORK_COMMUNICATORS "Communicators" #define NETWORK_ALARM_ATMOS "Atmosphere Alarms" #define NETWORK_ALARM_POWER "Power Alarms" @@ -109,7 +110,7 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret #define SUPERMATTER_WARNING 3 // Ambient temp > CRITICAL_TEMPERATURE OR integrity damaged #define SUPERMATTER_DANGER 4 // Integrity < 50% #define SUPERMATTER_EMERGENCY 5 // Integrity < 25% -#define SUPERMATTER_DELAMINATING 6 // Pretty obvious. +#define SUPERMATTER_DELAMINATING 6 // Pretty obvious. //wIP - PORT ALL OF THESE TO SUBSYSTEMS AND GET RID OF THE WHOLE LIST PROCESS THING // Fancy-pants START/STOP_PROCESSING() macros that lets us custom define what the list is. diff --git a/code/__defines/map.dm b/code/__defines/map.dm index 7d0f3706aff..fce63b9955c 100644 --- a/code/__defines/map.dm +++ b/code/__defines/map.dm @@ -9,4 +9,4 @@ #define MAP_LEVEL_XENOARCH_EXEMPT 0x080 // Z-levels exempt from xenoarch digsite generation. // Misc map defines. -#define SUBMAP_MAP_EDGE_PAD 15 // Automatically created submaps are forbidden from being this close to the main map's edge. \ No newline at end of file +#define SUBMAP_MAP_EDGE_PAD 8 // Automatically created submaps are forbidden from being this close to the main map's edge. //VOREStation Edit \ No newline at end of file diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 2dc4afe70aa..7f7e9e705ef 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -175,6 +175,7 @@ #define MAT_LEAD "lead" #define MAT_SUPERMATTER "supermatter" #define MAT_METALHYDROGEN "mhydrogen" +#define MAT_OSMIUM "osmium" #define SHARD_SHARD "shard" #define SHARD_SHRAPNEL "shrapnel" diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 8426edcfcfe..efb94d49631 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -210,13 +210,17 @@ #define O_GBLADDER "gas bladder" #define O_POLYP "polyp segment" #define O_ANCHOR "anchoring ligament" +#define O_REGBRUTE "pneumoregenitor" +#define O_REGBURN "thermoregenitor" +#define O_REGOXY "respiroregenitor" +#define O_REGTOX "toxoregenitor" #define O_ACID "acid gland" #define O_EGG "egg sac" #define O_RESIN "resin spinner" #define O_AREJECT "immune hub" #define O_VENTC "morphoplastic node" #define O_VRLINK "virtual node" -#define O_ALL list(O_STANDARD, O_MOUTH, O_CELL, O_PLASMA, O_HIVE, O_NUTRIENT, O_STRATA, O_RESPONSE, O_GBLADDER, O_POLYP, O_ANCHOR, O_ACID, O_EGG, O_RESIN, O_AREJECT, O_VENTC, O_VRLINK) +#define O_ALL list(O_STANDARD, O_MOUTH, O_CELL, O_PLASMA, O_HIVE, O_NUTRIENT, O_STRATA, O_RESPONSE, O_GBLADDER, O_POLYP, O_ANCHOR, O_REGBRUTE, O_REGBURN, O_REGOXY, O_REGTOX, O_ACID, O_EGG, O_RESIN, O_AREJECT, O_VENTC, O_VRLINK) // External organs, aka limbs #define BP_L_FOOT "l_foot" diff --git a/code/__defines/species_languages_vr.dm b/code/__defines/species_languages_vr.dm index 224478646db..1004c1e22c1 100644 --- a/code/__defines/species_languages_vr.dm +++ b/code/__defines/species_languages_vr.dm @@ -1,3 +1,5 @@ +#define SPECIES_WHITELIST_SELECTABLE 0x20 // Can select and customize, but not join as + #define LANGUAGE_BIRDSONG "Birdsong" #define LANGUAGE_SAGARU "Sagaru" #define LANGUAGE_CANILUNZT "Canilunzt" diff --git a/code/__defines/xenoarcheaology.dm b/code/__defines/xenoarcheaology.dm index 45e40cfbdeb..8a4988b78c0 100644 --- a/code/__defines/xenoarcheaology.dm +++ b/code/__defines/xenoarcheaology.dm @@ -36,7 +36,8 @@ #define ARCHAEO_ALIEN_ITEM 36 #define ARCHAEO_ALIEN_BOAT 37 #define ARCHAEO_IMPERION_CIRCUIT 38 -#define MAX_ARCHAEO 38 +#define ARCHAEO_TELECUBE 39 +#define MAX_ARCHAEO 39 #define DIGSITE_GARDEN 1 #define DIGSITE_ANIMAL 2 diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm index 4618bb536df..846291edc46 100644 --- a/code/_helpers/global_lists_vr.dm +++ b/code/_helpers/global_lists_vr.dm @@ -11,6 +11,8 @@ var/global/list/positive_traits = list() // Positive custom species traits, inde var/global/list/traits_costs = list() // Just path = cost list, saves time in char setup var/global/list/all_traits = list() // All of 'em at once (same instances) +var/global/list/sensorpreflist = list("Off", "Binary", "Vitals", "Tracking", "No Preference") //TFF 5/8/19 - Suit Sensors global list + var/global/list/custom_species_bases = list() // Species that can be used for a Custom Species icon base //stores numeric player size options indexed by name @@ -121,6 +123,7 @@ var/global/list/tf_vore_egg_types = list( "Xenomorph" = /obj/structure/closet/secure_closet/egg/xenomorph) var/global/list/edible_trash = list(/obj/item/broken_device, + /obj/item/clothing/accessory/collar, //TFF 10/7/19 - add option to nom collars, /obj/item/clothing/mask, /obj/item/clothing/glasses, /obj/item/clothing/gloves, diff --git a/code/_helpers/icons_vr.dm b/code/_helpers/icons_vr.dm index be5de68e82d..60765578e71 100644 --- a/code/_helpers/icons_vr.dm +++ b/code/_helpers/icons_vr.dm @@ -42,4 +42,18 @@ for(var/x_pixel = 1 to I.Width()) if (I.GetPixel(x_pixel, y_pixel)) return y_pixel - 1 - return null \ No newline at end of file + return null + +//Standard behaviour is to cut pixels from the main icon that are covered by pixels from the mask icon unless passed mask_ready, see below. +/proc/get_icon_difference(var/icon/main, var/icon/mask, var/mask_ready) + /*You should skip prep if the mask is already sprited properly. This significantly improves performance by eliminating most of the realtime icon work. + e.g. A 'ready' mask is a mask where the part you want cut out is missing (no pixels, 0 alpha) from the sprite, and everything else is solid white.*/ + + if(istype(main) && istype(mask)) + if(!mask_ready) //Prep the mask if we're using a regular old sprite and not a special-made mask. + mask.Blend(rgb(255,255,255), ICON_SUBTRACT) //Make all pixels on the mask as black as possible. + mask.Opaque(rgb(255,255,255)) //Make the transparent pixels (background) white. + mask.BecomeAlphaMask() //Make all the black pixels vanish (fully transparent), leaving only the white background pixels. + + main.AddAlphaMask(mask) //Make the pixels in the main icon that are in the transparent zone of the mask icon also vanish (fully transparent). + return main diff --git a/code/_helpers/mobs.dm b/code/_helpers/mobs.dm index 96c97ec9f6a..220f896436c 100644 --- a/code/_helpers/mobs.dm +++ b/code/_helpers/mobs.dm @@ -235,6 +235,12 @@ Proc for attack log creation, because really why not var/atom/original_loc = user.loc + var/obj/mecha/M = null + + if(istype(user.loc, /obj/mecha)) + original_loc = get_turf(original_loc) + M = user.loc + var/holding = user.get_active_hand() var/datum/progressbar/progbar @@ -253,7 +259,12 @@ Proc for attack log creation, because really why not . = FALSE break - if(user.loc != original_loc && !ignore_movement) + if(M) + if(user.loc != M || (M.loc != original_loc && !ignore_movement)) // Mech coooooode. + . = FALSE + break + + else if(user.loc != original_loc && !ignore_movement) . = FALSE break diff --git a/code/_helpers/text.dm b/code/_helpers/text.dm index 0343fe42498..eb363c08cb3 100644 --- a/code/_helpers/text.dm +++ b/code/_helpers/text.dm @@ -84,7 +84,6 @@ // 0 .. 9 if(48 to 57) //Numbers - if(!last_char_group) continue //suppress at start of string if(!allow_numbers) continue // If allow_numbers is 0, then don't do this. output += ascii2text(ascii_char) number_of_alphanumeric++ diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 643ab6d7905..6cde2645660 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -114,6 +114,19 @@ trigger_aiming(TARGET_CAN_CLICK) return 1 + // VOREStation Addition Start: inbelly item interaction + if(isbelly(loc) && (loc == A.loc)) + if(W) + var/resolved = W.resolve_attackby(A,src) + if(!resolved && A && W) + W.afterattack(A, src, 1, params) // 1: clicking something Adjacent + else + if(ismob(A)) // No instant mob attacking + setClickCooldown(get_attack_speed()) + UnarmedAttack(A, 1) + return + // VOREStation Addition End + if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that return diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index e367769b077..3bd1a0afb2d 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -2,6 +2,9 @@ /atom/proc/attack_generic(mob/user as mob) return 0 +/atom/proc/take_damage(var/damage) + return 0 + /* Humans: Adds an exception for gloves, to allow special glove types like the ninja ones. diff --git a/code/controllers/subsystems/garbage.dm b/code/controllers/subsystems/garbage.dm index a741869b5b3..9938fa20eb0 100644 --- a/code/controllers/subsystems/garbage.dm +++ b/code/controllers/subsystems/garbage.dm @@ -240,9 +240,9 @@ SUBSYSTEM_DEF(garbage) time = TICK_DELTA_TO_MS(tick)/100 if (time > highest_del_time) highest_del_time = time - if (time > 10) - log_game("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete)") - message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete).") + if (time > 20) //VOREStation Edit + log_game("Error: [type]([refID]) took longer than 2 seconds to delete (took [time/10] seconds to delete)") //VOREStation Edit + message_admins("Error: [type]([refID]) took longer than 2 seconds to delete (took [time/10] seconds to delete).") //VOREStation Edit postpone(time) /datum/controller/subsystem/garbage/proc/HardQueue(datum/D) diff --git a/code/datums/autolathe/autolathe.dm b/code/datums/autolathe/autolathe.dm index a049a4456ca..91c9ec37b7a 100644 --- a/code/datums/autolathe/autolathe.dm +++ b/code/datums/autolathe/autolathe.dm @@ -8,9 +8,12 @@ var/datum/category_collection/autolathe/autolathe_recipes for(var/material in I.matter) var/coeff = (no_scale ? 1 : 1.25) //most objects are more expensive to produce than to recycle resources[material] = I.matter[material]*coeff // but if it's a sheet or RCD cartridge, it's 1:1 - if(is_stack && istype(I, /obj/item/stack)) - var/obj/item/stack/IS = I - max_stack = IS.max_amount + if(is_stack) + if(istype(I, /obj/item/stack)) + var/obj/item/stack/IS = I + max_stack = IS.max_amount + else + max_stack = 10 qdel(I) /**************************** @@ -65,7 +68,7 @@ var/datum/category_collection/autolathe/autolathe_recipes var/list/resources var/hidden var/power_use = 0 - var/is_stack + var/is_stack // Creates multiple of an item if applied to non-stack items var/max_stack var/no_scale diff --git a/code/datums/autolathe/general.dm b/code/datums/autolathe/general.dm index 2e2fa3c6fba..2f4436bf55b 100644 --- a/code/datums/autolathe/general.dm +++ b/code/datums/autolathe/general.dm @@ -105,10 +105,12 @@ /datum/category_item/autolathe/general/tube name = "light tube" path =/obj/item/weapon/light/tube + is_stack = TRUE /datum/category_item/autolathe/general/bulb name = "light bulb" path =/obj/item/weapon/light/bulb + is_stack = TRUE /datum/category_item/autolathe/general/ashtray_glass name = "glass ashtray" diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 541ba771942..089a6be7224 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -205,7 +205,7 @@ if(telemob.can_be_drop_prey && telenommer.can_be_drop_pred) return 1 obstructed = 1 - else if(!isturf(destination.loc) || !destination.x || !destination.y || !destination.z) //If we're inside something or outside universe + else if(!((isturf(destination) && !destination.density) || (isturf(destination.loc) && !destination.loc.density)) || !destination.x || !destination.y || !destination.z) //If we're inside something or outside universe obstructed = 1 to_chat(teleatom, "Something is blocking way on the other side!") if(obstructed) diff --git a/code/datums/helper_datums/teleport_vr.dm b/code/datums/helper_datums/teleport_vr.dm index b3054a44c09..d8e84285358 100644 --- a/code/datums/helper_datums/teleport_vr.dm +++ b/code/datums/helper_datums/teleport_vr.dm @@ -1,5 +1,5 @@ //wrapper -/proc/do_noeffect_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=TRUE) +/proc/do_noeffect_teleport(ateleatom, adestination, aprecision=0, afteleport=1, aeffectin=null, aeffectout=null, asoundin=null, asoundout=null, local=FALSE) new /datum/teleport/instant/science/noeffect(arglist(args)) return diff --git a/code/datums/outfits/military/fleet.dm b/code/datums/outfits/military/fleet.dm index cf5028978d0..915917918cf 100644 --- a/code/datums/outfits/military/fleet.dm +++ b/code/datums/outfits/military/fleet.dm @@ -1,21 +1,21 @@ /decl/hierarchy/outfit/military/fleet/pt name = OUTFIT_MILITARY("Fleet PT") - uniform = /obj/item/clothing/under/pt/fleet + uniform = /obj/item/clothing/under/solgov/pt/fleet shoes = /obj/item/clothing/shoes/black /decl/hierarchy/outfit/military/fleet/utility name = OUTFIT_MILITARY("Fleet Utility") - uniform = /obj/item/clothing/under/utility/fleet - shoes = /obj/item/clothing/shoes/boots/jackboots + uniform = /obj/item/clothing/under/solgov/utility/fleet + shoes = /obj/item/clothing/shoes/boots/duty /decl/hierarchy/outfit/military/fleet/service name = OUTFIT_MILITARY("Fleet Service") - uniform = /obj/item/clothing/under/service/fleet + uniform = /obj/item/clothing/under/solgov/service/fleet shoes = /obj/item/clothing/shoes/dress/white /decl/hierarchy/outfit/military/fleet/dress name = OUTFIT_MILITARY("Fleet Dress") - uniform = /obj/item/clothing/under/service/fleet + uniform = /obj/item/clothing/under/solgov/service/fleet shoes = /obj/item/clothing/shoes/dress/white suit = /obj/item/clothing/suit/storage/toggle/dress/fleet gloves = /obj/item/clothing/gloves/white diff --git a/code/datums/outfits/military/marines.dm b/code/datums/outfits/military/marines.dm index d818dabcaaa..719b36c6909 100644 --- a/code/datums/outfits/military/marines.dm +++ b/code/datums/outfits/military/marines.dm @@ -1,22 +1,22 @@ /decl/hierarchy/outfit/military/marine/pt name = OUTFIT_MILITARY("Marine PT") - uniform = /obj/item/clothing/under/pt/marine + uniform = /obj/item/clothing/under/solgov/pt/marine shoes = /obj/item/clothing/shoes/black /decl/hierarchy/outfit/military/marine/utility name = OUTFIT_MILITARY("Marine Utility") - uniform = /obj/item/clothing/under/utility/marine + uniform = /obj/item/clothing/under/solgov/utility/marine shoes = /obj/item/clothing/shoes/boots/jungle /decl/hierarchy/outfit/military/marine/service name = OUTFIT_MILITARY("Marine Service") - uniform = /obj/item/clothing/under/service/marine + uniform = /obj/item/clothing/under/solgov/service/marine shoes = /obj/item/clothing/shoes/dress suit = /obj/item/clothing/suit/storage/service/marine /decl/hierarchy/outfit/military/marine/dress name = OUTFIT_MILITARY("Marine Dress") - uniform = /obj/item/clothing/under/mildress/marine + uniform = /obj/item/clothing/under/solgov/mildress/marine shoes = /obj/item/clothing/shoes/dress/white suit = /obj/item/clothing/suit/dress/marine gloves = /obj/item/clothing/gloves/white diff --git a/code/datums/outfits/military/sifguard.dm b/code/datums/outfits/military/sifguard.dm index e1280f0cfed..9348224a9eb 100644 --- a/code/datums/outfits/military/sifguard.dm +++ b/code/datums/outfits/military/sifguard.dm @@ -1,22 +1,22 @@ /decl/hierarchy/outfit/military/sifguard/pt name = OUTFIT_MILITARY("SifGuard PT") - uniform = /obj/item/clothing/under/pt/sifguard + uniform = /obj/item/clothing/under/solgov/pt/sifguard shoes = /obj/item/clothing/shoes/black /decl/hierarchy/outfit/military/sifguard/utility name = OUTFIT_MILITARY("SifGuard Utility") - uniform = /obj/item/clothing/under/utility/sifguard - shoes = /obj/item/clothing/shoes/boots/jackboots + uniform = /obj/item/clothing/under/solgov/utility/sifguard + shoes = /obj/item/clothing/shoes/boots/tactical /decl/hierarchy/outfit/military/sifguard/service name = OUTFIT_MILITARY("SifGuard Service") - uniform = /obj/item/clothing/under/utility/sifguard - shoes = /obj/item/clothing/shoes/boots/jackboots + uniform = /obj/item/clothing/under/solgov/utility/sifguard + shoes = /obj/item/clothing/shoes/boots/tactical suit = /obj/item/clothing/suit/storage/service/sifguard /decl/hierarchy/outfit/military/sifguard/dress name = OUTFIT_MILITARY("SifGuard Dress") - uniform = /obj/item/clothing/under/mildress/sifguard + uniform = /obj/item/clothing/under/solgov/mildress/sifguard shoes = /obj/item/clothing/shoes/dress suit = /obj/item/clothing/suit/dress/expedition gloves = /obj/item/clothing/gloves/white diff --git a/code/datums/riding.dm b/code/datums/riding.dm index 746cc6dcf75..4f9513397a7 100644 --- a/code/datums/riding.dm +++ b/code/datums/riding.dm @@ -101,7 +101,7 @@ if(keycheck(user)) if(!Process_Spacemove(direction) || !isturf(ridden.loc)) return - step(ridden, direction) + ridden.Move(get_step(ridden, direction)) handle_vehicle_layer() handle_vehicle_offsets() diff --git a/code/datums/supplypacks/engineering.dm b/code/datums/supplypacks/engineering.dm index e3b9a148cce..e387309da7a 100644 --- a/code/datums/supplypacks/engineering.dm +++ b/code/datums/supplypacks/engineering.dm @@ -21,6 +21,20 @@ containertype = /obj/structure/closet/crate/engineering containername = "Superconducting Magnetic Coil crate" +/datum/supply_pack/eng/smescoil/super_capacity + name = "Superconducting Capacitance Coil" + contains = list(/obj/item/weapon/smes_coil/super_capacity) + cost = 90 + containertype = /obj/structure/closet/crate/engineering + containername = "Superconducting Capacitance Coil crate" + +/datum/supply_pack/eng/smescoil/super_io + name = "Superconducting Transmission Coil" + contains = list(/obj/item/weapon/smes_coil/super_io) + cost = 90 + containertype = /obj/structure/closet/crate/engineering + containername = "Superconducting Transmission Coil crate" + /datum/supply_pack/eng/shield_capacitor name = "Shield Capacitor" contains = list(/obj/machinery/shield_capacitor) @@ -290,4 +304,4 @@ cost = 75 containername = "Tritium crate" containertype = /obj/structure/closet/crate/engineering - contains = list(/obj/fiftyspawner/tritium) \ No newline at end of file + contains = list(/obj/fiftyspawner/tritium) diff --git a/code/datums/supplypacks/hospitality_vr.dm b/code/datums/supplypacks/hospitality_vr.dm index 95a921f8176..decb7027db1 100644 --- a/code/datums/supplypacks/hospitality_vr.dm +++ b/code/datums/supplypacks/hospitality_vr.dm @@ -1,3 +1,6 @@ +/datum/supply_pack/randomised/hospitality/pizza + cost = 50 + /datum/supply_pack/randomised/hospitality/burgers_vr num_contained = 5 contains = list( @@ -79,6 +82,3 @@ cost = 50 containertype = /obj/structure/closet/crate/freezer containername = "Chinese takeout crate" - -/datum/supply_pack/randomised/hospitality/pizza - cost = 25 diff --git a/code/datums/supplypacks/medical.dm b/code/datums/supplypacks/medical.dm index 555df731c47..e345b18505f 100644 --- a/code/datums/supplypacks/medical.dm +++ b/code/datums/supplypacks/medical.dm @@ -62,7 +62,7 @@ /obj/item/weapon/surgical/circular_saw ) cost = 25 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Surgery crate" access = access_medical @@ -73,7 +73,7 @@ /obj/item/weapon/storage/box/cdeathalarm_kit ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Death Alarm crate" access = access_medical @@ -83,7 +83,7 @@ /obj/item/weapon/storage/firstaid/clotting ) cost = 100 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Clotting Medicine crate" access = access_medical @@ -97,7 +97,7 @@ /obj/item/weapon/storage/belt/medical = 3 ) cost = 10 - containertype = "/obj/structure/closet/crate" + containertype = /obj/structure/closet/crate containername = "Sterile equipment crate" /datum/supply_pack/med/extragear @@ -109,7 +109,7 @@ /obj/item/clothing/suit/storage/hooded/wintercoat/medical = 3 ) cost = 10 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical surplus equipment" access = access_medical @@ -133,7 +133,7 @@ /obj/item/weapon/reagent_containers/syringe ) cost = 50 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Chief medical officer equipment" access = access_cmo @@ -156,7 +156,7 @@ /obj/item/weapon/reagent_containers/syringe ) cost = 20 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical Doctor equipment" access = access_medical_equip @@ -179,7 +179,7 @@ /obj/item/weapon/reagent_containers/syringe ) cost = 20 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Chemist equipment" access = access_chemistry @@ -207,7 +207,7 @@ /obj/item/clothing/accessory/storage/white_vest ) cost = 20 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Paramedic equipment" access = access_medical_equip @@ -226,7 +226,7 @@ /obj/item/weapon/cartridge/medical ) cost = 20 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Psychiatrist equipment" access = access_psychiatrist @@ -247,7 +247,7 @@ /obj/item/weapon/storage/box/gloves ) cost = 10 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical scrubs crate" access = access_medical_equip @@ -264,7 +264,7 @@ /obj/item/weapon/pen ) cost = 20 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Autopsy equipment crate" access = access_morgue @@ -291,7 +291,7 @@ /obj/item/weapon/storage/box/gloves ) cost = 10 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical uniform crate" access = access_medical_equip @@ -309,7 +309,7 @@ /obj/item/weapon/storage/box/gloves ) cost = 50 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical biohazard equipment" access = access_medical_equip @@ -317,7 +317,7 @@ name = "Portable freezers crate" contains = list(/obj/item/weapon/storage/box/freezer = 7) cost = 25 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Portable freezers" access = access_medical_equip @@ -325,7 +325,7 @@ name = "Virus sample crate" contains = list(/obj/item/weapon/virusdish/random = 4) cost = 25 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Virus sample crate" access = access_cmo @@ -334,4 +334,18 @@ contains = list(/obj/item/device/defib_kit = 2) cost = 30 containertype = /obj/structure/closet/crate/medical - containername = "Defibrillator crate" \ No newline at end of file + containername = "Defibrillator crate" + +/datum/supply_pack/med/distillery + name = "Chemical distiller crate" + contains = list(/obj/machinery/portable_atmospherics/powered/reagent_distillery = 1) + cost = 175 + containertype = /obj/structure/largecrate + containername = "Chemical distiller crate" + +/datum/supply_pack/med/advdistillery + name = "Industrial Chemical distiller crate" + contains = list(/obj/machinery/portable_atmospherics/powered/reagent_distillery/industrial = 1) + cost = 250 + containertype = /obj/structure/largecrate + containername = "Industrial Chemical distiller crate" diff --git a/code/datums/supplypacks/medical_vr.dm b/code/datums/supplypacks/medical_vr.dm index 5a080c5e9f4..0538f838679 100644 --- a/code/datums/supplypacks/medical_vr.dm +++ b/code/datums/supplypacks/medical_vr.dm @@ -1,38 +1,50 @@ -/datum/supply_pack/med/medicalbiosuits - contains = list( - /obj/item/clothing/head/bio_hood/scientist = 3, - /obj/item/clothing/suit/bio_suit/scientist = 3, - /obj/item/clothing/suit/bio_suit/virology = 3, - /obj/item/clothing/head/bio_hood/virology = 3, - /obj/item/clothing/suit/bio_suit/cmo, - /obj/item/clothing/head/bio_hood/cmo, - /obj/item/clothing/shoes/white = 7, - /obj/item/clothing/mask/gas = 7, - /obj/item/weapon/tank/oxygen = 7, - /obj/item/weapon/storage/box/masks, - /obj/item/weapon/storage/box/gloves - ) - cost = 40 - -/datum/supply_pack/med/virologybiosuits - name = "Virology biohazard gear" - contains = list( - /obj/item/clothing/suit/bio_suit/virology = 3, - /obj/item/clothing/head/bio_hood/virology = 3, - /obj/item/clothing/mask/gas = 3, - /obj/item/weapon/tank/oxygen = 3, - /obj/item/weapon/storage/box/masks, - /obj/item/weapon/storage/box/gloves - ) - cost = 40 - containertype = "/obj/structure/closet/crate/secure" - containername = "Virology biohazard equipment" - access = access_medical_equip - -/datum/supply_pack/med/virus - name = "Virus sample crate" - contains = list(/obj/item/weapon/virusdish/random = 4) - cost = 25 - containertype = "/obj/structure/closet/crate/secure" - containername = "Virus sample crate" - access = access_medical_equip \ No newline at end of file +/datum/supply_pack/med/medicalbiosuits + contains = list( + /obj/item/clothing/head/bio_hood/scientist = 3, + /obj/item/clothing/suit/bio_suit/scientist = 3, + /obj/item/clothing/suit/bio_suit/virology = 3, + /obj/item/clothing/head/bio_hood/virology = 3, + /obj/item/clothing/suit/bio_suit/cmo, + /obj/item/clothing/head/bio_hood/cmo, + /obj/item/clothing/shoes/white = 7, + /obj/item/clothing/mask/gas = 7, + /obj/item/weapon/tank/oxygen = 7, + /obj/item/weapon/storage/box/masks, + /obj/item/weapon/storage/box/gloves + ) + cost = 40 + +/datum/supply_pack/med/virologybiosuits + name = "Virology biohazard gear" + contains = list( + /obj/item/clothing/suit/bio_suit/virology = 3, + /obj/item/clothing/head/bio_hood/virology = 3, + /obj/item/clothing/mask/gas = 3, + /obj/item/weapon/tank/oxygen = 3, + /obj/item/weapon/storage/box/masks, + /obj/item/weapon/storage/box/gloves + ) + cost = 40 + containertype = /obj/structure/closet/crate/secure + containername = "Virology biohazard equipment" + access = access_medical_equip + +/datum/supply_pack/med/virus + name = "Virus sample crate" + contains = list(/obj/item/weapon/virusdish/random = 4) + cost = 25 + containertype = /obj/structure/closet/crate/secure + containername = "Virus sample crate" + access = access_medical_equip + + +/datum/supply_pack/med/bloodpack + containertype = /obj/structure/closet/crate/medical/blood + +/datum/supply_pack/med/compactdefib + name = "Compact Defibrillator crate" + contains = list(/obj/item/device/defib_kit/compact = 1) + cost = 90 + containertype = /obj/structure/closet/crate/secure + containername = "Compact Defibrillator crate" + access = access_medical_equip diff --git a/code/datums/supplypacks/misc.dm b/code/datums/supplypacks/misc.dm index c4cd4992c14..bf5b8ba53b4 100644 --- a/code/datums/supplypacks/misc.dm +++ b/code/datums/supplypacks/misc.dm @@ -103,7 +103,7 @@ /obj/item/weapon/storage/fancy/candle_box = 3 ) cost = 10 - containertype = "/obj/structure/closet/crate" + containertype = /obj/structure/closet/crate containername = "Chaplain equipment crate" /datum/supply_pack/misc/hoverpod @@ -126,7 +126,7 @@ /obj/item/clothing/accessory/storage/webbing ) cost = 10 - containertype = "/obj/structure/closet/crate" + containertype = /obj/structure/closet/crate containername = "Webbing crate" /datum/supply_pack/misc/holoplant @@ -142,5 +142,31 @@ /obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose = 5 ) cost = 25 - containertype = "obj/structure/closet/crate" - containername = "Glucose Hypo Crate" \ No newline at end of file + containertype = /obj/structure/closet/crate + containername = "Glucose Hypo Crate" + +/datum/supply_pack/misc/mre_rations + num_contained = 6 + name = "Emergency - MREs" + contains = list(/obj/item/weapon/storage/mre, + /obj/item/weapon/storage/mre/menu2, + /obj/item/weapon/storage/mre/menu3, + /obj/item/weapon/storage/mre/menu4, + /obj/item/weapon/storage/mre/menu5, + /obj/item/weapon/storage/mre/menu6, + /obj/item/weapon/storage/mre/menu7, + /obj/item/weapon/storage/mre/menu8, + /obj/item/weapon/storage/mre/menu9, + /obj/item/weapon/storage/mre/menu10) + cost = 50 + containertype = /obj/structure/closet/crate/freezer + containername = "ready to eat rations" + +/datum/supply_pack/misc/paste_rations + name = "Emergency - Paste" + contains = list( + /obj/item/weapon/storage/mre/menu11 = 2 + ) + cost = 25 + containertype = /obj/structure/closet/crate/freezer + containername = "emergency rations" diff --git a/code/datums/supplypacks/misc_vr.dm b/code/datums/supplypacks/misc_vr.dm index f85d7b97232..9e4ee3879d5 100644 --- a/code/datums/supplypacks/misc_vr.dm +++ b/code/datums/supplypacks/misc_vr.dm @@ -13,24 +13,6 @@ containername = "Belt-miner gear crate" access = access_mining -/datum/supply_pack/misc/rations - name = "Emergency rations" - contains = list( - /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 4, - ) - cost = 20 - containertype = /obj/structure/closet/crate/freezer - containername = "emergency rations" - -/datum/supply_pack/misc/proteinrations - name = "Emergency meat rations" - contains = list( - /obj/item/weapon/reagent_containers/food/snacks/liquidprotein = 4, - ) - cost = 30 - containertype = /obj/structure/closet/crate/freezer - containername = "emergency meat rations" - /datum/supply_pack/misc/eva_rig name = "eva hardsuit (empty)" contains = list( @@ -43,6 +25,7 @@ access_eva, access_explorer, access_pilot) + one_access = TRUE /datum/supply_pack/misc/mining_rig name = "industrial hardsuit (empty)" @@ -53,4 +36,5 @@ containertype = /obj/structure/closet/crate/secure/gear containername = "industrial hardsuit crate" access = list(access_mining, - access_eva) \ No newline at end of file + access_eva) + one_access = TRUE \ No newline at end of file diff --git a/code/datums/supplypacks/recreation.dm b/code/datums/supplypacks/recreation.dm index 7059e43755b..357f0eaeadc 100644 --- a/code/datums/supplypacks/recreation.dm +++ b/code/datums/supplypacks/recreation.dm @@ -55,7 +55,7 @@ /obj/item/weapon/wrapping_paper = 3 ) cost = 10 - containertype = "/obj/structure/closet/crate" + containertype = /obj/structure/closet/crate containername = "Arts and Crafts crate" /datum/supply_pack/recreation/painters @@ -87,4 +87,14 @@ contains = list( /obj/item/weapon/storage/box/wormcan, /obj/item/weapon/storage/box/wormcan/deluxe + ) + +/datum/supply_pack/recreation/ltagturrets + name = "Laser Tag Turrets" + cost = 40 + containername = "laser tag turret crate" + containertype = /obj/structure/closet/crate + contains = list( + /obj/machinery/porta_turret/lasertag/blue, + /obj/machinery/porta_turret/lasertag/red ) \ No newline at end of file diff --git a/code/datums/supplypacks/recreation_vr.dm b/code/datums/supplypacks/recreation_vr.dm index c4d7ee0ccc5..2e61f93473c 100644 --- a/code/datums/supplypacks/recreation_vr.dm +++ b/code/datums/supplypacks/recreation_vr.dm @@ -40,11 +40,11 @@ containertype = /obj/structure/closet/crate containername = "wolfgirl cosplay crate" -/datum/supply_pack/randomised/recreation/figures_vr +/datum/supply_pack/randomised/recreation/figures name = "Action figures crate" num_contained = 5 contains = list( - /obj/random/action_figure + /obj/random/action_figure/supplypack ) cost = 200 containertype = /obj/structure/closet/crate diff --git a/code/datums/supplypacks/science.dm b/code/datums/supplypacks/science.dm index 83407c28662..ab55b8571e8 100644 --- a/code/datums/supplypacks/science.dm +++ b/code/datums/supplypacks/science.dm @@ -56,3 +56,25 @@ cost = 30 containertype = /obj/structure/closet/crate containername = "Integrated circuit crate" + +/datum/supply_pack/sci/xenoarch + name = "Xenoarchaeology Tech crate" + contains = list( + /obj/item/weapon/pickaxe/excavationdrill, + /obj/item/device/xenoarch_multi_tool, + /obj/item/clothing/suit/space/anomaly, + /obj/item/clothing/head/helmet/space/anomaly, + /obj/item/weapon/storage/belt/archaeology, + /obj/item/device/flashlight/lantern, + /obj/item/device/core_sampler, + /obj/item/device/gps, + /obj/item/device/beacon_locator, + /obj/item/device/radio/beacon, + /obj/item/clothing/glasses/meson, + /obj/item/weapon/pickaxe, + /obj/item/weapon/storage/bag/fossils, + /obj/item/weapon/hand_labeler) + cost = 100 + containertype = /obj/structure/closet/crate/secure/science + containername = "Xenoarchaeology Tech crate" + access = access_research \ No newline at end of file diff --git a/code/datums/supplypacks/security.dm b/code/datums/supplypacks/security.dm index 4e4c8c13110..6e9e82bdde3 100644 --- a/code/datums/supplypacks/security.dm +++ b/code/datums/supplypacks/security.dm @@ -124,6 +124,30 @@ /obj/item/clothing/gloves/black ) */ + +/datum/supply_pack/security/flexitac + name = "Armor - Tactical Light" + containertype = /obj/structure/closet/crate/secure/gear + containername = "Tactical Light armor crate" + cost = 75 + access = access_armory + contains = list( + /obj/item/clothing/suit/storage/vest/heavy/flexitac, + /obj/item/clothing/head/helmet/flexitac, + /obj/item/clothing/shoes/leg_guard/flexitac, + /obj/item/clothing/gloves/arm_guard/flexitac, + /obj/item/clothing/mask/balaclava/tactical, + /obj/item/clothing/glasses/sunglasses/sechud/tactical, + /obj/item/weapon/storage/belt/security/tactical, + /obj/item/clothing/suit/storage/vest/heavy/flexitac, + /obj/item/clothing/head/helmet/flexitac, + /obj/item/clothing/shoes/leg_guard/flexitac, + /obj/item/clothing/gloves/arm_guard/flexitac, + /obj/item/clothing/mask/balaclava/tactical, + /obj/item/clothing/glasses/sunglasses/sechud/tactical, + /obj/item/weapon/storage/belt/security/tactical + ) + /datum/supply_pack/security/securitybarriers name = "Misc - Security Barriers" contains = list(/obj/machinery/deployable/barrier = 4) @@ -372,4 +396,4 @@ cost = 25 containertype = /obj/structure/closet/crate/secure containername = "Security biohazard gear" - access = access_security \ No newline at end of file + access = access_security diff --git a/code/datums/supplypacks/security_vr.dm b/code/datums/supplypacks/security_vr.dm index 12f2fa33b3f..852b44adee7 100644 --- a/code/datums/supplypacks/security_vr.dm +++ b/code/datums/supplypacks/security_vr.dm @@ -6,6 +6,7 @@ access = list( access_security, access_xenobiology) + one_access = TRUE /datum/supply_pack/security/guardmutant name = "VARMAcorp autoNOMous security solution for hostile environments" @@ -15,6 +16,7 @@ access = list( access_security, access_xenobiology) + one_access = TRUE */ /datum/supply_pack/randomised/security/armor diff --git a/code/datums/supplypacks/supply.dm b/code/datums/supplypacks/supply.dm index e8f26993ff9..c0db598cc48 100644 --- a/code/datums/supplypacks/supply.dm +++ b/code/datums/supplypacks/supply.dm @@ -61,7 +61,7 @@ /obj/item/weapon/tool/wirecutters, /obj/item/weapon/tape_roll = 2) cost = 10 - containertype = "/obj/structure/closet/crate" + containertype = /obj/structure/closet/crate containername = "Shipping supplies crate" /datum/supply_pack/supply/bureaucracy @@ -111,7 +111,7 @@ /obj/item/clothing/glasses/meson ) cost = 10 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Shaft miner equipment" access = access_mining /* //VOREStation Edit - Pointless on Tether. diff --git a/code/datums/supplypacks/voidsuits.dm b/code/datums/supplypacks/voidsuits.dm index 1feb6fe92e2..22bff55fcf3 100644 --- a/code/datums/supplypacks/voidsuits.dm +++ b/code/datums/supplypacks/voidsuits.dm @@ -17,7 +17,7 @@ /obj/item/weapon/tank/oxygen = 2, ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Atmospheric voidsuit crate" access = access_atmospherics @@ -31,7 +31,7 @@ /obj/item/weapon/tank/oxygen = 2, ) cost = 50 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Heavy Duty Atmospheric voidsuit crate" access = access_atmospherics @@ -45,7 +45,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Engineering voidsuit crate" access = access_engine_equip @@ -59,7 +59,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Engineering Construction voidsuit crate" access = access_engine_equip @@ -73,7 +73,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 45 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Engineering Hazmat voidsuit crate" access = access_engine_equip @@ -87,7 +87,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 50 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Reinforced Engineering voidsuit crate" access = access_engine_equip @@ -101,7 +101,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical voidsuit crate" access = access_medical_equip @@ -115,7 +115,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical EMT voidsuit crate" access = access_medical_equip @@ -129,7 +129,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 45 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Medical Biohazard voidsuit crate" access = access_medical_equip @@ -143,7 +143,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 60 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Vey-Med Medical voidsuit crate" access = access_medical_equip @@ -157,7 +157,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Security voidsuit crate" /datum/supply_pack/voidsuits/security/crowd @@ -170,7 +170,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Security Crowd Control voidsuit crate" access = access_armory @@ -184,7 +184,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 50 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Security EVA Riot voidsuit crate" access = access_armory @@ -197,7 +197,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 40 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Mining voidsuit crate" access = access_mining @@ -210,7 +210,7 @@ /obj/item/weapon/tank/oxygen = 2 ) cost = 50 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Frontier Mining voidsuit crate" access = access_mining @@ -221,6 +221,6 @@ /obj/item/clothing/mask/gas/zaddat = 1 ) cost = 30 - containertype = "/obj/structure/closet/crate" + containertype = /obj/structure/closet/crate containername = "Zaddat Shroud crate" access = null \ No newline at end of file diff --git a/code/datums/supplypacks/voidsuits_vr.dm b/code/datums/supplypacks/voidsuits_vr.dm index 8fcfd8ae501..cfadfcf2131 100644 --- a/code/datums/supplypacks/voidsuits_vr.dm +++ b/code/datums/supplypacks/voidsuits_vr.dm @@ -79,7 +79,7 @@ /obj/item/weapon/tank/oxygen = 3 ) cost = 50 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Exploration voidsuit crate" access = access_explorer @@ -93,6 +93,6 @@ /obj/item/weapon/tank/oxygen = 1 ) cost = 20 - containertype = "/obj/structure/closet/crate/secure" + containertype = /obj/structure/closet/crate/secure containername = "Pilot voidsuit crate" access = access_pilot \ No newline at end of file diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 5bd34e704bd..482598027af 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -29,6 +29,7 @@ gender = PLURAL icon = 'icons/obj/items.dmi' icon_state = "soap" + flags = NOCONDUCT w_class = ITEMSIZE_SMALL slot_flags = SLOT_HOLSTER throwforce = 0 @@ -395,7 +396,7 @@ display_contents_with_number = 1 max_w_class = ITEMSIZE_NORMAL max_storage_space = 100 - + /obj/item/weapon/storage/part_replacer/adv name = "advanced rapid part exchange device" desc = "Special mechanical module made to store, sort, and apply standard machine parts. This one has a greatly upgraded storage capacity" @@ -718,7 +719,7 @@ desc = "Instant research tool. For testing purposes only." icon = 'icons/obj/stock_parts.dmi' icon_state = "smes_coil" - origin_tech = list(TECH_MATERIAL = 19, TECH_ENGINEERING = 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) + origin_tech = list(TECH_MATERIAL = 19, TECH_ENGINEERING = 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, TECH_PRECURSOR = 19) // Additional construction stock parts diff --git a/code/game/antagonist/station/highlander.dm b/code/game/antagonist/station/highlander.dm index e2ec983818a..f483b1df3bd 100644 --- a/code/game/antagonist/station/highlander.dm +++ b/code/game/antagonist/station/highlander.dm @@ -47,8 +47,8 @@ var/datum/antagonist/highlander/highlanders 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_station_access() - W.access += get_all_centcom_access() + W.access = get_all_station_access().Copy + W.access |= get_all_centcom_access() W.assignment = "Highlander" W.registered_name = player.real_name player.equip_to_slot_or_del(W, slot_wear_id) diff --git a/code/game/area/Space Station 13 areas_vr.dm b/code/game/area/Space Station 13 areas_vr.dm index 396ab608215..c03489b3071 100644 --- a/code/game/area/Space Station 13 areas_vr.dm +++ b/code/game/area/Space Station 13 areas_vr.dm @@ -1,121 +1,4 @@ -/area/crew_quarters/sleep/vistor_room_1 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_2 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_3 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_4 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_5 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_6 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_7 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_8 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_9 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_10 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_11 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/vistor_room_12 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_1 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_2 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_3 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_4 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_5 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_6 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_7 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_8 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_9 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/crew_quarters/sleep/Dorm_10 - flags = RAD_SHIELDED | BLUE_SHIELDED - -/area/teleporter/departing - name = "\improper Long-Range Teleporter" - icon_state = "teleporter" - music = "signal" - -// Override telescience shielding on some areas -/area/security/armoury - flags = BLUE_SHIELDED - -/area/security/tactical - flags = BLUE_SHIELDED - -/area/security/nuke_storage - flags = BLUE_SHIELDED - -/area/supply - flags = BLUE_SHIELDED - -// Add rad shielding to maintenance and construction sites -/area/vacant - flags = RAD_SHIELDED - -/area/maintenance - flags = RAD_SHIELDED - -/area/rnd/research_storage //Located entirely in maint under public access, so why not that too - flags = RAD_SHIELDED - -// New shuttles -/area/shuttle/administration/transit - name = "Deep Space (AS)" - icon_state = "shuttle" - -/area/shuttle/administration/away_mission - name = "Away Mission (AS)" - icon_state = "shuttle" - -/area/shuttle/awaymission/home - name = "NSB Adephagia (AM)" - icon_state = "shuttle2" - -/area/shuttle/awaymission/warp - name = "Deep Space (AM)" - icon_state = "shuttle" - -/area/shuttle/awaymission/away - name = "Away Mission (AM)" - icon_state = "shuttle2" - -/area/shuttle/awaymission/oldengbase - name = "Old Construction Site (AM)" - icon_state = "shuttle2" +//TFF 28/8/19 - cleanup of areas placement - removes all but rogueminer_vr stuff. /area/shuttle/belter/station name = "Belter Shuttle Landed" @@ -162,140 +45,6 @@ icon_state = "red2" shuttle_area = /area/shuttle/belter/belt/zone4 -/area/medical/resleeving - name = "Resleeving Lab" - icon_state = "genetics" - -/area/bigship - name = "Bigship" - requires_power = 0 - flags = RAD_SHIELDED - sound_env = SMALL_ENCLOSED - base_turf = /turf/space - icon_state = "red2" - -/area/bigship/teleporter - name = "Bigship Teleporter Room" - -//////// Small Cruiser Areas //////// -/area/houseboat - name = "Small Cruiser" - requires_power = 0 - flags = RAD_SHIELDED - base_turf = /turf/space - icon_state = "red2" - lightswitch = TRUE - -/area/houseboat/holodeck_area - name = "Small Cruiser - Holodeck" - icon_state = "blue2" - -/area/houseboat/holodeck/off - name = "Small Cruiser Holo - Off" - icon_state = "blue2" -/area/houseboat/holodeck/beach - name = "Small Cruiser Holo - Beach" - icon_state = "blue2" -/area/houseboat/holodeck/snow - name = "Small Cruiser Holo - Snow" - icon_state = "blue2" -/area/houseboat/holodeck/desert - name = "Small Cruiser Holo - Desert" - icon_state = "blue2" -/area/houseboat/holodeck/picnic - name = "Small Cruiser Holo - Picnic" - icon_state = "blue2" -/area/houseboat/holodeck/thunderdome - name = "Small Cruiser Holo - Thunderdome" - icon_state = "blue2" -/area/houseboat/holodeck/basketball - name = "Small Cruiser Holo - Basketball" - icon_state = "blue2" -/area/houseboat/holodeck/gaming - name = "Small Cruiser Holo - Gaming Table" - icon_state = "blue2" -/area/houseboat/holodeck/space - name = "Small Cruiser Holo - Space" - icon_state = "blue2" -/area/houseboat/holodeck/bunking - name = "Small Cruiser Holo - Bunking" - icon_state = "blue2" - -/area/shuttle/cruiser/cruiser - name = "Small Cruiser Shuttle - Cruiser" - icon_state = "blue2" - base_turf = /turf/simulated/floor/tiled/techfloor -/area/shuttle/cruiser/station - name = "Small Cruiser Shuttle - Station" - icon_state = "blue2" - - -// Tether Map has this shuttle -/area/shuttle/tether/surface - name = "Tether Shuttle Landed" - icon_state = "shuttle" - base_turf = /turf/simulated/floor/reinforced - -/area/shuttle/tether/station - name = "Tether Shuttle Dock" - icon_state = "shuttle2" - -/area/shuttle/tether/transit - name = "Tether Shuttle Transit" - icon_state = "shuttle2" - -// rnd (Research and Development) -/area/rnd/research/testingrange - name = "\improper Weapons Testing Range" - icon_state = "firingrange" - -/area/rnd/research/researchdivision - name = "\improper Research Division" - icon_state = "research" - -/area/rnd/outpost - name = "\improper Research Outpost Hallway" - icon_state = "research" - -/area/rnd/outpost/airlock - name = "\improper Research Outpost Airlock" - icon_state = "green" - -/area/rnd/outpost/eva - name = "Research Outpost EVA Storage" - icon_state = "eva" - -/area/rnd/outpost/chamber - name = "\improper Research Outpost Burn Chamber" - icon_state = "engine" - -/area/rnd/outpost/atmos - name = "Research Outpost Atmospherics" - icon_state = "atmos" - -/area/rnd/outpost/storage - name = "\improper Research Outpost Gas Storage" - icon_state = "toxstorage" - -/area/rnd/outpost/mixing - name = "\improper Research Outpost Gas Mixing" - icon_state = "toxmix" - -/area/rnd/outpost/heating - name = "\improper Research Outpost Gas Heating" - icon_state = "toxmix" - -/area/rnd/outpost/testing - name = "\improper Research Outpost Testing" - icon_state = "toxtest" - -/area/maintenance/substation/outpost - name = "Research Outpost Substation" - /area/engineering/engine_gas name = "\improper Engine Gas Storage" icon_state = "engine_waste" - -/area/chapel/observation - name = "\improper Chapel Observation" - icon_state = "chapel" \ No newline at end of file diff --git a/code/game/area/areas_vr.dm b/code/game/area/areas_vr.dm new file mode 100644 index 00000000000..d422c1cd0f1 --- /dev/null +++ b/code/game/area/areas_vr.dm @@ -0,0 +1,6 @@ +/area/shuttle_arrived() + .=..() + for(var/obj/machinery/telecomms/relay/R in contents) + R.reset_z() + for(var/obj/machinery/power/apc/A in contents) + A.update_area() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 7154b9f47d4..c8f0b44c3d5 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,6 +1,6 @@ /atom/movable layer = OBJ_LAYER - appearance_flags = TILE_BOUND|PIXEL_SCALE + appearance_flags = TILE_BOUND|PIXEL_SCALE|KEEP_TOGETHER //VOREStation Edit var/last_move = null var/anchored = 0 // var/elevation = 2 - not used anywhere @@ -68,40 +68,51 @@ if(!newloc.Enter(src, src.loc)) return + + if(!check_multi_tile_move_density_dir(direct, locs)) // We're big, and we can't move that way. + return + // Past this is the point of no return - var/atom/oldloc = loc - var/area/oldarea = get_area(oldloc) - var/area/newarea = get_area(newloc) - loc = newloc - . = TRUE - oldloc.Exited(src, newloc) - if(oldarea != newarea) - oldarea.Exited(src, newloc) + if(!locs || locs.len <= 1) // We're not a multi-tile object. + var/atom/oldloc = loc + var/area/oldarea = get_area(oldloc) + var/area/newarea = get_area(newloc) + loc = newloc + . = TRUE + oldloc.Exited(src, newloc) + if(oldarea != newarea) + oldarea.Exited(src, newloc) - for(var/i in oldloc) - if(i == src) // Multi tile objects - continue - var/atom/movable/thing = i - thing.Uncrossed(src) + for(var/i in oldloc) + if(i == src) // Multi tile objects + continue + var/atom/movable/thing = i + thing.Uncrossed(src) - newloc.Entered(src, oldloc) - if(oldarea != newarea) - newarea.Entered(src, oldloc) + newloc.Entered(src, oldloc) + if(oldarea != newarea) + newarea.Entered(src, oldloc) + + for(var/i in loc) + if(i == src) // Multi tile objects + continue + var/atom/movable/thing = i + thing.Crossed(src) + + else if(newloc) // We're a multi-tile object. + . = doMove(newloc) - for(var/i in loc) - if(i == src) // Multi tile objects - continue - var/atom/movable/thing = i - thing.Crossed(src) // //////////////////////////////////////// -/atom/movable/Move(atom/newloc, direct) +/atom/movable/Move(atom/newloc, direct = 0) if(!loc || !newloc) return FALSE var/atom/oldloc = loc if(loc != newloc) + if(!direct) + direct = get_dir(oldloc, newloc) if (!(direct & (direct - 1))) //Cardinal move . = ..() else //Diagonal move, split it into cardinal moves @@ -197,6 +208,13 @@ . = TRUE return CanPass(AM, loc) +/atom/movable/CanPass(atom/movable/mover, turf/target) + . = ..() + if(locs && locs.len >= 2) // If something is standing on top of us, let them pass. + if(mover.loc in locs) + . = TRUE + return . + //oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called! /atom/movable/Crossed(atom/movable/AM, oldloc) return diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 7118aafe804..8560582ee82 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -2,6 +2,7 @@ name = "cult blade" desc = "An arcane weapon wielded by the followers of Nar-Sie." icon_state = "cultblade" + origin_tech = list(TECH_COMBAT = 1, TECH_ARCANE = 1) w_class = ITEMSIZE_LARGE force = 30 throwforce = 10 @@ -49,6 +50,7 @@ name = "cult hood" icon_state = "culthood" desc = "A hood worn by the followers of Nar-Sie." + origin_tech = list(TECH_MATERIAL = 3, TECH_ARCANE = 1) flags_inv = HIDEFACE body_parts_covered = HEAD armor = list(melee = 50, bullet = 30, laser = 50, energy = 80, bomb = 25, bio = 10, rad = 0) @@ -73,6 +75,7 @@ name = "cult robes" desc = "A set of armored robes worn by the followers of Nar-Sie." icon_state = "cultrobes" + origin_tech = list(TECH_MATERIAL = 3, TECH_ARCANE = 1) body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade) armor = list(melee = 50, bullet = 30, laser = 50, energy = 80, bomb = 25, bio = 10, rad = 0) @@ -96,6 +99,7 @@ name = "cult helmet" desc = "A space worthy helmet used by the followers of Nar-Sie." icon_state = "cult_helmet" + origin_tech = list(TECH_MATERIAL = 3, TECH_ARCANE = 1) armor = list(melee = 60, bullet = 50, laser = 30, energy = 80, bomb = 30, bio = 30, rad = 30) siemens_coefficient = 0 @@ -105,6 +109,7 @@ /obj/item/clothing/suit/space/cult name = "cult armour" icon_state = "cult_armour" + origin_tech = list(TECH_MATERIAL = 3, TECH_ARCANE = 1) desc = "A bulky suit of armour, bristling with spikes. It looks space-worthy." w_class = ITEMSIZE_NORMAL allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency/oxygen,/obj/item/device/suit_cooling_unit) diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index c87427bc44d..24c2ed5f527 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -35,6 +35,22 @@ /obj/structure/cult/pylon/attackby(obj/item/W as obj, mob/user as mob) attackpylon(user, W.force) +/obj/structure/cult/pylon/take_damage(var/damage) + pylonhit(damage) + +/obj/structure/cult/pylon/bullet_act(var/obj/item/projectile/Proj) + pylonhit(Proj.get_structure_damage()) + +/obj/structure/cult/pylon/proc/pylonhit(var/damage) + if(!isbroken) + if(prob(1+ damage * 5)) + visible_message("The pylon shatters!") + playsound(get_turf(src), 'sound/effects/Glassbr3.ogg', 75, 1) + isbroken = 1 + density = 0 + icon_state = "pylon-broken" + set_light(0) + /obj/structure/cult/pylon/proc/attackpylon(mob/user as mob, var/damage) if(!isbroken) if(prob(1+ damage * 5)) diff --git a/code/game/gamemodes/cult/soulstone.dm b/code/game/gamemodes/cult/soulstone.dm index 61db88917a6..9980f94d129 100644 --- a/code/game/gamemodes/cult/soulstone.dm +++ b/code/game/gamemodes/cult/soulstone.dm @@ -10,7 +10,7 @@ desc = "A fragment of the legendary treasure known simply as the 'Soul Stone'. The shard still flickers with a fraction of the full artefacts power." w_class = ITEMSIZE_SMALL slot_flags = SLOT_BELT - origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4) + origin_tech = list(TECH_BLUESPACE = 4, TECH_MATERIAL = 4, TECH_ARCANE = 1) var/imprinted = "empty" var/possible_constructs = list("Juggernaut","Wraith","Artificer","Harvester") diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index f0aa03253f7..eb2a88b4979 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -126,7 +126,7 @@ var/global/datum/controller/gameticker/ticker create_characters() //Create player characters and transfer them. collect_minds() equip_characters() - data_core.manifest() + //data_core.manifest() //VOREStation Removal callHook("roundstart") @@ -280,8 +280,13 @@ var/global/datum/controller/gameticker/ticker else if(!player.mind.assigned_role) continue else - if (player.create_character()) // VOREStation Edit + //VOREStation Edit Start + var/mob/living/carbon/human/new_char = player.create_character() + if(new_char) qdel(player) + if(istype(new_char) && !(new_char.mind.assigned_role=="Cyborg")) + data_core.manifest_inject(new_char) + //VOREStation Edit End proc/collect_minds() diff --git a/code/game/jobs/job/assistant.dm b/code/game/jobs/job/assistant.dm index b79314b8716..06c22a4c8bc 100644 --- a/code/game/jobs/job/assistant.dm +++ b/code/game/jobs/job/assistant.dm @@ -13,7 +13,7 @@ access = list() //See /datum/job/assistant/get_access() minimal_access = list() //See /datum/job/assistant/get_access() outfit_type = /decl/hierarchy/outfit/job/assistant/intern - alt_titles = list("Apprentice Engineer","Medical Intern","Lab Assistant","Security Cadet","Jr. Cargo Tech") //VOREStation Edit + alt_titles = list("Apprentice Engineer","Medical Intern","Lab Assistant","Security Cadet","Jr. Cargo Tech", "Jr. Explorer") //VOREStation Edit timeoff_factor = 0 //VOREStation Edit - Interns, noh //VOREStation Add diff --git a/code/game/jobs/job/captain.dm b/code/game/jobs/job/captain.dm index 94a32c3841b..450f59ec32c 100644 --- a/code/game/jobs/job/captain.dm +++ b/code/game/jobs/job/captain.dm @@ -31,7 +31,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1) H.implant_loyalty(src) */ /datum/job/captain/get_access() - return get_all_station_access() + return get_all_station_access().Copy() /datum/job/hop title = "Head of Personnel" diff --git a/code/game/jobs/job/special.dm b/code/game/jobs/job/special.dm index 7d1ccead195..fbed7452404 100644 --- a/code/game/jobs/job/special.dm +++ b/code/game/jobs/job/special.dm @@ -37,8 +37,7 @@ return 1 get_access() - var/access = get_all_accesses() - return access + return get_all_accesses().Copy() /*/datum/job/centcom_visitor //For Pleasure // You mean for admin abuse... -Ace title = "CentCom Visitor" diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm index f7a454a7de5..889e11c4e4c 100644 --- a/code/game/machinery/OpTable.dm +++ b/code/game/machinery/OpTable.dm @@ -80,7 +80,7 @@ if(C == user) user.visible_message("[user] climbs on \the [src].","You climb on \the [src].") else - visible_message("\The [C] has been laid on \the [src] by [user].", 3) + visible_message("\The [C] has been laid on \the [src] by [user].") if(C.client) C.client.perspective = EYE_PERSPECTIVE C.client.eye = src diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index b259fe1dedc..f89927e375c 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -29,8 +29,7 @@ sleeper = sleepernew sleepernew.console = src set_dir(get_dir(src, sleepernew)) - return - return + /obj/machinery/sleep_console/attack_ai(var/mob/user) return attack_hand(user) @@ -45,7 +44,7 @@ to_chat(user, "Sleeper not found!") return - if(sleeper.panel_open) + if(panel_open) to_chat(user, "Close the maintenance panel first.") return @@ -108,6 +107,7 @@ else data["beaker"] = -1 data["filtering"] = S.filtering + data["pump"] = S.pumping var/stasis_level_name = "Error!" for(var/N in S.stasis_choices) @@ -142,6 +142,9 @@ if(href_list["sleeper_filter"]) if(S.filtering != text2num(href_list["sleeper_filter"])) S.toggle_filter() + if(href_list["pump"]) + if(S.pumping != text2num(href_list["pump"])) + S.toggle_pump() if(href_list["chemical"] && href_list["amount"]) if(S.occupant && S.occupant.stat != DEAD) if(href_list["chemical"] in S.available_chemicals) // Your hacks are bad and you should feel bad @@ -166,6 +169,7 @@ var/list/base_chemicals = list("inaprovaline" = "Inaprovaline", "paracetamol" = "Paracetamol", "anti_toxin" = "Dylovene", "dexalin" = "Dexalin") var/obj/item/weapon/reagent_containers/glass/beaker = null var/filtering = 0 + var/pumping = 0 var/obj/machinery/sleep_console/console var/stasis_level = 0 //Every 'this' life ticks are applied to the mob (when life_ticks%stasis_level == 1) var/stasis_choices = list("Complete (1%)" = 100, "Deep (10%)" = 10, "Moderate (20%)" = 5, "Light (50%)" = 2, "None (100%)" = 0) @@ -263,6 +267,17 @@ else toggle_filter() + if(pumping > 0) + if(beaker) + if(beaker.reagents.total_volume < beaker.reagents.maximum_volume) + var/pumped = 0 + for(var/datum/reagent/x in occupant.ingested.reagent_list) + occupant.reagents.trans_to_obj(beaker, 3) + pumped++ + if(ishuman(occupant)) + occupant.ingested.trans_to_obj(beaker, pumped + 1) + else + toggle_pump() /obj/machinery/sleeper/update_icon() icon_state = "sleeper_[occupant ? "1" : "0"]" @@ -301,14 +316,12 @@ return if(UNCONSCIOUS) to_chat(usr, "You struggle through the haze to hit the eject button. This will take a couple of minutes...") - sleep(2 MINUTES) - if(!src || !usr || !occupant || (occupant != usr)) //Check if someone's released/replaced/bombed him already - return - go_out() + if(do_after(usr, 2 MINUTES, src)) + go_out() if(CONSCIOUS) go_out() else - if(usr.stat != 0) + if(usr.stat != CONSCIOUS) return go_out() add_fingerprint(usr) @@ -326,6 +339,9 @@ if(filtering) toggle_filter() + if(pumping) + toggle_pump() + if(stat & (BROKEN|NOPOWER)) ..(severity) return @@ -340,6 +356,12 @@ return filtering = !filtering +/obj/machinery/sleeper/proc/toggle_pump() + if(!occupant || !beaker) + pumping = 0 + return + pumping = !pumping + /obj/machinery/sleeper/proc/go_in(var/mob/M, var/mob/user) if(!M) return @@ -370,7 +392,8 @@ update_icon() /obj/machinery/sleeper/proc/go_out() - if(!occupant) + if(!occupant || occupant.loc != src) + occupant = null // JUST IN CASE return if(occupant.client) occupant.client.eye = occupant.client.mob @@ -387,6 +410,7 @@ update_use_power(1) update_icon() toggle_filter() + toggle_pump() /obj/machinery/sleeper/proc/remove_beaker() if(beaker) diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index ed238841038..484678c942b 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -448,4 +448,8 @@ update_flag ..() src.air_contents.adjust_gas("phoron", MolesForPressure()) src.update_icon() - return 1 \ No newline at end of file + return 1 + +/obj/machinery/portable_atmospherics/canister/take_damage(var/damage) + src.health -= damage + healthcheck() \ No newline at end of file diff --git a/code/game/machinery/atmoalter/clamp.dm b/code/game/machinery/atmoalter/clamp.dm new file mode 100644 index 00000000000..318145c2292 --- /dev/null +++ b/code/game/machinery/atmoalter/clamp.dm @@ -0,0 +1,154 @@ +//Good luck. --BlueNexus + +//Static version of the clamp +/obj/machinery/clamp + name = "stasis clamp" + desc = "A magnetic clamp which can halt the flow of gas in a pipe, via a localised stasis field." + description_info = "Click-dragging this to yourself while adjacent will attempt to remove it from the pipe." + icon = 'icons/atmos/clamp.dmi' + icon_state = "pclamp0" + anchored = 1.0 + var/obj/machinery/atmospherics/pipe/simple/target = null + var/open = 1 + + var/datum/pipe_network/network_node1 + var/datum/pipe_network/network_node2 + +/obj/machinery/clamp/New(loc, var/obj/machinery/atmospherics/pipe/simple/to_attach = null) + ..() + if(istype(to_attach)) + target = to_attach + else + target = locate(/obj/machinery/atmospherics/pipe/simple) in loc + if(target) + update_networks() + dir = target.dir + return 1 + +/obj/machinery/clamp/proc/update_networks() + if(!target) + return + else + var/obj/machinery/atmospherics/pipe/node1 = target.node1 + var/obj/machinery/atmospherics/pipe/node2 = target.node2 + if(istype(node1)) + var/datum/pipeline/P1 = node1.parent + network_node1 = P1.network + if(istype(node2)) + var/datum/pipeline/P2 = node2.parent + network_node2 = P2.network + +/obj/machinery/clamp/attack_hand(var/mob/user) + if(!target) + return FALSE + if(!open) + open() + else + close() + to_chat(user, "You turn [open ? "off" : "on"] \the [src]") + return TRUE + +/obj/machinery/clamp/Destroy() + if(!open) + spawn(-1) open() + . = ..() + +/obj/machinery/clamp/proc/open() + if(open || !target) + return 0 + + target.build_network() + + + if(network_node1&&network_node2) + network_node1.merge(network_node2) + network_node2 = network_node1 + + if(network_node1) + network_node1.update = 1 + else if(network_node2) + network_node2.update = 1 + + update_networks() + + open = 1 + icon_state = "pclamp0" + target.in_stasis = 0 + return 1 + +/obj/machinery/clamp/proc/close() + if(!open) + return 0 + + qdel(target.parent) + + if(network_node1) + qdel(network_node1) + if(network_node2) + qdel(network_node2) + + var/obj/machinery/atmospherics/pipe/node1 = null + var/obj/machinery/atmospherics/pipe/node2 = null + + if(target.node1) + target.node1.build_network() + node1 = target.node1 + if(target.node2) + target.node2.build_network() + node2 = target.node2 + if(istype(node1) && node1.parent) + var/datum/pipeline/P1 = node1.parent + P1.build_pipeline(node1) + qdel(P1) + if(istype(node2) && node2.parent) + var/datum/pipeline/P2 = node2.parent + P2.build_pipeline(node2) + qdel(P2) +// P1.build_network() +// P2.build_network() + + open = 0 + icon_state = "pclamp1" + target.in_stasis = 1 + + return 1 + +/obj/machinery/clamp/MouseDrop(obj/over_object as obj) + if(!usr) + return + + if(open && over_object == usr && Adjacent(usr)) + to_chat(usr, "You begin to remove \the [src]...") + if (do_after(usr, 30, src)) + to_chat(usr, "You have removed \the [src].") + var/obj/item/clamp/C = new/obj/item/clamp(src.loc) + C.forceMove(usr.loc) + if(ishuman(usr)) + usr.put_in_hands(C) + qdel(src) + return + else + to_chat(usr, "You can't remove \the [src] while it's active!") + +/obj/item/clamp + name = "stasis clamp" + desc = "A magnetic clamp which can halt the flow of gas in a pipe, via a localised stasis field." + icon = 'icons/atmos/clamp.dmi' + icon_state = "pclamp0" + origin_tech = list(TECH_ENGINEERING = 4, TECH_MAGNET = 4) + +/obj/item/clamp/afterattack(var/atom/A, mob/user as mob, proximity) + if(!proximity) + return + + if (istype(A, /obj/machinery/atmospherics/pipe/simple)) + to_chat(user, "You begin to attach \the [src] to \the [A]...") + var/C = locate(/obj/machinery/clamp) in get_turf(A) + if (do_after(user, 30, src) && !C) + if(!user.unEquip(src)) + return + to_chat(user, "You have attached \the [src] to \the [A].") + new/obj/machinery/clamp(A.loc, A) + qdel(src) + if(C) + to_chat(user, "\The [C] is already attached to the pipe at this location!") diff --git a/code/game/machinery/atmoalter/portable_atmospherics.dm b/code/game/machinery/atmoalter/portable_atmospherics.dm index 8778b4e5f3b..085c070f7d8 100644 --- a/code/game/machinery/atmoalter/portable_atmospherics.dm +++ b/code/game/machinery/atmoalter/portable_atmospherics.dm @@ -149,6 +149,8 @@ var/power_losses var/last_power_draw = 0 var/obj/item/weapon/cell/cell + var/use_cell = TRUE + var/removeable_cell = TRUE /obj/machinery/portable_atmospherics/powered/powered() if(use_power) //using area power @@ -158,7 +160,7 @@ return 0 /obj/machinery/portable_atmospherics/powered/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/cell)) + if(use_cell && istype(I, /obj/item/weapon/cell)) if(cell) to_chat(user, "There is already a power cell installed.") return @@ -173,7 +175,7 @@ power_change() return - if(I.is_screwdriver()) + if(I.is_screwdriver() && removeable_cell) if(!cell) to_chat(user, "There is no power cell installed.") return diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 223a81ebfd9..fa71e660220 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -277,9 +277,13 @@ //Create the desired item. var/obj/item/I = new making.path(src.loc) - if(multiplier > 1 && istype(I, /obj/item/stack)) - var/obj/item/stack/S = I - S.amount = multiplier + if(multiplier > 1) + if(istype(I, /obj/item/stack)) + var/obj/item/stack/S = I + S.amount = multiplier + else + for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack. + new making.path(src.loc) updateUsrDialog() diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index b3d5af5f3ec..34fda2bb06f 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -113,7 +113,7 @@ triggerCameraAlarm() update_icon() update_coverage() - START_PROCESSING(SSobj, src) + START_PROCESSING(SSobj, src) /obj/machinery/camera/bullet_act(var/obj/item/projectile/P) take_damage(P.get_structure_damage()) @@ -283,7 +283,7 @@ icon_state = initial(icon_state) add_hiddenprint(user) -/obj/machinery/camera/proc/take_damage(var/force, var/message) +/obj/machinery/camera/take_damage(var/force, var/message) //prob(25) gives an average of 3-4 hits if (force >= toughness && (force > toughness*4 || prob(25))) destroy() diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index abd0434c5e9..206dffaa432 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -25,7 +25,7 @@ var/global/list/station_networks = list( var/global/list/engineering_networks = list( NETWORK_ENGINE, NETWORK_ENGINEERING, - NETWORK_ENGINEERING_OUTPOST, + //NETWORK_ENGINEERING_OUTPOST, //VOREStation Edit: Tether has no Engineering Outpost, NETWORK_ALARM_ATMOS, NETWORK_ALARM_FIRE, NETWORK_ALARM_POWER) @@ -43,6 +43,9 @@ var/global/list/engineering_networks = list( /obj/machinery/camera/network/civilian network = list(NETWORK_CIVILIAN) +/obj/machinery/camera/network/circuits + network = list(NETWORK_CIRCUITS) + /* /obj/machinery/camera/network/civilian_east network = list(NETWORK_CIVILIAN_EAST) diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index bad819a985d..7c7f7043920 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -7,9 +7,19 @@ use_power = 1 idle_power_usage = 5 active_power_usage = 60000 //60 kW. (this the power drawn when charging) + var/efficiency = 60000 //will provide the modified power rate when upgraded power_channel = EQUIP var/obj/item/weapon/cell/charging = null var/chargelevel = -1 + circuit = /obj/item/weapon/circuitboard/cell_charger + +/obj/machinery/cell_charger/New() + component_parts = list() + component_parts += new /obj/item/weapon/stock_parts/capacitor(src) + component_parts += new /obj/item/stack/cable_coil(src, 5) + RefreshParts() + ..() + return /obj/machinery/cell_charger/update_icon() icon_state = "ccharger[charging ? 1 : 0]" @@ -32,9 +42,9 @@ if(!..(user, 5)) return - user << "There's [charging ? "a" : "no"] cell in the charger." + to_chat(user, "[charging ? "[charging]" : "Nothing"] is in [src].") if(charging) - user << "Current charge: [charging.charge]" + to_chat(user, "Current charge: [charging.charge] / [charging.maxcharge]") /obj/machinery/cell_charger/attackby(obj/item/weapon/W, mob/user) if(stat & BROKEN) @@ -42,56 +52,60 @@ if(istype(W, /obj/item/weapon/cell) && anchored) if(istype(W, /obj/item/weapon/cell/device)) - user << " The charger isn't fitted for that type of cell." + to_chat(user, "\The [src] isn't fitted for that type of cell.") return if(charging) - user << "There is already a cell in the charger." + to_chat(user, "There is already [charging] in [src].") return else var/area/a = loc.loc // Gets our locations location, like a dream within a dream if(!isarea(a)) return if(a.power_equip == 0) // There's no APC in this area, don't try to cheat power! - user << "The [name] blinks red as you try to insert the cell!" + to_chat(user, "\The [src] blinks red as you try to insert [W]!") return user.drop_item() W.loc = src charging = W - user.visible_message("[user] inserts a cell into the charger.", "You insert a cell into the charger.") + user.visible_message("[user] inserts [charging] into [src].", "You insert [charging] into [src].") chargelevel = -1 update_icon() else if(W.is_wrench()) if(charging) - user << "Remove the cell first!" + to_chat(user, "Remove [charging] first!") return anchored = !anchored - user << "You [anchored ? "attach" : "detach"] the cell charger [anchored ? "to" : "from"] the ground" + to_chat(user, "You [anchored ? "attach" : "detach"] [src] [anchored ? "to" : "from"] the ground") playsound(src, W.usesound, 75, 1) + else if(default_deconstruction_screwdriver(user, W)) + return + else if(default_deconstruction_crowbar(user, W)) + return + else if(default_part_replacement(user, W)) + return /obj/machinery/cell_charger/attack_hand(mob/user) + add_fingerprint(user) + if(charging) - usr.put_in_hands(charging) - charging.add_fingerprint(user) + user.put_in_hands(charging) charging.update_icon() + user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") charging = null - user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.") chargelevel = -1 update_icon() /obj/machinery/cell_charger/attack_ai(mob/user) if(istype(user, /mob/living/silicon/robot) && Adjacent(user)) // Borgs can remove the cell if they are near enough - if(!charging) - return - - charging.loc = src.loc - charging.update_icon() - charging = null - update_icon() - user.visible_message("[user] removes the cell from the charger.", "You remove the cell from the charger.") - + if(charging) + user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") + charging.loc = src.loc + charging.update_icon() + charging = null + update_icon() /obj/machinery/cell_charger/emp_act(severity) if(stat & (BROKEN|NOPOWER)) @@ -108,9 +122,15 @@ return if(charging && !charging.fully_charged()) - charging.give(active_power_usage*CELLRATE) + charging.give(efficiency*CELLRATE) update_use_power(2) update_icon() else update_use_power(1) + +/obj/machinery/cell_charger/RefreshParts() + var/E = 0 + for(var/obj/item/weapon/stock_parts/capacitor/C in component_parts) + E += C.rating + efficiency = active_power_usage * (1+ (E - 1)*0.5) \ No newline at end of file diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm index 9b1dd198d92..eb78d41e263 100644 --- a/code/game/machinery/computer/card.dm +++ b/code/game/machinery/computer/card.dm @@ -279,7 +279,7 @@ if ("terminate") if (is_authenticated()) - modify.assignment = "Terminated" + modify.assignment = "Dismissed" //VOREStation Edit: setting adjustment modify.access = list() callHook("terminate_employee", list(modify)) diff --git a/code/game/machinery/computer/shutoff_monitor.dm b/code/game/machinery/computer/shutoff_monitor.dm new file mode 100644 index 00000000000..4dd79376c92 --- /dev/null +++ b/code/game/machinery/computer/shutoff_monitor.dm @@ -0,0 +1,42 @@ +/obj/machinery/computer/shutoff_monitor + name = "automated shutoff valve monitor" + desc = "Console used to remotely monitor shutoff valves on the station." + icon_keyboard = "power_key" + icon_screen = "power:0" + light_color = "#a97faa" + circuit = /obj/item/weapon/circuitboard/shutoff_monitor + +/obj/machinery/computer/shutoff_monitor/attack_hand(var/mob/user) + ..() + ui_interact(user) + +/obj/machinery/computer/shutoff_monitor/attack_robot(var/mob/user) // Borgs and AI will want to see this too + ..() + ui_interact(user) + +/obj/machinery/computer/shutoff_monitor/attack_ai(var/mob/user) + ui_interact(user) + +/obj/machinery/computer/shutoff_monitor/ui_interact(mob/user, ui_key = "shutoff_monitor", var/datum/nanoui/ui = null, var/force_open = 1, var/key_state = null) + var/data[0] + data["valves"] = list() + for(var/obj/machinery/atmospherics/valve/shutoff/S in GLOB.shutoff_valves) + data["valves"][++data["valves"].len] = list("name" = S.name, "enable" = S.close_on_leaks, "open" = S.open, "x" = S.x, "y" = S.y, "z" = S.z) + + // update the ui if it exists, returns null if no ui is passed/found + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + // the ui does not exist, so we'll create a new() one + // for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm + ui = new(user, src, ui_key, "shutoff_monitor.tmpl", "Automated Shutoff Valve Monitor", 625, 700, state = key_state) + // when the ui is first opened this is the data it will use + ui.set_initial_data(data) + // open the new ui window + ui.open() + // auto update every 20 Master Controller tick + ui.set_auto_update(20) // Longer term to reduce the rate of data collection and processing + +/obj/machinery/computer/shutoff_monitor/update_icon() + ..() + if(!(stat & (NOPOWER|BROKEN))) + overlays += image('icons/obj/computer.dmi', "ai-fixer-empty", overlay_layer) diff --git a/code/game/machinery/computer/timeclock_vr.dm b/code/game/machinery/computer/timeclock_vr.dm index f992aaab102..4969e89334b 100644 --- a/code/game/machinery/computer/timeclock_vr.dm +++ b/code/game/machinery/computer/timeclock_vr.dm @@ -170,6 +170,7 @@ foundjob.current_positions++ var/mob/living/carbon/human/H = usr H.mind.assigned_role = foundjob.title + H.mind.role_alt_title = newjob announce.autosay("[card.registered_name] has moved On-Duty as [card.assignment].", "Employee Oversight") return @@ -200,6 +201,7 @@ callHook("reassign_employee", list(card)) var/mob/living/carbon/human/H = usr H.mind.assigned_role = ptojob.title + H.mind.role_alt_title = ptojob.title foundjob.current_positions-- announce.autosay("[card.registered_name], [oldtitle], has moved Off-Duty.", "Employee Oversight") return diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 765ced8a398..42725bbe285 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -2,52 +2,6 @@ CONTAINS: Deployable items Barricades - -for reference: - access_security = 1 - access_brig = 2 - access_armory = 3 - access_forensics_lockers= 4 - access_medical = 5 - access_morgue = 6 - access_tox = 7 - access_tox_storage = 8 - access_genetics = 9 - access_engine = 10 - access_engine_equip= 11 - access_maint_tunnels = 12 - access_external_airlocks = 13 - access_emergency_storage = 14 - access_change_ids = 15 - access_ai_upload = 16 - access_teleporter = 17 - access_eva = 18 - access_heads = 19 - access_captain = 20 - access_all_personal_lockers = 21 - access_chapel_office = 22 - access_tech_storage = 23 - access_atmospherics = 24 - access_bar = 25 - access_janitor = 26 - access_crematorium = 27 - access_kitchen = 28 - access_robotics = 29 - access_rd = 30 - access_cargo = 31 - access_construction = 32 - access_chemistry = 33 - access_cargo_bot = 34 - access_hydroponics = 35 - access_manufacturing = 36 - access_library = 37 - access_lawyer = 38 - access_virology = 39 - access_cmo = 40 - access_qm = 41 - access_court = 42 - access_clown = 43 - access_mime = 44 */ //Barricades! @@ -80,6 +34,7 @@ for reference: return material /obj/structure/barricade/attackby(obj/item/W as obj, mob/user as mob) + user.setClickCooldown(user.get_attack_speed(W)) if(istype(W, /obj/item/stack)) var/obj/item/stack/D = W if(D.get_material_name() != material.name) @@ -96,37 +51,54 @@ for reference: return return else - user.setClickCooldown(user.get_attack_speed(W)) switch(W.damtype) if("fire") health -= W.force * 1 if("brute") health -= W.force * 0.75 - else - if(health <= 0) - visible_message("The barricade is smashed apart!") - dismantle() - qdel(src) - return + if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) + playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1) + else + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + CheckHealth() ..() +/obj/structure/barricade/proc/CheckHealth() + if(health <= 0) + dismantle() + return + +/obj/structure/barricade/take_damage(var/damage) + health -= damage + CheckHealth() + return + +/obj/structure/barricade/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + if(material == get_material_by_name("resin")) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) + playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1) + else + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + user.do_attack_animation(src) + health -= damage + CheckHealth() + return + /obj/structure/barricade/proc/dismantle() material.place_dismantled_product(get_turf(src)) + visible_message("\The [src] falls apart!") qdel(src) return /obj/structure/barricade/ex_act(severity) switch(severity) if(1.0) - visible_message("\The [src] is blown apart!") - qdel(src) - return + dismantle() if(2.0) health -= 25 - if(health <= 0) - visible_message("\The [src] is blown apart!") - dismantle() - return + CheckHealth() /obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff. if(istype(mover) && mover.checkpass(PASSTABLE)) @@ -158,6 +130,7 @@ for reference: icon_state = "barrier[locked]" /obj/machinery/deployable/barrier/attackby(obj/item/weapon/W as obj, mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(istype(W, /obj/item/weapon/card/id/)) if(allowed(user)) if (emagged < 2.0) @@ -196,11 +169,28 @@ for reference: health -= W.force * 0.75 if("brute") health -= W.force * 0.5 - else - if(health <= 0) - explode() + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + CheckHealth() ..() +/obj/machinery/deployable/barrier/proc/CheckHealth() + if(health <= 0) + explode() + return + +/obj/machinery/deployable/barrier/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + user.do_attack_animation(src) + health -= damage + CheckHealth() + return + +/obj/machinery/deployable/barrier/take_damage(var/damage) + health -= damage + CheckHealth() + return + /obj/machinery/deployable/barrier/ex_act(severity) switch(severity) if(1.0) @@ -208,8 +198,7 @@ for reference: return if(2.0) health -= 25 - if(health <= 0) - explode() + CheckHealth() return /obj/machinery/deployable/barrier/emp_act(severity) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index d276efef354..c55a7d8345f 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -308,7 +308,7 @@ operating = -1 return 1 -/obj/machinery/door/proc/take_damage(var/damage) +/obj/machinery/door/take_damage(var/damage) var/initialhealth = src.health src.health = max(0, src.health - damage) if(src.health <= 0 && initialhealth > 0) diff --git a/code/game/machinery/frame.dm b/code/game/machinery/frame.dm index c54734aec0d..0baa68cf223 100644 --- a/code/game/machinery/frame.dm +++ b/code/game/machinery/frame.dm @@ -90,12 +90,24 @@ circuit = /obj/item/weapon/circuitboard/recharger frame_size = 3 +/datum/frame/frame_types/cell_charger + name = "Heavy-Duty Cell Charger" + frame_class = FRAME_CLASS_MACHINE + circuit = /obj/item/weapon/circuitboard/cell_charger + frame_size = 3 + /datum/frame/frame_types/grinder name = "Grinder" frame_class = FRAME_CLASS_MACHINE circuit = /obj/item/weapon/circuitboard/grinder frame_size = 3 +/datum/frame/frame_types/reagent_distillery + name = "Distillery" + frame_class = FRAME_CLASS_MACHINE + circuit = /obj/item/weapon/circuitboard/distiller + frame_size = 4 + /datum/frame/frame_types/display name = "Display" frame_class = FRAME_CLASS_DISPLAY diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 6a86dcfcb3d..4251a0e6067 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -415,11 +415,15 @@ Class Procs: var/obj/item/weapon/circuitboard/M = circuit A.circuit = M A.anchored = 1 - A.density = 1 A.frame_type = M.board_type if(A.frame_type.circuit) A.need_circuit = 0 + if(A.frame_type.frame_class == FRAME_CLASS_ALARM || A.frame_type.frame_class == FRAME_CLASS_DISPLAY) + A.density = 0 + else + A.density = 1 + if(A.frame_type.frame_class == FRAME_CLASS_MACHINE) for(var/obj/D in component_parts) D.forceMove(src.loc) diff --git a/code/game/machinery/pipe/pipe_recipes.dm b/code/game/machinery/pipe/pipe_recipes.dm index f0ae4830552..a54cdd4eee7 100644 --- a/code/game/machinery/pipe/pipe_recipes.dm +++ b/code/game/machinery/pipe/pipe_recipes.dm @@ -27,6 +27,7 @@ var/global/list/atmos_pipe_recipes = null new /datum/pipe_recipe/pipe("Gas Pump", /obj/machinery/atmospherics/binary/pump), new /datum/pipe_recipe/pipe("Pressure Regulator", /obj/machinery/atmospherics/binary/passive_gate), new /datum/pipe_recipe/pipe("High Power Gas Pump",/obj/machinery/atmospherics/binary/pump/high_power), + //new /datum/pipe_recipe/pipe("Automatic Shutoff Valve",/obj/machinery/atmospherics/valve/shutoff), //VOREStation Removal: Without leaks, those are just regular valves, new /datum/pipe_recipe/pipe("Scrubber", /obj/machinery/atmospherics/unary/vent_scrubber), new /datum/pipe_recipe/meter("Meter"), new /datum/pipe_recipe/pipe("Gas Filter", /obj/machinery/atmospherics/trinary/atmos_filter), diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 948ef595c8d..56fa5c75a03 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -36,83 +36,75 @@ name = "turret" catalogue_data = list(/datum/category_item/catalogue/technology/turret) icon = 'icons/obj/turrets.dmi' - icon_state = "turret_cover" - anchored = 1 + icon_state = "turret_cover_normal" + anchored = TRUE - density = 0 - use_power = 1 //this turret uses and requires power + density = FALSE + use_power = TRUE //this turret uses and requires power idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power power_channel = EQUIP //drains power from the EQUIPMENT channel req_one_access = list(access_security, access_heads) - // icon_states for turrets. - // These are for the turret covers. - var/closed_state = "turret_cover" // For when it is closed. - var/raising_state = "popup" // When turret is opening. - var/opened_state = "open" // When fully opened. - var/lowering_state = "popdown" // When closing. - var/gun_active_state = "target_prism" // The actual gun's icon_state when active. - var/gun_disabled_state = "grey_target_prism" // Gun sprite when depowered/disabled. - var/gun_destroyed_state = "destroyed_target_prism" // Turret sprite for when the turret dies. - - var/raised = 0 //if the turret cover is "open" and the turret is raised - var/raising= 0 //if the turret is currently opening or closing its cover - var/health = 80 //the turret's health - var/maxhealth = 80 //turrets maximal health. - var/auto_repair = 0 //if 1 the turret slowly repairs itself. - var/locked = 1 //if the turret's behaviour control access is locked - var/controllock = 0 //if the turret responds to control panels + var/raised = FALSE //if the turret cover is "open" and the turret is raised + var/raising= FALSE //if the turret is currently opening or closing its cover + var/health = 80 //the turret's health + var/maxhealth = 80 //turrets maximal health. + var/auto_repair = FALSE //if 1 the turret slowly repairs itself. + var/locked = TRUE //if the turret's behaviour control access is locked + var/controllock = FALSE //if the turret responds to control panels var/installation = /obj/item/weapon/gun/energy/gun //the type of weapon installed - var/gun_charge = 0 //the charge of the gun inserted - var/projectile = null //holder for bullettype - var/eprojectile = null //holder for the shot when emagged - var/reqpower = 500 //holder for power needed - var/iconholder = null //holder for the icon_state. 1 for sprite based on icon_color, null for blue. - var/icon_color = "orange" // When iconholder is set to 1, the icon_state changes based on what is in this variable. - var/egun = null //holder to handle certain guns switching bullettypes + var/gun_charge = 0 //the charge of the gun inserted + var/projectile = null //holder for bullettype + var/lethal_projectile = null //holder for the shot when emagged + var/reqpower = 500 //holder for power needed + var/turret_type = "normal" + var/icon_color = "blue" + var/lethal_icon_color = "blue" - var/last_fired = 0 //1: if the turret is cooling down from a shot, 0: turret is ready to fire - var/shot_delay = 15 //1.5 seconds between each shot + var/last_fired = FALSE //TRUE: if the turret is cooling down from a shot, FALSE: turret is ready to fire + var/shot_delay = 1.5 SECONDS //1.5 seconds between each shot - var/check_arrest = 1 //checks if the perp is set to arrest - var/check_records = 1 //checks if a security record exists at all - var/check_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have - var/check_access = 1 //if this is active, the turret shoots everything that does not meet the access requirements - var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos) - var/check_synth = 0 //if active, will shoot at anything not an AI or cyborg - var/check_all = 0 //If active, will fire on anything, including synthetics. - var/ailock = 0 // AI cannot use this - var/faction = null //if set, will not fire at people in the same faction for any reason. + var/check_arrest = TRUE //checks if the perp is set to arrest + var/check_records = TRUE //checks if a security record exists at all + var/check_weapons = FALSE //checks if it can shoot people that have a weapon they aren't authorized to have + var/check_access = TRUE //if this is active, the turret shoots everything that does not meet the access requirements + var/check_anomalies = TRUE //checks if it can shoot at unidentified lifeforms (ie xenos) + var/check_synth = FALSE //if active, will shoot at anything not an AI or cyborg + var/check_all = FALSE //If active, will fire on anything, including synthetics. + var/ailock = FALSE // AI cannot use this + var/check_down = FALSE //If active, will shoot to kill when lethals are also on + var/faction = null //if set, will not fire at people in the same faction for any reason. - var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) + var/attacked = FALSE //if set to TRUE, the turret gets pissed off and shoots at people nearby (unless they have sec access!) - var/enabled = 1 //determines if the turret is on - var/lethal = 0 //whether in lethal or stun mode - var/disabled = 0 + var/enabled = TRUE //determines if the turret is on + var/lethal = FALSE //whether in lethal or stun mode + var/disabled = FALSE - var/shot_sound //what sound should play when the turret fires - var/eshot_sound //what sound should play when the emagged turret fires + var/shot_sound //what sound should play when the turret fires + var/lethal_shot_sound //what sound should play when the emagged turret fires var/datum/effect/effect/system/spark_spread/spark_system //the spark system, used for generating... sparks? - var/wrenching = 0 + var/wrenching = FALSE var/last_target //last target fired at, prevents turrets from erratically firing at all valid targets in range var/timeout = 10 // When a turret pops up, then finds nothing to shoot at, this number decrements until 0, when it pops down. var/can_salvage = TRUE // If false, salvaging doesn't give you anything. /obj/machinery/porta_turret/crescent req_one_access = list(access_cent_specops) - enabled = 0 - ailock = 1 - check_synth = 0 - check_access = 1 - check_arrest = 1 - check_records = 1 - check_weapons = 1 - check_anomalies = 1 - check_all = 0 + enabled = FALSE + ailock = TRUE + check_synth = FALSE + check_access = TRUE + check_arrest = TRUE + check_records = TRUE + check_weapons = TRUE + check_anomalies = TRUE + check_all = FALSE + check_down = TRUE /obj/machinery/porta_turret/can_catalogue(mob/user) // Dead turrets can't be scanned. if(stat & BROKEN) @@ -121,8 +113,8 @@ return ..() /obj/machinery/porta_turret/stationary - ailock = 1 - lethal = 1 + ailock = TRUE + lethal = TRUE installation = /obj/item/weapon/gun/energy/laser /obj/machinery/porta_turret/stationary/syndie // Generic turrets for POIs that need to not shoot their buddies. @@ -139,7 +131,6 @@ health = 250 // Since lasers do 40 each. maxhealth = 250 - /datum/category_item/catalogue/anomalous/precursor_a/alien_turret name = "Precursor Alpha Object - Turrets" desc = "An autonomous defense turret created by unknown ancient aliens. It utilizes an \ @@ -156,7 +147,7 @@ name = "interior anti-boarding turret" desc = "A very tough looking turret made by alien hands." catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/alien_turret) - icon_state = "alien_turret_cover" + icon_state = "turret_cover_alien" req_one_access = list(access_alien) installation = /obj/item/weapon/gun/energy/alien enabled = TRUE @@ -165,22 +156,51 @@ check_all = TRUE health = 250 // Similar to the AI turrets. maxhealth = 250 - - closed_state = "alien_turret_cover" - raising_state = "alien_popup" - opened_state = "alien_open" - lowering_state = "alien_popdown" - gun_active_state = "alien_gun" - gun_disabled_state = "alien_gun_disabled" - gun_destroyed_state = "alien_gun_destroyed" + turret_type = "alien" /obj/machinery/porta_turret/alien/destroyed // Turrets that are already dead, to act as a warning of what the rest of the submap contains. name = "broken interior anti-boarding turret" desc = "A very tough looking turret made by alien hands. This one looks destroyed, thankfully." - icon_state = "alien_gun_destroyed" + icon_state = "destroyed_target_prism_alien" stat = BROKEN can_salvage = FALSE // So you need to actually kill a turret to get the alien gun. +/obj/machinery/porta_turret/industrial + name = "industrial turret" + desc = "This variant appears to be much more rugged." + req_one_access = list(access_heads) + icon_state = "turret_cover_industrial" + installation = /obj/item/weapon/gun/energy/phasegun + health = 200 + maxhealth = 200 + turret_type = "industrial" + +/obj/machinery/porta_turret/industrial/bullet_act(obj/item/projectile/Proj) + var/damage = round(Proj.get_structure_damage() * 1.33) + + if(!damage) + return + + if(enabled) + if(!attacked && !emagged) + attacked = TRUE + spawn() + sleep(60) + attacked = FALSE + + take_damage(damage) + +/obj/machinery/porta_turret/industrial/attack_generic(mob/living/L, damage) + return ..(L, damage * 0.8) + +/obj/machinery/porta_turret/industrial/teleport_defense + name = "defense turret" + desc = "This variant appears to be much more durable, with a rugged outer coating." + req_one_access = list(access_heads) + installation = /obj/item/weapon/gun/energy/gun/burst + health = 250 + maxhealth = 250 + /obj/machinery/porta_turret/poi //These are always angry enabled = TRUE lethal = TRUE @@ -188,6 +208,98 @@ check_all = TRUE can_salvage = FALSE // So you can't just twoshot a turret and get a fancy gun +/obj/machinery/porta_turret/lasertag + name = "lasertag turret" + turret_type = "normal" + req_one_access = list() + installation = /obj/item/weapon/gun/energy/lasertag/omni + + locked = FALSE + enabled = FALSE + anchored = FALSE + //These two are used for lasertag + check_synth = FALSE + check_weapons = FALSE + //These vars aren't used + check_access = FALSE + check_arrest = FALSE + check_records = FALSE + check_anomalies = FALSE + check_all = FALSE + check_down = FALSE + +/obj/machinery/porta_turret/lasertag/red + turret_type = "red" + installation = /obj/item/weapon/gun/energy/lasertag/red + check_weapons = TRUE // Used to target blue players + +/obj/machinery/porta_turret/lasertag/blue + turret_type = "blue" + installation = /obj/item/weapon/gun/energy/lasertag/blue + check_synth = TRUE // Used to target red players + +/obj/machinery/porta_turret/lasertag/assess_living(var/mob/living/L) + if(!ishuman(L)) + return TURRET_NOT_TARGET + + if(L.invisibility >= INVISIBILITY_LEVEL_ONE) // Cannot see him. see_invisible is a mob-var + return TURRET_NOT_TARGET + + if(get_dist(src, L) > 7) //if it's too far away, why bother? + return TURRET_NOT_TARGET + + if(!(L in check_trajectory(L, src))) //check if we have true line of sight + return TURRET_NOT_TARGET + + if(L.lying) //Don't need to stun-lock the players + return TURRET_NOT_TARGET + + if(ishuman(L)) + var/mob/living/carbon/human/M = L + if(istype(M.wear_suit, /obj/item/clothing/suit/redtag) && check_synth) // Checks if they are a red player + return TURRET_PRIORITY_TARGET + + if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag) && check_weapons) // Checks if they are a blue player + return TURRET_PRIORITY_TARGET + +/obj/machinery/porta_turret/lasertag/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + var/data[0] + data["access"] = !isLocked(user) + data["locked"] = locked + data["enabled"] = enabled + data["is_lethal"] = 1 + data["lethal"] = lethal + + if(data["access"]) + var/settings[0] + settings[++settings.len] = list("category" = "Target Red", "setting" = "check_synth", "value" = check_synth) // Could not get the UI to work with new vars specifically for lasertag turrets -Nalarac + settings[++settings.len] = list("category" = "Target Blue", "setting" = "check_weapons", "value" = check_weapons) // So I'm using these variables since they don't do anything else in this case + data["settings"] = settings + + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) + if(!ui) + ui = new(user, src, ui_key, "turret_control.tmpl", "Turret Controls", 500, 300) + ui.set_initial_data(data) + ui.open() + ui.set_auto_update(1) + +/obj/machinery/porta_turret/lasertag/Topic(href, href_list) + if(..()) + return 1 + + if(href_list["command"] && href_list["value"]) + var/value = text2num(href_list["value"]) + if(href_list["command"] == "enable") + enabled = value + else if(href_list["command"] == "lethal") + lethal = value + else if(href_list["command"] == "check_synth") + check_synth = value + else if(href_list["command"] == "check_weapons") + check_weapons = value + + return 1 + /obj/machinery/porta_turret/Initialize() //Sets up a spark system spark_system = new /datum/effect/effect/system/spark_spread @@ -197,7 +309,7 @@ setup() // If turrets ever switch overlays, this will need to be cached and reapplied each time overlays_cut() is called. - var/image/turret_opened_overlay = image(icon, opened_state) + var/image/turret_opened_overlay = image(icon, "open_[turret_type]") turret_opened_overlay.layer = layer-0.1 add_overlay(turret_opened_overlay) return ..() @@ -209,81 +321,85 @@ /obj/machinery/porta_turret/update_icon() if(stat & BROKEN) // Turret is dead. - icon_state = gun_destroyed_state + icon_state = "destroyed_target_prism_[turret_type]" else if(raised || raising) // Turret is open. if(powered() && enabled) // Trying to shoot someone. - icon_state = gun_active_state + if(lethal) + icon_state = "[lethal_icon_color]_target_prism_[turret_type]" + else + icon_state = "[icon_color]_target_prism_[turret_type]" else // Disabled. - icon_state = gun_disabled_state + icon_state = "grey_target_prism_[turret_type]" else // Its closed. - icon_state = closed_state + icon_state = "turret_cover_[turret_type]" /obj/machinery/porta_turret/proc/setup() var/obj/item/weapon/gun/energy/E = installation //All energy-based weapons are applicable + var/obj/item/projectile/P = initial(E.projectile_type) //var/obj/item/ammo_casing/shottype = E.projectile_type - projectile = initial(E.projectile_type) - eprojectile = projectile - shot_sound = initial(E.fire_sound) - eshot_sound = shot_sound + projectile = P + lethal_projectile = projectile + shot_sound = initial(P.fire_sound) + lethal_shot_sound = shot_sound + + if(istype(P, /obj/item/projectile/energy)) + icon_color = "orange" + + else if(istype(P, /obj/item/projectile/beam/stun)) + icon_color = "blue" + + else if(istype(P, /obj/item/projectile/beam/lasertag)) + icon_color = "blue" + + else if(istype(P, /obj/item/projectile/beam)) + icon_color = "red" + + else + icon_color = "blue" + + lethal_icon_color = icon_color weapon_setup(installation) /obj/machinery/porta_turret/proc/weapon_setup(var/guntype) switch(guntype) - if(/obj/item/weapon/gun/energy/laser/practice) - iconholder = 1 - eprojectile = /obj/item/projectile/beam + if(/obj/item/weapon/gun/energy/gun/burst) + lethal_icon_color = "red" + lethal_projectile = /obj/item/projectile/beam/burstlaser + lethal_shot_sound = 'sound/weapons/Laser.ogg' + shot_delay = 1 SECOND -// if(/obj/item/weapon/gun/energy/laser/practice/sc_laser) -// iconholder = 1 -// eprojectile = /obj/item/projectile/beam - - if(/obj/item/weapon/gun/energy/retro) - iconholder = 1 - -// if(/obj/item/weapon/gun/energy/retro/sc_retro) -// iconholder = 1 - - if(/obj/item/weapon/gun/energy/captain) - iconholder = 1 - - if(/obj/item/weapon/gun/energy/lasercannon) - iconholder = 1 - - if(/obj/item/weapon/gun/energy/taser) - eprojectile = /obj/item/projectile/beam - eshot_sound = 'sound/weapons/Laser.ogg' - - if(/obj/item/weapon/gun/energy/stunrevolver) - eprojectile = /obj/item/projectile/beam - eshot_sound = 'sound/weapons/Laser.ogg' + if(/obj/item/weapon/gun/energy/phasegun) + icon_color = "orange" + lethal_icon_color = "orange" + lethal_projectile = /obj/item/projectile/energy/phase/heavy + shot_delay = 1 SECOND if(/obj/item/weapon/gun/energy/gun) - eprojectile = /obj/item/projectile/beam //If it has, going to kill mode - eshot_sound = 'sound/weapons/Laser.ogg' - egun = 1 + lethal_icon_color = "red" + lethal_projectile = /obj/item/projectile/beam //If it has, going to kill mode + lethal_shot_sound = 'sound/weapons/Laser.ogg' if(/obj/item/weapon/gun/energy/gun/nuclear) - eprojectile = /obj/item/projectile/beam //If it has, going to kill mode - eshot_sound = 'sound/weapons/Laser.ogg' - egun = 1 + lethal_icon_color = "red" + lethal_projectile = /obj/item/projectile/beam //If it has, going to kill mode + lethal_shot_sound = 'sound/weapons/Laser.ogg' if(/obj/item/weapon/gun/energy/xray) - eprojectile = /obj/item/projectile/beam/xray + lethal_icon_color = "green" + lethal_projectile = /obj/item/projectile/beam/xray projectile = /obj/item/projectile/beam/stun // Otherwise we fire xrays on both modes. - eshot_sound = 'sound/weapons/eluger.ogg' + lethal_shot_sound = 'sound/weapons/eluger.ogg' shot_sound = 'sound/weapons/Taser.ogg' - iconholder = 1 - icon_color = "green" /obj/machinery/porta_turret/proc/isLocked(mob/user) if(ailock && issilicon(user)) @@ -291,7 +407,7 @@ return 1 if(locked && !issilicon(user)) - to_chat(user, "Access denied.") + to_chat(user, "Controls locked.") return 1 return 0 @@ -325,6 +441,7 @@ settings[++settings.len] = list("category" = "Check Access Authorization", "setting" = "check_access", "value" = check_access) settings[++settings.len] = list("category" = "Check misc. Lifeforms", "setting" = "check_anomalies", "value" = check_anomalies) settings[++settings.len] = list("category" = "Neutralize All Entities", "setting" = "check_all", "value" = check_all) + settings[++settings.len] = list("category" = "Neutralize Downed Entities", "setting" = "check_down", "value" = check_down) data["settings"] = settings ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -376,6 +493,8 @@ check_anomalies = value else if(href_list["command"] == "check_all") check_all = value + else if(href_list["command"] == "check_down") + check_down = value return 1 @@ -426,20 +545,20 @@ "You begin [anchored ? "un" : ""]securing the turret." \ ) - wrenching = 1 + wrenching = TRUE if(do_after(user, 50 * I.toolspeed)) //This code handles moving the turret around. After all, it's a portable turret! if(!anchored) playsound(loc, I.usesound, 100, 1) - anchored = 1 + anchored = TRUE update_icon() to_chat(user, "You secure the exterior bolts on the turret.") else if(anchored) playsound(loc, I.usesound, 100, 1) - anchored = 0 + anchored = FALSE to_chat(user, "You unsecure the exterior bolts on the turret.") update_icon() - wrenching = 0 + wrenching = FALSE else if(istype(I, /obj/item/weapon/card/id)||istype(I, /obj/item/device/pda)) //Behavior lock/unlock mangement @@ -480,15 +599,14 @@ //the turret shoot much, much faster. to_chat(user, "You short out [src]'s threat assessment circuits.") visible_message("[src] hums oddly...") - emagged = 1 - iconholder = 1 - controllock = 1 - enabled = 0 //turns off the turret temporarily + emagged = TRUE + controllock = TRUE + enabled = FALSE //turns off the turret temporarily sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit - enabled = 1 //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here + enabled = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here return 1 -/obj/machinery/porta_turret/proc/take_damage(var/force) +/obj/machinery/porta_turret/take_damage(var/force) if(!raised && !raising) force = force / 8 if(force < 5) @@ -511,7 +629,7 @@ attacked = 1 spawn() sleep(60) - attacked = 0 + attacked = FALSE ..() @@ -527,12 +645,12 @@ check_access = prob(20) // check_access is a pretty big deal, so it's least likely to get turned on check_anomalies = prob(50) if(prob(5)) - emagged = 1 + emagged = TRUE enabled=0 spawn(rand(60,600)) if(!enabled) - enabled=1 + enabled = TRUE ..() @@ -617,10 +735,10 @@ if(faction && L.faction == faction) return TURRET_NOT_TARGET - if(!emagged && issilicon(L) && check_all == 0) // Don't target silica, unless told to neutralize everything. + if(!emagged && issilicon(L) && check_all == FALSE) // Don't target silica, unless told to neutralize everything. return TURRET_NOT_TARGET - if(L.stat && !emagged) //if the perp is dead/dying, no need to bother really + if(L.stat == DEAD && !emagged) //if the perp is dead, no need to bother really return TURRET_NOT_TARGET //move onto next potential victim! if(get_dist(src, L) > 7) //if it's too far away, why bother? @@ -637,13 +755,13 @@ if(check_synth || check_all) //If it's set to attack all non-silicons or everything, target them! if(L.lying) - return lethal ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET + return check_down ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET return TURRET_PRIORITY_TARGET if(iscuffed(L)) // If the target is handcuffed, leave it alone return TURRET_NOT_TARGET - if(isanimal(L) || issmall(L)) // Animals are not so dangerous + if(isanimal(L)) // Animals are not so dangerous return check_anomalies ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET if(isxenomorph(L) || isalien(L)) // Xenos are dangerous @@ -654,7 +772,7 @@ return TURRET_NOT_TARGET //if threat level < 4, keep going if(L.lying) //if the perp is lying down, it's still a target but a less-important target - return lethal ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET + return check_down ? TURRET_SECONDARY_TARGET : TURRET_NOT_TARGET return TURRET_PRIORITY_TARGET //if the perp has passed all previous tests, congrats, it is now a "shoot-me!" nominee @@ -690,7 +808,7 @@ var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc) flick_holder.layer = layer + 0.1 - flick(raising_state, flick_holder) + flick("popup_[turret_type]", flick_holder) sleep(10) qdel(flick_holder) @@ -711,7 +829,7 @@ var/atom/flick_holder = new /atom/movable/porta_turret_cover(loc) flick_holder.layer = layer + 0.1 - flick(lowering_state, flick_holder) + flick("popdown_[turret_type]", flick_holder) sleep(10) qdel(flick_holder) @@ -742,10 +860,10 @@ if(!(emagged || attacked)) //if it hasn't been emagged or attacked, it has to obey a cooldown rate if(last_fired || !raised) //prevents rapid-fire shooting, unless it's been emagged return - last_fired = 1 + last_fired = TRUE spawn() sleep(shot_delay) - last_fired = 0 + last_fired = FALSE var/turf/T = get_turf(src) var/turf/U = get_turf(target) @@ -758,8 +876,8 @@ update_icon() var/obj/item/projectile/A if(emagged || lethal) - A = new eprojectile(loc) - playsound(loc, eshot_sound, 75, 1) + A = new lethal_projectile(loc) + playsound(loc, lethal_shot_sound, 75, 1) else A = new projectile(loc) playsound(loc, shot_sound, 75, 1) @@ -780,8 +898,7 @@ //Shooting Code: A.firer = src A.old_style_target(target) - A.def_zone = def_zone - A.fire() + A.launch_projectile_from_turf(target, def_zone, src) // Reset the time needed to go back down, since we just tried to shoot at someone. timeout = 10 @@ -803,7 +920,6 @@ return enabled = TC.enabled lethal = TC.lethal - iconholder = TC.lethal check_synth = TC.check_synth check_access = TC.check_access @@ -839,7 +955,7 @@ if(I.is_wrench() && !anchored) playsound(loc, I.usesound, 100, 1) to_chat(user, "You secure the external bolts.") - anchored = 1 + anchored = TRUE build_step = 1 return @@ -864,7 +980,7 @@ else if(I.is_wrench()) playsound(loc, I.usesound, 75, 1) to_chat(user, "You unfasten the external bolts.") - anchored = 0 + anchored = FALSE build_step = 0 return diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index 3205d16a619..691492a88fd 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -1,6 +1,7 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31 -obj/machinery/recharger +/obj/machinery/recharger name = "recharger" + desc = "A standard recharger for all devices that use power." icon = 'icons/obj/stationobjs_vr.dmi' //VOREStation Edit icon_state = "recharger0" anchored = 1 @@ -24,10 +25,16 @@ obj/machinery/recharger ..() return -/obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob) - if(istype(user,/mob/living/silicon)) +/obj/machinery/recharger/examine(mob/user) + if(!..(user, 5)) return + to_chat(user, "[charging ? "[charging]" : "Nothing"] is in [src].") + if(charging) + var/obj/item/weapon/cell/C = charging.get_cell() + to_chat(user, "Current charge: [C.charge] / [C.maxcharge]") + +/obj/machinery/recharger/attackby(obj/item/weapon/G as obj, mob/user as mob) var/allowed = 0 for (var/allowed_type in allowed_devices) if(istype(G, allowed_type)) allowed = 1 @@ -38,32 +45,49 @@ obj/machinery/recharger return // Checks to make sure he's not in space doing it, and that the area got proper power. if(!powered()) - to_chat(user, "The [name] blinks red as you try to insert the item!") + to_chat(user, "\The [src] blinks red as you try to insert [G]!") return if(istype(G, /obj/item/weapon/gun/energy)) var/obj/item/weapon/gun/energy/E = G if(E.self_recharge) - to_chat(user, "Your gun has no recharge port.") + to_chat(user, "\The [E] has no recharge port.") return if(istype(G, /obj/item/modular_computer)) var/obj/item/modular_computer/C = G if(!C.battery_module) - to_chat(user, "This device does not have a battery installed.") + to_chat(user, "\The [C] does not have a battery installed. ") + return + if(istype(G, /obj/item/weapon/melee/baton)) + var/obj/item/weapon/melee/baton/B = G + if(B.use_external_power) + to_chat(user, "\The [B] has no recharge port.") + return + if(istype(G, /obj/item/device/flash)) + var/obj/item/device/flash/F = G + if(F.use_external_power) + to_chat(user, "\The [F] has no recharge port.") + return + if(istype(G, /obj/item/weapon/weldingtool/electric)) + var/obj/item/weapon/weldingtool/electric/EW = G + if(EW.use_external_power) + to_chat(user, "\The [EW] has no recharge port.") return else if(!G.get_cell() && !istype(G, /obj/item/ammo_casing/nsfw_batt)) //VOREStation Edit: NSFW charging - to_chat(user, "This device does not have a battery installed.") + to_chat(user, "\The [G] does not have a battery installed.") return user.drop_item() G.loc = src charging = G update_icon() + user.visible_message("[user] inserts [charging] into [src].", "You insert [charging] into [src].") + else if(portable && G.is_wrench()) if(charging) to_chat(user, "Remove [charging] first!") return anchored = !anchored - to_chat(user, "You [anchored ? "attached" : "detached"] the recharger.") + to_chat(user, "You [anchored ? "attached" : "detached"] [src].") playsound(loc, G.usesound, 75, 1) else if(default_deconstruction_screwdriver(user, G)) return @@ -73,17 +97,24 @@ obj/machinery/recharger return /obj/machinery/recharger/attack_hand(mob/user as mob) - if(istype(user,/mob/living/silicon)) - return - add_fingerprint(user) if(charging) + user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") charging.update_icon() user.put_in_hands(charging) charging = null update_icon() +/obj/machinery/cell_charger/attack_ai(mob/user) + if(istype(user, /mob/living/silicon/robot) && Adjacent(user)) // Borgs can remove the cell if they are near enough + if(charging) + user.visible_message("[user] removes [charging] from [src].", "You remove [charging] from [src].") + charging.update_icon() + charging.loc = src.loc + charging = null + update_icon() + /obj/machinery/recharger/process() if(stat & (NOPOWER|BROKEN) || !anchored) update_use_power(0) @@ -164,6 +195,7 @@ obj/machinery/recharger /obj/machinery/recharger/wallcharger name = "wall recharger" + desc = "A more powerful recharger designed for energy weapons." icon = 'icons/obj/stationobjs.dmi' icon_state = "wrecharger0" plane = TURF_PLANE diff --git a/code/game/machinery/telecomms/presets_vr.dm b/code/game/machinery/telecomms/presets_vr.dm index 1bd6b92460d..01a07a5f5ed 100644 --- a/code/game/machinery/telecomms/presets_vr.dm +++ b/code/game/machinery/telecomms/presets_vr.dm @@ -3,3 +3,6 @@ hide = 1 produces_heat = 0 autolinkers = list("hb_relay") + +/obj/machinery/telecomms/relay/proc/reset_z() + listening_level = z diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index 43911b54d87..663230b11ff 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1153,7 +1153,7 @@ /obj/item/toy/plushie/tabby_cat = 50) /obj/machinery/vending/fishing - name = "loot trawler" + name = "Loot Trawler" desc = "A special vendor for fishing equipment." product_ads = "Tired of trawling across the ocean floor? Get our loot!;Chum and rods.;Don't get baited into fishing without us!;Baby is your star-sign pisces? We'd make a perfect match.;Do not fear, plenty to catch around here.;Don't get reeled in helplessly, get your own rod today!" icon_state = "fishvendor" diff --git a/code/game/machinery/vending_vr.dm b/code/game/machinery/vending_vr.dm index 6027bc5eaf7..19a24e669ee 100644 --- a/code/game/machinery/vending_vr.dm +++ b/code/game/machinery/vending_vr.dm @@ -6,7 +6,6 @@ /obj/machinery/vending/security/New() products += list(/obj/item/weapon/gun/energy/taser = 8,/obj/item/weapon/gun/energy/stunrevolver = 4, /obj/item/weapon/reagent_containers/spray/pepper = 6,/obj/item/taperoll/police = 6, - /obj/item/weapon/gun/projectile/sec/flash = 4, /obj/item/ammo_magazine/m45/flash = 8, /obj/item/clothing/glasses/omnihud/sec = 6) ..() diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm index 54e2b9c87b4..b58956579ac 100644 --- a/code/game/mecha/combat/combat.dm +++ b/code/game/mecha/combat/combat.dm @@ -2,7 +2,7 @@ force = 30 var/melee_cooldown = 10 var/melee_can_hit = 1 - var/list/destroyable_obj = list(/obj/mecha, /obj/structure/window, /obj/structure/grille, /turf/simulated/wall, /obj/structure/girder) + //var/list/destroyable_obj = list(/obj/mecha, /obj/structure/window, /obj/structure/grille, /turf/simulated/wall, /obj/structure/girder) internal_damage_threshold = 50 maint_access = 0 //add_req_access = 0 @@ -26,14 +26,15 @@ return */ -/obj/mecha/combat/melee_action(target as obj|mob|turf) +/obj/mecha/combat/melee_action(atom/T) if(internal_damage&MECHA_INT_CONTROL_LOST) - target = safepick(oview(1,src)) - if(!melee_can_hit || !istype(target, /atom)) return - if(istype(target, /mob/living)) - var/mob/living/M = target + T = safepick(oview(1,src)) + if(!melee_can_hit) + return + if(istype(T, /mob/living)) + var/mob/living/M = T if(src.occupant.a_intent == I_HURT || istype(src.occupant, /mob/living/carbon/brain)) //Brains cannot change intents; Exo-piloting brains lack any form of physical feedback for control, limiting the ability to 'play nice'. - playsound(src, 'sound/weapons/punch4.ogg', 50, 1) + playsound(src, 'sound/weapons/heavysmash.ogg', 50, 1) if(damtype == "brute") step_away(M,src,15) /* @@ -44,8 +45,8 @@ melee_can_hit = 1 return */ - if(istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target + if(ishuman(T)) + var/mob/living/carbon/human/H = T // if (M.health <= 0) return var/obj/item/organ/external/temp = H.get_organ(pick(BP_TORSO, BP_TORSO, BP_TORSO, BP_HEAD)) @@ -63,6 +64,8 @@ H.reagents.add_reagent("carpotoxin", force) if(H.reagents.get_reagent_amount("cryptobiolin") + force < force*2) H.reagents.add_reagent("cryptobiolin", force) + if("halloss") + H.stun_effect_act(1, force / 2, BP_TORSO, src) else return if(update) H.UpdateDamageIcon() @@ -84,12 +87,12 @@ else return M.updatehealth() - src.occupant_message("You hit [target].") - src.visible_message("[src.name] hits [target].") + src.occupant_message("You hit [T].") + src.visible_message("[src.name] hits [T].") else step_away(M,src) - src.occupant_message("You push [target] out of the way.") - src.visible_message("[src] pushes [target] out of the way.") + src.occupant_message("You push [T] out of the way.") + src.visible_message("[src] pushes [T] out of the way.") melee_can_hit = 0 if(do_after(melee_cooldown)) @@ -97,27 +100,23 @@ return else - if(damtype == "brute") - for(var/target_type in src.destroyable_obj) - if(istype(target, target_type) && hascall(target, "attackby")) - src.occupant_message("You hit [target].") - src.visible_message("[src.name] hits [target]") - if(!istype(target, /turf/simulated/wall) && !istype(target, /obj/structure/girder)) - target:attackby(src,src.occupant) - else if(prob(5)) - target:dismantle_wall(1) - src.occupant_message("You smash through the wall.") - src.visible_message("[src.name] smashes through the wall") - playsound(src, 'sound/weapons/smash.ogg', 50, 1) - else if(istype(target, /turf/simulated/wall)) - target:take_damage(force) - else if(istype(target, /obj/structure/girder)) - target:take_damage(force * 3) //Girders have 200 health by default. Steel, non-reinforced walls take four punches, girders take (with this value-mod) two, girders took five without. - melee_can_hit = 0 + if(istype(T, /obj/machinery/disposal)) // Stops mechs from climbing into disposals + return + if(src.occupant.a_intent == I_HURT || istype(src.occupant, /mob/living/carbon/brain)) // Don't smash unless we mean it + if(damtype == "brute") + src.occupant_message("You hit [T].") + src.visible_message("[src.name] hits [T]") + playsound(src, 'sound/weapons/heavysmash.ogg', 50, 1) - if(do_after(melee_cooldown)) - melee_can_hit = 1 - break + if(istype(T, /obj/structure/girder)) + T:take_damage(force * 3) //Girders have 200 health by default. Steel, non-reinforced walls take four punches, girders take (with this value-mod) two, girders took five without. + else + T:take_damage(force) + + melee_can_hit = 0 + + if(do_after(melee_cooldown)) + melee_can_hit = 1 return /* diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 58b187670f6..48a46fae56c 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -15,6 +15,7 @@ icon_state = "mecha_equip" force = 5 origin_tech = list(TECH_MATERIAL = 2) + description_info = "Some equipment may gain new abilities or advantages if equipped to certain types of Exosuits." var/equip_cooldown = 0 var/equip_ready = 1 var/energy_drain = 0 @@ -25,6 +26,7 @@ var/equip_type = null //mechaequip2 var/allow_duplicate = FALSE var/ready_sound = 'sound/mecha/mech_reload_default.ogg' //Sound to play once the fire delay passed. + var/enable_special = FALSE // Will the tool do its special? /obj/item/mecha_parts/mecha_equipment/proc/do_after_cooldown(target=1) sleep(equip_cooldown) @@ -122,6 +124,15 @@ /obj/item/mecha_parts/mecha_equipment/proc/is_melee() return range&MELEE +/obj/item/mecha_parts/mecha_equipment/proc/enable_special_checks(atom/target) + if(ispath(required_type)) + return istype(target, required_type) + + for (var/path in required_type) + if (istype(target, path)) + return 1 + + return 0 /obj/item/mecha_parts/mecha_equipment/proc/action_checks(atom/target) if(!target) @@ -202,6 +213,10 @@ M.equipment += src chassis = M src.loc = M + + if(enable_special_checks(M)) + enable_special = TRUE + M.log_message("[src] initialized.") if(!M.selected) M.selected = src @@ -235,15 +250,14 @@ chassis.log_message("[src] removed from equipment.") chassis = null set_ready_state(1) + enable_special = FALSE return - /obj/item/mecha_parts/mecha_equipment/Topic(href,href_list) if(href_list["detach"]) src.detach() return - /obj/item/mecha_parts/mecha_equipment/proc/set_ready_state(state) equip_ready = state if(chassis) @@ -259,3 +273,6 @@ if(chassis) chassis.log_message("[src]: [message]") return + +/obj/item/mecha_parts/mecha_equipment/proc/MoveAction() //Allows mech equipment to do an action upon the mech moving + return diff --git a/code/game/mecha/equipment/tools/medical_tools.dm b/code/game/mecha/equipment/tools/medical_tools.dm index a7f0d418361..b61ada6d187 100644 --- a/code/game/mecha/equipment/tools/medical_tools.dm +++ b/code/game/mecha/equipment/tools/medical_tools.dm @@ -6,11 +6,11 @@ origin_tech = list(TECH_DATA = 2, TECH_BIO = 3) energy_drain = 20 range = MELEE - equip_cooldown = 50 + equip_cooldown = 30 var/mob/living/carbon/human/occupant = null var/datum/global_iterator/pr_mech_sleeper var/inject_amount = 5 - required_type = /obj/mecha/medical + required_type = list(/obj/mecha/medical) salvageable = 0 allow_duplicate = TRUE @@ -247,144 +247,6 @@ return -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer - name = "Cable Layer" - icon_state = "mecha_wire" - var/datum/event/event - var/turf/old_turf - var/obj/structure/cable/last_piece - var/obj/item/stack/cable_coil/cable - var/max_cable = 1000 - required_type = /obj/mecha/working - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/New() - cable = new(src) - cable.amount = 0 - ..() - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/attach() - ..() - event = chassis.events.addEvent("onMove",src,"layCable") - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/detach() - chassis.events.clearEvent("onMove",event) - return ..() - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/destroy() - chassis.events.clearEvent("onMove",event) - return ..() - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/action(var/obj/item/stack/cable_coil/target) - if(!action_checks(target)) - return - var/result = load_cable(target) - var/message - if(isnull(result)) - message = "Unable to load [target] - no cable found." - else if(!result) - message = "Reel is full." - else - message = "[result] meters of cable successfully loaded." - send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) - occupant_message(message) - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/Topic(href,href_list) - ..() - if(href_list["toggle"]) - set_ready_state(!equip_ready) - occupant_message("[src] [equip_ready?"dea":"a"]ctivated.") - log_message("[equip_ready?"Dea":"A"]ctivated.") - return - if(href_list["cut"]) - if(cable && cable.amount) - var/m = round(input(chassis.occupant,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1) - m = min(m, cable.amount) - if(m) - use_cable(m) - var/obj/item/stack/cable_coil/CC = new (get_turf(chassis)) - CC.amount = m - else - occupant_message("There's no more cable on the reel.") - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/get_equip_info() - var/output = ..() - if(output) - return "[output] \[Cable: [cable ? cable.amount : 0] m\][(cable && cable.amount) ? "- [!equip_ready?"Dea":"A"]ctivate|Cut" : null]" - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/load_cable(var/obj/item/stack/cable_coil/CC) - if(istype(CC) && CC.amount) - var/cur_amount = cable? cable.amount : 0 - var/to_load = max(max_cable - cur_amount,0) - if(to_load) - to_load = min(CC.amount, to_load) - if(!cable) - cable = new(src) - cable.amount = 0 - cable.amount += to_load - CC.use(to_load) - return to_load - else - return 0 - return - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/use_cable(amount) - if(!cable || cable.amount<1) - set_ready_state(1) - occupant_message("Cable depleted, [src] deactivated.") - log_message("Cable depleted, [src] deactivated.") - return - if(cable.amount < amount) - occupant_message("No enough cable to finish the task.") - return - cable.use(amount) - update_equip_info() - return 1 - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/reset() - last_piece = null - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/dismantleFloor(var/turf/new_turf) - if(istype(new_turf, /turf/simulated/floor)) - var/turf/simulated/floor/T = new_turf - if(!T.is_plating()) - T.make_plating(!(T.broken || T.burnt)) - return new_turf.is_plating() - -/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(var/turf/new_turf) - if(equip_ready || !istype(new_turf) || !dismantleFloor(new_turf)) - return reset() - var/fdirn = turn(chassis.dir,180) - for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already - if(LC.d1 == fdirn || LC.d2 == fdirn) - return reset() - if(!use_cable(1)) - return reset() - var/obj/structure/cable/NC = new(new_turf) - NC.cableColor("red") - NC.d1 = 0 - NC.d2 = fdirn - NC.update_icon() - - var/datum/powernet/PN - if(last_piece && last_piece.d2 != chassis.dir) - last_piece.d1 = min(last_piece.d2, chassis.dir) - last_piece.d2 = max(last_piece.d2, chassis.dir) - last_piece.update_icon() - PN = last_piece.powernet - - if(!PN) - PN = new() - PN.add_cable(NC) - NC.mergeConnectedNetworks(NC.d2) - - //NC.mergeConnectedNetworksOnTurf() - last_piece = NC - return 1 - /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun name = "syringe gun" desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)" @@ -402,7 +264,7 @@ range = MELEE|RANGED equip_cooldown = 10 origin_tech = list(TECH_MATERIAL = 3, TECH_BIO = 4, TECH_MAGNET = 4, TECH_DATA = 3) - required_type = /obj/mecha/medical + required_type = list(/obj/mecha/medical) //This is a list of datums so as to allow id changes, and force compile errors if removed. var/static/list/allowed_reagents = list( @@ -515,8 +377,7 @@ if(M) S.icon_state = initial(S.icon_state) S.icon = initial(S.icon) - if(M.can_inject()) - S.reagents.trans_to_mob(M, S.reagents.total_volume, CHEM_BLOOD) + S.reagents.trans_to_mob(M, S.reagents.total_volume, CHEM_BLOOD) M.take_organ_damage(2) S.visible_message(" [M] was hit by the syringe!") break diff --git a/code/game/mecha/equipment/tools/tools.dm b/code/game/mecha/equipment/tools/tools.dm index b621d97cba5..f8219451440 100644 --- a/code/game/mecha/equipment/tools/tools.dm +++ b/code/game/mecha/equipment/tools/tools.dm @@ -8,11 +8,13 @@ energy_drain = 10 var/dam_force = 20 var/obj/mecha/working/ripley/cargo_holder - required_type = /obj/mecha/working + required_type = list(/obj/mecha/working) + ready_sound = 'sound/mecha/gasdisconnected.ogg' /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/attach(obj/mecha/M as obj) ..() cargo_holder = M + return /obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp/action(atom/target) @@ -28,7 +30,48 @@ occupant_message("You can't load living things into the cargo compartment.") return if(O.anchored) - occupant_message("[target] is firmly secured.") + if(enable_special) + if(istype(O, /obj/machinery/door/firedoor)) // I love doors. + var/obj/machinery/door/firedoor/FD = O + if(FD.blocked) + FD.visible_message("\The [chassis] begins prying on \the [FD]!") + if(do_after(chassis.occupant,10 SECONDS,FD)) + playsound(FD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1) + FD.blocked = 0 + FD.update_icon() + FD.open(1) + FD.visible_message("\The [chassis] tears \the [FD] open!") + else if(FD.density) + FD.visible_message("\The [chassis] begins forcing \the [FD] open!") + if(do_after(chassis.occupant, 5 SECONDS,FD)) + playsound(FD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1) + FD.visible_message("\The [chassis] forces \the [FD] open!") + FD.open(1) + else + FD.visible_message("\The [chassis] forces \the [FD] closed!") + FD.close(1) + else if(istype(O, /obj/machinery/door/airlock)) // D o o r s. + var/obj/machinery/door/airlock/AD = O + if(AD.locked) + occupant_message("The airlock's bolts prevent it from being forced.") + else if(!AD.operating) + if(AD.welded) + AD.visible_message("\The [chassis] begins prying on \the [AD]!") + if(do_after(chassis.occupant, 15 SECONDS,AD) && chassis.Adjacent(AD)) + AD.welded = FALSE + AD.update_icon() + playsound(AD.loc, 'sound/machines/airlock_creaking.ogg', 100, 1) + AD.visible_message("\The [chassis] tears \the [AD] open!") + if(!AD.welded) + if(density) + spawn(0) + AD.open(1) + else + spawn(0) + AD.close(1) + return + else + occupant_message("[target] is firmly secured.") return if(cargo_holder.cargo.len >= cargo_holder.cargo_capacity) occupant_message("Not enough room in cargo compartment.") @@ -62,6 +105,15 @@ occupant_message("You squeeze [target] with [src.name]. Something cracks.") playsound(src.loc, "fracture", 5, 1, -2) //CRACK chassis.visible_message("[chassis] squeezes [target].") + else if(chassis.occupant.a_intent == I_DISARM && enable_special) + playsound(src.loc, 'sound/mecha/hydraulic.ogg', 10, 1, -2) + M.take_overall_damage(dam_force/2) + M.adjustOxyLoss(round(dam_force/3)) + M.updatehealth() + occupant_message("You slam [target] with [src.name]. Something cracks.") + playsound(src.loc, "fracture", 3, 1, -2) //CRACK 2 + chassis.visible_message("[chassis] slams [target].") + M.throw_at(get_step(M,get_dir(src, M)), 14, 1.5, chassis) else step_away(M,chassis) occupant_message("You push [target] out of the way.") @@ -73,12 +125,12 @@ /obj/item/mecha_parts/mecha_equipment/tool/drill name = "drill" - desc = "This is the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" + desc = "This is the drill that'll pierce the heavens!" icon_state = "mecha_drill" equip_cooldown = 30 energy_drain = 10 force = 15 - required_type = list(/obj/mecha/working/ripley, /obj/mecha/combat) + required_type = list(/obj/mecha/working/ripley) /obj/item/mecha_parts/mecha_equipment/tool/drill/action(atom/target) if(!action_checks(target)) return @@ -101,23 +153,20 @@ log_message("Drilled through [target]") target.ex_act(2) else if(istype(target, /turf/simulated/mineral)) - for(var/turf/simulated/mineral/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.GetDrilled() + if(enable_special) + for(var/turf/simulated/mineral/M in range(chassis,1)) + if(get_dir(chassis,M)&chassis.dir) + M.GetDrilled() + else + var/turf/simulated/mineral/M1 = target + M1.GetDrilled() log_message("Drilled through [target]") if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo if(ore_box) for(var/obj/item/weapon/ore/ore in range(chassis,1)) if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) - log_message("Drilled through [target]") - if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) - var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo - if(ore_box) - for(var/obj/item/weapon/ore/ore in range(chassis,1)) - if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) + ore.forceMove(ore_box) else if(target.loc == C) log_message("Drilled through [target]") target.ex_act(2) @@ -125,7 +174,7 @@ /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill name = "diamond drill" - desc = "This is an upgraded version of the drill that'll pierce the heavens! (Can be attached to: Combat and Engineering Exosuits)" + desc = "This is an upgraded version of the drill that'll pierce the heavens!" icon_state = "mecha_diamond_drill" origin_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3) equip_cooldown = 10 @@ -150,21 +199,115 @@ log_message("Drilled through [target]") target.ex_act(3) else if(istype(target, /turf/simulated/mineral)) - for(var/turf/simulated/mineral/M in range(chassis,1)) - if(get_dir(chassis,M)&chassis.dir) - M.GetDrilled() + if(enable_special) + for(var/turf/simulated/mineral/M in range(chassis,1)) + if(get_dir(chassis,M)&chassis.dir) + M.GetDrilled() + else + var/turf/simulated/mineral/M1 = target + M1.GetDrilled() log_message("Drilled through [target]") if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo if(ore_box) for(var/obj/item/weapon/ore/ore in range(chassis,1)) if(get_dir(chassis,ore)&chassis.dir) - ore.Move(ore_box) + ore.forceMove(ore_box) else if(target.loc == C) log_message("Drilled through [target]") target.ex_act(2) return 1 +/obj/item/mecha_parts/mecha_equipment/tool/drill/bore + name = "depth bore" + desc = "This is the drill that'll pierce the depths!" + icon_state = "mecha_bore" + equip_cooldown = 5 SECONDS + energy_drain = 30 + force = 20 + required_type = list(/obj/mecha/working/ripley) + +/obj/item/mecha_parts/mecha_equipment/tool/drill/bore/action(atom/target) + if(!action_checks(target)) return + if(isobj(target)) + var/obj/target_obj = target + if(target_obj.unacidable) return + set_ready_state(0) + chassis.use_power(energy_drain) + chassis.visible_message("[chassis] starts to bore into \the [target]", "You hear the bore.") + occupant_message("You start to bore into \the [target]") + var/T = chassis.loc + var/C = target.loc + if(do_after_cooldown(target)) + if(T == chassis.loc && src == chassis.selected) + if(istype(target, /turf/simulated/wall)) + var/turf/simulated/wall/W = target + if(W.reinf_material) + occupant_message("[target] is too durable to bore through.") + else + log_message("Bored through [target]") + target.ex_act(2) + else if(istype(target, /turf/simulated/mineral)) + var/turf/simulated/mineral/M = target + if(enable_special && !M.density) + M.ex_act(2) + log_message("Bored into [target]") + else + M.GetDrilled() + log_message("Bored through [target]") + if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment) + var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo + if(ore_box) + for(var/obj/item/weapon/ore/ore in range(chassis,1)) + if(get_dir(chassis,ore)&chassis.dir) + ore.forceMove(ore_box) + else if(target.loc == C) + log_message("Drilled through [target]") + target.ex_act(2) + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/orescanner + name = "mounted ore scanner" + desc = "An exosuit-mounted ore scanner." + icon_state = "mecha_analyzer" + origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 2, TECH_POWER = 2) + equip_cooldown = 5 + energy_drain = 30 + range = MELEE|RANGED + equip_type = EQUIP_SPECIAL + ready_sound = 'sound/items/goggles_charge.ogg' + required_type = list(/obj/mecha/working/ripley) + + var/obj/item/weapon/mining_scanner/my_scanner = null + var/exact_scan = FALSE + +/obj/item/mecha_parts/mecha_equipment/tool/orescanner/Initialize() + my_scanner = new(src) + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/orescanner/Destroy() + QDEL_NULL(my_scanner) + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/orescanner/action(var/atom/target) + if(!action_checks(target) || get_dist(chassis, target) > 5) + return FALSE + + if(!enable_special) + target = get_turf(chassis) + + var/datum/beam/ScanBeam = chassis.Beam(target,"g_beam",'icons/effects/beam.dmi',time=2 SECONDS,10,/obj/effect/ebeam,2) + + if(do_after(chassis.occupant, 2 SECONDS)) + my_scanner.ScanTurf(target, chassis.occupant, exact_scan) + + QDEL_NULL(ScanBeam) + +/obj/item/mecha_parts/mecha_equipment/tool/orescanner/advanced + name = "advanced ore scanner" + icon_state = "mecha_analyzer_adv" + exact_scan = TRUE + /obj/item/mecha_parts/mecha_equipment/tool/extinguisher name = "extinguisher" desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)" @@ -172,7 +315,7 @@ equip_cooldown = 5 energy_drain = 0 range = MELEE|RANGED - required_type = /obj/mecha/working + required_type = list(/obj/mecha/working) var/spray_particles = 5 var/spray_amount = 5 //units of liquid per particle. 5 is enough to wet the floor - it's a big fire extinguisher, so should be fine var/max_water = 1000 @@ -235,6 +378,48 @@ /obj/item/mecha_parts/mecha_equipment/tool/extinguisher/on_reagent_change() return +/obj/item/mecha_parts/mecha_equipment/tool/powertool + name = "pneumatic wrench" + desc = "An exosuit-mounted hydraulic wrench." + icon_state = "mecha_wrench" + origin_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 2, TECH_POWER = 2) + equip_cooldown = 3 + energy_drain = 15 + range = MELEE + equip_type = EQUIP_UTILITY + ready_sound = 'sound/items/Ratchet.ogg' + required_type = list(/obj/mecha/working/ripley) + + var/obj/item/my_tool = null + var/tooltype = /obj/item/weapon/tool/wrench/power + +/obj/item/mecha_parts/mecha_equipment/tool/powertool/Initialize() + my_tool = new tooltype(src) + my_tool.name = name + my_tool.anchored = TRUE + my_tool.canremove = FALSE + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/powertool/Destroy() + QDEL_NULL(my_tool) + return ..() + +/obj/item/mecha_parts/mecha_equipment/tool/powertool/action(var/atom/target) + if(!action_checks(target)) + return FALSE + + if(isliving(target)) + my_tool.attack(target, chassis.occupant, BP_TORSO) + + target.attackby(my_tool,chassis.occupant) + +/obj/item/mecha_parts/mecha_equipment/tool/powertool/prybar + name = "pneumatic prybar" + desc = "An exosuit-mounted pneumatic prybar." + icon_state = "mecha_crowbar" + tooltype = /obj/item/weapon/tool/crowbar/power + ready_sound = 'sound/mecha/gasdisconnected.ogg' + /obj/item/mecha_parts/mecha_equipment/tool/rcd name = "mounted RCD" desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)" @@ -1029,7 +1214,7 @@ energy_drain = 0 var/dam_force = 0 var/obj/mecha/working/ripley/cargo_holder - required_type = /obj/mecha/working/ripley + required_type = list(/obj/mecha/working/ripley) equip_type = EQUIP_SPECIAL @@ -1330,3 +1515,154 @@ sleep(equip_cooldown) wait = 0 return 1 + +/obj/item/mecha_parts/mecha_equipment/speedboost + name = "ripley leg actuator overdrive" + desc = "System enhancements and overdrives to make a ripley's legs move faster." + icon_state = "tesla" + origin_tech = list( TECH_POWER = 5, TECH_MATERIAL = 4, TECH_ENGINEERING = 4) + required_type = list(/obj/mecha/working/ripley) + + equip_type = EQUIP_HULL + +/obj/item/mecha_parts/mecha_equipment/speedboost/attach(obj/mecha/M as obj) + ..() + if(enable_special) + chassis.step_in = (chassis.step_in-2) // Make the ripley as fast as a durand + else + chassis.step_in = (chassis.step_in+1) // Improper parts slow the mech down + return + +/obj/item/mecha_parts/mecha_equipment/speedboost/detach() + chassis.step_in = initial(chassis.step_in) + ..() + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer + name = "Cable Layer" + icon_state = "mecha_wire" + var/turf/old_turf + var/obj/structure/cable/last_piece + var/obj/item/stack/cable_coil/cable + var/max_cable = 1000 + required_type = list(/obj/mecha/working) + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/New() + cable = new(src) + cable.amount = 0 + ..() + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/MoveAction() + layCable() + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/action(var/obj/item/stack/cable_coil/target) + if(!action_checks(target)) + return + var/result = load_cable(target) + var/message + if(isnull(result)) + message = "Unable to load [target] - no cable found." + else if(!result) + message = "Reel is full." + else + message = "[result] meters of cable successfully loaded." + send_byjax(chassis.occupant,"exosuit.browser","\ref[src]",src.get_equip_info()) + occupant_message(message) + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/Topic(href,href_list) + ..() + if(href_list["toggle"]) + set_ready_state(!equip_ready) + occupant_message("[src] [equip_ready?"dea":"a"]ctivated.") + log_message("[equip_ready?"Dea":"A"]ctivated.") + return + if(href_list["cut"]) + if(cable && cable.amount) + var/m = round(input(chassis.occupant,"Please specify the length of cable to cut","Cut cable",min(cable.amount,30)) as num, 1) + m = min(m, cable.amount) + if(m) + use_cable(m) + var/obj/item/stack/cable_coil/CC = new (get_turf(chassis)) + CC.amount = m + else + occupant_message("There's no more cable on the reel.") + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/get_equip_info() + var/output = ..() + if(output) + return "[output] \[Cable: [cable ? cable.amount : 0] m\][(cable && cable.amount) ? "- [!equip_ready?"Dea":"A"]ctivate|Cut" : null]" + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/load_cable(var/obj/item/stack/cable_coil/CC) + if(istype(CC) && CC.amount) + var/cur_amount = cable? cable.amount : 0 + var/to_load = max(max_cable - cur_amount,0) + if(to_load) + to_load = min(CC.amount, to_load) + if(!cable) + cable = new(src) + cable.amount = 0 + cable.amount += to_load + CC.use(to_load) + return to_load + else + return 0 + return + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/use_cable(amount) + if(!cable || cable.amount<1) + set_ready_state(1) + occupant_message("Cable depleted, [src] deactivated.") + log_message("Cable depleted, [src] deactivated.") + return + if(cable.amount < amount) + occupant_message("No enough cable to finish the task.") + return + cable.use(amount) + update_equip_info() + return 1 + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/reset() + last_piece = null + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/dismantleFloor(var/turf/new_turf) + new_turf = get_turf(chassis) + if(istype(new_turf, /turf/simulated/floor)) + var/turf/simulated/floor/T = new_turf + if(!T.is_plating()) + T.make_plating(!(T.broken || T.burnt)) + return new_turf.is_plating() + +/obj/item/mecha_parts/mecha_equipment/tool/cable_layer/proc/layCable(var/turf/new_turf) + new_turf = get_turf(chassis) + if(equip_ready || !istype(new_turf, /turf/simulated/floor) || !dismantleFloor(new_turf)) + return reset() + var/fdirn = turn(chassis.dir,180) + for(var/obj/structure/cable/LC in new_turf) // check to make sure there's not a cable there already + if(LC.d1 == fdirn || LC.d2 == fdirn) + return reset() + if(!use_cable(1)) + return reset() + var/obj/structure/cable/NC = new(new_turf) + NC.cableColor("red") + NC.d1 = 0 + NC.d2 = fdirn + NC.update_icon() + + var/datum/powernet/PN + if(last_piece && last_piece.d2 != chassis.dir) + last_piece.d1 = min(last_piece.d2, chassis.dir) + last_piece.d2 = max(last_piece.d2, chassis.dir) + last_piece.update_icon() + PN = last_piece.powernet + + if(!PN) + PN = new() + PN.add_cable(NC) + NC.mergeConnectedNetworks(NC.d2) + + //NC.mergeConnectedNetworksOnTurf() + last_piece = NC + return 1 \ No newline at end of file diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 3ea93b6f77f..5df2c54d10f 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -34,11 +34,18 @@ var/turf/aimloc = targloc if(deviation) aimloc = locate(targloc.x+GaussRandRound(deviation,1),targloc.y+GaussRandRound(deviation,1),targloc.z) - if(!aimloc || aimloc == curloc) + if(!aimloc || aimloc == curloc || (locs && aimloc in locs)) break playsound(chassis, fire_sound, fire_volume, 1) projectiles-- - var/P = new projectile(curloc) + var/turf/projectile_turf + if(chassis.locs && chassis.locs.len) // Multi tile. + for(var/turf/Tloc in chassis.locs) + if(get_dist(Tloc, aimloc) < get_dist(loc, aimloc)) + projectile_turf = get_turf(Tloc) + if(!projectile_turf) + projectile_turf = get_turf(curloc) + var/P = new projectile(projectile_turf) Fire(P, target, params) if(i == 1) set_ready_state(0) @@ -61,11 +68,14 @@ return /obj/item/mecha_parts/mecha_equipment/weapon/proc/Fire(atom/A, atom/target, params) - var/obj/item/projectile/P = A - P.dispersion = deviation - process_accuracy(P, chassis.occupant, target) - P.preparePixelProjectile(target, chassis.occupant, params) - P.fire() + if(istype(A, /obj/item/projectile)) // Sanity. + var/obj/item/projectile/P = A + P.dispersion = deviation + process_accuracy(P, chassis.occupant, target) + P.launch_projectile_from_turf(target, chassis.occupant.zone_sel.selecting, chassis.occupant, params) + else if(istype(A, /atom/movable)) + var/atom/movable/AM = A + AM.throw_at(target, 7, 1, chassis) /obj/item/mecha_parts/mecha_equipment/weapon/proc/process_accuracy(obj/projectile, mob/living/user, atom/target) var/obj/item/projectile/P = projectile @@ -416,6 +426,7 @@ var/heavy_blast = 1 var/light_blast = 2 var/flash_blast = 4 + does_spin = FALSE // No fun corkscrew missiles. /obj/item/missile/proc/warhead_special(var/target) explosion(target, devastation, heavy_blast, light_blast, flash_blast) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 9b17cb8613b..74cdb2d368b 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -49,6 +49,8 @@ var/mech_faction = null var/firstactivation = 0 //It's simple. If it's 0, no one entered it yet. Otherwise someone entered it at least once. + var/stomp_sound = 'sound/mecha/mechstep.ogg' + var/swivel_sound = 'sound/mecha/mechturn.ogg' //inner atmos var/use_internal_tank = 0 @@ -382,9 +384,16 @@ /obj/mecha/Move() . = ..() if(.) - events.fireEvent("onMove",get_turf(src)) + MoveAction() return +/obj/mecha/proc/MoveAction() //Allows mech equipment to do an action once the mech moves + if(!equipment.len) + return + + for(var/obj/item/mecha_parts/mecha_equipment/ME in equipment) + ME.MoveAction() + /obj/mecha/relaymove(mob/user,direction) if(user != src.occupant) //While not "realistic", this piece is player friendly. if(istype(user,/mob/living/carbon/brain)) @@ -441,21 +450,24 @@ /obj/mecha/proc/mechturn(direction) set_dir(direction) - playsound(src,'sound/mecha/mechturn.ogg',40,1) + if(swivel_sound) + playsound(src,swivel_sound,40,1) return 1 /obj/mecha/proc/mechstep(direction) - var/result = step(src,direction) - if(result) - playsound(src,"mechstep",40,1) + var/result = get_step(src,direction) + if(result && Move(result)) + if(stomp_sound) + playsound(src,stomp_sound,40,1) handle_equipment_movement() return result /obj/mecha/proc/mechsteprand() - var/result = step_rand(src) - if(result) - playsound(src,"mechstep",40,1) + var/result = get_step_rand(src) + if(result && Move(result)) + if(stomp_sound) + playsound(src,stomp_sound,40,1) handle_equipment_movement() return result @@ -473,9 +485,10 @@ else //I have no idea why I disabled this obstacle.Bumped(src) else if(istype(obstacle, /mob)) - step(obstacle,src.dir) + var/mob/M = obstacle + M.Move(get_step(obstacle,src.dir)) else - obstacle.Bumped(src) + . = ..(obstacle) return /////////////////////////////////// @@ -529,7 +542,7 @@ //////// Health related procs //////// //////////////////////////////////////// -/obj/mecha/proc/take_damage(amount, type="brute") +/obj/mecha/take_damage(amount, type="brute") if(amount) var/damage = absorbDamage(amount,type) health -= damage @@ -615,6 +628,11 @@ /obj/mecha/bullet_act(var/obj/item/projectile/Proj) //wrapper + if(istype(Proj, /obj/item/projectile/test)) + var/obj/item/projectile/test/Test = Proj + Test.hit |= occupant // Register a hit on the occupant, for things like turrets, or in simple-mob cases stopping friendly fire in firing line mode. + return + src.log_message("Hit by projectile. Type: [Proj.name]([Proj.check_armour]).",1) call((proc_res["dynbulletdamage"]||src), "dynbulletdamage")(Proj) //calls equipment ..() diff --git a/code/game/mecha/mecha_wreckage.dm b/code/game/mecha/mecha_wreckage.dm index 3e1b0aafc86..9894784e157 100644 --- a/code/game/mecha/mecha_wreckage.dm +++ b/code/game/mecha/mecha_wreckage.dm @@ -221,3 +221,11 @@ name = "Janus wreckage" icon_state = "janus-broken" description_info = "Due to the incredibly intricate design of this exosuit, it is impossible to salvage components from it." + +/obj/effect/decal/mecha_wreckage/shuttlecraft + name = "Shuttlecraft wreckage" + desc = "Remains of some unfortunate shuttlecraft. Completely unrepairable." + icon = 'icons/mecha/mecha64x64.dmi' + icon_state = "shuttle_standard-broken" + bound_width = 64 + bound_height = 64 diff --git a/code/game/mecha/medical/medical.dm b/code/game/mecha/medical/medical.dm index 90ab62681a3..6e9dee50475 100644 --- a/code/game/mecha/medical/medical.dm +++ b/code/game/mecha/medical/medical.dm @@ -5,6 +5,8 @@ max_universal_equip = 1 max_special_equip = 1 + stomp_sound = 'sound/mecha/mechmove01.ogg' + cargo_capacity = 1 /obj/mecha/medical/Initialize() @@ -13,7 +15,7 @@ if(isPlayerLevel(T.z)) new /obj/item/mecha_parts/mecha_tracking(src) - +/* // One horrific bastardization of glorious inheritence dead. A billion to go. ~Mech /obj/mecha/medical/mechturn(direction) set_dir(direction) playsound(src,'sound/mecha/mechmove01.ogg',40,1) @@ -29,4 +31,5 @@ var/result = step_rand(src) if(result) playsound(src,'sound/mecha/mechstep.ogg',25,1) - return result \ No newline at end of file + return result +*/ diff --git a/code/game/mecha/micro/micro_equipment.dm b/code/game/mecha/micro/micro_equipment.dm index b8e4557b476..d36f9fa0a3e 100644 --- a/code/game/mecha/micro/micro_equipment.dm +++ b/code/game/mecha/micro/micro_equipment.dm @@ -146,7 +146,7 @@ occupant_message("The ore compartment is full.") return 1 else - ore.Move(ore_box) + ore.forceMove(ore_box) else if(target.loc == C) log_message("Drilled through [target]") target.ex_act(2) diff --git a/code/game/mecha/working/hoverpod.dm b/code/game/mecha/space/hoverpod.dm similarity index 91% rename from code/game/mecha/working/hoverpod.dm rename to code/game/mecha/space/hoverpod.dm index 8c19c2b0040..85fc59d564b 100644 --- a/code/game/mecha/working/hoverpod.dm +++ b/code/game/mecha/space/hoverpod.dm @@ -17,6 +17,9 @@ var/datum/effect/effect/system/ion_trail_follow/ion_trail var/stabilization_enabled = 1 + stomp_sound = 'sound/machines/hiss.ogg' + swivel_sound = null + max_hull_equip = 2 max_weapon_equip = 0 max_utility_equip = 2 @@ -49,7 +52,7 @@ output += ..() return output -//No space drifting +// No space drifting /obj/mecha/working/hoverpod/check_for_support() //does the hoverpod have enough charge left to stabilize itself? if (!has_charge(step_energy_drain)) @@ -62,6 +65,11 @@ return ..() +// No falling if we've got our boosters on +/obj/mecha/working/hoverpod/can_fall() + return (stabilization_enabled && has_charge(step_energy_drain)) + +/* // One horrific bastardization of glorious inheritence dead. A billion to go. ~Mech //these three procs overriden to play different sounds /obj/mecha/working/hoverpod/mechturn(direction) set_dir(direction) @@ -80,7 +88,7 @@ if(result) playsound(src,'sound/machines/hiss.ogg',40,1) return result - +*/ //Hoverpod variants /obj/mecha/working/hoverpod/combatpod diff --git a/code/game/mecha/space/shuttle.dm b/code/game/mecha/space/shuttle.dm new file mode 100644 index 00000000000..7e361ece0c6 --- /dev/null +++ b/code/game/mecha/space/shuttle.dm @@ -0,0 +1,99 @@ +/obj/mecha/working/hoverpod/shuttlecraft + desc = "A more advanced variant of the hoverpod." + name = "Shuttle" + catalogue_data = list(/datum/category_item/catalogue/technology/hoverpod) + icon = 'icons/mecha/mecha64x64.dmi' + icon_state = "shuttle_standard" + initial_icon = "shuttle_standard" + internal_damage_threshold = 60 + step_in = 2 + step_energy_drain = 5 + max_temperature = 20000 + health = 300 + maxhealth = 300 + infra_luminosity = 6 + wreckage = /obj/effect/decal/mecha_wreckage/shuttlecraft + cargo_capacity = 3 + max_equip = 3 + + opacity = FALSE + + stomp_sound = 'sound/machines/generator/generator_end.ogg' + swivel_sound = 'sound/machines/hiss.ogg' + + // Paint colors! Null if not set. + var/base_paint + var/engine_paint + var/central_paint + var/front_paint + + var/image/base_paint_mask + var/image/engine_paint_mask + var/image/central_paint_mask + var/image/front_paint_mask + + bound_height = 64 + bound_width = 64 + + max_hull_equip = 2 + max_weapon_equip = 1 + max_utility_equip = 2 + max_universal_equip = 1 + max_special_equip = 1 + +/obj/mecha/working/hoverpod/Initialize() + ..() + ion_trail.stop() + +/obj/mecha/working/hoverpod/shuttlecraft/moved_inside(var/mob/living/carbon/human/H as mob) + . = ..(H) + if(.) + ion_trail.start() + +/obj/mecha/working/hoverpod/shuttlecraft/go_out() + . = ..() + if(!occupant) + ion_trail.stop() + +/obj/mecha/working/hoverpod/shuttlecraft/update_icon() + overlays.Cut() + ..() + + if(base_paint) + if(!base_paint_mask) + base_paint_mask = image(icon, "[initial_icon]-mask+base", src.layer + 1) + base_paint_mask.color = base_paint + overlays |= base_paint_mask + if(front_paint) + if(!front_paint_mask) + front_paint_mask = image(icon, "[initial_icon]-mask+front", src.layer + 1) + front_paint_mask.color = front_paint + overlays |= front_paint_mask + if(engine_paint) + if(!engine_paint_mask) + engine_paint_mask = image(icon, "[initial_icon]-mask+engine", src.layer + 1) + engine_paint_mask.color = engine_paint + overlays |= engine_paint_mask + if(central_paint) + if(!engine_paint_mask) + central_paint_mask = image(icon, "[initial_icon]-mask+central", src.layer + 2) + central_paint_mask.color = central_paint + overlays |= central_paint_mask + +/obj/mecha/working/hoverpod/shuttlecraft/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W,/obj/item/device/multitool) && state == 1) + var/new_paint_location = input("Please select a target zone.", "Paint Zone", null) as null|anything in list("Central", "Engine", "Base", "Front", "CANCEL") + if(new_paint_location && new_paint_location != "CANCEL") + var/new_paint_color = input("Please select a paint color.", "Paint Color", null) as color|null + if(new_paint_color) + switch(new_paint_location) + if("Central") + central_paint = new_paint_color + if("Engine") + engine_paint = new_paint_color + if("Front") + front_paint = new_paint_color + if("Base") + base_paint = new_paint_color + update_icon() + else ..() diff --git a/code/game/objects/effects/alien/aliens.dm b/code/game/objects/effects/alien/aliens.dm index 44963c31d2a..0de8d332b71 100644 --- a/code/game/objects/effects/alien/aliens.dm +++ b/code/game/objects/effects/alien/aliens.dm @@ -64,6 +64,19 @@ healthcheck() return +/obj/effect/alien/resin/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + user.do_attack_animation(src) + health -= damage + healthcheck() + return + +/obj/effect/alien/resin/take_damage(var/damage) + health -= damage + healthcheck() + return + /obj/effect/alien/resin/ex_act(severity) switch(severity) if(1.0) @@ -246,6 +259,18 @@ Alien plants should do something if theres a lot of poison health -= damage healthcheck() +/obj/effect/alien/weeds/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + user.do_attack_animation(src) + health -= damage + healthcheck() + return + +/obj/effect/alien/weeds/take_damage(var/damage) + health -= damage + healthcheck() + return + /obj/effect/alien/weeds/proc/healthcheck() if(health <= 0) qdel(src) @@ -401,6 +426,18 @@ Alien plants should do something if theres a lot of poison healthcheck() return +/obj/effect/alien/egg/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + user.do_attack_animation(src) + health -= damage + healthcheck() + return + +/obj/effect/alien/egg/take_damage(var/damage) + health -= damage + healthcheck() + return + /obj/effect/alien/egg/attackby(var/obj/item/weapon/W, var/mob/user) if(health <= 0) diff --git a/code/game/objects/effects/chem/coating.dm b/code/game/objects/effects/chem/coating.dm new file mode 100644 index 00000000000..a777bbe5e05 --- /dev/null +++ b/code/game/objects/effects/chem/coating.dm @@ -0,0 +1,36 @@ +/* + * Home of the floor chemical coating. + */ + +/obj/effect/decal/cleanable/chemcoating + icon = 'icons/effects/effects.dmi' + icon_state = "dirt" + +/obj/effect/decal/cleanable/chemcoating/New() + ..() + create_reagents(100) + +/obj/effect/decal/cleanable/chemcoating/Initialize() + ..() + var/turf/T = get_turf(src) + if(T) + for(var/obj/O in get_turf(src)) + if(O == src) + continue + if(istype(O, /obj/effect/decal/cleanable/chemcoating)) + var/obj/effect/decal/cleanable/chemcoating/C = O + if(C.reagents && C.reagents.reagent_list.len) + C.reagents.trans_to_obj(src,C.reagents.total_volume) + qdel(O) + +/obj/effect/decal/cleanable/chemcoating/Bumped(A as mob|obj) + if(reagents) + reagents.touch(A) + return ..() + +/obj/effect/decal/cleanable/chemcoating/Crossed(AM as mob|obj) + Bumped(AM) + +/obj/effect/decal/cleanable/chemcoating/update_icon() + ..() + color = reagents.get_color() diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 3b1584ca194..8b8bba5a9dd 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -53,7 +53,7 @@ var/global/list/image/splatter_cache=list() blood_DNA |= B.blood_DNA.Copy() qdel(B) drytime = world.time + DRYING_TIME * (amount+1) - START_PROCESSING(SSobj, src) + START_PROCESSING(SSobj, src) /obj/effect/decal/cleanable/blood/process() if(world.time > drytime) @@ -93,7 +93,6 @@ var/global/list/image/splatter_cache=list() S.overlays += S.blood_overlay if(S.blood_overlay && S.blood_overlay.color != basecolor) S.blood_overlay.color = basecolor - S.overlays.Cut() S.overlays += S.blood_overlay S.blood_DNA |= blood_DNA.Copy() perp.update_inv_shoes() diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index f21d6443fb1..551449a8fb6 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -408,6 +408,10 @@ steam.start() -- spawns the effect src.processing = 0 spawn(0) var/turf/T = get_turf(src.holder) + if(istype(holder, /atom/movable)) + var/atom/movable/AM = holder + if(AM.locs && AM.locs.len) + T = pick(AM.locs) if(T != src.oldposition) if(isturf(T)) var/obj/effect/effect/ion_trails/I = new /obj/effect/effect/ion_trails(src.oldposition) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 3ba9c1bac77..4e39439c124 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -492,13 +492,15 @@ var/list/global/slot_flags_enumeration = list( user << "You cannot locate any eyes on [M]!" return - if(U.get_accuracy_penalty(U)) //Should only trigger if they're not aiming well - var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U)) - if(!hit_zone) - U.do_attack_animation(M) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[U] attempts to stab [M] in the eyes, but misses!") - return + //this should absolutely trigger even if not aim-impaired in some way + var/hit_zone = get_zone_with_miss_chance(U.zone_sel.selecting, M, U.get_accuracy_penalty(U)) + if(!hit_zone) + U.do_attack_animation(M) + playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + //visible_message("[U] attempts to stab [M] in the eyes, but misses!") + for(var/mob/V in viewers(M)) + V.show_message("[U] attempts to stab [M] in the eyes, but misses!") + return add_attack_logs(user,M,"Attack eyes with [name]") @@ -714,7 +716,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. icon = 'icons/obj/device.dmi' //Worn icon generation for on-mob sprites -/obj/item/proc/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer) +/obj/item/proc/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer,var/icon/clip_mask = null) //VOREStation edit - add 'clip mask' argument. //Get the required information about the base icon var/icon/icon2use = get_worn_icon_file(body_type = body_type, slot_name = slot_name, default_icon = default_icon, inhands = inhands) var/state2use = get_worn_icon_state(slot_name = slot_name) @@ -736,6 +738,8 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. if(!inhands) apply_custom(standing_icon) //Pre-image overridable proc to customize the thing apply_addblends(icon2use,standing_icon) //Some items have ICON_ADD blend shaders + if(istype(clip_mask)) //VOREStation Edit - For taur bodies/tails clipping off parts of uniforms and suits. + standing_icon = get_icon_difference(standing_icon, clip_mask, 1) var/image/standing = image(standing_icon) standing.alpha = alpha diff --git a/code/game/objects/items/bells.dm b/code/game/objects/items/bells.dm index 43046d22b77..c7aa08a440f 100644 --- a/code/game/objects/items/bells.dm +++ b/code/game/objects/items/bells.dm @@ -10,6 +10,7 @@ attack_verb = list("annoyed") var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine") var/static/radial_use = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_use") + var/static/radial_pickup = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_pickup") /obj/item/weapon/deskbell/examine(mob/user) ..() @@ -26,6 +27,7 @@ //This defines the radials and what call we're assiging to them. var/list/options = list() options["examine"] = radial_examine + options["pick up"] = radial_pickup if(!broken) options["use"] = radial_use @@ -54,6 +56,9 @@ ring(user) add_fingerprint(user) + if("pick up") + ..() + /obj/item/weapon/deskbell/proc/ring(mob/user) if(user.a_intent == "harm") playsound(user.loc, 'sound/effects/deskbell_rude.ogg', 50, 1) @@ -78,9 +83,16 @@ to_chat(user,"You are not able to ring [src].") return 0 -/obj/item/weapon/deskbell/attackby(obj/item/i, mob/user, params) - if(!istype(i)) +/obj/item/weapon/deskbell/attackby(obj/item/W, mob/user, params) + if(!istype(W)) return + if(W.is_wrench() && isturf(loc)) + if(do_after(5)) + if(!src) return + to_chat(user, "You dissasemble the desk bell") + new /obj/item/stack/material/steel(get_turf(src), 1) + qdel(src) + return if(!broken) ring(user) diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index c2a77936c4e..46c425bb897 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -577,31 +577,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(mode==3) - var/turf/T = get_turf(user.loc) - if(!isnull(T)) - var/datum/gas_mixture/environment = T.return_air() - - var/pressure = environment.return_pressure() - var/total_moles = environment.total_moles - - if (total_moles) - var/o2_level = environment.gas["oxygen"]/total_moles - var/n2_level = environment.gas["nitrogen"]/total_moles - var/co2_level = environment.gas["carbon_dioxide"]/total_moles - var/phoron_level = environment.gas["phoron"]/total_moles - var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) - data["aircontents"] = list(\ - "pressure" = "[round(pressure,0.1)]",\ - "nitrogen" = "[round(n2_level*100,0.1)]",\ - "oxygen" = "[round(o2_level*100,0.1)]",\ - "carbon_dioxide" = "[round(co2_level*100,0.1)]",\ - "phoron" = "[round(phoron_level*100,0.01)]",\ - "other" = "[round(unknown_level, 0.01)]",\ - "temp" = "[round(environment.temperature-T0C,0.1)]",\ - "reading" = 1\ - ) - if(isnull(data["aircontents"])) - data["aircontents"] = list("reading" = 0) + data["aircontents"] = src.analyze_air() if(mode==6) if(has_reception) feeds.Cut() @@ -1544,3 +1520,37 @@ var/global/list/obj/item/device/pda/PDAs = list() /obj/item/device/pda/emp_act(severity) for(var/atom/A in src) A.emp_act(severity) + +/obj/item/device/pda/proc/analyze_air() + var/list/results = list() + var/turf/T = get_turf(src.loc) + if(!isnull(T)) + var/datum/gas_mixture/environment = T.return_air() + var/pressure = environment.return_pressure() + var/total_moles = environment.total_moles + if (total_moles) + var/o2_level = environment.gas["oxygen"]/total_moles + var/n2_level = environment.gas["nitrogen"]/total_moles + var/co2_level = environment.gas["carbon_dioxide"]/total_moles + var/phoron_level = environment.gas["phoron"]/total_moles + var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level) + + // entry is what the element is describing + // Type identifies which unit or other special characters to use + // Val is the information reported + // Bad_high/_low are the values outside of which the entry reports as dangerous + // Poor_high/_low are the values outside of which the entry reports as unideal + // Values were extracted from the template itself + results = list( + list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80), + list("entry" = "Temperature", "units" = "°C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5), + list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17), + list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40), + list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0) + ) + + if(isnull(results)) + results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80)) + return results diff --git a/code/game/objects/items/devices/communicator/UI.dm b/code/game/objects/items/devices/communicator/UI.dm index e37587812a0..a4859c08a56 100644 --- a/code/game/objects/items/devices/communicator/UI.dm +++ b/code/game/objects/items/devices/communicator/UI.dm @@ -116,7 +116,7 @@ data["flashlight"] = fon data["manifest"] = PDA_Manifest data["feeds"] = compile_news() - data["latest_news"] = get_recent_news() + //data["latest_news"] = get_recent_news() //VOREStation Edit, bandaid for catastrophic runtime lag in helper.dm if(cartridge) // If there's a cartridge, we need to grab the information from it data["cart_devices"] = cartridge.get_device_status() data["cart_templates"] = cartridge.ui_templates diff --git a/code/game/objects/items/devices/communicator/helper.dm b/code/game/objects/items/devices/communicator/helper.dm index b7a3b752d9f..273686fb463 100644 --- a/code/game/objects/items/devices/communicator/helper.dm +++ b/code/game/objects/items/devices/communicator/helper.dm @@ -19,17 +19,17 @@ // Poor_high/_low are the values outside of which the entry reports as unideal // Values were extracted from the template itself results = list( - list("entry" = "Pressure", "type" = "pressure", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80), - list("entry" = "Temperature", "type" = "temp", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5), - list("entry" = "Oxygen", "type" = "pressure", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17), - list("entry" = "Nitrogen", "type" = "pressure", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40), - list("entry" = "Carbon Dioxide", "type" = "pressure", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0), - list("entry" = "Phoron", "type" = "pressure", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0), - list("entry" = "Other", "type" = "pressure", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0) + list("entry" = "Pressure", "units" = "kPa", "val" = "[round(pressure,0.1)]", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80), + list("entry" = "Temperature", "units" = "°C", "val" = "[round(environment.temperature-T0C,0.1)]", "bad_high" = 35, "poor_high" = 25, "poor_low" = 15, "bad_low" = 5), + list("entry" = "Oxygen", "units" = "kPa", "val" = "[round(o2_level*100,0.1)]", "bad_high" = 140, "poor_high" = 135, "poor_low" = 19, "bad_low" = 17), + list("entry" = "Nitrogen", "units" = "kPa", "val" = "[round(n2_level*100,0.1)]", "bad_high" = 105, "poor_high" = 85, "poor_low" = 50, "bad_low" = 40), + list("entry" = "Carbon Dioxide", "units" = "kPa", "val" = "[round(co2_level*100,0.1)]", "bad_high" = 10, "poor_high" = 5, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Phoron", "units" = "kPa", "val" = "[round(phoron_level*100,0.01)]", "bad_high" = 0.5, "poor_high" = 0, "poor_low" = 0, "bad_low" = 0), + list("entry" = "Other", "units" = "kPa", "val" = "[round(unknown_level, 0.01)]", "bad_high" = 1, "poor_high" = 0.5, "poor_low" = 0, "bad_low" = 0) ) if(isnull(results)) - results = list(list("entry" = "pressure", "val" = "0")) + results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80)) return results diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm index 1fd41ec768e..acc89b39dc3 100644 --- a/code/game/objects/items/devices/flash.dm +++ b/code/game/objects/items/devices/flash.dm @@ -122,9 +122,9 @@ if(use_external_power) battery = get_external_power_supply() - if(times_used <= max_flashes && battery && battery.checked_use(charge_cost)) + if(times_used <= max_flashes && battery && battery.charge >= charge_cost) last_used = world.time - if(prob( max(0, times_used - safe_flashes) * 2 + (times_used >= 1) ) && can_break) //if you use it 10 times in a minute it has a 30% chance to break. + if(prob( max(0, times_used - safe_flashes) * 2 + (times_used >= safe_flashes)) && can_break) //if you use it 10 times in a minute it has a 30% chance to break. broken = TRUE if(user) to_chat(user, "The bulb has burnt out!") diff --git a/code/game/objects/items/devices/gps.dm b/code/game/objects/items/devices/gps.dm index 839dc7a2dc2..830fa803e42 100644 --- a/code/game/objects/items/devices/gps.dm +++ b/code/game/objects/items/devices/gps.dm @@ -4,12 +4,12 @@ var/list/GPS_list = list() name = "global positioning system" desc = "Triangulates the approximate co-ordinates using a nearby satellite network. Alt+click to toggle power." icon = 'icons/obj/gps.dmi' - icon_state = "gps-c" + icon_state = "gps-gen" w_class = ITEMSIZE_TINY slot_flags = SLOT_BELT origin_tech = list(TECH_MATERIAL = 2, TECH_BLUESPACE = 2, TECH_MAGNET = 1) matter = list(DEFAULT_WALL_MATERIAL = 500) - var/gps_tag = "COM0" + var/gps_tag = "GEN0" var/emped = FALSE var/tracking = FALSE // Will not show other signals or emit its own signal if false. var/long_range = FALSE // If true, can see farther, depending on get_map_levels(). @@ -171,22 +171,43 @@ var/list/GPS_list = list() /obj/item/device/gps/on // Defaults to off to avoid polluting the signal list with a bunch of GPSes without owners. If you need to spawn active ones, use these. tracking = TRUE +/obj/item/device/gps/command + icon_state = "gps-com" + gps_tag = "COM0" + +/obj/item/device/gps/command/on + tracking = TRUE + +/obj/item/device/gps/security + icon_state = "gps-sec" + gps_tag = "SEC0" + +/obj/item/device/gps/security/on + tracking = TRUE + +/obj/item/device/gps/medical + icon_state = "gps-med" + gps_tag = "MED0" + +/obj/item/device/gps/medical/on + tracking = TRUE + /obj/item/device/gps/science - icon_state = "gps-s" + icon_state = "gps-sci" gps_tag = "SCI0" /obj/item/device/gps/science/on tracking = TRUE /obj/item/device/gps/engineering - icon_state = "gps-e" + icon_state = "gps-eng" gps_tag = "ENG0" /obj/item/device/gps/engineering/on tracking = TRUE /obj/item/device/gps/mining - icon_state = "gps-m" + icon_state = "gps-mine" gps_tag = "MINE0" desc = "A positioning system helpful for rescuing trapped or injured miners, keeping one on you at all times while mining might just save your life. Alt+click to toggle power." @@ -194,15 +215,15 @@ var/list/GPS_list = list() tracking = TRUE /obj/item/device/gps/explorer - icon_state = "gps-ex" - gps_tag = "EX0" + icon_state = "gps-exp" + gps_tag = "EXP0" desc = "A positioning system helpful for rescuing trapped or injured explorers, keeping one on you at all times while exploring might just save your life. Alt+click to toggle power." /obj/item/device/gps/explorer/on tracking = TRUE /obj/item/device/gps/robot - icon_state = "gps-b" + icon_state = "gps-borg" gps_tag = "SYNTH0" desc = "A synthetic internal positioning system. Used as a recovery beacon for damaged synthetic assets, or a collaboration tool for mining or exploration teams. \ Alt+click to toggle power." diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index 5a98c7f73cd..68c862db09d 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -526,9 +526,8 @@ var/global/list/default_medbay_channels = list( return -1 if(!(0 in level)) var/turf/position = get_turf(src) - if(!position || !(position.z in level)) - if(!bluespace_radio) //VOREStation Edit - return -1 + if((!position || !(position.z in level)) && !bluespace_radio) //VOREStation Edit + return -1 if(freq in ANTAG_FREQS) if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys return -1 diff --git a/code/game/objects/items/devices/radio/radio_vr.dm b/code/game/objects/items/devices/radio/radio_vr.dm index 26684ce704b..932229d0ad3 100644 --- a/code/game/objects/items/devices/radio/radio_vr.dm +++ b/code/game/objects/items/devices/radio/radio_vr.dm @@ -56,14 +56,14 @@ ..() /obj/item/device/subspaceradio/MouseDrop() - if(ismob(loc)) - if(!CanMouseDrop(src)) - return - var/mob/M = loc - if(!M.unEquip(src)) - return - add_fingerprint(usr) - M.put_in_any_hand_if_possible(src) + if(ismob(loc)) + if(!CanMouseDrop(src)) + return + var/mob/M = loc + if(!M.unEquip(src)) + return + add_fingerprint(usr) + M.put_in_any_hand_if_possible(src) /obj/item/device/subspaceradio/attackby(obj/item/weapon/W, mob/user, params) if(W == handset) @@ -114,7 +114,7 @@ if(ismob(handset.loc)) var/mob/M = handset.loc if(M.drop_from_inventory(handset, src)) - to_chat(user, "\The [handset] snap back into the main unit.") + to_chat(user, "\The [handset] snaps back into the main unit.") else handset.forceMove(src) diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index ec121bfed2f..90ae753da2e 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -1,3 +1,4 @@ +#define DEFIB_TIME_LIMIT (10 MINUTES) //VOREStation addition- past this many seconds, defib is useless. /* CONTAINS: T-RAY @@ -54,6 +55,8 @@ HALOGEN COUNTER - Radcount on mobs if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") to_chat(user, "You don't have the dexterity to do this!") return + + flick("[icon_state]-scan", src) //makes it so that it plays the scan animation on a succesful scan user.visible_message("[user] has analyzed [M]'s vitals.","You have analyzed [M]'s vitals.") if (!ishuman(M) || M.isSynthetic()) @@ -81,8 +84,13 @@ HALOGEN COUNTER - Radcount on mobs dat += "\tKey: Suffocation/Toxin/Burns/Brute
" dat += "\tDamage Specifics: [OX] - [TX] - [BU] - [BR]
" dat += "Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)
" - if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH))) - dat += "Time of Death: [M.tod]
" + //VOREStation edit/addition starts + if(M.timeofdeath && (M.stat == DEAD || (M.status_flags & FAKEDEATH))) + dat += "Time of Death: [worldtime2stationtime(M.timeofdeath)]
" + var/tdelta = round(world.time - M.timeofdeath) + if(tdelta < (DEFIB_TIME_LIMIT * 10)) + dat += "Subject died [DisplayTimeText(tdelta)] ago - resuscitation may be possible!
" + //VOREStation edit/addition ends if(istype(M, /mob/living/carbon/human) && mode == 1) var/mob/living/carbon/human/H = M var/list/damaged = H.get_damaged_organs(1,1) @@ -501,3 +509,5 @@ HALOGEN COUNTER - Radcount on mobs else to_chat(user, "No radiation detected.") return + +#undef DEFIB_TIME_LIMIT //VOREStation addition \ No newline at end of file diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 6a51e9eb176..612a14c4d4f 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -220,6 +220,7 @@ W.heal_damage(heal_brute) playsound(src, pick(apply_sounds), 25) used = 1 //VOREStation Edit + update_icon() // VOREStation Edit - Support for stack icons affecting.update_damages() if(used == amount) if(affecting.is_bandaged()) @@ -266,6 +267,7 @@ use(1) affecting.salve() playsound(src, pick(apply_sounds), 25) + update_icon() // VOREStation Edit - Support for stack icons /obj/item/stack/medical/splint name = "medical splints" diff --git a/code/game/objects/items/stacks/medical_vr.dm b/code/game/objects/items/stacks/medical_vr.dm new file mode 100644 index 00000000000..eda72a3fce9 --- /dev/null +++ b/code/game/objects/items/stacks/medical_vr.dm @@ -0,0 +1,21 @@ +/obj/item/stack/medical/advanced + icon = 'icons/obj/stacks_vr.dmi' + +/obj/item/stack/medical/advanced/Initialize() + . = ..() + update_icon() + +/obj/item/stack/medical/advanced/update_icon() + switch(amount) + if(1 to 2) + icon_state = initial(icon_state) + if(3 to 4) + icon_state = "[initial(icon_state)]_4" + if(5 to 6) + icon_state = "[initial(icon_state)]_6" + if(7 to 8) + icon_state = "[initial(icon_state)]_8" + if(9) + icon_state = "[initial(icon_state)]_9" + else + icon_state = "[initial(icon_state)]_10" \ No newline at end of file diff --git a/code/game/objects/items/stacks/tiles/tile_types.dm b/code/game/objects/items/stacks/tiles/tile_types.dm index 93c70930d18..7c441e8169f 100644 --- a/code/game/objects/items/stacks/tiles/tile_types.dm +++ b/code/game/objects/items/stacks/tiles/tile_types.dm @@ -202,4 +202,12 @@ name = "roofing" singular_name = "roofing" desc = "A section of roofing material. You can use it to repair the ceiling, or expand it." - icon_state = "techtile_grid" \ No newline at end of file + icon_state = "techtile_grid" + +/obj/item/stack/tile/roofing/cyborg + name = "roofing synthesizer" + desc = "A device that makes roofing tiles." + uses_charge = 1 + charge_costs = list(250) + stacktype = /obj/item/stack/tile/roofing + build_type = /obj/item/stack/tile/roofing \ No newline at end of file diff --git a/code/game/objects/items/trash.dm b/code/game/objects/items/trash.dm index 3d9c4ea140c..dd3ddb29caf 100644 --- a/code/game/objects/items/trash.dm +++ b/code/game/objects/items/trash.dm @@ -76,6 +76,10 @@ name = "\improper \"LiquidFood\" ration" icon_state = "liquidfood" +/obj/item/trash/liquidprotein + name = "\improper \"LiquidProtein\" ration" + icon_state = "liquidprotein" + /obj/item/trash/tastybread name = "bread tube" icon_state = "tastybread" diff --git a/code/game/objects/items/trash_vr.dm b/code/game/objects/items/trash_vr.dm index 43cadda3f70..20f7e32c4c4 100644 --- a/code/game/objects/items/trash_vr.dm +++ b/code/game/objects/items/trash_vr.dm @@ -26,11 +26,6 @@ return ..() -/obj/item/trash/liquidprotein - name = "\improper \"LiquidProtein\" ration" - icon = 'icons/obj/trash_vr.dmi' - icon_state = "liquidprotein" - /obj/item/trash/fancyplate name = "dirty fancy plate" icon = 'icons/obj/trash_vr.dmi' diff --git a/code/game/objects/items/weapons/circuitboards/computer/computer.dm b/code/game/objects/items/weapons/circuitboards/computer/computer.dm index 8bc26a13f1d..2190650d67e 100644 --- a/code/game/objects/items/weapons/circuitboards/computer/computer.dm +++ b/code/game/objects/items/weapons/circuitboards/computer/computer.dm @@ -191,3 +191,8 @@ name = T_BOARD("RCON remote control console") build_path = /obj/machinery/computer/rcon origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_POWER = 5) + +/obj/item/weapon/circuitboard/shutoff_monitor + name = T_BOARD("automatic shutoff valve monitor") + build_path = /obj/machinery/computer/shutoff_monitor + origin_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 4) \ No newline at end of file diff --git a/code/game/objects/items/weapons/circuitboards/frame.dm b/code/game/objects/items/weapons/circuitboards/frame.dm index 913506c9e65..6b59d13ea56 100644 --- a/code/game/objects/items/weapons/circuitboards/frame.dm +++ b/code/game/objects/items/weapons/circuitboards/frame.dm @@ -144,6 +144,14 @@ build_path = /obj/machinery/recharger/wallcharger board_type = new /datum/frame/frame_types/wall_charger +/obj/item/weapon/circuitboard/cell_charger + name = T_BOARD("heavy-duty cell charger") + build_path = /obj/machinery/cell_charger + board_type = new /datum/frame/frame_types/cell_charger + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 1, + /obj/item/stack/cable_coil = 5) + /obj/item/weapon/circuitboard/washing name = T_BOARD("washing machine") build_path = /obj/machinery/washing_machine @@ -162,6 +170,15 @@ /obj/item/weapon/stock_parts/gear = 1, /obj/item/weapon/reagent_containers/glass/beaker/large = 1) +/obj/item/weapon/circuitboard/distiller + build_path = /obj/machinery/portable_atmospherics/powered/reagent_distillery + board_type = new /datum/frame/frame_types/reagent_distillery + req_components = list( + /obj/item/weapon/stock_parts/capacitor = 1, + /obj/item/weapon/stock_parts/micro_laser = 1, + /obj/item/weapon/stock_parts/motor = 2, + /obj/item/weapon/stock_parts/gear = 1) + /obj/item/weapon/circuitboard/teleporter_hub name = T_BOARD("teleporter hub") build_path = /obj/machinery/teleport/hub diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index 86e3badc6fd..d4a29d47f33 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -13,6 +13,10 @@ var/atom/target = null var/open_panel = 0 var/image_overlay = null + var/blast_dev = -1 + var/blast_heavy = -1 + var/blast_light = 2 + var/blast_flash = 3 /obj/item/weapon/plastique/New() wires = new(src) @@ -72,7 +76,7 @@ if(!target) target = src if(location) - explosion(location, -1, -1, 2, 3) + explosion(location, blast_dev, blast_heavy, blast_light, blast_flash) if(target) if (istype(target, /turf/simulated/wall)) @@ -88,3 +92,28 @@ /obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone) return + +/obj/item/weapon/plastique/seismic + name = "seismic charge" + desc = "Used to dig holes in specific areas without too much extra hole." + + blast_heavy = 2 + blast_light = 4 + blast_flash = 7 + +/obj/item/weapon/plastique/seismic/attackby(var/obj/item/I, var/mob/user) + . = ..() + if(open_panel) + if(istype(I, /obj/item/weapon/stock_parts/micro_laser)) + var/obj/item/weapon/stock_parts/SP = I + var/new_blast_power = max(1, round(SP.rating / 2) + 1) + if(new_blast_power > blast_heavy) + to_chat(user, "You install \the [I] into \the [src].") + user.drop_from_inventory(I) + qdel(I) + blast_heavy = new_blast_power + blast_light = blast_heavy + round(new_blast_power * 0.5) + blast_flash = blast_light + round(new_blast_power * 0.75) + else + to_chat(user, "The [I] is not any better than the component already installed into this charge!") + return . \ No newline at end of file diff --git a/code/game/objects/items/weapons/explosives_vr.dm b/code/game/objects/items/weapons/explosives_vr.dm new file mode 100644 index 00000000000..a82ca02bbc8 --- /dev/null +++ b/code/game/objects/items/weapons/explosives_vr.dm @@ -0,0 +1,17 @@ +/obj/item/weapon/plastique/seismic/locked + desc = "Used to dig holes in specific areas without too much extra hole. Has extra mechanism that safely implodes the bomb if it is used in close proximity to the facility." + +/obj/item/weapon/plastique/seismic/locked/explode(var/location) + if(!target) + target = get_atom_on_turf(src) + if(!target) + target = src + + var/turf/T = get_turf(target) + if(T.z in using_map.map_levels) + target.visible_message("\The [src] lets out a loud beep as safeties trigger, before imploding and falling apart.") + target.overlays -= image_overlay + qdel(src) + return 0 + else + return ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 7d725c36bba..625fb11e0cf 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -41,6 +41,19 @@ /obj/item/weapon/grenade/spawnergrenade/manhacks/raider spawner_type = /mob/living/simple_mob/mechanical/viscerator/raider +/obj/item/weapon/grenade/spawnergrenade/manhacks/station + desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones." + deliveryamt = 3 + spawner_type = /mob/living/simple_mob/mechanical/viscerator/station + origin_tech = list(TECH_MATERIAL = 3, TECH_MAGNET = 3, TECH_ILLEGAL = 1) + +/obj/item/weapon/grenade/spawnergrenade/ward + name = "sentry delivery grenade" + desc = "It is set to detonate in 5 seconds. It will deploy a single thermal-optic sentry drone." + spawner_type = /mob/living/simple_mob/mechanical/ward/monitor/crew + deliveryamt = 1 + origin_tech = list(TECH_MATERIAL = 4, TECH_MAGNET = 3, TECH_BLUESPACE = 2) + /obj/item/weapon/grenade/spawnergrenade/spesscarp name = "carp delivery grenade" spawner_type = /mob/living/simple_mob/animal/space/carp diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade_vr.dm b/code/game/objects/items/weapons/grenades/spawnergrenade_vr.dm new file mode 100644 index 00000000000..56204be9849 --- /dev/null +++ b/code/game/objects/items/weapons/grenades/spawnergrenade_vr.dm @@ -0,0 +1,30 @@ +/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked + desc = "It is set to detonate in 5 seconds. It will deploy three weaponized survey drones. This one has a safety interlock that prevents release if used while in proximity to the facility." + req_access = list(access_armory) //for toggling safety + var/locked = 1 + +/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked/detonate() + if(locked) + var/turf/T = get_turf(src) + if(T.z in using_map.map_levels) + icon_state = initial(icon_state) + active = 0 + return 0 + return ..() + +/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked/attackby(obj/item/I, mob/user) + var/obj/item/weapon/card/id/id = I.GetID() + if(istype(id)) + if(check_access(id)) + locked = !locked + to_chat(user, "You [locked ? "enable" : "disable"] the safety lock on \the [src].") + else + to_chat(user, "Access denied.") + user.visible_message("[user] swipes \the [I] against \the [src].") + else + return ..() + +/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked/emag_act(var/remaining_charges,var/mob/user) + ..() + locked = !locked + to_chat(user, "You [locked ? "enable" : "disable"] the safety lock on \the [src]!") \ No newline at end of file diff --git a/code/game/objects/items/weapons/id cards/station_ids.dm b/code/game/objects/items/weapons/id cards/station_ids.dm index c157d424925..4d37f154b36 100644 --- a/code/game/objects/items/weapons/id cards/station_ids.dm +++ b/code/game/objects/items/weapons/id cards/station_ids.dm @@ -31,6 +31,7 @@ var/dorm = 0 // determines if this ID has claimed a dorm already var/mining_points = 0 // For redeeming at mining equipment vendors + var/survey_points = 0 // For redeeming at explorer equipment vendors. /obj/item/weapon/card/id/examine(mob/user) set src in oview(1) @@ -170,7 +171,7 @@ /obj/item/weapon/card/id/synthetic/Initialize() . = ..() - access = get_all_station_access() + access_synth + access = get_all_station_access().Copy() + access_synth /obj/item/weapon/card/id/centcom name = "\improper CentCom. ID" @@ -181,7 +182,7 @@ /obj/item/weapon/card/id/centcom/Initialize() . = ..() - access = get_all_centcom_access() + access = get_all_centcom_access().Copy() /obj/item/weapon/card/id/centcom/station/Initialize() . = ..() diff --git a/code/game/objects/items/weapons/manuals.dm b/code/game/objects/items/weapons/manuals.dm index 0db669545c9..4911846d65b 100644 --- a/code/game/objects/items/weapons/manuals.dm +++ b/code/game/objects/items/weapons/manuals.dm @@ -98,11 +98,11 @@

OPERATING PRINCIPLES


-
  • The supermatter crystal serves as the fundamental power source of the engine. Upon being charged, it begins to emit large amounts of heat and radiation, as well and oxygen and phoron gas. As oxygen accelerates the reaction, and phoron carries the risk of fire, these must be filtered out. NOTE: Supermatter radiation will not charge radiation collectors.
  • +
  • The supermatter crystal serves as the fundamental power source of the engine. Upon being charged, it begins to emit large amounts of heat and radiation, as well and oxygen and phoron gas. As oxygen accelerates the reaction and reacts with phoron to start a fire, it must be filtered out. It's recommended to filter out all gases besides nitrogen for standard operation.

  • -
  • Air in the reactor chamber housing the supermatter is circulated through the reactor loop, which passes through the filters and thermoelectric generators. The thermoelectric generators transfer heat from the reactor loop to the colder radiator loop, thereby generating power. Additional power is generated from internal turbines in the circulators.
  • +
  • Gas in the reactor chamber housing the supermatter is circulated through the reactor loop, which passes through the filters and thermoelectric generators. The thermoelectric generators transfer heat from the reactor loop to the colder radiator loop, thereby generating power. Additional power is generated from internal turbines in the circulators.

  • -
  • Air in the radiator loop is circulated through the radiator bank, located in space. This rapidly cools the air, preserving the temperature differential needed for power generation.
  • +
  • Gas in the radiator loop is circulated through the radiator bank, located in space. This rapidly cools the air, preserving the temperature differential needed for power generation.

  • The MK 1 Prototype Thermoelectric Supermatter Engine is designed to operate at reactor temperatures of 3000K to 4000K and generate up to 1MW of power. Beyond 1MW, the thermoelectric generators will begin to lose power through electrical discharge, reducing efficiency, but additional power generation remains feasible.

  • @@ -113,19 +113,25 @@
  • Do not allow supermatter to contact any solid object apart from specially-designed supporting pallet.
  • Do not directly view supermatter without meson goggles.
  • While handles on pallet allow moving the supermatter via pulling, pushing should not be attempted.
  • +
  • Note that prosthetics do not protect against radiation or viewing the supermatter.

  • -

    STARTUP PROCEDURE

    +

    STANDARD STARTUP PROCEDURE

      -
    1. Fill reactor loop and radiator loop with two (2) standard canisters of nitrogen gas each.
    2. -
    3. Ensure that pumps and filters are on and operating at maximum power.
    4. -
    5. Fire 8-9 pulses from emitter at supermatter crystal. Reactor blast doors must be open for this procedure.
    6. +
    7. Fill reactor loop and radiator loop with three (3) standard canisters of nitrogen gas each.
    8. +
    9. Fill the waste handling radiator loop with one (1) standard canister of carbon dioxide gas.
    10. +
    11. Enable both the high power gas pumps near the thermo-electric generators and maximize the desired output.
    12. +
    13. Enable both the omni-filters and ensure they are set to filter nitrogen back into the system.
    14. +
    15. Enable the gas pump from the filters to waste handling and maximize the desired output.
    16. +
    17. Close the monitoring room blast doors and open the reactor blast doors,
    18. +
    19. Fire 8-9 pulses from emitter at supermatter crystal. The expected power output is around a megawatt. NOTE: It will take a few minutes to heat up.
    20. +
    21. Close the reactor blast doors and keep the monitoring room blast doors closed to prevent radiation leaking.

    OPERATION AND MAINTENANCE

    1. Ensure that radiation protection and meson goggles are worn at all times while working in the engine room.
    2. Ensure that reactor and radiator loops are undamaged and unobstructed.
    3. -
    4. Ensure that phoron and oxygen gas exhaust from filters is properly contained or disposed. Do not allow exhaust pressure to exceed 4500 kPa.
    5. +
    6. Ensure that, in a standard setup, only nitrogen is being filtered back into the system. Do not allow exhaust pressure to exceed 4500 kPa.
    7. Ensure that engine room Area Power Controller (APC) and engine Superconducting Magnetic Energy Storage unit (SMES) are properly charged.
    8. Ensure that reactor temperature does not exceed 5000K. In event of reactor temperature exceeding 5000K, see EMERGENCY COOLING PROCEDURE.
    9. In event of imminent and/or unavoidable delamination, see EJECTION PROCEDURE.
    10. @@ -135,12 +141,14 @@
      1. Open Emergency Cooling Valve 1 and Emergency Cooling Valve 2.
      2. When reactor temperature returns to safe operating levels, close Emergency Cooling Valve 1 and Emergency Cooling Valve 2.
      3. +
      4. Adding additional gas to the loops can have a positive effect in reducing reactor temperature.
      5. If reactor temperature does not return to safe operating levels, see EJECTION PROCEDURE.

      EJECTION PROCEDURE

        -
      1. Press Engine Ventilatory Control button to open engine core vent to space.
      2. +
      3. Ensure the engine room has power. The blast doors and ejection platform are unresponsive without power.
      4. +
      5. Press Engine Ventilatory Control button to open engine core blast door to space.
      6. Press Emergency Core Eject button to eject supermatter crystal. NOTE: Attempting crystal ejection while engine core vent is closed will result in ejection failure.
      7. In event of ejection failure, pending
      diff --git a/code/game/objects/items/weapons/material/material_weapons.dm b/code/game/objects/items/weapons/material/material_weapons.dm index 4f08c61a4c1..a911d1e1375 100644 --- a/code/game/objects/items/weapons/material/material_weapons.dm +++ b/code/game/objects/items/weapons/material/material_weapons.dm @@ -42,6 +42,9 @@ if(!isnull(matter[material_type])) matter[material_type] *= force_divisor // May require a new var instead. + if(!(material.conductive)) + src.flags |= NOCONDUCT + /obj/item/weapon/material/get_material() return material @@ -67,7 +70,7 @@ if(applies_material_colour) color = material.icon_colour if(material.products_need_process()) - START_PROCESSING(SSobj, src) + START_PROCESSING(SSobj, src) update_force() /obj/item/weapon/material/Destroy() diff --git a/code/game/objects/items/weapons/material/shards.dm b/code/game/objects/items/weapons/material/shards.dm index ba7438a6851..937391737ac 100644 --- a/code/game/objects/items/weapons/material/shards.dm +++ b/code/game/objects/items/weapons/material/shards.dm @@ -61,6 +61,58 @@ return return ..() +/obj/item/weapon/material/shard/afterattack(var/atom/target, mob/living/carbon/human/user as mob) + var/active_hand //hand the shard is in + var/will_break + var/gloves_are_heavy = FALSE//this is a fucking mess + var/break_damage = 4 + var/light_glove_d = rand(2, 4) + var/no_glove_d = rand(4, 6) + var/list/h_gloves = list(/obj/item/clothing/gloves/captain, /obj/item/clothing/gloves/cyborg, + /obj/item/clothing/gloves/swat, /obj/item/clothing/gloves/combat, + /obj/item/clothing/gloves/botanic_leather, /obj/item/clothing/gloves/duty, + /obj/item/clothing/gloves/tactical, /obj/item/clothing/gloves/vox, + /obj/item/clothing/gloves/gauntlets) + + if(istype(user.l_hand, src)) + active_hand = BP_L_HAND + else + active_hand = BP_R_HAND + + if(prob(75)) + will_break = TRUE + else + will_break = FALSE + + if(user.gloves && (user.gloves.body_parts_covered & HANDS)) + var/obj/item/clothing/gloves/UG = user.gloves.type + for(var/I in h_gloves) + if(UG == I) + gloves_are_heavy = TRUE + if(will_break) + user.visible_message("[user] hit \the [target] with \the [src], shattering it!", "You shatter \the [src] in your hand!") + playsound(user, pick('sound/effects/Glassbr1.ogg', 'sound/effects/Glassbr2.ogg', 'sound/effects/Glassbr3.ogg'), 30, 1) + qdel(src) + + if(gloves_are_heavy == FALSE) + to_chat(user, "\The [src] partially cuts into your hand through your gloves as you hit \the [target]!") + if(will_break) + user.visible_message("[user] hit \the [target] with \the [src], shattering it!", "You shatter \the [src] in your hand!") + user.apply_damage(light_glove_d + break_damage, BRUTE, active_hand, 0 ,0, src, src.sharp, src.edge) + playsound(user, pick('sound/effects/Glassbr1.ogg', 'sound/effects/Glassbr2.ogg', 'sound/effects/Glassbr3.ogg'), 30, 1) + qdel(src) + else + user.apply_damage(light_glove_d, BRUTE, active_hand, 0 ,0, src, src.sharp, src.edge) + else + to_chat(user, "\The [src] cuts into your hand as you hit \the [target]!") + if(will_break) + user.visible_message("[user] hit \the [target] with \the [src], shattering it!", "You shatter \the [src] in your hand!") + user.apply_damage(no_glove_d + break_damage, BRUTE, active_hand, 0 ,0, src, src.sharp, src.edge) + playsound(user, pick('sound/effects/Glassbr1.ogg', 'sound/effects/Glassbr2.ogg', 'sound/effects/Glassbr3.ogg'), 30, 1) + qdel(src) + else + user.apply_damage(no_glove_d, BRUTE, active_hand, 0 ,0, src, src.sharp, src.edge) + /obj/item/weapon/material/shard/Crossed(AM as mob|obj) ..() if(isliving(AM)) diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index f825577d6ff..d935d4eaa29 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -12,6 +12,12 @@ var/lpower = 2 var/lcolor = "#0099FF" + // If it uses energy. + var/use_cell = FALSE + var/hitcost = 120 + var/obj/item/weapon/cell/bcell = null + var/cell_type = /obj/item/weapon/cell/device + /obj/item/weapon/melee/energy/proc/activate(mob/living/user) if(active) return @@ -38,7 +44,31 @@ w_class = initial(w_class) set_light(0,0) +/obj/item/weapon/melee/energy/proc/use_charge(var/cost) + if(active) + if(bcell) + if(bcell.checked_use(cost)) + return 1 + else + return 0 + return null + +/obj/item/weapon/melee/energy/examine(mob/user) + if(!..(user, 1)) + return + + if(use_cell) + if(bcell) + to_chat(user, "The blade is [round(bcell.percent())]% charged.") + if(!bcell) + to_chat(user, "The blade does not have a power source installed.") + /obj/item/weapon/melee/energy/attack_self(mob/living/user as mob) + if(use_cell) + if((!bcell || bcell.charge < hitcost) && !active) + to_chat(user, "\The [src] does not seem to have power.") + return + var/datum/gender/TU = gender_datums[user.get_visible_gender()] if (active) if ((CLUMSY in user.mutations) && prob(50)) @@ -64,6 +94,37 @@ "\The [user] is falling on \the [src]! It looks like [TU.he] [TU.is] trying to commit suicide.")) return (BRUTELOSS|FIRELOSS) +/obj/item/weapon/melee/energy/attack(mob/M, mob/user) + if(active && use_cell) + if(!use_charge(hitcost)) + deactivate(user) + visible_message("\The [src]'s blade flickers, before deactivating.") + return ..() + +/obj/item/weapon/melee/energy/attackby(obj/item/weapon/W, mob/user) + if(use_cell) + if(istype(W, cell_type)) + if(!bcell) + user.drop_item() + W.loc = src + bcell = W + to_chat(user, "You install a cell in [src].") + update_icon() + else + to_chat(user, "[src] already has a cell.") + else if(W.is_screwdriver() && bcell) + bcell.update_icon() + bcell.forceMove(get_turf(loc)) + bcell = null + to_chat(user, "You remove the cell from \the [src].") + deactivate() + update_icon() + return + return ..() + +/obj/item/weapon/melee/energy/get_cell() + return bcell + /* * Energy Axe */ @@ -90,11 +151,13 @@ /obj/item/weapon/melee/energy/axe/activate(mob/living/user) ..() + damtype = SEARING icon_state = "axe1" to_chat(user, "\The [src] is now energised.") /obj/item/weapon/melee/energy/axe/deactivate(mob/living/user) ..() + damtype = BRUTE icon_state = initial(icon_state) to_chat(user, "\The [src] is de-energised. It's just a regular axe now.") @@ -103,6 +166,20 @@ visible_message("\The [user] swings \the [src] towards [TU.his] head! It looks like [TU.he] [TU.is] trying to commit suicide.") return (BRUTELOSS|FIRELOSS) +/obj/item/weapon/melee/energy/axe/charge + name = "charge axe" + desc = "An energised axe." + active_force = 35 + active_throwforce = 20 + force = 15 + + use_cell = TRUE + hitcost = 120 + +/obj/item/weapon/melee/energy/axe/charge/loaded/New() + ..() + bcell = new/obj/item/weapon/cell/device/weapon(src) + /* * Energy Sword */ @@ -274,64 +351,7 @@ armor_penetration = 25 projectile_parry_chance = 40 - var/hitcost = 75 - var/obj/item/weapon/cell/bcell = null - var/cell_type = /obj/item/weapon/cell/device - -/obj/item/weapon/melee/energy/sword/charge/proc/use_charge(var/cost) - if(active) - if(bcell) - if(bcell.checked_use(cost)) - return 1 - else - return 0 - return null - -/obj/item/weapon/melee/energy/sword/charge/examine(mob/user) - if(!..(user, 1)) - return - - if(bcell) - to_chat(user, "The blade is [round(bcell.percent())]% charged.") - if(!bcell) - to_chat(user, "The blade does not have a power source installed.") - -/obj/item/weapon/melee/energy/sword/charge/attack_self(mob/user as mob) - if((!bcell || bcell.charge < hitcost) && !active) - to_chat(user, "\The [src] does not seem to have power.") - return - ..() - -/obj/item/weapon/melee/energy/sword/charge/attack(mob/M, mob/user) - if(active) - if(!use_charge(hitcost)) - deactivate(user) - visible_message("\The [src]'s blade flickers, before retracting.") - return ..() - -/obj/item/weapon/melee/energy/sword/charge/attackby(obj/item/weapon/W, mob/user) - if(istype(W, cell_type)) - if(!bcell) - user.drop_item() - W.loc = src - bcell = W - to_chat(user, "You install a cell in [src].") - update_icon() - else - to_chat(user, "[src] already has a cell.") - else if(W.is_screwdriver() && bcell) - bcell.update_icon() - bcell.forceMove(get_turf(loc)) - bcell = null - to_chat(user, "You remove the cell from \the [src].") - deactivate() - update_icon() - return - else - ..() - -/obj/item/weapon/melee/energy/sword/charge/get_cell() - return bcell + hitcost = 75 /obj/item/weapon/melee/energy/sword/charge/loaded/New() ..() diff --git a/code/game/objects/items/weapons/mop.dm b/code/game/objects/items/weapons/mop.dm index 0cfdd4792dd..f8669aef9d9 100644 --- a/code/game/objects/items/weapons/mop.dm +++ b/code/game/objects/items/weapons/mop.dm @@ -10,6 +10,7 @@ GLOBAL_LIST_BOILERPLATE(all_mops, /obj/item/weapon/mop) throw_speed = 5 throw_range = 10 w_class = ITEMSIZE_NORMAL + flags = NOCONDUCT attack_verb = list("mopped", "bashed", "bludgeoned", "whacked") var/mopping = 0 var/mopcount = 0 diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 7d754d8f147..1d1934bf8a8 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -67,6 +67,7 @@ item_state = "candlebox5" throwforce = 2 slot_flags = SLOT_BELT + max_storage_space = ITEMSIZE_COST_SMALL * 5 starts_with = list(/obj/item/weapon/flame/candle = 5) /obj/item/weapon/storage/fancy/whitecandle_box @@ -78,6 +79,7 @@ item_state = "whitecandlebox5" throwforce = 2 slot_flags = SLOT_BELT + max_storage_space = ITEMSIZE_COST_SMALL * 5 starts_with = list(/obj/item/weapon/flame/candle/white = 5) /obj/item/weapon/storage/fancy/blackcandle_box @@ -89,6 +91,7 @@ item_state = "blackcandlebox5" throwforce = 2 slot_flags = SLOT_BELT + max_storage_space = ITEMSIZE_COST_SMALL * 5 starts_with = list(/obj/item/weapon/flame/candle/black = 5) @@ -179,6 +182,21 @@ return ..() +/* + * Cracker Packet + */ + +/obj/item/weapon/storage/fancy/crackers + name = "\improper Getmore Crackers" + icon = 'icons/obj/food.dmi' + icon_state = "crackerbox" + icon_type = "cracker" + max_storage_space = ITEMSIZE_COST_TINY * 6 + max_w_class = ITEMSIZE_TINY + w_class = ITEMSIZE_SMALL + can_hold = list(/obj/item/weapon/reagent_containers/food/snacks/cracker) + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/cracker = 6) + //////////// //CIG PACK// //////////// diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 9b323c3b686..3555a314f7f 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -160,6 +160,12 @@ max_storage_space = ITEMSIZE_COST_SMALL * 7 starts_with = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/clotting = 8) +/obj/item/weapon/storage/firstaid/bonemed + name = "bone repair kit" + desc = "Contains chemicals to mend broken bones." + max_storage_space = ITEMSIZE_COST_SMALL * 7 + starts_with = list(/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/bonemed = 8) + /* * Pill Bottles */ diff --git a/code/game/objects/items/weapons/storage/firstaid_vr.dm b/code/game/objects/items/weapons/storage/firstaid_vr.dm index 6f9bf71fb46..55cce5358c1 100644 --- a/code/game/objects/items/weapons/storage/firstaid_vr.dm +++ b/code/game/objects/items/weapons/storage/firstaid_vr.dm @@ -12,51 +12,61 @@ name = "bottle of Rezadone pills" desc = "A powder with almost magical properties, this substance can effectively treat genetic damage in humanoids, though excessive consumption has side effects." starts_with = list(/obj/item/weapon/reagent_containers/pill/rezadone = 7) + wrapper_color = COLOR_GREEN_GRAY /obj/item/weapon/storage/pill_bottle/peridaxon name = "bottle of Peridaxon pills" desc = "Used to encourage recovery of internal organs and nervous systems. Medicate cautiously." starts_with = list(/obj/item/weapon/reagent_containers/pill/peridaxon = 7) + wrapper_color = COLOR_PURPLE /obj/item/weapon/storage/pill_bottle/carthatoline name = "bottle of Carthatoline pills" desc = "Carthatoline is strong evacuant used to treat severe poisoning." starts_with = list(/obj/item/weapon/reagent_containers/pill/carthatoline = 7) + wrapper_color = COLOR_GREEN_GRAY /obj/item/weapon/storage/pill_bottle/alkysine name = "bottle of Alkysine pills" desc = "Alkysine is a drug used to lessen the damage to neurological tissue after a catastrophic injury. Can heal brain tissue." starts_with = list(/obj/item/weapon/reagent_containers/pill/alkysine = 7) + wrapper_color = COLOR_YELLOW /obj/item/weapon/storage/pill_bottle/imidazoline name = "bottle of Imidazoline pills" desc = "Heals eye damage." starts_with = list(/obj/item/weapon/reagent_containers/pill/imidazoline = 7) + wrapper_color = COLOR_PURPLE_GRAY /obj/item/weapon/storage/pill_bottle/osteodaxon name = "bottle of Osteodaxon pills" desc = "An experimental drug used to heal bone fractures." starts_with = list(/obj/item/weapon/reagent_containers/pill/osteodaxon = 7) + wrapper_color = COLOR_WHITE /obj/item/weapon/storage/pill_bottle/myelamine name = "bottle of Myelamine pills" desc = "Used to rapidly clot internal hemorrhages by increasing the effectiveness of platelets." starts_with = list(/obj/item/weapon/reagent_containers/pill/myelamine = 7) + wrapper_color = COLOR_PALE_PURPLE_GRAY /obj/item/weapon/storage/pill_bottle/hyronalin name = "bottle of Hyronalin pills" desc = "Hyronalin is a medicinal drug used to counter the effect of radiation poisoning." starts_with = list(/obj/item/weapon/reagent_containers/pill/hyronalin = 7) + wrapper_color = COLOR_TEAL /obj/item/weapon/storage/pill_bottle/arithrazine name = "bottle of Arithrazine pills" desc = "Arithrazine is an unstable medication used for the most extreme cases of radiation poisoning." starts_with = list(/obj/item/weapon/reagent_containers/pill/arithrazine = 7) + wrapper_color = COLOR_TEAL /obj/item/weapon/storage/pill_bottle/corophizine name = "bottle of Corophizine pills" desc = "A wide-spectrum antibiotic drug. Powerful and uncomfortable in equal doses." starts_with = list(/obj/item/weapon/reagent_containers/pill/corophizine = 7) + wrapper_color = COLOR_PALE_GREEN_GRAY /obj/item/weapon/storage/pill_bottle/healing_nanites name = "bottle of Healing nanites capsules" diff --git a/code/game/objects/items/weapons/storage/mre.dm b/code/game/objects/items/weapons/storage/mre.dm new file mode 100644 index 00000000000..c3adc484e0f --- /dev/null +++ b/code/game/objects/items/weapons/storage/mre.dm @@ -0,0 +1,276 @@ +/* +MRE Stuff + */ + +/obj/item/weapon/storage/mre + name = "standard MRE" + desc = "A vacuum-sealed bag containing a day's worth of nutrients for an adult in strenuous situations. There is no visible expiration date on the package." + icon = 'icons/obj/food.dmi' + icon_state = "mre" + max_storage_space = ITEMSIZE_COST_SMALL * 6 + max_w_class = ITEMSIZE_SMALL + var/opened = FALSE + var/meal_desc = "This one is menu 1, meat pizza." + starts_with = list( + /obj/item/weapon/storage/mrebag, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/examine(mob/user) + . = ..() + to_chat(user, meal_desc) + +/obj/item/weapon/storage/mre/update_icon() + if(opened) + icon_state = "[initial(icon_state)][opened]" + . = ..() + +/obj/item/weapon/storage/mre/attack_self(mob/user) + open(user) + +/obj/item/weapon/storage/mre/open(mob/user) + if(!opened) + to_chat(usr, "You tear open the bag, breaking the vacuum seal.") + opened = 1 + update_icon() + . = ..() + +/obj/item/weapon/storage/mre/menu2 + meal_desc = "This one is menu 2, margherita." + starts_with = list( + /obj/item/weapon/storage/mrebag/menu2, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu3 + meal_desc = "This one is menu 3, vegetable pizza." + starts_with = list( + /obj/item/weapon/storage/mrebag/menu3, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu4 + meal_desc = "This one is menu 4, hamburger." + starts_with = list( + /obj/item/weapon/storage/mrebag/menu4, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu5 + meal_desc = "This one is menu 5, taco." + starts_with = list( + /obj/item/weapon/storage/mrebag/menu5, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu6 + meal_desc = "This one is menu 6, meatbread." + starts_with = list( + /obj/item/weapon/storage/mrebag/menu6, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu7 + meal_desc = "This one is menu 7, salad." + starts_with = list( + /obj/item/weapon/storage/mrebag/menu7, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu8 + meal_desc = " This one is menu 8, hot chili." + starts_with = list( + /obj/item/weapon/storage/mrebag/menu8, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu9 + name = "vegan MRE" + meal_desc = "This one is menu 9, boiled rice (skrell-safe)." + icon_state = "vegmre" + starts_with = list( + /obj/item/weapon/storage/mrebag/menu9, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert/menu9, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread/vegan, + /obj/random/mre/drink, + /obj/random/mre/sauce/vegan, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu10 + name = "protein MRE" + meal_desc = "This one is menu 10, protein." + icon_state = "meatmre" + starts_with = list( + /obj/item/weapon/storage/mrebag/menu10, + /obj/item/weapon/storage/mrebag/menu10, + /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/protein, + /obj/random/mre/sauce/sugarfree, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mre/menu11 + name = "emergency MRE" + meal_desc = "This one is menu 11, nutriment paste. Only for emergencies." + icon_state = "crayonmre" + starts_with = list( + /obj/item/weapon/reagent_containers/food/snacks/liquidfood, + /obj/item/weapon/reagent_containers/food/snacks/liquidfood, + /obj/item/weapon/reagent_containers/food/snacks/liquidfood, + /obj/item/weapon/reagent_containers/food/snacks/liquidfood, + /obj/item/weapon/reagent_containers/food/snacks/liquidprotein, + /obj/item/weapon/reagent_containers/food/snacks/liquidprotein, + ) + +/obj/item/weapon/storage/mre/menu12 + name = "crayon MRE" + meal_desc = "This one doesn't have a menu listing. How very odd." + icon_state = "crayonmre" + starts_with = list( + /obj/item/weapon/storage/fancy/crayons, + /obj/item/weapon/storage/mrebag/dessert/menu11, + /obj/random/mre/sauce/crayon, + /obj/random/mre/sauce/crayon, + /obj/random/mre/sauce/crayon + ) + +/obj/item/weapon/storage/mre/random + meal_desc = "The menu label is faded out." + starts_with = list( + /obj/random/mre/main, + /obj/item/weapon/storage/mrebag/side, + /obj/item/weapon/storage/mrebag/dessert, + /obj/item/weapon/storage/fancy/crackers, + /obj/random/mre/spread, + /obj/random/mre/drink, + /obj/random/mre/sauce, + /obj/item/weapon/material/kitchen/utensil/spoon/plastic + ) + +/obj/item/weapon/storage/mrebag + name = "main course" + desc = "A vacuum-sealed bag containing the MRE's main course. Self-heats when opened." + icon = 'icons/obj/food.dmi' + icon_state = "pouch_medium" + storage_slots = 1 + w_class = ITEMSIZE_SMALL + max_w_class = ITEMSIZE_SMALL + var/opened = FALSE + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/slice/meatpizza/filled) + +/obj/item/weapon/storage/mrebag/Initialize() + . = ..() + +/obj/item/weapon/storage/mrebag/update_icon() + if(opened) + icon_state = "[initial(icon_state)][opened]" + . = ..() + +/obj/item/weapon/storage/mrebag/attack_self(mob/user) + open(user) + +/obj/item/weapon/storage/mrebag/open(mob/user) + if(!opened) + to_chat(usr, "The pouch heats up as you break the vaccum seal.") + opened = 1 + update_icon() + . = ..() + +/obj/item/weapon/storage/mrebag/menu2 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/slice/margherita/filled) + +/obj/item/weapon/storage/mrebag/menu3 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/slice/vegetablepizza/filled) + +/obj/item/weapon/storage/mrebag/menu4 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/monkeyburger) + +/obj/item/weapon/storage/mrebag/menu5 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/taco) + +/obj/item/weapon/storage/mrebag/menu6 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/slice/meatbread/filled) + +/obj/item/weapon/storage/mrebag/menu7 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/tossedsalad) + +/obj/item/weapon/storage/mrebag/menu8 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/hotchili) + +/obj/item/weapon/storage/mrebag/menu9 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/boiledrice) + +/obj/item/weapon/storage/mrebag/menu10 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/meatcube) + +/obj/item/weapon/storage/mrebag/side + name = "side dish" + desc = "A vacuum-sealed bag containing the MRE's side dish. Self-heats when opened." + icon_state = "pouch_small" + starts_with = list(/obj/random/mre/side) + +/obj/item/weapon/storage/mrebag/side/menu10 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/meatcube) + +/obj/item/weapon/storage/mrebag/dessert + name = "dessert" + desc = "A vacuum-sealed bag containing the MRE's dessert." + icon_state = "pouch_small" + starts_with = list(/obj/random/mre/dessert) + +/obj/item/weapon/storage/mrebag/dessert/menu9 + starts_with = list(/obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit) + +/obj/item/weapon/storage/mrebag/dessert/menu11 + starts_with = list(/obj/item/weapon/pen/crayon/rainbow) diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 53c092d923d..371082f1f6b 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -9,6 +9,7 @@ sharp = 0 edge = 0 throwforce = 7 + flags = NOCONDUCT w_class = ITEMSIZE_NORMAL origin_tech = list(TECH_COMBAT = 2) attack_verb = list("beaten") @@ -18,6 +19,7 @@ var/status = 0 //whether the thing is on or not var/obj/item/weapon/cell/bcell = null var/hitcost = 240 + var/use_external_power = FALSE //only used to determine if it's a cyborg baton /obj/item/weapon/melee/baton/New() ..() @@ -108,6 +110,8 @@ user <<"The baton does not have a power source installed." /obj/item/weapon/melee/baton/attackby(obj/item/weapon/W, mob/user) + if(use_external_power) + return if(istype(W, /obj/item/weapon/cell)) if(istype(W, /obj/item/weapon/cell/device)) if(!bcell) @@ -136,6 +140,11 @@ return ..() /obj/item/weapon/melee/baton/attack_self(mob/user) + if(use_external_power) + //try to find our power cell + var/mob/living/silicon/robot/R = loc + if (istype(R)) + bcell = R.cell if(bcell && bcell.charge > hitcost) status = !status user << "[src] is now [status ? "on" : "off"]." @@ -204,16 +213,7 @@ //secborg stun baton module /obj/item/weapon/melee/baton/robot hitcost = 500 - -/obj/item/weapon/melee/baton/robot/attack_self(mob/user) - //try to find our power cell - var/mob/living/silicon/robot/R = loc - if (istype(R)) - bcell = R.cell - return ..() - -/obj/item/weapon/melee/baton/robot/attackby(obj/item/weapon/W, mob/user) - return + use_external_power = TRUE //Makeshift stun baton. Replacement for stun gloves. /obj/item/weapon/melee/baton/cattleprod @@ -274,13 +274,4 @@ // Borg version, for the lost module. /obj/item/weapon/melee/baton/shocker/robot - -/obj/item/weapon/melee/baton/shocker/robot/attack_self(mob/user) - //try to find our power cell - var/mob/living/silicon/robot/R = loc - if (istype(R)) - bcell = R.cell - return ..() - -/obj/item/weapon/melee/baton/shocker/robot/attackby(obj/item/weapon/W, mob/user) - return \ No newline at end of file + use_external_power = TRUE \ No newline at end of file diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm index 3a969562f88..33c5a750786 100644 --- a/code/game/objects/items/weapons/tools/weldingtool.dm +++ b/code/game/objects/items/weapons/tools/weldingtool.dm @@ -504,6 +504,14 @@ mounted_pack.return_nozzle() to_chat(user, "\The [src] retracts to its fueltank.") +/obj/item/weapon/weldingtool/tubefed/survival + name = "tube-fed emergency welding tool" + desc = "A bulky, cooler-burning welding tool that draws from a worn welding tank." + icon_state = "tubewelder" + max_fuel = 5 + toolspeed = 1.75 + eye_safety_modifier = 2 + /* * Electric/Arc Welder */ diff --git a/code/game/objects/items/weapons/traps.dm b/code/game/objects/items/weapons/traps.dm index 27927b81802..1e63201f4e1 100644 --- a/code/game/objects/items/weapons/traps.dm +++ b/code/game/objects/items/weapons/traps.dm @@ -11,6 +11,8 @@ origin_tech = list(TECH_MATERIAL = 1) matter = list(DEFAULT_WALL_MATERIAL = 18750) var/deployed = 0 + var/camo_net = FALSE + var/stun_length = 0.25 SECONDS /obj/item/weapon/beartrap/suicide_act(mob/user) var/datum/gender/T = gender_datums[user.get_visible_gender()] @@ -98,6 +100,7 @@ set_dir(L.dir) can_buckle = 1 buckle_mob(L) + L.Stun(stun_length) L << "The steel jaws of \the [src] bite into you, trapping you in place!" deployed = 0 can_buckle = initial(can_buckle) @@ -122,6 +125,21 @@ ..() if(!deployed) + if(camo_net) + alpha = 255 + icon_state = "beartrap0" else + if(camo_net) + alpha = 50 + icon_state = "beartrap1" + +/obj/item/weapon/beartrap/hunting + name = "hunting trap" + desc = "A mechanically activated leg trap. High-tech and reliable. Looks like it could really hurt if you set it off." + stun_length = 1 SECOND + camo_net = TRUE + color = "#C9DCE1" + + origin_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_PHORON = 2, TECH_ARCANE = 1) diff --git a/code/game/objects/items/weapons/weldbackpack.dm b/code/game/objects/items/weapons/weldbackpack.dm index 5df0c9dbe33..4225ed810a7 100644 --- a/code/game/objects/items/weapons/weldbackpack.dm +++ b/code/game/objects/items/weapons/weldbackpack.dm @@ -7,6 +7,7 @@ w_class = ITEMSIZE_LARGE var/max_fuel = 350 var/obj/item/weapon/nozzle = null //Attached welder, or other spray device. + var/nozzle_type = /obj/item/weapon/weldingtool/tubefed var/nozzle_attached = 0 /obj/item/weapon/weldpack/Initialize() @@ -15,7 +16,7 @@ reagents = R R.my_atom = src R.add_reagent("fuel", max_fuel) - nozzle = new/obj/item/weapon/weldingtool/tubefed(src) + nozzle = new nozzle_type(src) nozzle_attached = 1 /obj/item/weapon/weldpack/Destroy() @@ -145,3 +146,14 @@ ..(user) user << text("\icon[] [] units of fuel left!", src, src.reagents.total_volume) return + +/obj/item/weapon/weldpack/survival + name = "emergency welding kit" + desc = "A heavy-duty, portable welding fluid carrier." + slot_flags = SLOT_BACK + icon = 'icons/obj/storage.dmi' + icon_state = "welderpack-e" + item_state = "welderpack" + w_class = ITEMSIZE_LARGE + max_fuel = 100 + nozzle_type = /obj/item/weapon/weldingtool/tubefed/survival diff --git a/code/game/objects/mob_spawner_vr.dm b/code/game/objects/mob_spawner_vr.dm index 0422c408f83..23ec38c907e 100644 --- a/code/game/objects/mob_spawner_vr.dm +++ b/code/game/objects/mob_spawner_vr.dm @@ -84,7 +84,7 @@ if(destructible) take_damage(Proj.get_structure_damage()) -/obj/structure/mob_spawner/proc/take_damage(var/damage) +/obj/structure/mob_spawner/take_damage(var/damage) health -= damage if(health <= 0) visible_message("\The [src] breaks apart!") diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 520d5cb58b9..61005069daa 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -173,6 +173,9 @@ */ return +/obj/proc/hear_signlang(mob/M as mob, text, verb, datum/language/speaking) // Saycode gets worse every day. + return FALSE + /obj/proc/see_emote(mob/M as mob, text, var/emote_type) return diff --git a/code/game/objects/random/mapping.dm b/code/game/objects/random/mapping.dm index eb5741c6a19..d39983af2f2 100644 --- a/code/game/objects/random/mapping.dm +++ b/code/game/objects/random/mapping.dm @@ -65,6 +65,21 @@ prob(10);/obj/effect/mine/stun, prob(10);/obj/effect/mine/incendiary,) +/obj/random/humanoidremains + name = "Random Humanoid Remains" + desc = "This is a random pile of remains." + spawn_nothing_percentage = 15 + icon = 'icons/effects/blood.dmi' + icon_state = "remains" + +/obj/random/humanoidremains/item_to_spawn() + return pick(prob(30);/obj/effect/decal/remains/human, + prob(25);/obj/effect/decal/remains/ribcage, + prob(25);/obj/effect/decal/remains/tajaran, + prob(10);/obj/effect/decal/remains/unathi, + prob(10);/obj/effect/decal/remains/posi + ) + /obj/random_multi/single_item/captains_spare_id name = "Multi Point - Captain's Spare" id = "Captain's spare id" @@ -396,5 +411,54 @@ /obj/item/clothing/mask/luchador/rudos, /obj/item/clothing/mask/luchador/tecnicos, /obj/structure/closet/crate + ), + prob(1);list( + /obj/machinery/artifact, + /obj/structure/anomaly_container + ), + prob(1);list( + /obj/random/curseditem, + /obj/random/humanoidremains, + /obj/structure/closet/crate ) ) + +/* + * Turf swappers. + */ + +/obj/random/turf + name = "random Sif turf" + desc = "This is a random Sif turf." + + spawn_nothing_percentage = 20 + + var/override_outdoors = FALSE // Do we override our chosen turf's outdoors? + var/turf_outdoors = TRUE // Will our turf be outdoors? + +/obj/random/turf/spawn_item() + var/build_path = item_to_spawn() + + var/turf/T1 = get_turf(src) + T1.ChangeTurf(build_path, 1, 1, FALSE) + + if(override_outdoors) + T1.outdoors = turf_outdoors + +/obj/random/turf/item_to_spawn() + return pick(prob(25);/turf/simulated/floor/outdoors/grass/sif, + prob(25);/turf/simulated/floor/outdoors/dirt, + prob(25);/turf/simulated/floor/outdoors/grass/sif/forest, + prob(25);/turf/simulated/floor/outdoors/rocks) + +/obj/random/turf/lava + name = "random Lava spawn" + desc = "This is a random lava spawn." + + override_outdoors = TRUE + turf_outdoors = FALSE + +/obj/random/turf/lava/item_to_spawn() + return pick(prob(5);/turf/simulated/floor/lava, + prob(3);/turf/simulated/floor/outdoors/rocks/caves, + prob(1);/turf/simulated/mineral) diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm index 19638bf46fb..b058a6b9186 100644 --- a/code/game/objects/random/misc.dm +++ b/code/game/objects/random/misc.dm @@ -530,3 +530,161 @@ /obj/random/janusmodule/item_to_spawn() return pick(subtypesof(/obj/item/weapon/circuitboard/mecha/imperion)) + +/obj/random/curseditem + name = "random cursed item" + desc = "For use in dungeons." + icon = 'icons/obj/storage.dmi' + icon_state = "red" + +/obj/random/curseditem/item_to_spawn() + var/possible_object_paths = list(/obj/item/weapon/paper/carbon/cursedform) + possible_object_paths |= subtypesof(/obj/item/clothing/head/psy_crown) + return pick(possible_object_paths) + +//Random MRE stuff + +/obj/random/mre + name = "random MRE" + desc = "This is a random single MRE." + icon = 'icons/obj/food.dmi' + icon_state = "mre" + drop_get_turf = FALSE + +/obj/random/mre/item_to_spawn() + return pick(/obj/item/weapon/storage/mre, + /obj/item/weapon/storage/mre/menu2, + /obj/item/weapon/storage/mre/menu3, + /obj/item/weapon/storage/mre/menu4, + /obj/item/weapon/storage/mre/menu5, + /obj/item/weapon/storage/mre/menu6, + /obj/item/weapon/storage/mre/menu7, + /obj/item/weapon/storage/mre/menu8, + /obj/item/weapon/storage/mre/menu9, + /obj/item/weapon/storage/mre/menu10) + + +/obj/random/mre/main + name = "random MRE main course" + desc = "This is a random main course for MREs." + icon_state = "pouch" + drop_get_turf = FALSE + +/obj/random/mre/main/item_to_spawn() + return pick(/obj/item/weapon/storage/mrebag, + /obj/item/weapon/storage/mrebag/menu2, + /obj/item/weapon/storage/mrebag/menu3, + /obj/item/weapon/storage/mrebag/menu4, + /obj/item/weapon/storage/mrebag/menu5, + /obj/item/weapon/storage/mrebag/menu6, + /obj/item/weapon/storage/mrebag/menu7, + /obj/item/weapon/storage/mrebag/menu8) + +/obj/random/mre/side + name = "random MRE side dish" + desc = "This is a random side dish for MREs." + icon_state = "pouch" + drop_get_turf = FALSE + +/obj/random/mre/side/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/snacks/tossedsalad, + /obj/item/weapon/reagent_containers/food/snacks/boiledrice, + /obj/item/weapon/reagent_containers/food/snacks/poppypretzel, + /obj/item/weapon/reagent_containers/food/snacks/twobread, + /obj/item/weapon/reagent_containers/food/snacks/jelliedtoast) + +/obj/random/mre/dessert + name = "random MRE dessert" + desc = "This is a random dessert for MREs." + icon_state = "pouch" + drop_get_turf = FALSE + +/obj/random/mre/dessert/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/snacks/candy, + /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar, + /obj/item/weapon/reagent_containers/food/snacks/donut/normal, + /obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly, + /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, + /obj/item/weapon/reagent_containers/food/snacks/cookie) + +/obj/random/mre/dessert/vegan + name = "random vegan MRE dessert" + desc = "This is a random vegan dessert for MREs." + +/obj/random/mre/dessert/vegan/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/snacks/candy, + /obj/item/weapon/reagent_containers/food/snacks/chocolatebar, + /obj/item/weapon/reagent_containers/food/snacks/donut/cherryjelly, + /obj/item/weapon/reagent_containers/food/snacks/plumphelmetbiscuit) + +/obj/random/mre/drink + name = "random MRE drink" + desc = "This is a random drink for MREs." + icon_state = "packet" + drop_get_turf = FALSE + +/obj/random/mre/drink/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/condiment/small/packet/coffee, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/tea, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/cocoa, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/grape, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/orange, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/watermelon, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/apple) + +/obj/random/mre/spread + name = "random MRE spread" + desc = "This is a random spread packet for MREs." + icon_state = "packet" + drop_get_turf = FALSE + +/obj/random/mre/spread/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/condiment/small/packet/jelly, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/honey) + +/obj/random/mre/spread/vegan + name = "random vegan MRE spread" + desc = "This is a random vegan spread packet for MREs" + +/obj/random/mre/spread/vegan/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/condiment/small/packet/jelly) + +/obj/random/mre/sauce + name = "random MRE sauce" + desc = "This is a random sauce packet for MREs." + icon_state = "packet" + drop_get_turf = FALSE + +/obj/random/mre/sauce/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/condiment/small/packet/salt, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/pepper, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/sugar, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/capsaicin, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/ketchup, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/mayo, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/soy) + +/obj/random/mre/sauce/vegan/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/condiment/small/packet/salt, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/pepper, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/sugar, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/soy) + +/obj/random/mre/sauce/sugarfree/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/condiment/small/packet/salt, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/pepper, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/capsaicin, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/ketchup, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/mayo, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/soy) + +/obj/random/mre/sauce/crayon/item_to_spawn() + return pick(/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/generic, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/red, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/orange, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/yellow, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/green, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/blue, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/purple, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/grey, + /obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/brown) diff --git a/code/game/objects/random/mob_vr.dm b/code/game/objects/random/mob_vr.dm index 62e3e376c77..c1ce7aaf15d 100644 --- a/code/game/objects/random/mob_vr.dm +++ b/code/game/objects/random/mob_vr.dm @@ -229,3 +229,6 @@ prob(50);/obj/random/soap, prob(60);/obj/random/drinkbottle, prob(500);/obj/random/maintenance/clean) + +/obj/random/action_figure/supplypack + drop_get_turf = FALSE \ No newline at end of file diff --git a/code/game/objects/structures/catwalk.dm b/code/game/objects/structures/catwalk.dm index 68b9ccc787d..20fd025ea96 100644 --- a/code/game/objects/structures/catwalk.dm +++ b/code/game/objects/structures/catwalk.dm @@ -98,7 +98,7 @@ return 0 return 1 -/obj/structure/catwalk/proc/take_damage(amount) +/obj/structure/catwalk/take_damage(amount) health -= amount if(health <= 0) visible_message("\The [src] breaks down!") diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 4234c993917..95d38c4473d 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -468,3 +468,10 @@ if(istype(src.loc, /obj/structure/closet)) return (loc.return_air_for_internal_lifeform(L)) return return_air() + +/obj/structure/closet/take_damage(var/damage) + if(damage < STRUCTURE_MIN_DAMAGE_THRESHOLD) + return + dump_contents() + spawn(1) qdel(src) + return 1 \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo_vr.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo_vr.dm new file mode 100644 index 00000000000..332b629d7b8 --- /dev/null +++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo_vr.dm @@ -0,0 +1,3 @@ +/obj/structure/closet/secure_closet/miner/Initialize() + starts_with += /obj/item/device/gps/mining + return ..() \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index 8380c059ec7..43f50a83873 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -11,6 +11,8 @@ starts_with = list( /obj/item/clothing/accessory/storage/brown_vest, /obj/item/blueprints, + ///obj/item/clamp, //VOREStation Removal: without leaks those are pointless, + ///obj/item/clamp, //VOREStation Removal: without leaks those are pointless, /obj/item/clothing/under/rank/chief_engineer, /obj/item/clothing/under/rank/chief_engineer/skirt, /obj/item/clothing/head/hardhat/white, @@ -95,6 +97,7 @@ /obj/item/clothing/glasses/meson, /obj/item/weapon/cartridge/engineering, /obj/item/taperoll/engineering, + /obj/item/clothing/head/hardhat, /obj/item/clothing/suit/storage/hooded/wintercoat/engineering, /obj/item/clothing/shoes/boots/winter/engineering, /obj/item/weapon/tank/emergency/oxygen/engi, @@ -123,8 +126,10 @@ starts_with = list( /obj/item/clothing/accessory/storage/brown_vest, /obj/item/clothing/suit/fire/firefighter, + /obj/item/clothing/head/hardhat/red, /obj/item/device/flashlight, /obj/item/weapon/extinguisher, + ///obj/item/clamp, //VOREStation Removal: without leaks those are pointless, /obj/item/device/radio/headset/headset_eng, /obj/item/device/radio/headset/headset_eng/alt, /obj/item/clothing/suit/storage/hazardvest, diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical_vr.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical_vr.dm new file mode 100644 index 00000000000..e47f8358918 --- /dev/null +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical_vr.dm @@ -0,0 +1,3 @@ +/obj/structure/closet/secure_closet/paramedic/Initialize() + starts_with += /obj/item/device/gps/medical + return ..() \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 368fbf10f4a..ed90b934f9d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -302,7 +302,7 @@ GLOBAL_LIST_BOILERPLATE(all_brig_closets, /obj/structure/closet/secure_closet/br var/id = null starts_with = list( - /obj/item/clothing/under/color/orange, + /obj/item/clothing/under/color/orange/prison, /obj/item/clothing/shoes/orange) diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm index 9bdc9659e22..3c3b5bbcff8 100644 --- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm +++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm @@ -140,7 +140,7 @@ icon_closed = "orange" starts_with = list( - /obj/item/clothing/under/color/orange = 3, + /obj/item/clothing/under/color/orange/prison = 3, /obj/item/clothing/shoes/orange = 3) diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index e399c04d0ba..6517dda8f8b 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -3,7 +3,7 @@ /obj/structure/closet/crate name = "crate" desc = "A rectangular steel crate." - icon = 'icons/obj/storage.dmi' + icon = 'icons/obj/storage_vr.dmi' //VOREStation edit icon_state = "crate" icon_opened = "crateopen" icon_closed = "crate" @@ -293,6 +293,9 @@ /obj/structure/closet/crate/solar name = "solar pack crate" + icon_state = "engi_crate" //VOREStation Edit + icon_opened = "engi_crateopen" //VOREStation Edit + icon_closed = "engi_crate" //VOREStation Edit starts_with = list( /obj/item/solar_assembly = 21, @@ -343,12 +346,13 @@ desc = "A crate of emergency rations." starts_with = list( - /obj/item/weapon/reagent_containers/food/snacks/liquidfood = 4) + /obj/random/mre = 6) /obj/structure/closet/crate/bin name = "large bin" desc = "A large bin." + icon = 'icons/obj/storage.dmi' //VOREStation edit icon_state = "largebin" icon_opened = "largebinopen" icon_closed = "largebin" @@ -417,6 +421,7 @@ /obj/structure/closet/crate/secure/bin name = "secure bin" desc = "A secure bin." + icon = 'icons/obj/storage.dmi' //VOREStation edit icon_state = "largebins" icon_opened = "largebinsopen" icon_closed = "largebins" @@ -429,7 +434,7 @@ /obj/structure/closet/crate/large name = "large crate" desc = "A hefty metal crate." - icon = 'icons/obj/storage.dmi' + icon = 'icons/obj/storage_vr.dmi' //VOREStation Edit icon_state = "largemetal" icon_opened = "largemetalopen" icon_closed = "largemetal" @@ -457,10 +462,10 @@ /obj/structure/closet/crate/secure/large name = "large crate" desc = "A hefty metal crate with an electronic locking system." - icon = 'icons/obj/storage.dmi' - icon_state = "largemetal" - icon_opened = "largemetalopen" - icon_closed = "largemetal" + icon = 'icons/obj/storage_vr.dmi' //VOREStation Edit + icon_state = "largemetalsecure" //VOREStation Edit + icon_opened = "largemetalsecureopen" //VOREStation Edit + icon_closed = "largemetalsecure" //VOREStation Edit redlight = "largemetalr" greenlight = "largemetalg" diff --git a/code/game/objects/structures/crates_lockers/crates_vr.dm b/code/game/objects/structures/crates_lockers/crates_vr.dm index c2a5cee915b..85eccb3d77e 100644 --- a/code/game/objects/structures/crates_lockers/crates_vr.dm +++ b/code/game/objects/structures/crates_lockers/crates_vr.dm @@ -31,4 +31,9 @@ ..() - return \ No newline at end of file + return + +/obj/structure/closet/crate/medical/blood + icon_state = "blood" + icon_opened = "bloodopen" + icon_closed = "blood" \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/largecrate.dm b/code/game/objects/structures/crates_lockers/largecrate.dm index a7a4b778235..79bd5e2949b 100644 --- a/code/game/objects/structures/crates_lockers/largecrate.dm +++ b/code/game/objects/structures/crates_lockers/largecrate.dm @@ -1,7 +1,7 @@ /obj/structure/largecrate name = "large crate" desc = "A hefty wooden crate." - icon = 'icons/obj/storage.dmi' + icon = 'icons/obj/storage_vr.dmi' //VOREStation Edit icon_state = "densecrate" density = 1 var/list/starts_with @@ -82,10 +82,11 @@ starts_with = list(/obj/structure/vehiclecage/quadtrailer) /obj/structure/largecrate/animal - icon_state = "mulecrate" + icon_state = "lisacrate" //VOREStation Edit /obj/structure/largecrate/animal/mulebot name = "Mulebot crate" + icon_state = "mulecrate" //VOREStation Edit starts_with = list(/mob/living/bot/mulebot) /obj/structure/largecrate/animal/corgi diff --git a/code/game/objects/structures/crates_lockers/largecrate_vr.dm b/code/game/objects/structures/crates_lockers/largecrate_vr.dm index c151409e62e..6886a08a3c1 100644 --- a/code/game/objects/structures/crates_lockers/largecrate_vr.dm +++ b/code/game/objects/structures/crates_lockers/largecrate_vr.dm @@ -50,7 +50,7 @@ /mob/living/simple_mob/animal/wolf, /mob/living/simple_mob/animal/space/bear;0.5, /mob/living/simple_mob/animal/space/carp, - /mob/living/simple_mob/animal/space/mimic, + /mob/living/simple_mob/vore/aggressive/mimic, /mob/living/simple_mob/vore/aggressive/rat, /mob/living/simple_mob/vore/aggressive/rat/tame, // /mob/living/simple_mob/otie;0.5 diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index d4cf8f63b33..15bfe8ac893 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -1,14 +1,82 @@ +/obj/structure/flora + name = "flora" + desc = "A perfectly generic plant." + anchored = TRUE // Usually, plants don't move. Usually. + plane = DECAL_PLANE + layer = BELOW_MOB_LAYER + var/randomize_size = FALSE + var/max_x_scale = 1.25 + var/max_y_scale = 1.25 + var/min_x_scale = 0.9 + var/min_y_scale = 0.9 + var/harvest_tool = null // The type of item used to harvest the plant. + var/harvest_count = 0 + + var/randomize_harvest_count = TRUE + var/max_harvests = 0 + var/min_harvests = -1 + var/list/harvest_loot = null // Should be an associative list for things to spawn, and their weights. An example would be a branch from a tree. + +/obj/structure/flora/Initialize() + ..() + + if(randomize_size) + icon_scale_x = rand(min_x_scale * 100, max_x_scale * 100) / 100 + icon_scale_y = rand(min_y_scale * 100, max_y_scale * 100) / 100 + + if(prob(50)) + icon_scale_x *= -1 + update_transform() + + if(randomize_harvest_count) + max_harvests = max(0, rand(min_harvests, max_harvests)) // Incase you want to weight it more toward 'not harvestable', set min_harvests to a negative value. + +/obj/structure/flora/examine(mob/user) + . = ..(user) + if(harvest_count < max_harvests) + to_chat(user, "\The [src] seems to have something hanging from it.") + +/obj/structure/flora/attackby(var/obj/item/weapon/W, var/mob/living/user) + if(can_harvest(W)) + var/harvest_spawn = pickweight(harvest_loot) + var/atom/movable/AM = spawn_harvest(harvest_spawn, user) + + if(!AM) + to_chat(user, "You fail to harvest anything from \the [src].") + + else + to_chat(user, "You harvest \the [AM] from \the [src].") + return + + ..(W, user) + +/obj/structure/flora/proc/can_harvest(var/obj/item/I) + . = FALSE + if(harvest_tool && istype(I, harvest_tool) && harvest_loot && harvest_loot.len && harvest_count < max_harvests) + . = TRUE + return . + +/obj/structure/flora/proc/spawn_harvest(var/path = null, var/mob/user = null) + if(!ispath(path)) + return 0 + var/turf/Target = get_turf(src) + if(user) + Target = get_turf(user) + + var/atom/movable/AM = new path(Target) + + harvest_count++ + return AM //bushes /obj/structure/flora/bush name = "bush" icon = 'icons/obj/flora/snowflora.dmi' icon_state = "snowbush1" - anchored = 1 /obj/structure/flora/bush/New() ..() @@ -20,6 +88,7 @@ icon = 'icons/obj/plants.dmi' icon_state = "plant-26" + anchored = FALSE //newbushes @@ -27,7 +96,6 @@ name = "bush" icon = 'icons/obj/flora/ausflora.dmi' icon_state = "firstbush_1" - anchored = 1 /obj/structure/flora/ausbushes/New() ..() @@ -122,7 +190,7 @@ /obj/structure/flora/ausbushes/ppflowers/New() ..() - icon_state = "ppflowers_[rand(1, 4)]" + icon_state = "ppflowers_[rand(1, 3)]" /obj/structure/flora/ausbushes/sparsegrass icon_state = "sparsegrass_1" @@ -144,6 +212,7 @@ icon_state = "hangskele" desc = "It's an anatomical model of a human skeletal system made of plaster." + plane = OBJ_PLANE //potted plants credit: Flashkirby /obj/structure/flora/pottedplant @@ -152,6 +221,8 @@ icon = 'icons/obj/plants.dmi' icon_state = "plant-01" + plane = OBJ_PLANE + /obj/structure/flora/pottedplant/large name = "large potted plant" desc = "This is a large plant. Three branches support pairs of waxy leaves." @@ -348,4 +419,22 @@ /obj/structure/flora/sif/eyes/Initialize() icon_state = "[initial(icon_state)][rand(1,3)]" - . = ..() \ No newline at end of file + . = ..() + +/datum/category_item/catalogue/flora/mosstendrils + name = "Sivian Flora - Moss Stalks" + desc = "A plant native to Sif. The plant is most closely related to the common, dense moss found covering Sif's terrain. \ + It has evolved a method of camouflage utilizing white hairs on its dorsal sides to make it appear as a small mound of snow from \ + above. It has no known use, though it is a common furnishing in contemporary homes." + value = CATALOGUER_REWARD_TRIVIAL + +/obj/structure/flora/sif/tendrils + name = "stocky tendrils" + desc = "A 'plant' made up of hardened moss. It has tiny hairs that bunch together to look like snow." + icon_state = "grass" + randomize_size = TRUE + catalogue_data = list(/datum/category_item/catalogue/flora/mosstendrils) + +/obj/structure/flora/sif/tendrils/Initialize() + icon_state = "[initial(icon_state)][rand(1,3)]" + . = ..() diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index 03657ce45d4..c67348a94ae 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -14,19 +14,10 @@ var/product_amount = 10 // How much of a stack you get, if the above is defined. var/is_stump = FALSE // If true, suspends damage tracking and most other effects. var/indestructable = FALSE // If true, the tree cannot die. - var/randomize_size = FALSE // If true, the tree will choose a random scale in the X and Y directions to stretch. /obj/structure/flora/tree/Initialize() icon_state = choose_icon_state() - if(randomize_size) - icon_scale_x = rand(90, 125) / 100 - icon_scale_y = rand(90, 125) / 100 - - if(prob(50)) - icon_scale_x *= -1 - update_transform() - return ..() /obj/structure/flora/tree/update_transform() @@ -39,7 +30,17 @@ /obj/structure/flora/tree/proc/choose_icon_state() return icon_state +/obj/structure/flora/tree/can_harvest(var/obj/item/I) + . = FALSE + if(!is_stump && harvest_tool && istype(I, harvest_tool) && harvest_loot && harvest_loot.len && harvest_count < max_harvests) + . = TRUE + return . + /obj/structure/flora/tree/attackby(var/obj/item/weapon/W, var/mob/living/user) + if(can_harvest(W)) + ..(W, user) + return + if(!istype(W)) return ..() @@ -267,6 +268,14 @@ product = /obj/item/stack/material/log/sif catalogue_data = list(/datum/category_item/catalogue/flora/sif_tree) randomize_size = TRUE + + harvest_tool = /obj/item/weapon/material/knife + max_harvests = 2 + min_harvests = -4 + harvest_loot = list( + /obj/item/weapon/reagent_containers/food/snacks/siffruit = 5 + ) + var/light_shift = 0 /obj/structure/flora/tree/sif/choose_icon_state() diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index a24f2868da9..072dd43de6e 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -212,7 +212,7 @@ else return ..() -/obj/structure/girder/proc/take_damage(var/damage) +/obj/structure/girder/take_damage(var/damage) health -= damage if(health <= 0) dismantle() diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index c4b91fc73ab..1057a5094c3 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -281,3 +281,8 @@ return TRUE return FALSE +/obj/structure/grille/take_damage(var/damage) + health -= damage + spawn(1) healthcheck() + return 1 + diff --git a/code/game/objects/structures/handrail_vr.dm b/code/game/objects/structures/handrail_vr.dm new file mode 100644 index 00000000000..340d8dedd3d --- /dev/null +++ b/code/game/objects/structures/handrail_vr.dm @@ -0,0 +1,8 @@ +/obj/structure/handrail + name = "handrail" + icon = 'icons/obj/handrail_vr.dmi' + icon_state = "handrail" + desc = "A safety railing with buckles to secure yourself to when floor isn't stable enough." + density = 0 + anchored = 1 + can_buckle = 1 diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 2192b5690c4..f5bebdf5294 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -137,6 +137,13 @@ user.visible_message("[user] [attack_verb] at [src]!") return 1 +/obj/structure/inflatable/take_damage(var/damage) + health -= damage + if(health <= 0) + visible_message("The [src] deflates!") + spawn(1) puncture() + return 1 + /obj/item/inflatable/door/ name = "inflatable door" desc = "A folded membrane which rapidly expands into a simple door on activation." diff --git a/code/game/objects/structures/ledges.dm b/code/game/objects/structures/ledges.dm new file mode 100644 index 00000000000..1afa2efb014 --- /dev/null +++ b/code/game/objects/structures/ledges.dm @@ -0,0 +1,85 @@ +/obj/structure/ledge + name = "rock ledge" + desc = "An easily scaleable rocky ledge." + icon = 'icons/obj/ledges.dmi' + density = 1 + throwpass = 1 + climbable = 1 + anchored = 1 + var/solidledge = 1 + flags = ON_BORDER + layer = STAIRS_LAYER + icon_state = "ledge" + +/obj/structure/ledge_corner + icon_state = "ledge-corner" + flags = 0 + name = "rock ledge" + desc = "An easily scaleable rocky ledge." + icon = 'icons/obj/ledges.dmi' + density = 1 + throwpass = 1 + climbable = 1 + anchored = 1 + layer = STAIRS_LAYER + +/obj/structure/ledge/ledge_nub + desc = "Part of a rocky ledge." + icon_state = "ledge-nub" + density = 0 + solidledge = 0 + +/obj/structure/ledge/ledge_stairs + name = "rock stairs" + desc = "A colorful set of rocky stairs" + icon_state = "ledge-stairs" + density = 0 + solidledge = 0 + +/obj/structure/ledge/CanPass(atom/movable/mover, turf/target) + if(istype(mover) && mover.checkpass(PASSTABLE)) + return TRUE + if(solidledge && get_dir(mover, target) == turn(dir, 180)) + return !density + return TRUE + +/obj/structure/ledge/CheckExit(atom/movable/O as mob|obj, target as turf) + if(istype(O) && O.checkpass(PASSTABLE)) + return 1 + if(solidledge && get_dir(O.loc, target) == dir) + return 0 + return 1 + +/obj/structure/ledge/do_climb(var/mob/living/user) + if(!can_climb(user)) + return + + usr.visible_message("[user] starts climbing onto \the [src]!") + climbers |= user + + if(!do_after(user,(issmall(user) ? 20 : 34))) + climbers -= user + return + + if(!can_climb(user, post_climb_check=1)) + climbers -= user + return + + if(get_turf(user) == get_turf(src)) + usr.forceMove(get_step(src, src.dir)) + else + usr.forceMove(get_turf(src)) + + usr.visible_message("[user] climbed over \the [src]!") + climbers -= user + +/obj/structure/ledge/can_climb(var/mob/living/user, post_climb_check=0) + if(!..()) + return 0 + + if(get_turf(user) == get_turf(src)) + var/obj/occupied = neighbor_turf_impassable() + if(occupied) + to_chat(user, "You can't climb there, there's \a [occupied] in the way.") + return 0 + return 1 \ No newline at end of file diff --git a/code/game/objects/structures/loot_piles.dm b/code/game/objects/structures/loot_piles.dm index c94003e9fb8..f74770664bb 100644 --- a/code/game/objects/structures/loot_piles.dm +++ b/code/game/objects/structures/loot_piles.dm @@ -340,7 +340,7 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh /obj/item/weapon/stock_parts/subspace/transmitter, /obj/item/weapon/stock_parts/subspace/treatment, /obj/item/frame, - /obj/item/broken_device, + /obj/item/broken_device/random, /obj/item/borg/upgrade/restart, /obj/item/weapon/cell, /obj/item/weapon/cell/high, diff --git a/code/game/objects/structures/musician.dm b/code/game/objects/structures/musician.dm index f563a380cb3..ff1826116a6 100644 --- a/code/game/objects/structures/musician.dm +++ b/code/game/objects/structures/musician.dm @@ -1,8 +1,8 @@ //This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32 #define MUSICIAN_HEARCHECK_MINDELAY 4 -#define INSTRUMENT_MAX_LINE_LENGTH 300 -#define INSTRUMENT_MAX_LINE_NUMBER 50 +#define INSTRUMENT_MAX_LINE_LENGTH 50 +#define INSTRUMENT_MAX_LINE_NUMBER 300 /datum/song var/name = "Untitled" diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm index 8f21f72781e..bf15ffdfd70 100644 --- a/code/game/objects/structures/plasticflaps.dm +++ b/code/game/objects/structures/plasticflaps.dm @@ -8,6 +8,7 @@ layer = MOB_LAYER plane = MOB_PLANE explosion_resistance = 5 + var/can_pass_lying = 1 var/list/mobs_can_pass = list( /mob/living/bot, /mob/living/simple_mob/slime/xenobio, @@ -18,9 +19,9 @@ /obj/structure/plasticflaps/attackby(obj/item/P, mob/user) if(P.is_wirecutter()) playsound(src, P.usesound, 50, 1) - user << "You start to cut the plastic flaps." + to_chat(user, "You start to cut the plastic flaps.") if(do_after(user, 10 * P.toolspeed)) - user << "You cut the plastic flaps." + to_chat(user, "You cut the plastic flaps.") var/obj/item/stack/material/plastic/A = new /obj/item/stack/material/plastic( src.loc ) A.amount = 4 qdel(src) @@ -41,7 +42,7 @@ var/mob/living/M = A if(istype(M)) - if(M.lying) + if(M.lying && can_pass_lying) return ..() for(var/mob_type in mobs_can_pass) if(istype(A, mob_type)) @@ -63,5 +64,6 @@ /obj/structure/plasticflaps/mining //A specific type for mining that doesn't allow airflow because of them damn crates name = "airtight plastic flaps" - desc = "Heavy duty, airtight, plastic flaps." + desc = "Heavy duty, airtight, plastic flaps. Have extra safety installed, preventing passage of living beings." can_atmos_pass = ATMOS_PASS_NO + can_pass_lying = 0 \ No newline at end of file diff --git a/code/game/objects/structures/props/blackbox.dm b/code/game/objects/structures/props/blackbox.dm index b6bae732f8f..a28b82349f0 100644 --- a/code/game/objects/structures/props/blackbox.dm +++ b/code/game/objects/structures/props/blackbox.dm @@ -105,4 +105,28 @@ **16/FEB/2562**
      Something chitters.
      End of transcript. - "} \ No newline at end of file + "} + +/obj/structure/prop/blackbox/xenofrigate + catalogue_data = list(/datum/category_item/catalogue/information/blackbox/xenofrigate) + +/datum/category_item/catalogue/information/blackbox/xenofrigate + name = "Black Box Data - MBT-540" + desc = {" +
      + Begin Log + @$&@$& Human ##:##:##: Attention unidentified vessel, state your designation and intent.
      + !#@$&&^ Human ##:##:##: Commander I don't think they're going to stop.
      + @$&@$& Human ##:##:##: Unidentified vessel, you have until the count of three before we engage weapon-
      + !#@$&&^ Human ##:##:##: Commander! Think about what you're-
      + A repeating clicking, before silence.
      + End of first log.
      + **
      + Begin Log
      + #!#^@$& Skrell ##:##:##: Director, I think you should see this.
      + ^@$& Skrell ##:##:##: Yes? What is it?
      + #!#^@$& Skrell ##:##:##: Another one of those ships has appeared near th-462$^ ---n colonies. I would strongly advise pursuing it.
      + ^@$& Skrell ##:##:##: A wise decision. If it is damaged like the last one, we may be able to finally see what is - What?
      + A repeating ping, before silence.
      + End of second log. + "} diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index 9d96f0cc25f..8027b5db5e8 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -52,7 +52,7 @@ if(0.5 to 1.0) to_chat(user, "It has a few scrapes and dents.") -/obj/structure/railing/proc/take_damage(amount) +/obj/structure/railing/take_damage(amount) health -= amount if(health <= 0) visible_message("\The [src] breaks down!") diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm index 4b741ed648a..431ef0cdbb0 100644 --- a/code/game/objects/structures/simple_doors.dm +++ b/code/game/objects/structures/simple_doors.dm @@ -124,15 +124,22 @@ icon_state = material.door_icon_base /obj/structure/simple_door/attackby(obj/item/weapon/W as obj, mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(istype(W,/obj/item/weapon/pickaxe)) var/obj/item/weapon/pickaxe/digTool = W - user << "You start digging the [name]." + visible_message("[user] starts digging [src]!") if(do_after(user,digTool.digspeed*hardness) && src) - user << "You finished digging." + visible_message("[user] finished digging [src]!") Dismantle() else if(istype(W,/obj/item/weapon)) //not sure, can't not just weapons get passed to this proc? - hardness -= W.force/100 - user << "You hit the [name] with your [W.name]!" + hardness -= W.force/10 + visible_message("[user] hits [src] with [W]!") + if(material == get_material_by_name("resin")) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) + playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1) + else + playsound(src, 'sound/weapons/smash.ogg', 50, 1) CheckHardness() else if(istype(W,/obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W @@ -142,12 +149,33 @@ attack_hand(user) return +/obj/structure/simple_door/bullet_act(var/obj/item/projectile/Proj) + hardness -= Proj.force/10 + CheckHardness() + +/obj/structure/simple_door/take_damage(var/damage) + hardness -= damage/10 + CheckHardness() + +/obj/structure/simple_door/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + if(material == get_material_by_name("resin")) + playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) + else if(material == (get_material_by_name(MAT_WOOD) || get_material_by_name(MAT_SIFWOOD))) + playsound(loc, 'sound/effects/woodcutting.ogg', 100, 1) + else + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + user.do_attack_animation(src) + hardness -= damage/10 + CheckHardness() + /obj/structure/simple_door/proc/CheckHardness() if(hardness <= 0) Dismantle(1) /obj/structure/simple_door/proc/Dismantle(devastated = 0) material.place_dismantled_product(get_turf(src)) + visible_message("The [src] is destroyed!") qdel(src) /obj/structure/simple_door/ex_act(severity = 1) diff --git a/code/game/objects/structures/trash_pile.dm b/code/game/objects/structures/trash_pile.dm index 3258f40edb6..bc06bb0dbd9 100644 --- a/code/game/objects/structures/trash_pile.dm +++ b/code/game/objects/structures/trash_pile.dm @@ -132,7 +132,7 @@ prob(5);/obj/item/weapon/storage/backpack/satchel/norm, prob(5);/obj/item/weapon/storage/box, // prob(5);/obj/random/cigarettes, - prob(4);/obj/item/broken_device, + prob(4);/obj/item/broken_device/random, prob(4);/obj/item/clothing/head/hardhat, prob(4);/obj/item/clothing/mask/breath, prob(4);/obj/item/clothing/shoes/black, diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index cc3bcf16481..b2867d5eadb 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -47,7 +47,7 @@ else to_chat(user, "There is a thick layer of silicate covering it.") -/obj/structure/window/proc/take_damage(var/damage = 0, var/sound_effect = 1) +/obj/structure/window/take_damage(var/damage = 0, var/sound_effect = 1) var/initialhealth = health if(silicate) diff --git a/code/game/turfs/flooring/shuttle_vr.dm b/code/game/turfs/flooring/shuttle_vr.dm index f7f1b6e497c..0b80dc72117 100644 --- a/code/game/turfs/flooring/shuttle_vr.dm +++ b/code/game/turfs/flooring/shuttle_vr.dm @@ -8,3 +8,8 @@ oxygen = 0 nitrogen = 0 temperature = TCMB + +/turf/simulated/shuttle/floor/white/airless + oxygen = 0 + nitrogen = 0 + temperature = TCMB diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 1c74b467e22..6bf7cf38b4b 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -13,6 +13,8 @@ var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to var/can_dirty = TRUE // If false, tile never gets dirty + var/can_start_dirty = TRUE // If false, cannot start dirty roundstart + var/dirty_prob = 2 // Chance of being dirty roundstart var/dirt = 0 // This is not great. diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 606c0b2bb91..31bfd62684d 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -43,9 +43,10 @@ set_flooring(get_flooring_data(floortype)) else footstep_sounds = base_footstep_sounds - if(can_dirty) - if(prob(2)) - new /obj/effect/decal/cleanable/dirt(src) //5% chance to start with dirt on a floor tile- give the janitor something to do + if(can_dirty && can_start_dirty) + if(prob(dirty_prob)) + dirt += rand(50,100) + update_dirt() //5% chance to start with dirt on a floor tile- give the janitor something to do /turf/simulated/floor/proc/set_flooring(var/decl/flooring/newflooring) make_plating(defer_icon_update = 1) diff --git a/code/game/turfs/simulated/outdoors/grass.dm b/code/game/turfs/simulated/outdoors/grass.dm index 72b2ee7e57a..e557fb16da0 100644 --- a/code/game/turfs/simulated/outdoors/grass.dm +++ b/code/game/turfs/simulated/outdoors/grass.dm @@ -33,7 +33,8 @@ var/list/grass_types = list( var/tree_chance = 2 grass_types = list( - /obj/structure/flora/sif/eyes + /obj/structure/flora/sif/eyes = 1, + /obj/structure/flora/sif/tendrils = 10 ) catalogue_data = list(/datum/category_item/catalogue/flora/sif_grass) @@ -50,7 +51,7 @@ var/list/grass_types = list( //edge_blending_priority++ if(grass_chance && prob(grass_chance) && !check_density()) - var/grass_type = pick(grass_types) + var/grass_type = pickweight(grass_types) new grass_type(src) . = ..() diff --git a/code/game/turfs/simulated/outdoors/snow.dm b/code/game/turfs/simulated/outdoors/snow.dm index 0f9be4ddbfd..cccc028fa30 100644 --- a/code/game/turfs/simulated/outdoors/snow.dm +++ b/code/game/turfs/simulated/outdoors/snow.dm @@ -58,3 +58,10 @@ to_chat(M, "You slide across the ice!") M.SetStunned(1) step(M,M.dir) + +// Ice that is used for, say, areas floating on water or similar. +/turf/simulated/floor/outdoors/shelfice + name = "ice" + icon_state = "ice" + desc = "Looks slippery." + movement_cost = 4 diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index cb1a0f631af..1847767083e 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -153,7 +153,7 @@ visible_message("\The [src] spontaneously combusts!.") //!!OH SHIT!! return -/turf/simulated/wall/proc/take_damage(dam) +/turf/simulated/wall/take_damage(dam) if(dam) damage = max(0, damage + dam) update_damage() diff --git a/code/game/turfs/simulated_vr.dm b/code/game/turfs/simulated_vr.dm new file mode 100644 index 00000000000..6c7325305fe --- /dev/null +++ b/code/game/turfs/simulated_vr.dm @@ -0,0 +1,5 @@ +/turf/simulated + can_start_dirty = FALSE // We have enough premapped dirt where needed + +/turf/simulated/floor/plating + can_start_dirty = TRUE // But let maints and decrepit areas have some randomness \ No newline at end of file diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index 0c97ec387ef..8a0d7852f57 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -28,7 +28,7 @@ if(N == /turf/space) var/turf/below = GetBelow(src) - if(istype(below) && (air_master.has_valid_zone(below) || air_master.has_valid_zone(src))) + if(istype(below) && (air_master.has_valid_zone(below) || air_master.has_valid_zone(src)) && !istype(below, /turf/unsimulated/wall)) // VOREStation Edit: Weird open space N = /turf/simulated/open var/obj/fire/old_fire = fire diff --git a/code/game/turfs/unsimulated/sky_vr.dm b/code/game/turfs/unsimulated/sky_vr.dm index 8ba1cf0cb57..d012d08b6cd 100644 --- a/code/game/turfs/unsimulated/sky_vr.dm +++ b/code/game/turfs/unsimulated/sky_vr.dm @@ -1,67 +1,69 @@ -/////////////////// -// Generic skyfall turf -// Really only works well if the map doesn't have 'indoor' areas otherwise they can fall into one. -// TODO: Fix that. -/turf/unsimulated/floor/sky - name = "the sky" - desc = "It's the sky! Be careful!" - icon = 'icons/turf/floors.dmi' - icon_state = "sky_slow" - dir = SOUTH - initialized = FALSE - var/does_skyfall = TRUE - var/list/skyfall_levels - -/turf/unsimulated/floor/sky/Initialize() - . = ..() - if(does_skyfall && !LAZYLEN(skyfall_levels)) - error("[x],[y],[z], [get_area(src)] doesn't have skyfall_levels defined! Can't skyfall!") - if(locate(/turf/simulated) in orange(src,1)) - set_light(2, 2, color) - -/turf/unsimulated/floor/sky/Entered(atom/movable/AM,atom/oldloc) - . = ..() - if(!does_skyfall) - return //We don't do that - if(isobserver(AM)) - return //Don't ghostport, very annoying - if(AM.throwing) - return //Being thrown over, not fallen yet - - var/mob/living/L - if(isliving(AM)) - L = AM - if(L.is_floating) - return //Flyers/nograv can ignore it - - do_fall(AM) - -/turf/unsimulated/floor/sky/hitby(var/atom/movable/AM, var/speed) - . = ..() - - if(!does_skyfall) - return //We don't do that - - do_fall(AM) - -/turf/unsimulated/floor/sky/proc/do_fall(atom/movable/AM) - //Bye - var/attempts = 100 - var/turf/simulated/T - while(attempts && !T) - var/turf/simulated/candidate = locate(rand(5,world.maxx-5),rand(5,world.maxy-5),pick(skyfall_levels)) - if(candidate.density) - attempts-- - continue - - T = candidate - break - - if(!T) - return - - AM.forceMove(T) - if(isliving(AM)) - var/mob/living/L = AM - message_admins("\The [AM] fell out of the sky.") - L.fall_impact(T, 42, 90, FALSE, TRUE) //You will not be defibbed from this. +/////////////////// +// Generic skyfall turf +// Really only works well if the map doesn't have 'indoor' areas otherwise they can fall into one. +// TODO: Fix that. +/turf/unsimulated/floor/sky + name = "the sky" + desc = "It's the sky! Be careful!" + icon = 'icons/turf/floors.dmi' + icon_state = "sky_slow" + dir = SOUTH + initialized = FALSE + var/does_skyfall = TRUE + var/list/skyfall_levels + +/turf/unsimulated/floor/sky/Initialize() + . = ..() + if(does_skyfall && !LAZYLEN(skyfall_levels)) + error("[x],[y],[z], [get_area(src)] doesn't have skyfall_levels defined! Can't skyfall!") + if(locate(/turf/simulated) in orange(src,1)) + set_light(2, 2, color) + +/turf/unsimulated/floor/sky/Entered(atom/movable/AM,atom/oldloc) + . = ..() + if(!does_skyfall) + return //We don't do that + if(isobserver(AM)) + return //Don't ghostport, very annoying + if(AM.throwing) + return //Being thrown over, not fallen yet + if(/obj/item/projectile) + return // Bullets/lasers/pewpew should not fall out of the sky. pew. + + var/mob/living/L + if(isliving(AM)) + L = AM + if(L.is_floating) + return //Flyers/nograv can ignore it + + do_fall(AM) + +/turf/unsimulated/floor/sky/hitby(var/atom/movable/AM, var/speed) + . = ..() + + if(!does_skyfall) + return //We don't do that + + do_fall(AM) + +/turf/unsimulated/floor/sky/proc/do_fall(atom/movable/AM) + //Bye + var/attempts = 100 + var/turf/simulated/T + while(attempts && !T) + var/turf/simulated/candidate = locate(rand(5,world.maxx-5),rand(5,world.maxy-5),pick(skyfall_levels)) + if(candidate.density) + attempts-- + continue + + T = candidate + break + + if(!T) + return + + AM.forceMove(T) + if(isliving(AM)) + var/mob/living/L = AM + message_admins("\The [AM] fell out of the sky.") + L.fall_impact(T, 42, 90, FALSE, TRUE) //You will not be defibbed from this. diff --git a/code/global.dm b/code/global.dm index a1ecb08cff5..e9bcbb49f49 100644 --- a/code/global.dm +++ b/code/global.dm @@ -53,7 +53,7 @@ var/list/lastsignalers = list() // Keeps last 100 signals here in format: "[src] var/list/lawchanges = list() // Stores who uploaded laws to which silicon-based lifeform, and what the law was. var/list/reg_dna = list() -var/mouse_respawn_time = 5 // Amount of time that must pass between a player dying as a mouse and repawning as a mouse. In minutes. +var/mouse_respawn_time = 2.5 // Amount of time that must pass between a player dying as a mouse and repawning as a mouse. In minutes. Vorestation Edit - Changed to 2.5 minutes, half of 5, in accordance with mouse nerfs and realignment. var/list/monkeystart = list() var/list/wizardstart = list() diff --git a/code/global_vr.dm b/code/global_vr.dm index 9506dd62d35..cfa9186b1d2 100644 --- a/code/global_vr.dm +++ b/code/global_vr.dm @@ -6,6 +6,10 @@ robot_module_types += "Pupdozer" return 1 +var/list/shell_module_types = list( + "Standard", "Service", "Clerical" +) + var/global/list/acceptable_fruit_types= list( "ambrosia", "apple", diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index 4bad67b3703..67cc4d496c3 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -148,6 +148,7 @@ var/list/admin_verbs_spawn = list( /datum/admins/proc/spawn_plant, /datum/admins/proc/spawn_atom, //allows us to spawn instances, /client/proc/respawn_character, + /client/proc/spawn_character_mob, //VOREStation Add, /client/proc/virus2_editor, /client/proc/spawn_chemdisp_cartridge, /client/proc/map_template_load, diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm index a6e50cb1082..2b2a6672ebd 100644 --- a/code/modules/admin/verbs/adminhelp.dm +++ b/code/modules/admin/verbs/adminhelp.dm @@ -490,6 +490,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new) if(alert(usr, "You already have a ticket open. Is this for the same issue?",,"Yes","No") != "No") if(current_ticket) current_ticket.MessageNoRecipient(msg) + to_chat(usr, "PM to-Admins: [msg]") return else to_chat(usr, "Ticket not found, creating new one...") diff --git a/code/modules/admin/verbs/adminhelp_vr.dm b/code/modules/admin/verbs/adminhelp_vr.dm index 9f3aee4a838..f2df8e4eb29 100644 --- a/code/modules/admin/verbs/adminhelp_vr.dm +++ b/code/modules/admin/verbs/adminhelp_vr.dm @@ -1,8 +1,8 @@ -/datum/admin_help/proc/send2adminchat() +/datum/admin_help/proc/send2adminchat() if(!config.chat_webhook_url) return - var/list/adm = get_admin_counts() + var/list/adm = get_admin_counts() var/list/afkmins = adm["afk"] var/list/allmins = adm["total"] @@ -14,3 +14,25 @@ query_string += "&admin_number=[allmins.len]" query_string += "&admin_number_afk=[afkmins.len]" world.Export("[config.chat_webhook_url]?[query_string]") + +/client/verb/adminspice() + set category = "Admin" + set name = "Request Spice" + set desc = "Request admins to spice round up for you" + + //handle muting and automuting + if(prefs.muted & MUTE_ADMINHELP) + to_chat(usr, "Error: You cannot request spice (muted from adminhelps).") + return + + if(alert(usr, "Are you sure you want to request the admins spice things up for you? You accept the consequences if you do.",,"No","Yes") != "No") + message_admins("[ADMIN_FULLMONTY(usr)] has requested the round be spiced up a little.") + to_chat(usr, "You have requested some more spice in your round.") + else + to_chat(usr, "Spice request cancelled.") + return + + //if they requested spice, then remove spice verb temporarily to prevent spamming + usr.verbs -= /client/verb/adminspice + spawn(6000) + usr.verbs += /client/verb/adminspice // 10 minute cool-down for spice request diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 321655bb15a..11541128c50 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -282,11 +282,11 @@ var/obj/item/device/pda/pda = H.wear_id id = pda.id id.icon_state = "gold" - id.access = get_all_accesses() + id.access = get_all_accesses().Copy() else var/obj/item/weapon/card/id/id = new/obj/item/weapon/card/id(M); id.icon_state = "gold" - id.access = get_all_accesses() + id.access = get_all_accesses().Copy() id.registered_name = H.real_name id.assignment = "Colony Director" id.name = "[id.registered_name]'s ID Card ([id.assignment])" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 3475e60314b..72e2b3b39b6 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -368,7 +368,7 @@ Traitors and the like can also be revived with the previous role mostly intact. return var/location = alert(src,"Please specify where to spawn them.", "Location", "Right Here", "Arrivals", "Cancel") - if(!location) + if(location == "Cancel" || !location) return var/announce = alert(src,"Announce as if they had just arrived?", "Announce", "Yes", "No", "Cancel") diff --git a/code/modules/admin/verbs/randomverbs_vr.dm b/code/modules/admin/verbs/randomverbs_vr.dm new file mode 100644 index 00000000000..9fee7c58d08 --- /dev/null +++ b/code/modules/admin/verbs/randomverbs_vr.dm @@ -0,0 +1,74 @@ +/client/proc/spawn_character_mob() + set category = "Special Verbs" + set name = "Spawn Character As Mob" + set desc = "Spawn a specified ckey as a chosen mob." + if(!holder) + to_chat(src, "Only administrators may use this command.") + return + + var/client/picked_client = input(src, "Who are we spawning as a mob?", "Client", "Cancel") as null|anything in GLOB.clients + if(!picked_client) + return + var/list/types = typesof(/mob/living) + var/mob_type = input(src, "Mob path to spawn as?", "Mob") as text + if(!mob_type) + return + var/list/matches = new() + for(var/path in types) + if(findtext("[path]", mob_type)) + matches += path + if(matches.len==0) + return + var/mob/living/chosen + if(matches.len==1) + chosen = matches[1] + else + chosen = input("Select a mob type", "Select Mob", matches[1]) as null|anything in matches + if(!chosen) + return + + var/char_name = alert(src, "Spawn mob with their character name?", "Mob name", "Yes", "No", "Cancel") + var/name = 0 + if(char_name == "Cancel") + return + if(char_name == "Yes") + name = 1 + var/vorgans = alert(src, "Spawn mob with their character's vore organs and prefs?", "Vore organs", "Yes", "No", "Cancel") + var/organs + if(vorgans == "Cancel") + return + if(vorgans == "Yes") + organs = 1 + if(vorgans == "No") + organs = 0 + + var/spawnloc + if(!src.mob) + to_chat(src, "Can't spawn them in unless you're in a valid spawn location!") + return + spawnloc = get_turf(src.mob) + + var/mob/living/new_mob = new chosen(spawnloc) + + if(!new_mob) + to_chat(src, "Spawning failed, try again or bully coders") + return + new_mob.ai_holder_type = /datum/ai_holder/simple_mob/inert //Dont want the mob AI to activate if the client dc's or anything + + if(name) + new_mob.real_name = picked_client.prefs.real_name + new_mob.name = picked_client.prefs.real_name + + + new_mob.key = picked_client.key //Finally put them in the mob + if(organs) + new_mob.copy_from_prefs_vr() + + log_admin("[key_name_admin(src)] has spawned [new_mob.key] as mob [new_mob.type].") + message_admins("[key_name_admin(src)] has spawned [new_mob.key] as mob [new_mob.type].", 1) + + to_chat(new_mob, "You've been spawned as a mob! Have fun.") + + feedback_add_details("admin_verb","SCAM") //heh + + return new_mob \ No newline at end of file diff --git a/code/modules/admin/verbs/smite_vr.dm b/code/modules/admin/verbs/smite_vr.dm index 0d048dde2d8..b0d4b8aa8cf 100644 --- a/code/modules/admin/verbs/smite_vr.dm +++ b/code/modules/admin/verbs/smite_vr.dm @@ -18,7 +18,6 @@ feedback_add_details("admin_verb","SMITEV") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! switch(smite_choice) - /* if(SMITE_SHADEKIN_ATTACK) var/turf/Tt = get_turf(target) //Turf for target @@ -35,22 +34,22 @@ if(!Ts) return //Didn't find shadekin spawn turf - var/mob/living/simple_mob/shadekin/red/shadekin = new(Ts) + var/mob/living/simple_mob/shadekin/red/ai/shadekin = new(Ts) //Abuse of shadekin shadekin.real_name = shadekin.name shadekin.init_vore() shadekin.ability_flags |= 0x1 - shadekin.specific_targets = TRUE //Don't attack others shadekin.phase_shift() - shadekin.target_mob = target - shadekin.stance = STANCE_ATTACK + shadekin.ai_holder.give_target(target) + shadekin.ai_holder.hostile = FALSE + shadekin.ai_holder.mauling = TRUE shadekin.Life() //Remove when done spawn(10 SECONDS) if(shadekin) - shadekin.death()*/ //VORESTATION AI TEMPORARY REMOVAL + shadekin.death() - /*if(SMITE_SHADEKIN_NOMF) + if(SMITE_SHADEKIN_NOMF) var/list/kin_types = list( "Red Eyes (Dark)" = /mob/living/simple_mob/shadekin/red/dark, "Red Eyes (Light)" = /mob/living/simple_mob/shadekin/red/white, @@ -93,7 +92,6 @@ shadekin.real_name = shadekin.name shadekin.init_vore() shadekin.can_be_drop_pred = TRUE - shadekin.ai_inactive = TRUE shadekin.dir = SOUTH shadekin.ability_flags |= 0x1 shadekin.phase_shift() //Homf @@ -119,7 +117,7 @@ target.ghostize() qdel(target) qdel(shadekin) - */ + if(SMITE_REDSPACE_ABDUCT) redspace_abduction(target, src) diff --git a/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm b/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm index ed83a0896af..16609cc9619 100644 --- a/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm +++ b/code/modules/ai/aI_holder_subtypes/slime_xenobio_ai.dm @@ -175,9 +175,8 @@ if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too. return TRUE // Monkeys are always food (sorry Pun Pun). else if(H.species && H.species.name == SPECIES_PROMETHEAN) // Prometheans are always our friends. - if(H in grudges) // Unless they're an ass. - return TRUE - return FALSE + if(!(H in grudges)) // Unless they're an ass. + return FALSE if(discipline && !rabid) return FALSE // We're a good slime. diff --git a/code/modules/ai/ai_holder_combat.dm b/code/modules/ai/ai_holder_combat.dm index 12cf9e24360..63154e4fe41 100644 --- a/code/modules/ai/ai_holder_combat.dm +++ b/code/modules/ai/ai_holder_combat.dm @@ -65,6 +65,11 @@ on_engagement(target) melee_attack(target) + else if(distance <= 1 && !holder.ICheckRangedAttack(target)) // Doesn't have projectile, but is pointblank + ai_log("engage_target() : Attempting a melee attack.", AI_LOG_TRACE) + on_engagement(target) + melee_attack(target) + // Shoot them. else if(holder.ICheckRangedAttack(target) && (distance <= max_range(target)) ) on_engagement(target) diff --git a/code/modules/ai/ai_holder_targeting.dm b/code/modules/ai/ai_holder_targeting.dm index dfe5c85b63b..e70e991d6ec 100644 --- a/code/modules/ai/ai_holder_targeting.dm +++ b/code/modules/ai/ai_holder_targeting.dm @@ -4,6 +4,7 @@ var/hostile = FALSE // Do we try to hurt others? var/retaliate = FALSE // Attacks whatever struck it first. Mobs will still attack back if this is false but hostile is true. var/mauling = FALSE // Attacks unconscious mobs + var/handle_corpse = FALSE // Allows AI to acknowledge corpses (e.g. nurse spiders) var/atom/movable/target = null // The thing (mob or object) we're trying to kill. var/atom/movable/preferred_target = null// If set, and if given the chance, we will always prefer to target this over other options. @@ -121,7 +122,7 @@ if(L.key && !L.client) // SSD players get a pass return FALSE if(L.stat) - if(L.stat == DEAD) // Leave dead things alone + if(L.stat == DEAD && !handle_corpse) // Leave dead things alone return FALSE if(L.stat == UNCONSCIOUS) // Do we have mauling? Yes? Then maul people who are sleeping but not SSD if(mauling) @@ -266,4 +267,4 @@ /datum/ai_holder/proc/lose_taunt() ai_log("lose_taunt() : Resetting preferred_target.", AI_LOG_INFO) - preferred_target = null \ No newline at end of file + preferred_target = null diff --git a/code/modules/artifice/cursedform.dm b/code/modules/artifice/cursedform.dm new file mode 100644 index 00000000000..17f8fbf6183 --- /dev/null +++ b/code/modules/artifice/cursedform.dm @@ -0,0 +1,40 @@ +/obj/item/weapon/paper/carbon/cursedform + name = "Form - Inventory Requisition r10.7.1E" + +/obj/item/weapon/paper/carbon/cursedform/Initialize() + ..() + info = {"

      Form - Inventory Requisition r10.7.1E

      General Request Form


      General


      Name:
      Department:
      Departmental Rank:
      Organization(If not Nanotrasen):
      Date:



      Requested Item(s):
      Quantity:
      Reason for request:
      Is this replacement equipment?:
      If `Yes`; above, specify equiment and reason for replacement:


      Authorization


      Authorizing Department:
      Authorizing Dept. Head:


      Contact and Delivery


      EPv2 Address of requesting party(Do not leave blank):
      Delivery location or department:


      Nanotrasen Employee Identification Number:
      Signature of Requester and Date





      Authorizor`s Nanotrasen Employee Identification Number:
      Authorizing Signature and Date(Include authorizing department`s stamp below)




      Shipping Department Only

      (Do not write below this line)

      Nanotrasen Purchasing Approval Code:
      Nanotrasen Employee Identification Number:
      Receiving Shipping Employee:
      Signature and Date


      "} + info_links = {"

      Form - Inventory Requisition r10.7.1E

      General Request Form


      General


      Name: write
      Department: write
      Departmental Rank: write
      Organization(If not Nanotrasen): write
      Date: write



      Requested Item(s): write
      Quantity: write
      Reason for request: write
      Is this replacement equipment?: write
      If `Yes` above, specify equiment and reason for replacement: write


      Authorization


      Authorizing Department: write
      Authorizing Dept. Head: write


      Contact and Delivery


      EPv2 Address of requesting party(Do not leave blank): write
      Delivery location or department: write


      Nanotrasen Employee Identification Number: write
      Signature of Requester and Date

      write



      Authorizor`s Nanotrasen Employee Identification Number: write
      Authorizing Signature and Date(Include authorizing department`s stamp below)

      write


      Shipping Department Only

      (Do not write below this line)

      Nanotrasen Purchasing Approval Code: write
      Nanotrasen Employee Identification Number: write
      Receiving Shipping Employee: write
      Signature and Date

      write
      write"} + +/obj/item/weapon/paper/carbon/cursedform/AltClick() // No fun. + return + +/obj/item/weapon/paper/carbon/cursedform/burnpaper(obj/item/weapon/flame/P, mob/user) + var/class = "warning" + var/datum/gender/TU = gender_datums[user.get_visible_gender()] + + if(P.lit && !user.restrained()) + if(istype(P, /obj/item/weapon/flame/lighter/zippo)) + class = "rose" + + user.visible_message("[user] holds \the [P] up to \the [src], it looks like [TU.hes] trying to burn it!", \ + "You hold \the [P] up to \the [src], burning it slowly.") + + if(do_after(user, 2 SECONDS, src) && P.lit) + user.visible_message("[user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ + "You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") + + if(user.get_inactive_hand() == src) + user.drop_from_inventory(src) + + new /obj/effect/decal/cleanable/ash(src.loc) + qdel(src) + + else + to_chat(user,"You must hold \the [P] steady to burn \the [src].") + + if(isliving(user)) + var/mob/living/L = user + L.visible_message("[L] convulses, the very letters of \the [src] searing themselves into their eyes!", \ + "You convulse, the very letters of \the [src] searing themselves into your eyes!") + L.add_modifier(/datum/modifier/grievous_wounds, 10 MINUTES) diff --git a/code/modules/artifice/telecube.dm b/code/modules/artifice/telecube.dm new file mode 100644 index 00000000000..bb2af4b83dd --- /dev/null +++ b/code/modules/artifice/telecube.dm @@ -0,0 +1,236 @@ +/* + * Home of the telecube. + */ + +/datum/category_item/catalogue/anomalous/precursor_a/telecube + name = "Quantomatically Entangled Digicube" + + desc = "An enigmatic cube that appears superficially similar to a Positronic Cube. \ + However, the similarities hopefully end there, as this device emits no sound during \ + operation or observation. Its alloy composition is unknown, though it is incredibly \ + dense, as it resists any and all forms of radiation.
      \ + Upon physical contact, however, the device will translocate the offending entity to a \ + matching twin cube, generating no detectable radiation. This process occurs at speeds \ + unmatched even by modern predictions of Bluespace technology, and with no visible power \ + source." + + value = CATALOGUER_REWARD_HARD + +// Standard one needs to be smacked onto another one to link together. +/obj/item/weapon/telecube + name = "locus" + desc = "A strange metallic cube that pulses silently." + description_info = "Ctrl-Clicking on this object will attempt to activate its unique ability." + icon = 'icons/obj/props/telecube.dmi' + icon_state = "cube" + w_class = ITEMSIZE_SMALL + origin_tech = list(TECH_MATERIAL = 7, TECH_POWER = 6, TECH_BLUESPACE = 7, TECH_ANOMALY = 2, TECH_PRECURSOR = 2) + + catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/telecube) + + slowdown = 5 + + throw_range = 2 + + var/obj/item/weapon/telecube/mate = null + + var/start_paired = FALSE + var/mirror_colors = FALSE + + var/randomize_colors = FALSE + + var/glow_color = "#FFFFFF" + var/image/glow = null + var/image/charge = null + + var/shell_color = "#FFFFFF" + var/image/shell = null + + var/cooldown_time = 30 SECONDS + var/last_teleport = 0 + +// How far the cube will search for things to teleport. 0 = only contacting objects / mobs. + var/teleport_range = 0 // For all that is holy, do not change this unless you know what you're doing. + + var/omniteleport = FALSE // Will this teleport anchored things too? + +/obj/item/weapon/telecube/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + last_teleport = world.time + + glow = image(icon = icon, icon_state = "[icon_state]-ready") + glow.plane = PLANE_LIGHTING_ABOVE + charge = image(icon = icon, icon_state = "[icon_state]-charging") + charge.plane = PLANE_LIGHTING_ABOVE + shell = image(icon = icon, icon_state = "[icon_state]") + + if(teleport_range) + description_info += "
      " + description_info += "Alt-Clicking on this object will utilize its second unique ability." + + if(randomize_colors) + glow_color = rgb(rand(0, 255),rand(0, 255),rand(0, 255)) + shell_color = rgb(rand(0, 255),rand(0, 255),rand(0, 255)) + + if(start_paired) + mate = new(src.loc) + if(mirror_colors) + mate.glow_color = shell_color + mate.shell_color = glow_color + else + mate.glow_color = glow_color + mate.shell_color = shell_color + mate.pair_cube(src) + + glow.color = glow_color + charge.color = glow_color + shell.color = shell_color + + return + +/obj/item/weapon/telecube/process() + ..() + update_icon() + +/obj/item/weapon/telecube/update_icon() + . = ..() + glow.color = glow_color + charge.color = glow_color + shell.color = shell_color + + if(shell.color != initial(shell.color)) + cut_overlay(shell) + add_overlay(shell) + + if(world.time < (last_teleport + cooldown_time)) + cut_overlay(charge) + cut_overlay(glow) + add_overlay(charge) + else + cut_overlay(glow) + cut_overlay(charge) + add_overlay(glow) + +/obj/item/weapon/telecube/Destroy() + STOP_PROCESSING(SSobj, src) + if(mate) + var/turf/T = get_turf(mate) + mate.visible_message("\The [mate] collapses into itself!") + mate.mate = null + mate = null + explosion(T,1,3,7) + + ..() + +/obj/item/weapon/telecube/proc/pair_cube(var/obj/item/weapon/telecube/M) + if(mate) + return 0 + else + mate = M + update_icon() + return 1 + +/obj/item/weapon/telecube/proc/teleport_to_mate(var/atom/movable/A, var/areaporting = FALSE) + . = FALSE + + if(!A) + return . + + if(A == src || A == mate) + A.visible_message("\The [A] distorts and fades, before popping back into existence.") + return . + + var/mob/living/L = src.loc + + if(istype(L)) + L.drop_from_inventory(src) + forceMove(get_turf(src)) + + if(world.time < (last_teleport + cooldown_time)) + return . + + if((A.anchored && !omniteleport) || !mate) + A.visible_message("\The [A] distorts for a moment, before reforming in the same position.") + return . + + var/turf/TLocate = get_turf(mate) + + var/turf/T1 = get_turf(locate(TLocate.x + (A.x - x), TLocate.y + (A.y - y), TLocate.z)) + + if(T1) + A.visible_message("\The [A] fades out of existence.") + A.forceMove(T1) + . = TRUE + A.visible_message("\The [A] fades into existence.") + else + return . + + if(teleport_range && !areaporting) + for(var/atom/movable/M in orange(teleport_range, A)) + teleport_to_mate(M, TRUE) + +/obj/item/weapon/telecube/proc/swap_with_mate() + . = FALSE + + if(!mate || !teleport_range) + return . + + var/list/objects_near_me = range(teleport_range, get_turf(src)) + var/list/objects_near_mate = range(teleport_range, get_turf(mate)) + + for(var/atom/movable/M in objects_near_me) + teleport_to_mate(M, TRUE) + + for(var/atom/movable/M1 in objects_near_mate) + mate.teleport_to_mate(M1, TRUE) + + . = TRUE + return . + +/obj/item/weapon/telecube/CtrlClick(mob/user) + if(Adjacent(user)) + if(teleport_to_mate(user)) + last_teleport = world.time + return + +/obj/item/weapon/telecube/AltClick(mob/user) + if(Adjacent(user)) + if(swap_with_mate()) + last_teleport = world.time + mate.last_teleport = world.time + return + +/obj/item/weapon/telecube/Bump(atom/movable/AM) + if(teleport_to_mate(AM)) + last_teleport = world.time + . = ..() + +/obj/item/weapon/telecube/Bumped(atom/movable/M as mob|obj) + if(teleport_to_mate(M)) + last_teleport = world.time + . = ..() + +// Subtypes + +/obj/item/weapon/telecube/mated + start_paired = TRUE + +/obj/item/weapon/telecube/randomized + randomize_colors = TRUE + +/obj/item/weapon/telecube/randomized/mated + start_paired = TRUE + +/obj/item/weapon/telecube/precursor + glow_color = "#FF1D8E" + shell_color = "#2F1B26" + +/obj/item/weapon/telecube/precursor/mated + start_paired = TRUE + +/obj/item/weapon/telecube/precursor/mated/zone + teleport_range = 2 + +/obj/item/weapon/telecube/precursor/mated/mirrorcolor + mirror_colors = TRUE diff --git a/code/modules/blob/blob.dm b/code/modules/blob/blob.dm index c9ab387753a..877c684b5ea 100644 --- a/code/modules/blob/blob.dm +++ b/code/modules/blob/blob.dm @@ -40,7 +40,7 @@ else icon_state = "blob_damaged" -/obj/effect/blob/proc/take_damage(var/damage) +/obj/effect/blob/take_damage(var/damage) // VOREStation Edit health -= damage if(health < 0) playsound(loc, 'sound/effects/splat.ogg', 50, 1) diff --git a/code/modules/blob2/overmind/overmind.dm b/code/modules/blob2/overmind/overmind.dm index 6477c86f227..223cb41e605 100644 --- a/code/modules/blob2/overmind/overmind.dm +++ b/code/modules/blob2/overmind/overmind.dm @@ -9,7 +9,6 @@ var/list/overminds = list() mouse_opacity = 1 see_in_dark = 8 invisibility = INVISIBILITY_OBSERVER - layer = FLY_LAYER + 0.1 faction = "blob" var/obj/structure/blob/core/blob_core = null // The blob overmind's core diff --git a/code/modules/catalogue/cataloguer.dm b/code/modules/catalogue/cataloguer.dm index 60e86eadeee..f1c57564430 100644 --- a/code/modules/catalogue/cataloguer.dm +++ b/code/modules/catalogue/cataloguer.dm @@ -312,3 +312,15 @@ GLOBAL_LIST_EMPTY(all_cataloguers) interact(usr) // So it refreshes the window. return 1 +/obj/item/device/cataloguer/attackby(obj/item/weapon/W, mob/user) + if(istype(W, /obj/item/weapon/card/id) && !busy) + busy = TRUE + var/obj/item/weapon/card/id/ID = W + if(points_stored) + ID.survey_points += points_stored + points_stored = 0 + to_chat(user, "You swipe the id over \the [src].") + else + to_chat(user, "\The [src] has no points available.") + busy = FALSE + return ..() diff --git a/code/modules/catalogue/cataloguer_vr.dm b/code/modules/catalogue/cataloguer_vr.dm new file mode 100644 index 00000000000..d1dfac5deac --- /dev/null +++ b/code/modules/catalogue/cataloguer_vr.dm @@ -0,0 +1,56 @@ +/obj/item/device/cataloguer/compact + name = "compact cataloguer" + icon = 'icons/vore/custom_items_vr.dmi' + icon_state = "tricorder" + action_button_name = "Toggle Cataloguer" + var/deployed = TRUE + scan_range = 1 + toolspeed = 1.2 + +/obj/item/device/cataloguer/compact/update_icon() + if(busy) + icon_state = "[initial(icon_state)]_s" + else + icon_state = initial(icon_state) + +/obj/item/device/cataloguer/compact/ui_action_click() + toggle() + +/obj/item/device/cataloguer/compact/verb/toggle() + set name = "Toggle Cataloguer" + set category = "Object" + + if(busy) + to_chat(usr, span("warning", "\The [src] is currently scanning something.")) + return + deployed = !(deployed) + if(deployed) + w_class = ITEMSIZE_NORMAL + icon_state = "[initial(icon_state)]" + to_chat(usr, span("notice", "You flip open \the [src].")) + else + w_class = ITEMSIZE_SMALL + icon_state = "[initial(icon_state)]_closed" + to_chat(usr, span("notice", "You close \the [src].")) + + if (ismob(usr)) + var/mob/M = usr + M.update_action_buttons() + +/obj/item/device/cataloguer/compact/afterattack(atom/target, mob/user, proximity_flag) + if(!deployed) + to_chat(user, span("warning", "\The [src] is closed.")) + return + return ..() + +/obj/item/device/cataloguer/compact/pulse_scan(mob/user) + if(!deployed) + to_chat(user, span("warning", "\The [src] is closed.")) + return + return ..() + +/obj/item/device/cataloguer/compact/pathfinder + name = "pathfinder's cataloguer" + icon_state = "tricorder_med" + scan_range = 3 + toolspeed = 1 diff --git a/code/modules/catalogue/rewards/construction.dm b/code/modules/catalogue/rewards/construction.dm deleted file mode 100644 index 8bfca1f79d4..00000000000 --- a/code/modules/catalogue/rewards/construction.dm +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef T_BOARD -#error T_BOARD macro is not defined but we need it! -#endif - -/obj/item/weapon/circuitboard/exploration_equipment_vendor - name = T_BOARD("Exploration Equipment Vendor") - board_type = new /datum/frame/frame_types/machine - build_path = /obj/machinery/equipment_vendor/exploration - origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 2) - req_components = list( - /obj/item/weapon/stock_parts/console_screen = 1, - /obj/item/weapon/stock_parts/matter_bin = 3) diff --git a/code/modules/catalogue/rewards/equipment_vendor.dm b/code/modules/catalogue/rewards/equipment_vendor.dm deleted file mode 100644 index 655675dfe53..00000000000 --- a/code/modules/catalogue/rewards/equipment_vendor.dm +++ /dev/null @@ -1,164 +0,0 @@ -/**********************Exploration Equipment Vendor**************************/ - -/obj/machinery/equipment_vendor/exploration - name = "exploration equipment vendor" - desc = "An equipment vendor for explorers, points collected with cataloguers can be spent here." - icon = 'icons/obj/machines/mining_machines_vr.dmi' - icon_state = "exploration" - density = TRUE - anchored = TRUE - circuit = /obj/item/weapon/circuitboard/exploration_equipment_vendor - var/icon_deny = "exploration-deny" - var/icon_vend = "exploration-vend" - var/obj/item/device/cataloguer/inserted_cataloguer - var/list/prize_list = list( - new /datum/data/exploration_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 1), - new /datum/data/exploration_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 10), - new /datum/data/exploration_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 30), - new /datum/data/exploration_equipment("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 10), - new /datum/data/exploration_equipment("Absinthe", /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, 10), - new /datum/data/exploration_equipment("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 15), - new /datum/data/exploration_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 20), - new /datum/data/exploration_equipment("Laser Pointer", /obj/item/device/laser_pointer, 90), - new /datum/data/exploration_equipment("Plush Toy", /obj/random/plushie, 30), - new /datum/data/exploration_equipment("Shelter Capsule", /obj/item/device/survivalcapsule, 50), - new /datum/data/exploration_equipment("Point Transfer Card", /obj/item/weapon/card/exploration_point_card, 50), - new /datum/data/exploration_equipment("Survival Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/miner, 50), - new /datum/data/exploration_equipment("Mini-Translocator", /obj/item/device/perfect_tele/one_beacon, 120), - new /datum/data/exploration_equipment("Space Cash", /obj/item/weapon/spacecash/c100, 100), - new /datum/data/exploration_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 250), - new /datum/data/exploration_equipment("Luxury Shelter Capsule", /obj/item/device/survivalcapsule/luxury, 310) - ) - -/datum/data/exploration_equipment - var/equipment_name = "generic" - var/equipment_path = null - var/cost = 0 - -/datum/data/exploration_equipment/New(name, path, cost) - src.equipment_name = name - src.equipment_path = path - src.cost = cost - -/obj/machinery/equipment_vendor/exploration/power_change() - var/old_stat = stat - ..() - if(old_stat != stat) - update_icon() - if(inserted_cataloguer && !powered()) - visible_message("The cataloguer slot indicator light flickers on \the [src] as it spits out the device before powering down.") - inserted_cataloguer.forceMove(get_turf(src)) - -/obj/machinery/equipment_vendor/exploration/update_icon() - if(panel_open) - icon_state = "[initial(icon_state)]-open" - else if(powered()) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]-off" - -/obj/machinery/equipment_vendor/exploration/attack_hand(mob/user) - if(..()) - return - interact(user) - -/obj/machinery/equipment_vendor/exploration/attack_ghost(mob/user) - interact(user) - -/obj/machinery/equipment_vendor/exploration/interact(mob/user) - user.set_machine(src) - - var/dat - dat +="
      " - if(istype(inserted_cataloguer)) - dat += "You have [inserted_cataloguer.points_stored] exploration points collected. Eject Cataloguer.
      " - else - dat += "No Cataloguer inserted. Insert Cataloguer.
      " - dat += "
      " - dat += "
      Equipment point cost list:
      " - for(var/datum/data/exploration_equipment/prize in prize_list) - dat += "" - dat += "
      [prize.equipment_name][prize.cost]Purchase
      " - var/datum/browser/popup = new(user, "miningvendor", "Exploration Equipment Vendor", 400, 600) - popup.set_content(dat) - popup.open() - -/obj/machinery/equipment_vendor/exploration/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["choice"]) - if(istype(inserted_cataloguer)) - if(href_list["choice"] == "eject") - to_chat(usr, "You eject the ID from [src]'s card slot.") - usr.put_in_hands(inserted_cataloguer) - inserted_cataloguer = null - else if(href_list["choice"] == "insert") - var/obj/item/device/cataloguer/C = usr.get_active_hand() - if(istype(C) && !inserted_cataloguer && usr.unEquip(C)) - C.forceMove(src) - inserted_cataloguer = C - interact(usr) - to_chat(usr, "You insert the ID into [src]'s card slot.") - else - to_chat(usr, "No valid ID.") - flick(icon_deny, src) - - if(href_list["purchase"]) - if(istype(inserted_cataloguer)) - var/datum/data/exploration_equipment/prize = locate(href_list["purchase"]) - if (!prize || !(prize in prize_list)) - to_chat(usr, "Error: Invalid choice!") - flick(icon_deny, src) - return - if(prize.cost > inserted_cataloguer.points_stored) - to_chat(usr, "Error: Insufficent points for [prize.equipment_name]!") - flick(icon_deny, src) - else - inserted_cataloguer.points_stored -= prize.cost - to_chat(usr, "[src] clanks to life briefly before vending [prize.equipment_name]!") - flick(icon_vend, src) - new prize.equipment_path(drop_location()) - else - to_chat(usr, "Error: Please insert a valid ID!") - flick(icon_deny, src) - updateUsrDialog() - -/obj/machinery/equipment_vendor/exploration/attackby(obj/item/I, mob/user, params) - if(default_deconstruction_screwdriver(user, I)) - updateUsrDialog() - return - if(default_part_replacement(user, I)) - return - if(default_deconstruction_crowbar(user, I)) - return - if(istype(I,/obj/item/device/cataloguer)) - if(!powered()) - return - else if(!inserted_cataloguer && user.unEquip(I)) - I.forceMove(src) - inserted_cataloguer = I - interact(user) - return - ..() - -/obj/machinery/equipment_vendor/exploration/dismantle() - if(inserted_cataloguer) - inserted_cataloguer.forceMove(loc) //Prevents deconstructing the ORM from deleting whatever ID was inside it. - . = ..() - -/obj/machinery/equipment_vendor/exploration/proc/new_prize(var/name, var/path, var/cost) // Generic proc for adding new entries. Good for abusing for FUN and PROFIT. - if(!cost) - cost = 100 - if(!path) - path = /obj/item/stack/marker_beacon - if(!name) - name = "Generic Entry" - prize_list += new /datum/data/exploration_equipment(name, path, cost) - -/obj/machinery/equipment_vendor/exploration/ex_act(severity, target) - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(5, 1, src) - s.start() - if(prob(50 / severity) && severity < 3) - qdel(src) diff --git a/code/modules/catalogue/rewards/exp_point_items.dm b/code/modules/catalogue/rewards/exp_point_items.dm deleted file mode 100644 index 47e066763ba..00000000000 --- a/code/modules/catalogue/rewards/exp_point_items.dm +++ /dev/null @@ -1,23 +0,0 @@ -/obj/item/weapon/card/exploration_point_card - name = "exploration point card" - desc = "A small card preloaded with exploration points. Swipe your Cataloguer over it to transfer the points, then discard." - icon_state = "data" - var/points = 50 - -/obj/item/weapon/card/exploration_point_card/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/device/cataloguer)) - if(points) - var/obj/item/device/cataloguer/C = I - C.points_stored += points - to_chat(user, "You transfer [points] points to [C].") - points = 0 - else - to_chat(user, "There's no points left on [src].") - ..() - -/obj/item/weapon/card/exploration_point_card/examine(mob/user) - ..(user) - to_chat(user, "There's [points] points on the card.") - -/obj/item/weapon/card/exploration_point_card/can_catalogue(mob/user) - return FALSE \ No newline at end of file diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 6f35aff05f5..fe4b1a93996 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -390,7 +390,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O else return TOPIC_NOACTION - if(((!(setting_species.spawn_flags & SPECIES_CAN_JOIN)) || (!is_alien_whitelisted(preference_mob(),setting_species))) && !check_rights(R_ADMIN, 0)) + if(((!(setting_species.spawn_flags & SPECIES_CAN_JOIN)) || (!is_alien_whitelisted(preference_mob(),setting_species))) && !check_rights(R_ADMIN, 0) && !(setting_species.spawn_flags & SPECIES_WHITELIST_SELECTABLE)) //VOREStation Edit: selectability return TOPIC_NOACTION var/prev_species = pref.species @@ -818,7 +818,12 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O dat += "

      [current_species.name] \[change\]


      " dat += "" dat += "" - dat += "" + //vorestation edit begin + if(current_species.wikilink) + dat += "" + else + dat += "" + //vorestation edit end dat += "
      [current_species.blurb][current_species.blurb]

      See the wiki for more details.
      [current_species.blurb]" if("preview" in icon_states(current_species.icobase)) usr << browse_rsc(icon(current_species.icobase,"preview"), "species_preview_[current_species.name].png") @@ -873,7 +878,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O dat += "You cannot play as this species.
      If you wish to be whitelisted, you can make an application post on the forums.

      " else if(restricted == 2) dat += "You cannot play as this species.
      This species is not available for play as a station race..

      " - if(!restricted || check_rights(R_ADMIN, 0)) + if(!restricted || check_rights(R_ADMIN, 0) || current_species.spawn_flags & SPECIES_WHITELIST_SELECTABLE) //VOREStation Edit: selectability dat += "\[select\]" dat += "" diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories.dm b/code/modules/client/preference_setup/loadout/loadout_accessories.dm index 4c6066c2404..9f008afe085 100644 --- a/code/modules/client/preference_setup/loadout/loadout_accessories.dm +++ b/code/modules/client/preference_setup/loadout/loadout_accessories.dm @@ -34,7 +34,7 @@ display_name = "wallet, polychromic" path = /obj/item/weapon/storage/wallet/poly cost = 0 //VOREStation Edit - + /datum/gear/accessory/wallet/womens display_name = "wallet, womens" @@ -209,6 +209,8 @@ ..() var/list/sweaters = list() for(var/sweater in typesof(/obj/item/clothing/accessory/sweater)) + if(sweater in typesof(/obj/item/clothing/accessory/sweater/fluff)) //VOREStation addition + continue //VOREStation addition var/obj/item/clothing/suit/sweater_type = sweater sweaters[initial(sweater_type.name)] = sweater_type gear_tweaks += new/datum/gear_tweak/path(sortAssoc(sweaters)) diff --git a/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm b/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm index 0f186f5dfca..63b32a27079 100644 --- a/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_accessories_vr.dm @@ -40,11 +40,11 @@ allowed_roles = list("Colony Director", "Head of Personnel", "Security Officer", "Warden", "Head of Security","Detective","Explorer","Pathfinder") /datum/gear/accessory/brown_vest - display_name = "webbing, brown" + display_name = "webbing, brown (Eng, Sec, Med, Exploration, Miner)" allowed_roles = list("Station Engineer","Atmospheric Technician","Chief Engineer","Security Officer","Detective","Head of Security","Warden","Paramedic","Chief Medical Officer","Medical Doctor","Chemist","Field Medic","Pathfinder","Shaft Miner") /datum/gear/accessory/black_vest - display_name = "webbing, black" + display_name = "webbing, black (Eng, Sec, Med, Exploration, Miner)" allowed_roles = list("Station Engineer","Atmospheric Technician","Chief Engineer","Security Officer","Detective","Head of Security","Warden","Paramedic","Chief Medical Officer","Medical Doctor","Chemist","Field Medic","Pathfinder","Shaft Miner") /datum/gear/accessory/white_vest @@ -52,11 +52,11 @@ allowed_roles = list("Paramedic","Chief Medical Officer","Medical Doctor","Chemist","Field Medic") /datum/gear/accessory/brown_drop_pouches - display_name = "drop pouches, brown" + display_name = "drop pouches, brown (Eng, Sec, Med, Exploration, Miner)" allowed_roles = list("Station Engineer","Atmospheric Technician","Chief Engineer","Security Officer","Detective","Head of Security","Warden","Paramedic","Chief Medical Officer","Medical Doctor","Chemist","Field Medic","Pathfinder","Shaft Miner") /datum/gear/accessory/black_drop_pouches - display_name = "drop pouches, black" + display_name = "drop pouches, black (Eng, Sec, Med, Exploration, Miner)" allowed_roles = list("Station Engineer","Atmospheric Technician","Chief Engineer","Security Officer","Detective","Head of Security","Warden","Paramedic","Chief Medical Officer","Medical Doctor","Chemist","Field Medic","Pathfinder","Shaft Miner") /datum/gear/accessory/white_drop_pouches @@ -75,14 +75,20 @@ description = "A small necklace device that will notify an offsite cloning facility should you expire after activating it." /datum/gear/accessory/tronket - display_name = "metal necklace" - description = "A shiny steel chain with a vague metallic object dangling off it." - path = /obj/item/clothing/accessory/tronket + display_name = "metal necklace" + description = "A shiny steel chain with a vague metallic object dangling off it." + path = /obj/item/clothing/accessory/tronket + +/datum/gear/accessory/pilotpin + display_name = "pilot qualification pin" + description = "An iron pin denoting the qualification to fly SCG spacecraft." + path = /obj/item/clothing/accessory/solgov/specialty/pilot + allowed_roles = list("Pathfinder", "Pilot", "Field Medic") /datum/gear/accessory/flops - display_name = "drop straps" - description = "Wearing suspenders over shoulders? That's been so out for centuries and you know better." - path = /obj/item/clothing/accessory/flops + display_name = "drop straps" + description = "Wearing suspenders over shoulders? That's been so out for centuries and you know better." + path = /obj/item/clothing/accessory/flops /datum/gear/accessory/flops/New() ..() diff --git a/code/modules/client/preference_setup/loadout/loadout_smoking.dm b/code/modules/client/preference_setup/loadout/loadout_smoking.dm index cbedca3a675..96db8bf2fe0 100644 --- a/code/modules/client/preference_setup/loadout/loadout_smoking.dm +++ b/code/modules/client/preference_setup/loadout/loadout_smoking.dm @@ -27,6 +27,8 @@ ..() var/list/zippos = list() for(var/zippo in typesof(/obj/item/weapon/flame/lighter/zippo)) + if(zippo in typesof(/obj/item/weapon/flame/lighter/zippo/fluff)) //VOREStation addition + continue //VOREStation addition var/obj/item/weapon/flame/lighter/zippo/zippo_type = zippo zippos[initial(zippo_type.name)] = zippo_type gear_tweaks += new/datum/gear_tweak/path(sortAssoc(zippos)) diff --git a/code/modules/client/preference_setup/loadout/loadout_suit.dm b/code/modules/client/preference_setup/loadout/loadout_suit.dm index e2a661f5f35..1802d2c0096 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit.dm @@ -106,6 +106,8 @@ datum/gear/suit/duster ..() var/list/hazards = list() for(var/hazard_style in typesof(/obj/item/clothing/suit/storage/hazardvest)) + if(hazard_style in typesof(/obj/item/clothing/suit/storage/hazardvest/fluff)) //VOREStation addition + continue //VOREStation addition var/obj/item/clothing/suit/storage/hazardvest/hazardvest = hazard_style hazards[initial(hazardvest.name)] = hazardvest gear_tweaks += new/datum/gear_tweak/path(sortAssoc(hazards)) @@ -493,3 +495,11 @@ datum/gear/suit/duster display_name = "snowsuit, supply" path = /obj/item/clothing/suit/storage/snowsuit/cargo allowed_roles = list("Quartermaster","Shaft Miner","Cargo Technician","Head of Personnel") + +/datum/gear/suit/miscellaneous/cardigan + display_name = "cardigan" + path = /obj/item/clothing/suit/storage/toggle/cardigan + +/datum/gear/suit/miscellaneous/cardigan/New() + ..() + gear_tweaks = list(gear_tweak_free_color_choice) \ No newline at end of file diff --git a/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm b/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm index 719ba98a382..e7bb0493f32 100644 --- a/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm +++ b/code/modules/client/preference_setup/loadout/loadout_suit_vr.dm @@ -1,9 +1,3 @@ -/datum/gear/suit/roles/poncho/cloak/research - allowed_roles = list("Research Director","Scientist", "Roboticist", "Xenobiologist", "Explorer", "Pathfinder") - -/datum/gear/suit/roles/poncho/cloak/medical - allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist", "Field Medic") - /datum/gear/suit/wintercoat/medical allowed_roles = list("Medical Doctor","Chief Medical Officer","Chemist","Paramedic","Geneticist", "Psychiatrist", "Field Medic") diff --git a/code/modules/client/preference_setup/loadout/loadout_uniform.dm b/code/modules/client/preference_setup/loadout/loadout_uniform.dm index 868145b33f5..7de598fc83b 100644 --- a/code/modules/client/preference_setup/loadout/loadout_uniform.dm +++ b/code/modules/client/preference_setup/loadout/loadout_uniform.dm @@ -65,6 +65,8 @@ ..() var/list/skirts = list() for(var/skirt in (typesof(/obj/item/clothing/under/skirt))) + if(skirt in typesof(/obj/item/clothing/under/skirt/fluff)) //VOREStation addition + continue //VOREStation addition var/obj/item/clothing/under/skirt/skirt_type = skirt skirts[initial(skirt_type.name)] = skirt_type gear_tweaks += new/datum/gear_tweak/path(sortAssoc(skirts)) @@ -223,6 +225,8 @@ ..() var/list/msuits = list() for(var/msuit in typesof(/obj/item/clothing/under/suit_jacket)) + if(msuit in typesof(/obj/item/clothing/under/suit_jacket/female/fluff)) //VOREStation addition + continue //VOREStation addition var/obj/item/clothing/suit/msuit_type = msuit msuits[initial(msuit_type.name)] = msuit_type gear_tweaks += new/datum/gear_tweak/path(sortAssoc(msuits)) @@ -502,3 +506,14 @@ display_name = "plain ascetic garb" path = /obj/item/clothing/under/ascetic +/datum/gear/uniform/pleated + display_name = "pleated skirt" + path = /obj/item/clothing/under/skirt/pleated + +/datum/gear/uniform/pleated/New() + ..() + gear_tweaks = list(gear_tweak_free_color_choice) + +/datum/gear/uniform/lilacdress + display_name = "lilac dress" + path = /obj/item/clothing/under/dress/lilacdress diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm index 757f392335a..2a1e88cd359 100644 --- a/code/modules/client/preference_setup/loadout/loadout_utility.dm +++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm @@ -123,7 +123,7 @@ display_name = "implant, tracking" path = /obj/item/weapon/implant/tracking/weak cost = 0 //VOREStation Edit. Changed cost to 0 -/* VOREStation Edit - Make languages great again + /datum/gear/utility/implant/language cost = 2 exploitable = 0 @@ -137,7 +137,7 @@ display_name = "vocal synthesizer, Skrellian" description = "A surgically implanted vocal synthesizer which allows the owner to speak Common Skrellian, if they know it." path = /obj/item/weapon/implant/language/skrellian -*/ + /datum/gear/utility/pen display_name = "Fountain Pen" path = /obj/item/weapon/pen/fountain diff --git a/code/modules/client/preference_setup/vore/06_vantag.dm b/code/modules/client/preference_setup/vore/06_vantag.dm index 65bc66a4955..c65c379bf23 100644 --- a/code/modules/client/preference_setup/vore/06_vantag.dm +++ b/code/modules/client/preference_setup/vore/06_vantag.dm @@ -27,7 +27,7 @@ /datum/category_item/player_setup_item/vore/vantag/content(var/mob/user) . += "
      " - . += "Event Volunteer: [pref.vantag_volunteer ? "Yes" : "No"]
      " + . += "Event Volunteer: [pref.vantag_volunteer ? "Yes" : "No"]
      " . += "Event Pref: [vantag_choices_list[pref.vantag_preference]]
      " /datum/category_item/player_setup_item/vore/vantag/OnTopic(var/href, var/list/href_list, var/mob/user) diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm index fe87d35fbe5..06b748f3592 100644 --- a/code/modules/client/preference_setup/vore/07_traits.dm +++ b/code/modules/client/preference_setup/vore/07_traits.dm @@ -96,7 +96,7 @@ log_game("TRAITS [pref.client_ckey]/([character]) with: [english_traits]") //Terrible 'fake' key_name()... but they aren't in the same entity yet /datum/category_item/player_setup_item/vore/traits/content(var/mob/user) - . += "Custom Species " + . += "Custom Species Name: " . += "[pref.custom_species ? pref.custom_species : "-Input Name-"]
      " var/datum/species/selected_species = all_species[pref.species] diff --git a/code/modules/client/preference_setup/vore/09_misc.dm b/code/modules/client/preference_setup/vore/09_misc.dm index 09369d49017..2911c8a10d0 100644 --- a/code/modules/client/preference_setup/vore/09_misc.dm +++ b/code/modules/client/preference_setup/vore/09_misc.dm @@ -1,5 +1,4 @@ -/datum/preferences - var/show_in_directory = TRUE +//TFF 5/8/19 - moved /datum/preferences to preferences_vr.dm /datum/category_item/player_setup_item/vore/misc name = "Misc Settings" @@ -7,20 +6,35 @@ /datum/category_item/player_setup_item/vore/misc/load_character(var/savefile/S) S["show_in_directory"] >> pref.show_in_directory - + S["sensorpref"] >> pref.sensorpref //TFF 5/8/19 - add sensor pref setting to load after saved /datum/category_item/player_setup_item/vore/misc/save_character(var/savefile/S) S["show_in_directory"] << pref.show_in_directory + S["sensorpref"] << pref.sensorpref //TFF 5/8/19 - add sensor pref setting to be saveable + +//TFF 5/8/19 - add new datum category to allow for setting multiple settings when this is selected in the loadout. +/datum/category_item/player_setup_item/vore/misc/copy_to_mob(var/mob/living/carbon/human/character) + if(pref.sensorpref > 5 || pref.sensorpref < 1) + pref.sensorpref = 5 + character.sensorpref = pref.sensorpref /datum/category_item/player_setup_item/vore/misc/sanitize_character() pref.show_in_directory = sanitize_integer(pref.show_in_directory, 0, 1, initial(pref.show_in_directory)) + pref.sensorpref = sanitize_integer(pref.sensorpref, 1, sensorpreflist.len, initial(pref.sensorpref)) //TFF - 5/8/19 - add santisation for sensor prefs /datum/category_item/player_setup_item/vore/misc/content(var/mob/user) . += "
      " . += "Appear in Character Directory: [pref.show_in_directory ? "Yes" : "No"]
      " + . += "Suit Sensors Preference: [sensorpreflist[pref.sensorpref]]
      " //TFF 5/8/19 - Allow selection of sensor settings from off, binary, vitals, tracking, or random /datum/category_item/player_setup_item/vore/misc/OnTopic(var/href, var/list/href_list, var/mob/user) if(href_list["toggle_show_in_directory"]) pref.show_in_directory = pref.show_in_directory ? 0 : 1; return TOPIC_REFRESH + //TFF 5/8/19 - add new thing so you can choose the sensor setting your character can get. + else if(href_list["toggle_sensor_setting"]) + var/new_sensorpref = input(user, "Choose your character's sensor preferences:", "Character Preferences", sensorpreflist[pref.sensorpref]) as null|anything in sensorpreflist + if (!isnull(new_sensorpref) && CanUseTopic(user)) + pref.sensorpref = sensorpreflist.Find(new_sensorpref) + return TOPIC_REFRESH return ..(); diff --git a/code/modules/client/preferences_vr.dm b/code/modules/client/preferences_vr.dm index 23105324a52..61c2d83025a 100644 --- a/code/modules/client/preferences_vr.dm +++ b/code/modules/client/preferences_vr.dm @@ -1 +1,4 @@ -//File isn't currently being used. +//TFF 5/8/19 - minor refactoring of this thing from 09_misc.dm to call this for preferences. +datum/preferences + var/show_in_directory = 1 //TFF 5/8/19 - show in Character Directory + var/sensorpref = 5 //TFF 5/8/19 - set character's suit sensor level diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index b5aa5d7594d..4cc526df6ce 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -293,6 +293,17 @@ punch_force = initial(punch_force) wearer = null +/obj/item/clothing/gloves + var/datum/unarmed_attack/special_attack = null //do the gloves have a special unarmed attack? + var/special_attack_type = null + +/obj/item/clothing/gloves/New() + ..() + if(special_attack_type && ispath(special_attack_type)) + special_attack = new special_attack_type + + + ///////////////////////////////////////////////////////////////////// //Rings @@ -502,6 +513,7 @@ if(usr.put_in_hands(holding)) usr.visible_message("\The [usr] pulls a knife out of their boot!") holding = null + overlays -= image(icon, "[icon_state]_knife") else usr << "Your need an empty, unbroken hand to do that." holding.forceMove(src) @@ -546,7 +558,6 @@ update_icon() /obj/item/clothing/shoes/update_icon() - overlays.Cut() if(holding) overlays += image(icon, "[icon_state]_knife") if(ismob(usr)) diff --git a/code/modules/clothing/clothing_vr.dm b/code/modules/clothing/clothing_vr.dm index fc2d5c48c2a..b6e387c9bf9 100644 --- a/code/modules/clothing/clothing_vr.dm +++ b/code/modules/clothing/clothing_vr.dm @@ -126,9 +126,28 @@ return ..() // Taur suits need to be shifted so its centered on their taur half. -/obj/item/clothing/suit/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer = 0) +/obj/item/clothing/suit/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer = 0,var/icon/clip_mask) var/image/standing = ..() if(taurized) //Special snowflake var on suits standing.pixel_x = -16 standing.layer = BODY_LAYER + 15 // 15 is above tail layer, so will not be covered by taurbody. return standing + +//TFF 5/8/19 - sets Vorestation /obj/item/clothing/under sensor setting default? +/obj/item/clothing/under + sensor_mode = 3 + var/sensorpref = 5 + +//TFF 5/8/19 - define numbers and specifics for suit sensor settings +/obj/item/clothing/under/New(var/mob/living/carbon/human/H) + ..() + sensorpref = isnull(H) ? 1 : (ishuman(H) ? H.sensorpref : 1) + switch(sensorpref) + if(1) sensor_mode = 0 //Sensors off + if(2) sensor_mode = 1 //Sensors on binary + if(3) sensor_mode = 2 //Sensors display vitals + if(4) sensor_mode = 3 //Sensors display vitals and enables tracking + if(5) sensor_mode = pick(0,1,2,3) //Select a random setting + else + sensor_mode = pick(0,1,2,3) + log_debug("Invalid switch for suit sensors, defaulting to random. [sensorpref] chosen") \ No newline at end of file diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 820c5afdd47..e0167527f08 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -1,477 +1,494 @@ -/////////////////////////////////////////////////////////////////////// -//Glasses -/* -SEE_SELF // can see self, no matter what -SEE_MOBS // can see all mobs, no matter what -SEE_OBJS // can see all objs, no matter what -SEE_TURFS // can see all turfs (and areas), no matter what -SEE_PIXELS// if an object is located on an unlit area, but some of its pixels are - // in a lit area (via pixel_x,y or smooth movement), can see those pixels -BLIND // can't see anything -*/ -/////////////////////////////////////////////////////////////////////// - -/obj/item/clothing/glasses - name = "glasses" - icon = 'icons/obj/clothing/glasses.dmi' - w_class = ITEMSIZE_SMALL - slot_flags = SLOT_EYES - plane_slots = list(slot_glasses) - var/vision_flags = 0 - var/darkness_view = 0//Base human is 2 - var/see_invisible = -1 - var/prescription = 0 - var/toggleable = 0 - var/off_state = "degoggles" - var/active = 1 - var/activation_sound = 'sound/items/goggles_charge.ogg' - var/obj/screen/overlay = null - var/list/away_planes //Holder for disabled planes - - sprite_sheets = list( - "Teshari" = 'icons/mob/species/seromi/eyes.dmi', - "Vox" = 'icons/mob/species/vox/eyes.dmi' - ) - -/obj/item/clothing/glasses/update_clothing_icon() - if (ismob(src.loc)) - var/mob/M = src.loc - M.update_inv_glasses() - -/obj/item/clothing/glasses/attack_self(mob/user) - if(toggleable) - if(active) - active = 0 - icon_state = off_state - user.update_inv_glasses() - flash_protection = FLASH_PROTECTION_NONE - tint = TINT_NONE - away_planes = enables_planes - enables_planes = null - to_chat(usr, "You deactivate the optical matrix on the [src].") - else - active = 1 - icon_state = initial(icon_state) - user.update_inv_glasses() - flash_protection = initial(flash_protection) - tint = initial(tint) - enables_planes = away_planes - away_planes = null - to_chat(usr, "You activate the optical matrix on the [src].") - user.update_action_buttons() - user.recalculate_vis() - ..() - -/obj/item/clothing/glasses/meson - name = "optical meson scanner" - desc = "Used for seeing walls, floors, and stuff through anything." - icon_state = "meson" - item_state_slots = list(slot_r_hand_str = "meson", slot_l_hand_str = "meson") - action_button_name = "Toggle Goggles" - origin_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2) - toggleable = 1 - vision_flags = SEE_TURFS - enables_planes = list(VIS_FULLBRIGHT, VIS_MESONS) - -/obj/item/clothing/glasses/meson/New() - ..() - overlay = global_hud.meson - -/obj/item/clothing/glasses/meson/prescription - name = "prescription mesons" - desc = "Optical Meson Scanner with prescription lenses." - prescription = 1 - -/obj/item/clothing/glasses/meson/aviator - name = "engineering aviators" - icon_state = "aviator_eng" - off_state = "aviator" - item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") - action_button_name = "Toggle HUD" - activation_sound = 'sound/effects/pop.ogg' - -/obj/item/clothing/glasses/meson/aviator/prescription - name = "prescription engineering aviators" - desc = "Engineering Aviators with prescription lenses." - prescription = 1 - -/obj/item/clothing/glasses/hud/health/aviator - name = "medical HUD aviators" - desc = "Modified aviator glasses with a toggled health HUD." - icon_state = "aviator_med" - off_state = "aviator" - action_button_name = "Toggle Mode" - toggleable = 1 - activation_sound = 'sound/effects/pop.ogg' - -/obj/item/clothing/glasses/hud/health/aviator/prescription - name = "prescription medical HUD aviators" - desc = "Modified aviator glasses with a toggled health HUD. Comes with bonus prescription lenses." - prescription = 6 - -/obj/item/clothing/glasses/science - name = "Science Goggles" - desc = "The goggles do nothing!" - icon_state = "purple" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - toggleable = 1 - action_button_name = "Toggle Goggles" - item_flags = AIRTIGHT - -/obj/item/clothing/glasses/science/New() - ..() - overlay = global_hud.science - -/obj/item/clothing/glasses/goggles - name = "goggles" - desc = "Just some plain old goggles." - icon_state = "plaingoggles" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - item_flags = AIRTIGHT - body_parts_covered = EYES - -/obj/item/clothing/glasses/night - name = "night vision goggles" - desc = "You can totally see in the dark now!" - icon_state = "night" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - origin_tech = list(TECH_MAGNET = 2) - darkness_view = 7 - toggleable = 1 - action_button_name = "Toggle Goggles" - off_state = "denight" - flash_protection = FLASH_PROTECTION_REDUCED - enables_planes = list(VIS_FULLBRIGHT) - -/obj/item/clothing/glasses/night/vox - name = "Alien Optics" - species_restricted = list("Vox") - flags = PHORONGUARD - -/obj/item/clothing/glasses/night/New() - ..() - overlay = global_hud.nvg - -/obj/item/clothing/glasses/eyepatch - name = "eyepatch" - desc = "Yarr." - icon_state = "eyepatch" - item_state_slots = list(slot_r_hand_str = "blindfold", slot_l_hand_str = "blindfold") - body_parts_covered = 0 - var/eye = null - -/obj/item/clothing/glasses/eyepatch/verb/switcheye() - set name = "Switch Eyepatch" - set category = "Object" - set src in usr - if(!istype(usr, /mob/living)) return - if(usr.stat) return - - eye = !eye - if(eye) - icon_state = "[icon_state]_1" - else - icon_state = initial(icon_state) - update_clothing_icon() - -/obj/item/clothing/glasses/monocle - name = "monocle" - desc = "Such a dapper eyepiece!" - icon_state = "monocle" - item_state_slots = list(slot_r_hand_str = "headset", slot_l_hand_str = "headset") - body_parts_covered = 0 - -/obj/item/clothing/glasses/material - name = "optical material scanner" - desc = "Very confusing glasses." - icon_state = "material" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3) - toggleable = 1 - action_button_name = "Toggle Goggles" - vision_flags = SEE_OBJS - enables_planes = list(VIS_FULLBRIGHT) - -/obj/item/clothing/glasses/material/New() - ..() - overlay = global_hud.material - -/obj/item/clothing/glasses/material/prescription - name = "prescription optical material scanner" - prescription = 1 - -/obj/item/clothing/glasses/regular - name = "prescription glasses" - desc = "Made by Nerd. Co." - icon_state = "glasses" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - prescription = 1 - body_parts_covered = 0 - -/obj/item/clothing/glasses/regular/scanners - name = "scanning goggles" - desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it." - icon_state = "uzenwa_sissra_1" - -/obj/item/clothing/glasses/regular/hipster - name = "prescription glasses" - desc = "Made by Uncool. Co." - icon_state = "hipster_glasses" - -/obj/item/clothing/glasses/threedglasses - desc = "A long time ago, people used these glasses to makes images from screens threedimensional." - name = "3D glasses" - icon_state = "3d" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - body_parts_covered = 0 - -/obj/item/clothing/glasses/gglasses - name = "green glasses" - desc = "Forest green glasses, like the kind you'd wear when hatching a nasty scheme." - icon_state = "gglasses" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - body_parts_covered = 0 - -/obj/item/clothing/glasses/regular/rimless - name = "prescription rimless glasses" - desc = "Sleek modern glasses with a single sculpted lens." - icon_state = "glasses_rimless" - prescription = 1 - -/obj/item/clothing/glasses/rimless - name = "rimless glasses" - desc = "Sleek modern glasses with a single sculpted lens." - icon_state = "glasses_rimless" - prescription = 0 - -/obj/item/clothing/glasses/regular/thin - name = "prescription thin-rimmed glasses" - desc = "Glasses with frames are so last century." - icon_state = "glasses_thin" - prescription = 1 - -/obj/item/clothing/glasses/thin - name = "thin-rimmed glasses" - desc = "Glasses with frames are so last century." - icon_state = "glasses_thin" - prescription = 0 - - -/obj/item/clothing/glasses/sunglasses - name = "sunglasses" - desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." - icon_state = "sun" - item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") - darkness_view = -1 - flash_protection = FLASH_PROTECTION_MODERATE - -/obj/item/clothing/glasses/sunglasses/aviator - name = "aviators" - desc = "A pair of designer sunglasses." - icon_state = "aviator" - -/obj/item/clothing/glasses/welding - name = "welding goggles" - desc = "Protects the eyes from welders, approved by the mad scientist association." - icon_state = "welding-g" - item_state_slots = list(slot_r_hand_str = "welding-g", slot_l_hand_str = "welding-g") - action_button_name = "Flip Welding Goggles" - matter = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 1000) - item_flags = AIRTIGHT - var/up = 0 - flash_protection = FLASH_PROTECTION_MAJOR - tint = TINT_HEAVY - -/obj/item/clothing/glasses/welding/attack_self() - toggle() - -/obj/item/clothing/glasses/welding/verb/toggle() - set category = "Object" - set name = "Adjust welding goggles" - set src in usr - - if(usr.canmove && !usr.stat && !usr.restrained()) - if(src.up) - src.up = !src.up - flags_inv |= HIDEEYES - body_parts_covered |= EYES - icon_state = initial(icon_state) - flash_protection = initial(flash_protection) - tint = initial(tint) - to_chat(usr, "You flip \the [src] down to protect your eyes.") - else - src.up = !src.up - flags_inv &= ~HIDEEYES - body_parts_covered &= ~EYES - icon_state = "[initial(icon_state)]up" - flash_protection = FLASH_PROTECTION_NONE - tint = TINT_NONE - to_chat(usr, "You push \the [src] up out of your face.") - update_clothing_icon() - usr.update_action_buttons() - -/obj/item/clothing/glasses/welding/superior - name = "superior welding goggles" - desc = "Welding goggles made from more expensive materials, strangely smells like potatoes." - icon_state = "rwelding-g" - tint = TINT_MODERATE - -/obj/item/clothing/glasses/sunglasses/blindfold - name = "blindfold" - desc = "Covers the eyes, preventing sight." - icon_state = "blindfold" - item_state_slots = list(slot_r_hand_str = "blindfold", slot_l_hand_str = "blindfold") - flash_protection = FLASH_PROTECTION_MAJOR - tint = BLIND - -/obj/item/clothing/glasses/sunglasses/blindfold/tape - name = "length of tape" - desc = "It's a robust DIY blindfold!" - icon = 'icons/obj/bureaucracy.dmi' - icon_state = "tape_cross" - item_state_slots = list(slot_r_hand_str = null, slot_l_hand_str = null) - w_class = ITEMSIZE_TINY - -/obj/item/clothing/glasses/sunglasses/prescription - name = "prescription sunglasses" - prescription = 1 - -/obj/item/clothing/glasses/sunglasses/big - desc = "Strangely ancient technology used to help provide rudimentary eye cover. Larger than average enhanced shielding blocks many flashes." - icon_state = "bigsunglasses" - -/obj/item/clothing/glasses/fakesunglasses //Sunglasses without flash immunity - name = "stylish sunglasses" - desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes." - icon_state = "sun" - item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") - -/obj/item/clothing/glasses/fakesunglasses/aviator - name = "stylish aviators" - desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes." - icon_state = "aviator" - -/obj/item/clothing/glasses/sunglasses/sechud - name = "\improper HUD sunglasses" - desc = "Sunglasses with a HUD." - icon_state = "sunSecHud" - enables_planes = list(VIS_CH_ID,VIS_CH_WANTED,VIS_CH_IMPTRACK,VIS_CH_IMPLOYAL,VIS_CH_IMPCHEM) - -/obj/item/clothing/glasses/sunglasses/sechud/tactical - name = "tactical HUD" - desc = "Flash-resistant goggles with inbuilt combat and security information." - icon_state = "swatgoggles" - -/obj/item/clothing/glasses/sunglasses/sechud/aviator - name = "security HUD aviators" - desc = "Modified aviator glasses that can be switch between HUD and flash protection modes." - icon_state = "aviator_sec" - off_state = "aviator" - action_button_name = "Toggle Mode" - var/on = 1 - toggleable = 1 - activation_sound = 'sound/effects/pop.ogg' - -/obj/item/clothing/glasses/sunglasses/sechud/aviator/attack_self(mob/user) - if(toggleable && !user.incapacitated()) - on = !on - if(on) - flash_protection = FLASH_PROTECTION_NONE - enables_planes = away_planes - away_planes = null - to_chat(usr, "You switch the [src] to HUD mode.") - else - flash_protection = initial(flash_protection) - away_planes = enables_planes - enables_planes = null - to_chat(usr, "You switch \the [src] to flash protection mode.") - update_icon() - user << activation_sound - user.recalculate_vis() - user.update_inv_glasses() - user.update_action_buttons() - -/obj/item/clothing/glasses/sunglasses/sechud/aviator/update_icon() - if(on) - icon_state = initial(icon_state) - else - icon_state = off_state - -/obj/item/clothing/glasses/sunglasses/sechud/aviator/prescription - name = "prescription security HUD aviators" - desc = "Modified aviator glasses that can be switch between HUD and flash protection modes. Comes with bonus prescription lenses." - prescription = 6 - -/obj/item/clothing/glasses/sunglasses/medhud - name = "\improper HUD sunglasses" - desc = "Sunglasses with a HUD." - icon_state = "sunMedHud" - enables_planes = list(VIS_CH_STATUS,VIS_CH_HEALTH) - -/obj/item/clothing/glasses/thermal - name = "optical thermal scanner" - desc = "Thermals in the shape of glasses." - icon_state = "thermal" - item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") - origin_tech = list(TECH_MAGNET = 3) - toggleable = 1 - action_button_name = "Toggle Goggles" - vision_flags = SEE_MOBS - enables_planes = list(VIS_FULLBRIGHT) - flash_protection = FLASH_PROTECTION_REDUCED - - emp_act(severity) - if(istype(src.loc, /mob/living/carbon/human)) - var/mob/living/carbon/human/M = src.loc - M << "The Optical Thermal Scanner overloads and blinds you!" - if(M.glasses == src) - M.Blind(3) - M.eye_blurry = 5 - // Don't cure being nearsighted - if(!(M.disabilities & NEARSIGHTED)) - M.disabilities |= NEARSIGHTED - spawn(100) - M.disabilities &= ~NEARSIGHTED - ..() - -/obj/item/clothing/glasses/thermal/New() - ..() - overlay = global_hud.thermal - -/obj/item/clothing/glasses/thermal/syndi //These are now a traitor item, concealed as mesons. -Pete - name = "optical meson scanner" - desc = "Used for seeing walls, floors, and stuff through anything." - icon_state = "meson" - item_state_slots = list(slot_r_hand_str = "meson", slot_l_hand_str = "meson") - origin_tech = list(TECH_MAGNET = 3, TECH_ILLEGAL = 4) - -/obj/item/clothing/glasses/thermal/plain - toggleable = 0 - activation_sound = null - action_button_name = null - -/obj/item/clothing/glasses/thermal/plain/monocle - name = "thermonocle" - desc = "A monocle thermal." - icon_state = "thermoncle" - item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") - toggleable = 1 - action_button_name = "Toggle Monocle" - flags = null //doesn't protect eyes because it's a monocle, duh - - body_parts_covered = 0 - -/obj/item/clothing/glasses/thermal/plain/eyepatch - name = "optical thermal eyepatch" - desc = "An eyepatch with built-in thermal optics" - icon_state = "eyepatch" - item_state_slots = list(slot_r_hand_str = "blindfold", slot_l_hand_str = "blindfold") - body_parts_covered = 0 - toggleable = 1 - action_button_name = "Toggle Eyepatch" - -/obj/item/clothing/glasses/thermal/plain/jensen - name = "optical thermal implants" - desc = "A set of implantable lenses designed to augment your vision" - icon_state = "thermalimplants" - item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") +/////////////////////////////////////////////////////////////////////// +//Glasses +/* +SEE_SELF // can see self, no matter what +SEE_MOBS // can see all mobs, no matter what +SEE_OBJS // can see all objs, no matter what +SEE_TURFS // can see all turfs (and areas), no matter what +SEE_PIXELS// if an object is located on an unlit area, but some of its pixels are + // in a lit area (via pixel_x,y or smooth movement), can see those pixels +BLIND // can't see anything +*/ +/////////////////////////////////////////////////////////////////////// + +/obj/item/clothing/glasses + name = "glasses" + icon = 'icons/obj/clothing/glasses.dmi' + w_class = ITEMSIZE_SMALL + slot_flags = SLOT_EYES + plane_slots = list(slot_glasses) + var/vision_flags = 0 + var/darkness_view = 0//Base human is 2 + var/see_invisible = -1 + var/prescription = 0 + var/toggleable = 0 + var/off_state = "degoggles" + var/active = 1 + var/activation_sound = 'sound/items/goggles_charge.ogg' + var/obj/screen/overlay = null + var/list/away_planes //Holder for disabled planes + + sprite_sheets = list( + "Teshari" = 'icons/mob/species/seromi/eyes.dmi', + "Vox" = 'icons/mob/species/vox/eyes.dmi' + ) + +/obj/item/clothing/glasses/update_clothing_icon() + if (ismob(src.loc)) + var/mob/M = src.loc + M.update_inv_glasses() + +/obj/item/clothing/glasses/attack_self(mob/user) + if(toggleable) + if(active) + active = 0 + icon_state = off_state + user.update_inv_glasses() + flash_protection = FLASH_PROTECTION_NONE + tint = TINT_NONE + away_planes = enables_planes + enables_planes = null + to_chat(usr, "You deactivate the optical matrix on the [src].") + else + active = 1 + icon_state = initial(icon_state) + user.update_inv_glasses() + flash_protection = initial(flash_protection) + tint = initial(tint) + enables_planes = away_planes + away_planes = null + to_chat(usr, "You activate the optical matrix on the [src].") + user.update_action_buttons() + user.recalculate_vis() + ..() + +/obj/item/clothing/glasses/meson + name = "optical meson scanner" + desc = "Used for seeing walls, floors, and stuff through anything." + icon_state = "meson" + item_state_slots = list(slot_r_hand_str = "meson", slot_l_hand_str = "meson") + action_button_name = "Toggle Goggles" + origin_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2) + toggleable = 1 + vision_flags = SEE_TURFS + enables_planes = list(VIS_FULLBRIGHT, VIS_MESONS) + +/obj/item/clothing/glasses/meson/New() + ..() + overlay = global_hud.meson + +/obj/item/clothing/glasses/meson/prescription + name = "prescription mesons" + desc = "Optical Meson Scanner with prescription lenses." + prescription = 1 + +/obj/item/clothing/glasses/meson/aviator + name = "engineering aviators" + icon_state = "aviator_eng" + off_state = "aviator" + item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") + action_button_name = "Toggle HUD" + activation_sound = 'sound/effects/pop.ogg' + +/obj/item/clothing/glasses/meson/aviator/prescription + name = "prescription engineering aviators" + desc = "Engineering Aviators with prescription lenses." + prescription = 1 + +/obj/item/clothing/glasses/hud/health/aviator + name = "medical HUD aviators" + desc = "Modified aviator glasses with a toggled health HUD." + icon_state = "aviator_med" + off_state = "aviator" + action_button_name = "Toggle Mode" + toggleable = 1 + activation_sound = 'sound/effects/pop.ogg' + +/obj/item/clothing/glasses/hud/health/aviator/prescription + name = "prescription medical HUD aviators" + desc = "Modified aviator glasses with a toggled health HUD. Comes with bonus prescription lenses." + prescription = 6 + +/obj/item/clothing/glasses/science + name = "Science Goggles" + desc = "The goggles do nothing!" + icon_state = "purple" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + toggleable = 1 + action_button_name = "Toggle Goggles" + item_flags = AIRTIGHT + +/obj/item/clothing/glasses/science/New() + ..() + overlay = global_hud.science + +/obj/item/clothing/glasses/goggles + name = "goggles" + desc = "Just some plain old goggles." + icon_state = "plaingoggles" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + item_flags = AIRTIGHT + body_parts_covered = EYES + +/obj/item/clothing/glasses/night + name = "night vision goggles" + desc = "You can totally see in the dark now!" + icon_state = "night" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + origin_tech = list(TECH_MAGNET = 2) + darkness_view = 7 + toggleable = 1 + action_button_name = "Toggle Goggles" + off_state = "denight" + flash_protection = FLASH_PROTECTION_REDUCED + enables_planes = list(VIS_FULLBRIGHT) + +/obj/item/clothing/glasses/night/vox + name = "Alien Optics" + species_restricted = list("Vox") + flags = PHORONGUARD + +/obj/item/clothing/glasses/night/New() + ..() + overlay = global_hud.nvg + +/obj/item/clothing/glasses/eyepatch + name = "eyepatch" + desc = "Yarr." + icon_state = "eyepatch" + item_state_slots = list(slot_r_hand_str = "blindfold", slot_l_hand_str = "blindfold") + body_parts_covered = 0 + var/eye = null + +/obj/item/clothing/glasses/eyepatch/verb/switcheye() + set name = "Switch Eyepatch" + set category = "Object" + set src in usr + if(!istype(usr, /mob/living)) return + if(usr.stat) return + + eye = !eye + if(eye) + icon_state = "[icon_state]_1" + else + icon_state = initial(icon_state) + update_clothing_icon() + +/obj/item/clothing/glasses/monocle + name = "monocle" + desc = "Such a dapper eyepiece!" + icon_state = "monocle" + item_state_slots = list(slot_r_hand_str = "headset", slot_l_hand_str = "headset") + body_parts_covered = 0 + +/obj/item/clothing/glasses/material + name = "optical material scanner" + desc = "Very confusing glasses." + icon_state = "material" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + origin_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3) + toggleable = 1 + action_button_name = "Toggle Goggles" + vision_flags = SEE_OBJS + enables_planes = list(VIS_FULLBRIGHT) + +/obj/item/clothing/glasses/material/New() + ..() + overlay = global_hud.material + +/obj/item/clothing/glasses/material/prescription + name = "prescription optical material scanner" + prescription = 1 + +/obj/item/clothing/glasses/graviton + name = "graviton goggles" + desc = "The secrets of space travel are.. not quite yours." + icon_state = "grav" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + origin_tech = list(TECH_MAGNET = 2, TECH_BLUESPACE = 1) + darkness_view = 5 + toggleable = 1 + action_button_name = "Toggle Goggles" + off_state = "denight" + vision_flags = SEE_OBJS | SEE_TURFS + flash_protection = FLASH_PROTECTION_REDUCED + enables_planes = list(VIS_FULLBRIGHT, VIS_MESONS) + +/obj/item/clothing/glasses/graviton/New() + ..() + overlay = global_hud.material + +/obj/item/clothing/glasses/regular + name = "prescription glasses" + desc = "Made by Nerd. Co." + icon_state = "glasses" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + prescription = 1 + body_parts_covered = 0 + +/obj/item/clothing/glasses/regular/scanners + name = "scanning goggles" + desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it." + icon_state = "uzenwa_sissra_1" + +/obj/item/clothing/glasses/regular/hipster + name = "prescription glasses" + desc = "Made by Uncool. Co." + icon_state = "hipster_glasses" + +/obj/item/clothing/glasses/threedglasses + desc = "A long time ago, people used these glasses to makes images from screens threedimensional." + name = "3D glasses" + icon_state = "3d" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + body_parts_covered = 0 + +/obj/item/clothing/glasses/gglasses + name = "green glasses" + desc = "Forest green glasses, like the kind you'd wear when hatching a nasty scheme." + icon_state = "gglasses" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + body_parts_covered = 0 + +/obj/item/clothing/glasses/regular/rimless + name = "prescription rimless glasses" + desc = "Sleek modern glasses with a single sculpted lens." + icon_state = "glasses_rimless" + +/obj/item/clothing/glasses/rimless + name = "rimless glasses" + desc = "Sleek modern glasses with a single sculpted lens." + icon_state = "glasses_rimless" + prescription = 0 + +/obj/item/clothing/glasses/regular/thin + name = "prescription thin-rimmed glasses" + desc = "Glasses with frames are so last century." + icon_state = "glasses_thin" + prescription = 1 + +/obj/item/clothing/glasses/thin + name = "thin-rimmed glasses" + desc = "Glasses with frames are so last century." + icon_state = "glasses_thin" + prescription = 0 + + +/obj/item/clothing/glasses/sunglasses + name = "sunglasses" + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes." + icon_state = "sun" + item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") + darkness_view = -1 + flash_protection = FLASH_PROTECTION_MODERATE + +/obj/item/clothing/glasses/sunglasses/aviator + name = "aviators" + desc = "A pair of designer sunglasses." + icon_state = "aviator" + +/obj/item/clothing/glasses/welding + name = "welding goggles" + desc = "Protects the eyes from welders, approved by the mad scientist association." + icon_state = "welding-g" + item_state_slots = list(slot_r_hand_str = "welding-g", slot_l_hand_str = "welding-g") + action_button_name = "Flip Welding Goggles" + matter = list(DEFAULT_WALL_MATERIAL = 1500, "glass" = 1000) + item_flags = AIRTIGHT + var/up = 0 + flash_protection = FLASH_PROTECTION_MAJOR + tint = TINT_HEAVY + +/obj/item/clothing/glasses/welding/attack_self() + toggle() + +/obj/item/clothing/glasses/welding/verb/toggle() + set category = "Object" + set name = "Adjust welding goggles" + set src in usr + + if(usr.canmove && !usr.stat && !usr.restrained()) + if(src.up) + src.up = !src.up + flags_inv |= HIDEEYES + body_parts_covered |= EYES + icon_state = initial(icon_state) + flash_protection = initial(flash_protection) + tint = initial(tint) + to_chat(usr, "You flip \the [src] down to protect your eyes.") + else + src.up = !src.up + flags_inv &= ~HIDEEYES + body_parts_covered &= ~EYES + icon_state = "[initial(icon_state)]up" + flash_protection = FLASH_PROTECTION_NONE + tint = TINT_NONE + to_chat(usr, "You push \the [src] up out of your face.") + update_clothing_icon() + usr.update_action_buttons() + +/obj/item/clothing/glasses/welding/superior + name = "superior welding goggles" + desc = "Welding goggles made from more expensive materials, strangely smells like potatoes." + icon_state = "rwelding-g" + tint = TINT_MODERATE + +/obj/item/clothing/glasses/sunglasses/blindfold + name = "blindfold" + desc = "Covers the eyes, preventing sight." + icon_state = "blindfold" + item_state_slots = list(slot_r_hand_str = "blindfold", slot_l_hand_str = "blindfold") + flash_protection = FLASH_PROTECTION_MAJOR + tint = BLIND + +/obj/item/clothing/glasses/sunglasses/blindfold/tape + name = "length of tape" + desc = "It's a robust DIY blindfold!" + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "tape_cross" + item_state_slots = list(slot_r_hand_str = null, slot_l_hand_str = null) + w_class = ITEMSIZE_TINY + +/obj/item/clothing/glasses/sunglasses/prescription + name = "prescription sunglasses" + prescription = 1 + +/obj/item/clothing/glasses/sunglasses/big + desc = "Strangely ancient technology used to help provide rudimentary eye cover. Larger than average enhanced shielding blocks many flashes." + icon_state = "bigsunglasses" + +/obj/item/clothing/glasses/fakesunglasses //Sunglasses without flash immunity + name = "stylish sunglasses" + desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes." + icon_state = "sun" + item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") + +/obj/item/clothing/glasses/fakesunglasses/aviator + name = "stylish aviators" + desc = "A pair of designer sunglasses. Doesn't seem like it'll block flashes." + icon_state = "aviator" + +/obj/item/clothing/glasses/sunglasses/sechud + name = "\improper HUD sunglasses" + desc = "Sunglasses with a HUD." + icon_state = "sunSecHud" + enables_planes = list(VIS_CH_ID,VIS_CH_WANTED,VIS_CH_IMPTRACK,VIS_CH_IMPLOYAL,VIS_CH_IMPCHEM) + +/obj/item/clothing/glasses/sunglasses/sechud/tactical + name = "tactical HUD" + desc = "Flash-resistant goggles with inbuilt combat and security information." + icon_state = "swatgoggles" + +/obj/item/clothing/glasses/sunglasses/sechud/aviator + name = "security HUD aviators" + desc = "Modified aviator glasses that can be switch between HUD and flash protection modes." + icon_state = "aviator_sec" + off_state = "aviator" + action_button_name = "Toggle Mode" + var/on = 1 + toggleable = 1 + activation_sound = 'sound/effects/pop.ogg' + +/obj/item/clothing/glasses/sunglasses/sechud/aviator/attack_self(mob/user) + if(toggleable && !user.incapacitated()) + on = !on + if(on) + flash_protection = FLASH_PROTECTION_NONE + enables_planes = away_planes + away_planes = null + to_chat(usr, "You switch the [src] to HUD mode.") + else + flash_protection = initial(flash_protection) + away_planes = enables_planes + enables_planes = null + to_chat(usr, "You switch \the [src] to flash protection mode.") + update_icon() + user << activation_sound + user.recalculate_vis() + user.update_inv_glasses() + user.update_action_buttons() + +/obj/item/clothing/glasses/sunglasses/sechud/aviator/update_icon() + if(on) + icon_state = initial(icon_state) + else + icon_state = off_state + +/obj/item/clothing/glasses/sunglasses/sechud/aviator/prescription + name = "prescription security HUD aviators" + desc = "Modified aviator glasses that can be switch between HUD and flash protection modes. Comes with bonus prescription lenses." + prescription = 6 + +/obj/item/clothing/glasses/sunglasses/medhud + name = "\improper HUD sunglasses" + desc = "Sunglasses with a HUD." + icon_state = "sunMedHud" + enables_planes = list(VIS_CH_STATUS,VIS_CH_HEALTH) + +/obj/item/clothing/glasses/thermal + name = "optical thermal scanner" + desc = "Thermals in the shape of glasses." + icon_state = "thermal" + item_state_slots = list(slot_r_hand_str = "glasses", slot_l_hand_str = "glasses") + origin_tech = list(TECH_MAGNET = 3) + toggleable = 1 + action_button_name = "Toggle Goggles" + vision_flags = SEE_MOBS + enables_planes = list(VIS_FULLBRIGHT) + flash_protection = FLASH_PROTECTION_REDUCED + + emp_act(severity) + if(istype(src.loc, /mob/living/carbon/human)) + var/mob/living/carbon/human/M = src.loc + M << "The Optical Thermal Scanner overloads and blinds you!" + if(M.glasses == src) + M.Blind(3) + M.eye_blurry = 5 + // Don't cure being nearsighted + if(!(M.disabilities & NEARSIGHTED)) + M.disabilities |= NEARSIGHTED + spawn(100) + M.disabilities &= ~NEARSIGHTED + ..() + +/obj/item/clothing/glasses/thermal/New() + ..() + overlay = global_hud.thermal + +/obj/item/clothing/glasses/thermal/syndi //These are now a traitor item, concealed as mesons. -Pete + name = "optical meson scanner" + desc = "Used for seeing walls, floors, and stuff through anything." + icon_state = "meson" + item_state_slots = list(slot_r_hand_str = "meson", slot_l_hand_str = "meson") + origin_tech = list(TECH_MAGNET = 3, TECH_ILLEGAL = 4) + +/obj/item/clothing/glasses/thermal/plain + toggleable = 0 + activation_sound = null + action_button_name = null + +/obj/item/clothing/glasses/thermal/plain/monocle + name = "thermonocle" + desc = "A monocle thermal." + icon_state = "thermoncle" + item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") + toggleable = 1 + action_button_name = "Toggle Monocle" + flags = null //doesn't protect eyes because it's a monocle, duh + + body_parts_covered = 0 + +/obj/item/clothing/glasses/thermal/plain/eyepatch + name = "optical thermal eyepatch" + desc = "An eyepatch with built-in thermal optics" + icon_state = "eyepatch" + item_state_slots = list(slot_r_hand_str = "blindfold", slot_l_hand_str = "blindfold") + body_parts_covered = 0 + toggleable = 1 + action_button_name = "Toggle Eyepatch" + +/obj/item/clothing/glasses/thermal/plain/jensen + name = "optical thermal implants" + desc = "A set of implantable lenses designed to augment your vision" + icon_state = "thermalimplants" + item_state_slots = list(slot_r_hand_str = "sunglasses", slot_l_hand_str = "sunglasses") diff --git a/code/modules/clothing/gloves/arm_guards.dm b/code/modules/clothing/gloves/arm_guards.dm index d258cb5b637..21e7a99b353 100644 --- a/code/modules/clothing/gloves/arm_guards.dm +++ b/code/modules/clothing/gloves/arm_guards.dm @@ -44,4 +44,14 @@ icon_state = "arm_guards_combat" item_state_slots = list(slot_r_hand_str = "swat", slot_l_hand_str = "swat") siemens_coefficient = 0.6 - armor = list(melee = 50, bullet = 50, laser = 50, energy = 30, bomb = 30, bio = 0, rad = 0) \ No newline at end of file + armor = list(melee = 50, bullet = 50, laser = 50, energy = 30, bomb = 30, bio = 0, rad = 0) + +/obj/item/clothing/gloves/arm_guard/flexitac + name = "tactical arm guards" + desc = "These arm guards will protect your hands and arms from a variety of weapons while still allowing mobility." + icon_state = "arm_guards_flexitac" + item_state_slots = list(slot_r_hand_str = "swat", slot_l_hand_str = "swat") + siemens_coefficient = 0.6 + armor = list(melee = 40, bullet = 40, laser = 60, energy = 35, bomb = 30, bio = 0, rad = 0) + min_cold_protection_temperature = T0C - 20 + cold_protection = ARMS \ No newline at end of file diff --git a/code/modules/clothing/gloves/gauntlets.dm b/code/modules/clothing/gloves/gauntlets.dm index b65884d3f9c..8807fb93ad5 100644 --- a/code/modules/clothing/gloves/gauntlets.dm +++ b/code/modules/clothing/gloves/gauntlets.dm @@ -18,6 +18,10 @@ var/mob/living/carbon/human/H = user if(H.gloves) gloves = H.gloves + if(!istype(gloves)) + to_chat(user, "You are unable to wear \the [src] as \the [H.gloves] are in the way.") + gloves = null + return 0 if(gloves.overgloves) to_chat(user, "You are unable to wear \the [src] as \the [H.gloves] are in the way.") gloves = null diff --git a/code/modules/clothing/head/flowercrowns.dm b/code/modules/clothing/head/flowercrowns.dm index 6c6469de734..7e13993bcb1 100644 --- a/code/modules/clothing/head/flowercrowns.dm +++ b/code/modules/clothing/head/flowercrowns.dm @@ -7,33 +7,27 @@ /obj/item/clothing/head/woodcirclet/attackby(obj/item/W as obj, mob/user as mob) var/obj/item/complete - if(istype(W,/obj/item/seeds/poppyseed)) - user << "You attach the poppy to the circlet and create a beautiful flower crown." - complete = new /obj/item/clothing/head/poppy_crown(get_turf(user)) - user.drop_from_inventory(W) - user.drop_from_inventory(src) - qdel(W) - qdel(src) - user.put_in_hands(complete) - return - else if(istype(W,/obj/item/seeds/sunflowerseed)) - user << "You attach the sunflower to the circlet and create a beautiful flower crown." - complete = new /obj/item/clothing/head/sunflower_crown(get_turf(user)) - user.drop_from_inventory(W) - user.drop_from_inventory(src) - qdel(W) - qdel(src) - user.put_in_hands(complete) - return - else if(istype(W,/obj/item/seeds/lavenderseed)) - user << "You attach the lavender to the circlet and create a beautiful flower crown." - complete = new /obj/item/clothing/head/lavender_crown(get_turf(user)) + if(istype(W, /obj/item/weapon/reagent_containers/food/snacks/grown)) + var/obj/item/weapon/reagent_containers/food/snacks/grown/G = W + if(G.seed.kitchen_tag == "poppy") + to_chat(user, "You attach the poppy to the circlet and create a beautiful flower crown.") + complete = new /obj/item/clothing/head/poppy_crown(get_turf(user)) + else if(G.seed.kitchen_tag == "sunflower") + to_chat(user, "You attach the sunflower to the circlet and create a beautiful flower crown.") + complete = new /obj/item/clothing/head/sunflower_crown(get_turf(user)) + else if(G.seed.kitchen_tag == "lavender") + to_chat(user, "You attach the lavender to the circlet and create a beautiful flower crown.") + complete = new /obj/item/clothing/head/lavender_crown(get_turf(user)) + else if(G.seed.kitchen_tag == "rose") + to_chat(user, "You attach the rose to the circlet and create a beautiful flower crown.") + complete = new /obj/item/clothing/head/rose_crown(get_turf(user)) user.drop_from_inventory(W) user.drop_from_inventory(src) qdel(W) qdel(src) user.put_in_hands(complete) return + return ..() //Flower crowns @@ -53,4 +47,10 @@ name = "poppy crown" desc = "A flower crown weaved with poppies." icon_state = "poppy_crown" - body_parts_covered = 0 \ No newline at end of file + body_parts_covered = 0 + +/obj/item/clothing/head/rose_crown + name = "rose crown" + desc = "A flower crown weaved with roses." + icon_state = "poppy_crown" + body_parts_covered = 0 diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 70c19a1260c..f246a8563cb 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -103,6 +103,18 @@ siemens_coefficient = 0.6 valid_accessory_slots = null +/obj/item/clothing/head/helmet/flexitac + name = "tactical light helmet" + desc = "A tan helmet made from advanced ceramic with an integrated tactical flashlight." + icon_state = "flexitac" + armor = list(40, bullet = 40, laser = 60, energy = 35, bomb = 30, bio = 0, rad = 0) + siemens_coefficient = 0.6 + brightness_on = 6 + light_overlay = "helmet_light_dual_green" + action_button_name = "Toggle Head-light" + min_cold_protection_temperature = T0C - 20 + cold_protection = HEAD + /obj/item/clothing/head/helmet/swat name = "\improper SWAT helmet" desc = "They're often used by highly trained SWAT Officers." diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index b706e71e9dc..a9232aa65ce 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -219,7 +219,7 @@ /obj/item/clothing/head/psy_crown name = "broken crown" desc = "A crown-of-thorns with a missing gem." - var/tension_threshold = 150 + var/tension_threshold = 125 var/cooldown = null // world.time of when this was last triggered. var/cooldown_duration = 3 MINUTES // How long the cooldown should be. var/flavor_equip = null // Message displayed to someone who puts this on their head. Drones don't get a message. @@ -273,3 +273,17 @@ /obj/item/clothing/head/psy_crown/wrath/activate_ability(var/mob/living/wearer) ..() wearer.add_modifier(/datum/modifier/berserk, 30 SECONDS) + +/obj/item/clothing/head/psy_crown/gluttony + name = "green crown" + desc = "A crown-of-thorns set with a green gemstone that seems to glow unnaturally. It feels rather disturbing to touch." + description_info = "This has a chance to cause the wearer to become extremely durable, but hungry when in extreme danger." + icon_state = "gluttonycrown" + flavor_equip = "You feel a bit hungrier after putting on this crown." + flavor_unequip = "You feel sated after removing the crown." + flavor_drop = "You feel much more sated after letting go of the crown." + flavor_activate = "An otherworldly feeling seems to enter your mind, and it drives your mind into gluttony!" + +/obj/item/clothing/head/psy_crown/gluttony/activate_ability(var/mob/living/wearer) + ..() + wearer.add_modifier(/datum/modifier/gluttonyregeneration, 45 SECONDS) diff --git a/code/modules/clothing/shoes/leg_guards.dm b/code/modules/clothing/shoes/leg_guards.dm index da381165374..fba1c2cd3f4 100644 --- a/code/modules/clothing/shoes/leg_guards.dm +++ b/code/modules/clothing/shoes/leg_guards.dm @@ -6,6 +6,7 @@ species_restricted = null //Unathi and Taj can wear leg armor now w_class = ITEMSIZE_NORMAL step_volume_mod = 1.3 + can_hold_knife = TRUE /obj/item/clothing/shoes/leg_guard/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0) if(..()) //This will only run if no other problems occured when equiping. @@ -46,3 +47,14 @@ item_state_slots = list(slot_r_hand_str = "jackboots", slot_l_hand_str = "jackboots") siemens_coefficient = 0.6 armor = list(melee = 50, bullet = 50, laser = 50, energy = 30, bomb = 30, bio = 0, rad = 0) + +/obj/item/clothing/shoes/leg_guard/flexitac + name = "tactical leg guards" + desc = "These will protect your legs and feet from a variety of weapons while still allowing mobility." + icon_state = "leg_guards_flexitac" + item_state_slots = list(slot_r_hand_str = "jackboots", slot_l_hand_str = "jackboots") + siemens_coefficient = 0.6 + slowdown = SHOES_SLOWDOWN+0.2 + armor = list(melee = 40, bullet = 40, laser = 60, energy = 35, bomb = 30, bio = 0, rad = 0) + min_cold_protection_temperature = T0C - 20 + cold_protection = LEGS \ No newline at end of file diff --git a/code/modules/clothing/shoes/magboots.dm b/code/modules/clothing/shoes/magboots.dm index 17a44db61d1..5020307699b 100644 --- a/code/modules/clothing/shoes/magboots.dm +++ b/code/modules/clothing/shoes/magboots.dm @@ -2,6 +2,7 @@ desc = "Magnetic boots, often used during extravehicular activity to ensure the user remains safely attached to the vehicle. They're large enough to be worn over other footwear." name = "magboots" icon_state = "magboots0" + item_flags = PHORONGUARD item_state_slots = list(slot_r_hand_str = "magboots", slot_l_hand_str = "magboots") species_restricted = null force = 3 diff --git a/code/modules/clothing/spacesuits/rig/modules/combat.dm b/code/modules/clothing/spacesuits/rig/modules/combat.dm index 3e8cb36a6c1..890da50468b 100644 --- a/code/modules/clothing/spacesuits/rig/modules/combat.dm +++ b/code/modules/clothing/spacesuits/rig/modules/combat.dm @@ -89,6 +89,19 @@ new_grenade.activate(H) new_grenade.throw_at(target,fire_force,fire_distance) +/obj/item/rig_module/grenade_launcher/smoke + name = "mounted smoke-bomb launcher" + desc = "A shoulder-mounted smoke-bomb dispenser." + + interface_name = "integrated smoke-bomb launcher" + interface_desc = "Discharges loaded smoke-bombs against the wearer's location." + + fire_force = 15 + + charges = list( + list("smoke bomb", "smoke bomb", /obj/item/weapon/grenade/smokebomb, 6) + ) + /obj/item/rig_module/mounted name = "mounted laser cannon" diff --git a/code/modules/clothing/spacesuits/rig/modules/ninja.dm b/code/modules/clothing/spacesuits/rig/modules/ninja.dm index b5d58c8da6c..704ed7a47b5 100644 --- a/code/modules/clothing/spacesuits/rig/modules/ninja.dm +++ b/code/modules/clothing/spacesuits/rig/modules/ninja.dm @@ -192,8 +192,6 @@ smoke = null return ..() - - /obj/item/rig_module/self_destruct/activate() return diff --git a/code/modules/clothing/spacesuits/rig/modules/vision.dm b/code/modules/clothing/spacesuits/rig/modules/vision.dm index a4092d47ef2..f42204a444b 100644 --- a/code/modules/clothing/spacesuits/rig/modules/vision.dm +++ b/code/modules/clothing/spacesuits/rig/modules/vision.dm @@ -15,16 +15,19 @@ /datum/rig_vision/nvg mode = "night vision" + /datum/rig_vision/nvg/New() glasses = new /obj/item/clothing/glasses/night /datum/rig_vision/thermal mode = "thermal scanner" + /datum/rig_vision/thermal/New() glasses = new /obj/item/clothing/glasses/thermal /datum/rig_vision/meson mode = "meson scanner" + /datum/rig_vision/meson/New() glasses = new /obj/item/clothing/glasses/meson @@ -35,14 +38,22 @@ /datum/rig_vision/sechud mode = "security HUD" + /datum/rig_vision/sechud/New() glasses = new /obj/item/clothing/glasses/hud/security /datum/rig_vision/medhud mode = "medical HUD" + /datum/rig_vision/medhud/New() glasses = new /obj/item/clothing/glasses/hud/health +/datum/rig_vision/material + mode = "material scanner" + +/datum/rig_vision/material/New() + glasses = new /obj/item/clothing/glasses/material + /obj/item/rig_module/vision name = "hardsuit visor" @@ -81,6 +92,7 @@ interface_desc = "An integrated multi-mode vision system." vision_modes = list(/datum/rig_vision/meson, + /datum/rig_vision/material, /datum/rig_vision/nvg, /datum/rig_vision/thermal, /datum/rig_vision/sechud, @@ -103,7 +115,7 @@ name = "hardsuit material scanner" desc = "A layered, translucent visor system for a hardsuit." - icon_state = "material" + icon_state = "material" //VOREStation Edit usable = 0 @@ -112,6 +124,20 @@ vision_modes = list(/datum/rig_vision/material) +/obj/item/rig_module/vision/mining + + name = "hardsuit mining scanners" + desc = "A layered, translucent visor system for a hardsuit." + icon_state = "optics" + + usable = 0 + + interface_name = "mining scanners" + interface_desc = "An integrated mining scanner array." + + vision_modes = list(/datum/rig_vision/material, + /datum/rig_vision/meson) + /obj/item/rig_module/vision/thermal name = "hardsuit thermal scanner" @@ -215,4 +241,4 @@ if(!vision) vision = vision_datum processed_vision += vision_datum - vision_modes = processed_vision \ No newline at end of file + vision_modes = processed_vision diff --git a/code/modules/clothing/spacesuits/rig/rig_attackby.dm b/code/modules/clothing/spacesuits/rig/rig_attackby.dm index 3d5fc130047..67080dd1e04 100644 --- a/code/modules/clothing/spacesuits/rig/rig_attackby.dm +++ b/code/modules/clothing/spacesuits/rig/rig_attackby.dm @@ -105,7 +105,7 @@ else if(W.is_wrench()) if(!air_supply) - to_chat(user, "There is not tank to remove.") + to_chat(user, "There is no tank to remove.") return if(user.r_hand && user.l_hand) @@ -137,7 +137,7 @@ if("cell") if(cell) - to_chat(user, "You detatch \the [cell] from \the [src]'s battery mount.") + to_chat(user, "You detach \the [cell] from \the [src]'s battery mount.") for(var/obj/item/rig_module/module in installed_modules) module.deactivate() if(user.r_hand && user.l_hand) @@ -165,7 +165,7 @@ return var/obj/item/rig_module/removed = possible_removals[removal_choice] - to_chat(user, "You detatch \the [removed] from \the [src].") + to_chat(user, "You detach \the [removed] from \the [src].") removed.forceMove(get_turf(src)) removed.removed() installed_modules -= removed diff --git a/code/modules/clothing/spacesuits/rig/rig_pieces.dm b/code/modules/clothing/spacesuits/rig/rig_pieces.dm index 5c4853a7917..6bc6865a212 100644 --- a/code/modules/clothing/spacesuits/rig/rig_pieces.dm +++ b/code/modules/clothing/spacesuits/rig/rig_pieces.dm @@ -23,7 +23,7 @@ /obj/item/clothing/gloves/gauntlets/rig name = "gauntlets" - item_flags = THICKMATERIAL + item_flags = THICKMATERIAL|PHORONGUARD body_parts_covered = HANDS heat_protection = HANDS cold_protection = HANDS diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index 3c10a03a8b2..300368260a1 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -30,23 +30,36 @@ brightness_on = 4 on = 0 -/obj/item/clothing/head/helmet/space/attack_self(mob/user) +/obj/item/clothing/head/helmet/space/verb/toggle_camera() + set name = "Toggle Helmet Camera" + set desc = "Turn your helmet's camera on or off." + set category = "Object" + set src in usr + if(usr.stat || usr.restrained() || usr.incapacitated()) + return - if(!camera && camera_networks) + if(camera_networks) + if(!camera) + camera = new /obj/machinery/camera(src) + camera.replace_networks(camera_networks) + camera.set_status(FALSE) //So the camera will activate in the following check. - camera = new /obj/machinery/camera(src) - camera.replace_networks(camera_networks) - camera.c_tag = user.name - user << "User scanned as [camera.c_tag]. Camera activated." - user.update_action_buttons() - return 1 + if(camera.status == TRUE) + camera.set_status(FALSE) + to_chat(usr, "Camera deactivated.") + else + camera.set_status(TRUE) + camera.c_tag = usr.name + to_chat(usr, "User scanned as [camera.c_tag]. Camera activated.") - ..() + else + to_chat(usr, "This helmet does not have a built-in camera.") + return /obj/item/clothing/head/helmet/space/examine() ..() if(camera_networks && get_dist(usr,src) <= 1) - usr << "This helmet has a built-in camera. It's [camera ? "" : "in"]active." + to_chat(usr, "This helmet has a built-in camera. It's [camera ? "" : "in"]active.") /obj/item/clothing/suit/space name = "Space suit" @@ -95,18 +108,18 @@ if(user.wear_suit == src) for(var/obj/item/organ/external/E in user.bad_external_organs) if(E.is_broken() && E.apply_splint(src)) - user << "You feel [src] constrict about your [E.name], supporting it." + to_chat(user, "You feel [src] constrict about your [E.name], supporting it.") supporting_limbs |= E else // Otherwise, remove the splints. for(var/obj/item/organ/external/E in supporting_limbs) if(E.splinted == src && E.remove_splint(src)) - user << "\The [src] stops supporting your [E.name]." + to_chat(user, "\The [src] stops supporting your [E.name].") supporting_limbs.Cut() /obj/item/clothing/suit/space/proc/handle_fracture(var/mob/living/carbon/human/user, var/obj/item/organ/external/E) if(!istype(user) || isnull(supporting_limbs)) return if(E.is_broken() && E.apply_splint(src)) - user << "You feel [src] constrict about your [E.name], supporting it." + to_chat(user, "You feel [src] constrict about your [E.name], supporting it.") supporting_limbs |= E diff --git a/code/modules/clothing/spacesuits/void/station.dm b/code/modules/clothing/spacesuits/void/station.dm index 2168fbb1b5b..ac652e22363 100644 --- a/code/modules/clothing/spacesuits/void/station.dm +++ b/code/modules/clothing/spacesuits/void/station.dm @@ -94,6 +94,7 @@ desc = "A special suit that protects against hazardous, low pressure environments. Has reinforced plating." icon_state = "rig-mining" item_state_slots = list(slot_r_hand_str = "mining_voidsuit", slot_l_hand_str = "mining_voidsuit") + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/pickaxe) armor = list(melee = 50, bullet = 5, laser = 20, energy = 5, bomb = 55, bio = 100, rad = 20) //Mining Surplus Voidsuit diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index db33ec9662b..9df94753e68 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -378,6 +378,16 @@ item_state = "tacwebvest" armor = list(melee = 40, bullet = 40, laser = 60, energy = 35, bomb = 30, bio = 0, rad = 0) +/obj/item/clothing/suit/storage/vest/heavy/flexitac //a reskin of the above to have a matching armor set + name = "tactical light vest" + desc = "An armored vest made from advanced flexible ceramic plates. It's surprisingly mobile, if a little unfashionable." + icon_state = "flexitac" + item_state = "flexitac" + armor = list(melee = 40, bullet = 40, laser = 60, energy = 35, bomb = 30, bio = 0, rad = 0) + cold_protection = UPPER_TORSO|LOWER_TORSO + min_cold_protection_temperature = T0C - 20 + slowdown = 0.3 + /obj/item/clothing/suit/storage/vest/detective name = "detective armor vest" desc = "A simple kevlar plate carrier in a vintage brown, it has a badge clipped to the chest that reads, 'Private investigator'." diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm index 0f8b999b4cc..91f441fa373 100644 --- a/code/modules/clothing/suits/miscellaneous.dm +++ b/code/modules/clothing/suits/miscellaneous.dm @@ -323,7 +323,7 @@ obj/item/clothing/suit/kamishimo item_state_slots = list(slot_r_hand_str = "leather_jacket", slot_l_hand_str = "leather_jacket") flags_inv = HIDEHOLSTER -obj/item/clothing/suit/storage/toggle/peacoat +/obj/item/clothing/suit/storage/toggle/peacoat name = "peacoat" desc = "A well-tailored, stylish peacoat." icon_state = "peacoat" @@ -338,6 +338,14 @@ obj/item/clothing/suit/storage/toggle/peacoat blood_overlay_type = "coat" allowed = list(/obj/item/weapon/tank/emergency/oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy,/obj/item/weapon/gun/projectile,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs,/obj/item/weapon/storage/fancy/cigarettes,/obj/item/weapon/flame/lighter) flags_inv = HIDEHOLSTER + +/obj/item/clothing/suit/storage/toggle/cardigan + name = "cardigan" + desc = "A cozy cardigan in a classic style." + icon_state = "cardigan" + addblends = "cardigan_a" + flags_inv = HIDEHOLSTER + /* * stripper */ diff --git a/code/modules/clothing/under/accessories/clothing.dm b/code/modules/clothing/under/accessories/clothing.dm index 66636aac6f7..d5991e4f100 100644 --- a/code/modules/clothing/under/accessories/clothing.dm +++ b/code/modules/clothing/under/accessories/clothing.dm @@ -349,6 +349,25 @@ desc = "A really cheesy holiday sweater, it actually kinda itches." icon_state = "turtleneck_winterred" +/obj/item/clothing/accessory/sweater/uglyxmas + name = "ugly Christmas sweater" + desc = "A gift that probably should've stayed in the back of the closet." + icon_state = "uglyxmas" + +/obj/item/clothing/accessory/sweater/flowersweater + name = "flowery sweater" + desc = "An oversized and flowery pink sweater." + icon_state = "flowersweater" + +/obj/item/clothing/accessory/sweater/redneck + name = "red turtleneck" + desc = "A comfortable turtleneck in a dark red." + icon_state = "turtleneck_red" + +//*** +// End of sweaters +//*** + /obj/item/clothing/accessory/cowledvest name = "cowled vest" desc = "A body warmer for the 26th century." diff --git a/code/modules/clothing/under/accessories/storage.dm b/code/modules/clothing/under/accessories/storage.dm index 83cf2e3049d..0c1cfee9cae 100644 --- a/code/modules/clothing/under/accessories/storage.dm +++ b/code/modules/clothing/under/accessories/storage.dm @@ -9,12 +9,15 @@ var/obj/item/weapon/storage/internal/hold w_class = ITEMSIZE_NORMAL on_rolled = list("down" = "none") + var/hide_on_roll = FALSE /obj/item/clothing/accessory/storage/New() ..() hold = new/obj/item/weapon/storage/internal(src) hold.max_storage_space = slots * 2 hold.max_w_class = ITEMSIZE_SMALL + if (!hide_on_roll) + on_rolled["down"] = icon_state /obj/item/clothing/accessory/storage/attack_hand(mob/user as mob) if (has_suit) //if we are part of a suit diff --git a/code/modules/clothing/under/accessories/torch.dm b/code/modules/clothing/under/accessories/torch.dm index c7fe8538081..7cdec72747d 100644 --- a/code/modules/clothing/under/accessories/torch.dm +++ b/code/modules/clothing/under/accessories/torch.dm @@ -310,9 +310,9 @@ department tags desc = "Insignia denoting assignment to the command department. These fit Fleet uniforms." on_rolled = list("rolled" = "dept_fleet_sleeves", "down" = "none") -/obj/item/clothing/accessory/solgov/department/command/army - icon_state = "dept_army" - desc = "Insignia denoting assignment to the command department. These fit Army uniforms." +/obj/item/clothing/accessory/solgov/department/command/marine + icon_state = "dept_marine" + desc = "Insignia denoting assignment to the command department. These fit marine uniforms." on_rolled = list("down" = "none") /obj/item/clothing/accessory/solgov/department/engineering @@ -328,9 +328,9 @@ department tags desc = "Insignia denoting assignment to the engineering department. These fit Fleet uniforms." on_rolled = list("rolled" = "dept_fleet_sleeves", "down" = "none") -/obj/item/clothing/accessory/solgov/department/engineering/army - icon_state = "dept_army" - desc = "Insignia denoting assignment to the engineering department. These fit Army uniforms." +/obj/item/clothing/accessory/solgov/department/engineering/marine + icon_state = "dept_marine" + desc = "Insignia denoting assignment to the engineering department. These fit marine uniforms." on_rolled = list("down" = "none") /obj/item/clothing/accessory/solgov/department/security @@ -346,9 +346,9 @@ department tags desc = "Insignia denoting assignment to the security department. These fit Fleet uniforms." on_rolled = list("rolled" = "dept_fleet_sleeves", "down" = "none") -/obj/item/clothing/accessory/solgov/department/security/army - icon_state = "dept_army" - desc = "Insignia denoting assignment to the security department. These fit Army uniforms." +/obj/item/clothing/accessory/solgov/department/security/marine + icon_state = "dept_marine" + desc = "Insignia denoting assignment to the security department. These fit marine uniforms." on_rolled = list("down" = "none") /obj/item/clothing/accessory/solgov/department/medical @@ -364,9 +364,9 @@ department tags desc = "Insignia denoting assignment to the medical department. These fit Fleet uniforms." on_rolled = list("rolled" = "dept_fleet_sleeves", "down" = "none") -/obj/item/clothing/accessory/solgov/department/medical/army - icon_state = "dept_army" - desc = "Insignia denoting assignment to the medical department. These fit Army uniforms." +/obj/item/clothing/accessory/solgov/department/medical/marine + icon_state = "dept_marine" + desc = "Insignia denoting assignment to the medical department. These fit marine uniforms." on_rolled = list("down" = "none") /obj/item/clothing/accessory/solgov/department/supply @@ -382,9 +382,9 @@ department tags desc = "Insignia denoting assignment to the supply department. These fit Fleet uniforms." on_rolled = list("rolled" = "dept_fleet_sleeves", "down" = "none") -/obj/item/clothing/accessory/solgov/department/supply/army - icon_state = "dept_army" - desc = "Insignia denoting assignment to the supply department. These fit Army uniforms." +/obj/item/clothing/accessory/solgov/department/supply/marine + icon_state = "dept_marine" + desc = "Insignia denoting assignment to the supply department. These fit marine uniforms." on_rolled = list("down" = "none") /obj/item/clothing/accessory/solgov/department/service @@ -400,9 +400,9 @@ department tags desc = "Insignia denoting assignment to the service department. These fit Fleet uniforms." on_rolled = list("rolled" = "dept_fleet_sleeves", "down" = "none") -/obj/item/clothing/accessory/solgov/department/service/army - icon_state = "dept_army" - desc = "Insignia denoting assignment to the service department. These fit Army uniforms." +/obj/item/clothing/accessory/solgov/department/service/marine + icon_state = "dept_marine" + desc = "Insignia denoting assignment to the service department. These fit marine uniforms." on_rolled = list("down" = "none") /obj/item/clothing/accessory/solgov/department/exploration @@ -418,9 +418,9 @@ department tags desc = "Insignia denoting assignment to the exploration department. These fit Fleet uniforms." on_rolled = list("rolled" = "dept_fleet_sleeves", "down" = "none") -/obj/item/clothing/accessory/solgov/department/exploration/army - icon_state = "dept_army" - desc = "Insignia denoting assignment to the exploration department. These fit Army uniforms." +/obj/item/clothing/accessory/solgov/department/exploration/marine + icon_state = "dept_marine" + desc = "Insignia denoting assignment to the exploration department. These fit marine uniforms." on_rolled = list("down" = "none") /obj/item/clothing/accessory/solgov/department/research @@ -611,103 +611,103 @@ ranks - fleet /************** ranks - marines **************/ -/obj/item/clothing/accessory/solgov/rank/army - name = "army ranks" +/obj/item/clothing/accessory/solgov/rank/marine + name = "marine ranks" desc = "Insignia denoting marine rank of some kind. These appear blank." - icon_state = "armyrank_enlisted" + icon_state = "marinerank_enlisted" on_rolled = list("down" = "none") -/obj/item/clothing/accessory/solgov/rank/army/enlisted +/obj/item/clothing/accessory/solgov/rank/marine/enlisted name = "ranks (E-1 private)" desc = "Insignia denoting the rank of Private." - icon_state = "armyrank_enlisted" + icon_state = "marinerank_enlisted" -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e2 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e2 name = "ranks (E-2 private second class)" desc = "Insignia denoting the rank of Private Second Class." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e3 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e3 name = "ranks (E-3 private first class)" desc = "Insignia denoting the rank of Private First Class." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e4 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e4 name = "ranks (E-4 corporal)" desc = "Insignia denoting the rank of Corporal." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e5 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e5 name = "ranks (E-5 sergeant)" desc = "Insignia denoting the rank of Sergeant." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e6 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e6 name = "ranks (E-6 staff sergeant)" desc = "Insignia denoting the rank of Staff Sergeant." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e7 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e7 name = "ranks (E-7 sergeant first class)" desc = "Insignia denoting the rank of Sergeant First Class." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e8 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e8 name = "ranks (E-8 master sergeant)" desc = "Insignia denoting the rank of Master Sergeant." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e8_alt +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e8_alt name = "ranks (E-8 first sergeant)" desc = "Insignia denoting the rank of First Sergeant." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e9 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e9 name = "ranks (E-9 sergeant major)" desc = "Insignia denoting the rank of Sergeant Major." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e9_alt1 +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e9_alt1 name = "ranks (E-9 command sergeant major)" desc = "Insignia denoting the rank of Command Sergeant Major." -/obj/item/clothing/accessory/solgov/rank/army/enlisted/e9_alt2 - name = "ranks (E-9 sergeant major of the Army)" - desc = "Insignia denoting the rank of Sergeant Major of the Army." +/obj/item/clothing/accessory/solgov/rank/marine/enlisted/e9_alt2 + name = "ranks (E-9 sergeant major of the marine)" + desc = "Insignia denoting the rank of Sergeant Major of the marine." -/obj/item/clothing/accessory/solgov/rank/army/officer +/obj/item/clothing/accessory/solgov/rank/marine/officer name = "ranks (O-1 second lieutenant)" desc = "Insignia denoting the rank of Second Lieutenant." - icon_state = "armyrank_officer" + icon_state = "marinerank_officer" -/obj/item/clothing/accessory/solgov/rank/army/officer/o2 +/obj/item/clothing/accessory/solgov/rank/marine/officer/o2 name = "ranks (O-2 first lieutenant)" desc = "Insignia denoting the rank of First Lieutenant." -/obj/item/clothing/accessory/solgov/rank/army/officer/o3 +/obj/item/clothing/accessory/solgov/rank/marine/officer/o3 name = "ranks (O-3 captain)" desc = "Insignia denoting the rank of Captain." -/obj/item/clothing/accessory/solgov/rank/army/officer/o4 +/obj/item/clothing/accessory/solgov/rank/marine/officer/o4 name = "ranks (O-4 major)" desc = "Insignia denoting the rank of Major." -/obj/item/clothing/accessory/solgov/rank/army/officer/o5 +/obj/item/clothing/accessory/solgov/rank/marine/officer/o5 name = "ranks (O-5 lieutenant colonel)" desc = "Insignia denoting the rank of Lieutenant Colonel." -/obj/item/clothing/accessory/solgov/rank/army/officer/o6 +/obj/item/clothing/accessory/solgov/rank/marine/officer/o6 name = "ranks (O-6 colonel)" desc = "Insignia denoting the rank of Colonel." -/obj/item/clothing/accessory/solgov/rank/army/flag +/obj/item/clothing/accessory/solgov/rank/marine/flag name = "ranks (O-7 brigadier general)" desc = "Insignia denoting the rank of Brigadier General." - icon_state = "armyrank_command" + icon_state = "marinerank_command" -/obj/item/clothing/accessory/solgov/rank/army/flag/o8 +/obj/item/clothing/accessory/solgov/rank/marine/flag/o8 name = "ranks (O-8 major general)" desc = "Insignia denoting the rank of Major General." -/obj/item/clothing/accessory/solgov/rank/army/flag/o9 +/obj/item/clothing/accessory/solgov/rank/marine/flag/o9 name = "ranks (O-9 lieutenant general)" desc = "Insignia denoting the rank of lieutenant general." -/obj/item/clothing/accessory/solgov/rank/army/flag/o10 +/obj/item/clothing/accessory/solgov/rank/marine/flag/o10 name = "ranks (O-10 general)" desc = "Insignia denoting the rank of General." -/obj/item/clothing/accessory/solgov/rank/army/flag/o10_alt +/obj/item/clothing/accessory/solgov/rank/marine/flag/o10_alt name = "ranks (O-10 field marshal)" desc = "Insignia denoting the rank of Field Marshal." diff --git a/code/modules/clothing/under/color.dm b/code/modules/clothing/under/color.dm index cc5d7ed9171..9384d6db7f9 100644 --- a/code/modules/clothing/under/color.dm +++ b/code/modules/clothing/under/color.dm @@ -30,13 +30,16 @@ icon_state = "grey" rolled_sleeves = 0 +//TFF 5/8/19 - add a non perma-set orange jumpsuit, splits prison into its own obj with override var settings. /obj/item/clothing/under/color/orange name = "orange jumpsuit" - desc = "It's standardized prisoner-wear. Its suit sensors are permanently set to the \"Tracking\" position." icon_state = "orange" + rolled_sleeves = 0 + +/obj/item/clothing/under/color/orange/prison + desc = "It's standardized prisoner-wear. Its suit sensors are permanently set to the \"Tracking\" position." has_sensor = 2 sensor_mode = 3 - rolled_sleeves = 0 /obj/item/clothing/under/color/pink name = "pink jumpsuit" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 943577663ff..c90d575b983 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -453,6 +453,10 @@ icon_state = "sari_green" item_state_slots = list(slot_r_hand_str = "dress_green", slot_l_hand_str = "dress_green") +/obj/item/clothing/under/dress/lilacdress + name = "lilac dress" + desc = "A simple black dress adorned in fake purple lilacs." + icon_state = "lilacdress" /* * wedding stuff diff --git a/code/modules/clothing/under/shorts.dm b/code/modules/clothing/under/shorts.dm index 4ac2ad5f2e3..26a00a4a636 100644 --- a/code/modules/clothing/under/shorts.dm +++ b/code/modules/clothing/under/shorts.dm @@ -130,6 +130,12 @@ desc = "A piece of cloth wrapped around the waist." icon_state = "loincloth" +/obj/item/clothing/under/skirt/pleated + name = "pleated skirt" + desc = "A simple pleated skirt. It's like high school all over again." + icon_state = "pleated" + addblends = "pleated_a" + /obj/item/clothing/under/skirt/outfit name = "black skirt" desc = "A black skirt, very fancy!" diff --git a/code/modules/clothing/under/solgov.dm b/code/modules/clothing/under/solgov.dm index 39109c480aa..0859cdf1e4a 100644 --- a/code/modules/clothing/under/solgov.dm +++ b/code/modules/clothing/under/solgov.dm @@ -1,7 +1,18 @@ //SolGov Uniforms +//Master +/obj/item/clothing/under/solgov + name = "master solgov uniform" + desc = "You shouldn't be seeing this." + icon = 'icons/obj/clothing/uniforms_solgov.dmi' + rolled_down = 0 + rolled_sleeves = 0 + item_icons = list(slot_w_uniform_str = 'icons/mob/uniform_solgov.dmi') + armor = list(melee = 5, bullet = 0, laser = 5, energy = 5, bomb = 0, bio = 5, rad = 5) + siemens_coefficient = 0.8 + //PT -/obj/item/clothing/under/pt +/obj/item/clothing/under/solgov/pt name = "pt uniform" desc = "Shorts! Shirt! Miami! Sexy!" icon_state = "miami" @@ -10,19 +21,19 @@ siemens_coefficient = 0.9 body_parts_covered = UPPER_TORSO|LOWER_TORSO -/obj/item/clothing/under/pt/sifguard +/obj/item/clothing/under/solgov/pt/sifguard name = "\improper SifGuard pt uniform" desc = "A baggy shirt bearing the seal of the Sif Defense Force and some dorky looking blue shorts." icon_state = "expeditionpt" worn_state = "expeditionpt" -/obj/item/clothing/under/pt/fleet +/obj/item/clothing/under/solgov/pt/fleet name = "fleet pt uniform" desc = "A pair of black shorts and two tank tops, seems impractical. Looks good though." icon_state = "fleetpt" worn_state = "fleetpt" -/obj/item/clothing/under/pt/marine +/obj/item/clothing/under/solgov/pt/marine name = "marine pt uniform" desc = "Does NOT leave much to the imagination." icon_state = "marinept" @@ -53,63 +64,62 @@ worn_state = "greyutility" //Here's the real ones -/obj/item/clothing/under/utility/sifguard +/obj/item/clothing/under/solgov/utility/sifguard name = "\improper SifGuard uniform" desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has silver trim." icon_state = "blackutility_crew" worn_state = "blackutility_crew" armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 10, rad = 10) -/obj/item/clothing/under/utility/sifguard/medical - name = "\improper SifGuard medical uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has silver trim and blue blazes." - icon_state = "blackutility_med" - worn_state = "blackutility_med" +/obj/item/clothing/under/solgov/utility/sifguard/command + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/command) -/obj/item/clothing/under/utility/sifguard/medical/command - name = "\improper SifGuard medical command uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has gold trim and blue blazes." - icon_state = "blackutility_medcom" - worn_state = "blackutility_medcom" +/obj/item/clothing/under/solgov/utility/sifguard/engineering + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/engineering) -/obj/item/clothing/under/utility/sifguard/engineering - name = "\improper SifGuard engineering uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has silver trim and organge blazes." - icon_state = "blackutility_eng" - worn_state = "blackutility_eng" +/obj/item/clothing/under/solgov/utility/sifguard/security + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/security) -/obj/item/clothing/under/utility/sifguard/engineering/command - name = "\improper SifGuard engineering command uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has gold trim and organge blazes." - icon_state = "blackutility_engcom" - worn_state = "blackutility_engcom" +/obj/item/clothing/under/solgov/utility/sifguard/medical + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/medical) -/obj/item/clothing/under/utility/sifguard/supply - name = "\improper SifGuard supply uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has silver trim and brown blazes." - icon_state = "blackutility_sup" - worn_state = "blackutility_sup" +/obj/item/clothing/under/solgov/utility/sifguard/supply + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/supply) -/obj/item/clothing/under/utility/sifguard/security - name = "\improper SifGuard security uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has silver trim and red blazes." - icon_state = "blackutility_sec" - worn_state = "blackutility_sec" +/obj/item/clothing/under/solgov/utility/sifguard/exploration + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/exploration) -/obj/item/clothing/under/utility/sifguard/security/command - name = "\improper SifGuard security command uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has gold trim and red blazes." - icon_state = "blackutility_seccom" - worn_state = "blackutility_seccom" +/obj/item/clothing/under/solgov/utility/sifguard/research + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/research) -/obj/item/clothing/under/utility/sifguard/command - name = "\improper SifGuard command uniform" - desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has gold trim and gold blazes." +/obj/item/clothing/under/solgov/utility/sifguard/officer + name = "\improper Sifuard officer's uniform" + desc = "The utility uniform of the Sif Defense Force, made from biohazard resistant material. This one has gold trim." icon_state = "blackutility_com" worn_state = "blackutility_com" +/obj/item/clothing/under/solgov/utility/sifguard/officer/command + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/command) -/obj/item/clothing/under/utility/fleet +/obj/item/clothing/under/solgov/utility/sifguard/officer/engineering + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/engineering) + +/obj/item/clothing/under/solgov/utility/sifguard/officer/security + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/security) + +/obj/item/clothing/under/solgov/utility/sifguard/officer/medical + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/medical) + +/obj/item/clothing/under/solgov/utility/sifguard/officer/supply + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/supply) + +/obj/item/clothing/under/solgov/utility/sifguard/officer/exploration + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/exploration) + +/obj/item/clothing/under/solgov/utility/sifguard/officer/research + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/research) + +/obj/item/clothing/under/solgov/utility/fleet name = "fleet coveralls" desc = "The utility uniform of the SCG Fleet, made from an insulated material." icon_state = "navyutility" @@ -117,116 +127,96 @@ armor = list(melee = 0, bullet = 0, laser = 0,energy = 10, bomb = 0, bio = 0, rad = 0) siemens_coefficient = 0.7 -/obj/item/clothing/under/utility/fleet/medical - name = "fleet medical coveralls" - desc = "The utility uniform of the SCG Fleet, made from an insulated material. This one has blue cuffs." - icon_state = "navyutility_med" - worn_state = "navyutility_med" +/obj/item/clothing/under/solgov/utility/fleet/command + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/command/fleet) -/obj/item/clothing/under/utility/fleet/engineering - name = "fleet engineering coveralls" - desc = "The utility uniform of the SCG Fleet, made from an insulated material. This one has orange cuffs." - icon_state = "navyutility_eng" - worn_state = "navyutility_eng" +/obj/item/clothing/under/solgov/utility/fleet/command/pilot + starting_accessories = list(/obj/item/clothing/accessory/solgov/specialty/pilot) -/obj/item/clothing/under/utility/fleet/supply - name = "fleet supply coveralls" - desc = "The utility uniform of the SCG Fleet, made from an insulated material. This one has brown cuffs." - icon_state = "navyutility_sup" - worn_state = "navyutility_sup" +/obj/item/clothing/under/solgov/utility/fleet/engineering + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/engineering/fleet) -/obj/item/clothing/under/utility/fleet/security - name = "fleet security coveralls" - desc = "The utility uniform of the SCG Fleet, made from an insulated material. This one has red cuffs." - icon_state = "navyutility_sec" - worn_state = "navyutility_sec" +/obj/item/clothing/under/solgov/utility/fleet/security + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/security/fleet) -/obj/item/clothing/under/utility/fleet/command - name = "fleet command coveralls" - desc = "The utility uniform of the SCG Fleet, made from an insulated material. This one has gold cuffs." - icon_state = "navyutility_com" - worn_state = "navyutility_com" +/obj/item/clothing/under/solgov/utility/fleet/medical + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/medical/fleet) + +/obj/item/clothing/under/solgov/utility/fleet/supply + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/supply/fleet) + +/obj/item/clothing/under/solgov/utility/fleet/exploration + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/exploration/fleet) -/obj/item/clothing/under/utility/marine +/obj/item/clothing/under/solgov/utility/marine name = "marine fatigues" desc = "The utility uniform of the SCG Marine Corps, made from durable material." icon_state = "greyutility" worn_state = "greyutility" armor = list(melee = 10, bullet = 0, laser = 10,energy = 0, bomb = 0, bio = 0, rad = 0) -/obj/item/clothing/under/utility/marine/green +/obj/item/clothing/under/solgov/utility/marine/command + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/command/marine) + +/obj/item/clothing/under/solgov/utility/marine/engineering + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/engineering/marine) + +/obj/item/clothing/under/solgov/utility/marine/security + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/security/marine) + +/obj/item/clothing/under/solgov/utility/marine/medical + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/medical/marine) + +/obj/item/clothing/under/solgov/utility/marine/supply + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/supply/marine) + +/obj/item/clothing/under/solgov/utility/marine/exploration + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/exploration/marine) + +/obj/item/clothing/under/solgov/utility/marine/green name = "green fatigues" desc = "A green version of the SCG marine utility uniform, made from durable material." icon_state = "greenutility" worn_state = "greenutility" -/obj/item/clothing/under/utility/marine/tan +/obj/item/clothing/under/solgov/utility/marine/tan name = "tan fatigues" desc = "A tan version of the SCG marine utility uniform, made from durable material." icon_state = "tanutility" worn_state = "tanutility" -/obj/item/clothing/under/utility/marine/medical - name = "marine medical fatigues" - desc = "The utility uniform of the SCG Marine Corps, made from durable material. This one has blue markings." - icon_state = "greyutility_med" - worn_state = "greyutility_med" - -/obj/item/clothing/under/utility/marine/engineering - name = "marine engineering fatigues" - desc = "The utility uniform of the SCG Marine Corps, made from durable material. This one has orange markings." - icon_state = "greyutility_eng" - worn_state = "greyutility_eng" - -/obj/item/clothing/under/utility/marine/supply - name = "marine supply fatigues" - desc = "The utility uniform of the SCG Marine Corps, made from durable material. This one has brown markings." - icon_state = "greyutility_sup" - worn_state = "greyutility_sup" - -/obj/item/clothing/under/utility/marine/security - name = "marine security fatigues" - desc = "The utility uniform of the SCG Marine Corps, made from durable material. This one has red markings." - icon_state = "greyutility_sec" - worn_state = "greyutility_sec" - -/obj/item/clothing/under/utility/marine/command - name = "marine command coveralls" - desc = "The utility uniform of the SCG Marine Corps, made from durable material. This one has gold markings." - icon_state = "greyutility_com" - worn_state = "greyutility_com" - //Service -/obj/item/clothing/under/service +/obj/item/clothing/under/solgov/service name = "service uniform" desc = "A service uniform of some kind." icon_state = "whiteservice" worn_state = "whiteservice" - armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) + armor = list(melee = 5, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 5, rad = 0) siemens_coefficient = 0.9 -/obj/item/clothing/under/service/fleet +/obj/item/clothing/under/solgov/service/fleet name = "fleet service uniform" desc = "The service uniform of the SCG Fleet, made from immaculate white fabric." icon_state = "whiteservice" worn_state = "whiteservice" -/obj/item/clothing/under/service/marine +/obj/item/clothing/under/solgov/service/marine name = "marine service uniform" desc = "The service uniform of the SCG Marine Corps. Slimming." icon_state = "greenservice" worn_state = "greenservice" -/obj/item/clothing/under/service/marine/command +/obj/item/clothing/under/solgov/service/marine/command name = "marine command service uniform" desc = "The service uniform of the SCG Marine Corps. Slimming and stylish." icon_state = "greenservice_com" worn_state = "greenservice_com" //Dress -/obj/item/clothing/under/mildress + +/obj/item/clothing/under/solgov/mildress name = "dress uniform" desc = "A dress uniform of some kind." icon_state = "greydress" @@ -234,25 +224,71 @@ armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0) siemens_coefficient = 0.9 -/obj/item/clothing/under/mildress/sifguard +/obj/item/clothing/under/solgov/mildress/sifguard name = "\improper SifGuard dress uniform" desc = "The dress uniform of the Sif Defense Force in silver trim." - icon_state = "greydress" - worn_state = "greydress" -/obj/item/clothing/under/mildress/sifguard/command +/obj/item/clothing/under/solgov/mildress/sifguard/command + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/command/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/engineering + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/engineering/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/security + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/security/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/medical + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/medical/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/supply + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/supply/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/service + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/service/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/exploration + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/exploration/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/research + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/research/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer name = "\improper SifGuard command dress uniform" desc = "The dress uniform of the Sif Defense Force in gold trim." icon_state = "greydress_com" worn_state = "greydress_com" -/obj/item/clothing/under/mildress/marine +/obj/item/clothing/under/solgov/mildress/sifguard/officer/command + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/command/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer/engineering + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/engineering/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer/security + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/security/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer/medical + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/medical/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer/supply + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/supply/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer/service + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/service/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer/exploration + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/exploration/service) + +/obj/item/clothing/under/solgov/mildress/sifguard/officer/research + starting_accessories = list(/obj/item/clothing/accessory/solgov/department/research/service) + +/obj/item/clothing/under/solgov/mildress/marine name = "marine dress uniform" desc = "The dress uniform of the SCG Marine Corps, class given form." icon_state = "blackdress" worn_state = "blackdress" -/obj/item/clothing/under/mildress/marine/command +/obj/item/clothing/under/solgov/mildress/marine/command name = "marine command dress uniform" desc = "The dress uniform of the SCG Marine Corps, even classier in gold." icon_state = "blackdress_com" diff --git a/code/modules/events/camera_damage.dm b/code/modules/events/camera_damage.dm index 3205a93137a..6a86581b706 100644 --- a/code/modules/events/camera_damage.dm +++ b/code/modules/events/camera_damage.dm @@ -33,6 +33,6 @@ return acquire_random_camera(remaining_attempts--) /datum/event/camera_damage/proc/is_valid_camera(var/obj/machinery/camera/C) - // Only return a functional camera, not installed in a silicon, and that exists somewhere players have access + // Only return a functional camera, not installed in a silicon/hardsuit/circuit/etc, and that exists somewhere players have access var/turf/T = get_turf(C) - return T && C.can_use() && !istype(C.loc, /mob/living/silicon) && (T.z in using_map.player_levels) + return T && C.can_use() && istype(C.loc, /turf) && (T.z in using_map.player_levels) diff --git a/code/modules/events/ion_storm.dm b/code/modules/events/ion_storm.dm index 0bf0f82aa64..c50b44dc261 100644 --- a/code/modules/events/ion_storm.dm +++ b/code/modules/events/ion_storm.dm @@ -14,8 +14,8 @@ for (var/mob/living/silicon/ai/target in silicon_mob_list) var/law = target.generate_ion_law() - target << "You have detected a change in your laws information:" - target << law + to_chat(target, "You have detected a change in your laws information:") + to_chat(target, law) target.add_ion_law(law) target.show_laws() /* //VOREstation edit. Was fucking up all PDA messagess. diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index 6cb8c267fb8..be7a6f6e794 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -11,8 +11,8 @@ description_antag = "Some fishing rods can be utilized as long-range, sharp weapons, though their pseudo ranged ability comes at the cost of slow speed." icon_state = "fishing_rod" item_state = "fishing_rod" - force_divisor = 0.25 - throwforce = 7 + force_divisor = 0.02 //VOREStation Edit + throwforce = 1 //VOREStation Edit sharp = TRUE attack_verb = list("whipped", "battered", "slapped", "fished", "hooked") hitsound = 'sound/weapons/punchmiss.ogg' diff --git a/code/modules/fishing/fishing_vr.dm b/code/modules/fishing/fishing_vr.dm new file mode 100644 index 00000000000..e545cc0edfb --- /dev/null +++ b/code/modules/fishing/fishing_vr.dm @@ -0,0 +1,42 @@ +#define FISHING_RARE "rare" +#define FISHING_UNCOMMON "uncommon" +#define FISHING_COMMON "common" +#define FISHING_JUNK "junk" +#define FISHING_NOTHING "nothing" + +GLOBAL_LIST_INIT(indoor_fishing_chance_list, list(FISHING_RARE = 5, FISHING_UNCOMMON = 20, FISHING_COMMON = 30, FISHING_JUNK = 5, FISHING_NOTHING = 50)) +GLOBAL_LIST_INIT(indoor_fishing_junk_list, list( + /obj/random/junk = 15, + /obj/random/maintenance/clean = 1 + )) + +/turf/simulated/floor/water/indoors + min_fishing_time = 33 + max_fishing_time = 99 + +/turf/simulated/floor/water/indoors/handle_fish() + if(has_fish) + rare_fish_list = GLOB.generic_fishing_rare_list + uncommon_fish_list = GLOB.generic_fishing_uncommon_list + common_fish_list = GLOB.generic_fishing_common_list + junk_list = GLOB.indoor_fishing_junk_list + fishing_loot = GLOB.indoor_fishing_chance_list + +/turf/simulated/floor/water/deep/indoors + min_fishing_time = 33 + max_fishing_time = 99 + +/turf/simulated/floor/water/deep/indoors/handle_fish() + if(has_fish) + rare_fish_list = GLOB.generic_fishing_rare_list + uncommon_fish_list = GLOB.generic_fishing_uncommon_list + common_fish_list = GLOB.generic_fishing_common_list + junk_list = GLOB.indoor_fishing_junk_list + fishing_loot = GLOB.indoor_fishing_chance_list + + +#undef FISHING_RARE +#undef FISHING_UNCOMMON +#undef FISHING_COMMON +#undef FISHING_JUNK +#undef FISHING_NOTHING \ No newline at end of file diff --git a/code/modules/food/drinkingglass/metaglass.dm b/code/modules/food/drinkingglass/metaglass.dm index 0b64df0af94..1980c588734 100644 --- a/code/modules/food/drinkingglass/metaglass.dm +++ b/code/modules/food/drinkingglass/metaglass.dm @@ -312,7 +312,7 @@ Drinks Data glass_icon_state = "atomicbombglass" glass_center_of_mass = list("x"=15, "y"=7) -/datum/reagent/ethanol/b52 +/datum/reagent/ethanol/coffee/b52 glass_icon_state = "b52glass" /datum/reagent/ethanol/bahama_mama diff --git a/code/modules/food/food/condiment.dm b/code/modules/food/food/condiment.dm index a6625ccf306..522f79b89b7 100644 --- a/code/modules/food/food/condiment.dm +++ b/code/modules/food/food/condiment.dm @@ -182,6 +182,198 @@ . = ..() reagents.add_reagent("sugar", 20) +//MRE condiments and drinks. + +/obj/item/weapon/reagent_containers/food/condiment/small/packet + icon_state = "packet_small" + w_class = ITEMSIZE_TINY + possible_transfer_amounts = "1;5;10" + amount_per_transfer_from_this = 1 + volume = 5 + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/salt + name = "salt packet" + desc = "Contains 5u of table salt." + icon_state = "packet_small_white" + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/salt/Initialize() + . = ..() + reagents.add_reagent("sodiumchloride", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/pepper + name = "pepper packet" + desc = "Contains 5u of black pepper." + icon_state = "packet_small_black" + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/pepper/Initialize() + . = ..() + reagents.add_reagent("blackpepper", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/sugar + name = "sugar packet" + desc = "Contains 5u of refined sugar." + icon_state = "packet_small_white" + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/sugar/Initialize() + . = ..() + reagents.add_reagent("sugar", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/jelly + name = "jelly packet" + desc = "Contains 10u of cherry jelly. Best used for spreading on crackers." + icon_state = "packet_medium" + volume = 10 + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/jelly/Initialize() + . = ..() + reagents.add_reagent("cherryjelly", 10) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/honey + name = "honey packet" + desc = "Contains 10u of honey." + icon_state = "packet_medium" + volume = 10 + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/honey/Initialize() + . = ..() + reagents.add_reagent("honey", 10) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/capsaicin + name = "hot sauce packet" + desc = "Contains 5u of hot sauce. Enjoy in moderation." + icon_state = "packet_small_red" + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/capsaicin/Initialize() + . = ..() + reagents.add_reagent("capsaicin", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/ketchup + name = "ketchup packet" + desc = "Contains 5u of ketchup." + icon_state = "packet_small_red" + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/ketchup/Initialize() + . = ..() + reagents.add_reagent("ketchup", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/mayo + name = "mayonnaise packet" + desc = "Contains 5u of mayonnaise." + icon_state = "packet_small_white" + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/mayo/Initialize() + . = ..() + reagents.add_reagent("mayo", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/soy + name = "soy sauce packet" + desc = "Contains 5u of soy sauce." + icon_state = "packet_small_black" + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/soy/Initialize() + . = ..() + reagents.add_reagent("soysauce", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/coffee + name = "coffee powder packet" + desc = "Contains 5u of coffee powder. Mix with 25u of water and heat." + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/coffee/Initialize() + . = ..() + reagents.add_reagent("coffeepowder", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/tea + name = "tea powder packet" + desc = "Contains 5u of black tea powder. Mix with 25u of water and heat." + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/tea/Initialize() + . = ..() + reagents.add_reagent("tea", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/cocoa + name = "cocoa powder packet" + desc = "Contains 5u of cocoa powder. Mix with 25u of water and heat." + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/cocoa/Initialize() + . = ..() + reagents.add_reagent("coco", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/grape + name = "grape juice powder packet" + desc = "Contains 5u of powdered grape juice. Mix with 15u of water." + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/grape/Initialize() + . = ..() + reagents.add_reagent("instantgrape", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/orange + name = "orange juice powder packet" + desc = "Contains 5u of powdered orange juice. Mix with 15u of water." + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/orange/Initialize() + . = ..() + reagents.add_reagent("instantorange", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/watermelon + name = "watermelon juice powder packet" + desc = "Contains 5u of powdered watermelon juice. Mix with 15u of water." + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/watermelon/Initialize() + . = ..() + reagents.add_reagent("instantwatermelon", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/apple + name = "apple juice powder packet" + desc = "Contains 5u of powdered apple juice. Mix with 15u of water." + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/apple/Initialize() + . = ..() + reagents.add_reagent("instantapple", 5) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/protein + name = "protein powder packet" + desc = "Contains 10u of powdered protein. Mix with 20u of water." + icon_state = "packet_medium" + volume = 10 + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/protein/Initialize() + . = ..() + reagents.add_reagent("protein", 10) + +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon + name = "crayon powder packet" + desc = "Contains 10u of powdered crayon. Mix with 30u of water." + volume = 10 +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/generic/Initialize() + . = ..() + reagents.add_reagent("crayon_dust", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/red/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_red", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/orange/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_orange", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/yellow/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_yellow", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/green/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_green", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/blue/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_blue", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/purple/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_purple", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/grey/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_grey", 10) +/obj/item/weapon/reagent_containers/food/condiment/small/packet/crayon/brown/Initialize() + . = ..() + reagents.add_reagent("crayon_dust_brown", 10) + +//End of MRE stuff. + /obj/item/weapon/reagent_containers/food/condiment/flour name = "flour sack" desc = "A big bag of flour. Good for baking!" diff --git a/code/modules/food/food/drinks/bottle.dm b/code/modules/food/food/drinks/bottle.dm index 4888bc81248..0a56f946d53 100644 --- a/code/modules/food/food/drinks/bottle.dm +++ b/code/modules/food/food/drinks/bottle.dm @@ -178,6 +178,7 @@ throw_speed = 3 throw_range = 5 item_state = "beer" + flags = NOCONDUCT attack_verb = list("stabbed", "slashed", "attacked") sharp = 1 edge = 0 diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index f0c5725aa1d..0906bf0c50c 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -21,12 +21,7 @@ /obj/item/weapon/reagent_containers/food/snacks/Initialize() . = ..() if(nutriment_amt) - reagents.add_reagent("nutriment",nutriment_amt,nutriment_desc) - -/obj/item/weapon/reagent_containers/food/snacks/Initialize() - . = ..() - if(nutriment_amt) - reagents.add_reagent("nutriment", nutriment_amt) + reagents.add_reagent("nutriment",(nutriment_amt*2),nutriment_desc) //Placeholder for effect that trigger on eating that aren't tied to reagents. /obj/item/weapon/reagent_containers/food/snacks/proc/On_Consume(var/mob/M) @@ -755,7 +750,18 @@ /obj/item/weapon/reagent_containers/food/snacks/fishfingers/Initialize() . = ..() reagents.add_reagent("protein", 4) - reagents.add_reagent("carpotoxin", 3) + bitesize = 3 + +/obj/item/weapon/reagent_containers/food/snacks/zestfish + name = "Zesty Fish" + desc = "Lightly seasoned fish fillets." + icon_state = "zestfish" + filling_color = "#FFDEFE" + center_of_mass = list("x"=16, "y"=13) + +/obj/item/weapon/reagent_containers/food/snacks/zestfish/Initialize() + . = ..() + reagents.add_reagent("protein", 4) bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/hugemushroomslice @@ -977,7 +983,6 @@ /obj/item/weapon/reagent_containers/food/snacks/fishburger/Initialize() . = ..() reagents.add_reagent("protein", 6) - reagents.add_reagent("carpotoxin", 3) bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/tofuburger @@ -1316,7 +1321,6 @@ /obj/item/weapon/reagent_containers/food/snacks/cubancarp/Initialize() . = ..() reagents.add_reagent("protein", 3) - reagents.add_reagent("carpotoxin", 3) reagents.add_reagent("capsaicin", 3) bitesize = 3 @@ -1977,7 +1981,6 @@ /obj/item/weapon/reagent_containers/food/snacks/fishandchips/Initialize() . = ..() reagents.add_reagent("protein", 3) - reagents.add_reagent("carpotoxin", 3) bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/sandwich @@ -2212,6 +2215,21 @@ . = ..() bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/kudzudonburi + name = "Zhan-Kudzu Overtaker" + desc = "Seasoned Kudzu and fish donburi." + icon_state = "kudzudonburi" + trash = /obj/item/trash/snack_bowl + filling_color = "#FFFBDB" + center_of_mass = list("x"=17, "y"=11) + nutriment_amt = 16 + nutriment_desc = list("rice" = 2, "gauze" = 4, "fish" = 10) + +/obj/item/weapon/reagent_containers/food/snacks/kudzudonburi/Initialize() + . = ..() + reagents.add_reagent("protein", 4) + bitesize = 2 + /obj/item/weapon/reagent_containers/food/snacks/pastatomato name = "Spaghetti" desc = "Spaghetti and crushed tomatoes. Just like your abusive father used to make!" @@ -2359,6 +2377,14 @@ . = ..() reagents.add_reagent("cherryjelly", 5) +/obj/item/weapon/reagent_containers/food/snacks/jellysandwich/peanutbutter + desc = "You wish you had some peanut butter to go with this... Oh wait!" + icon_state = "pbandj" + +/obj/item/weapon/reagent_containers/food/snacks/jellysandwich/peanutbutter/Initialize() + . = ..() + reagents.add_reagent("peanutbutter", 5) + /obj/item/weapon/reagent_containers/food/snacks/boiledslimecore name = "Boiled slime Core" desc = "A boiled red thing." @@ -2729,6 +2755,35 @@ /obj/item/weapon/reagent_containers/food/snacks/slice/cheesecake/filled filled = TRUE +/obj/item/weapon/reagent_containers/food/snacks/sliceable/peanutcake + name = "Peanut Cake" + desc = "DANGEROUSLY nutty. Sometimes literally." + icon_state = "peanutcake" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/slice/peanutcake + slices_num = 5 + filling_color = "#4F3500" + center_of_mass = list("x"=16, "y"=10) + nutriment_desc = list("cake" = 10, "peanuts" = 15) + nutriment_amt = 10 + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/peanutcake/Initialize() + . = ..() + reagents.add_reagent("protein", 5) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/slice/peanutcake + name = "Peanut Cake slice" + desc = "Slice of nutty goodness." + icon_state = "peanutcake_slice" + trash = /obj/item/trash/plate + filling_color = "#4F3500" + bitesize = 2 + center_of_mass = list("x"=16, "y"=14) + whole_path = /obj/item/weapon/reagent_containers/food/snacks/sliceable/peanutcake + +/obj/item/weapon/reagent_containers/food/snacks/slice/peanutcake/filled + filled = TRUE + /obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake name = "Vanilla Cake" desc = "A plain cake, not a lie." @@ -3028,6 +3083,7 @@ filling_color = "#F5DEB8" center_of_mass = list("x"=16, "y"=6) nutriment_desc = list("salt" = 1, "cracker" = 2) + w_class = ITEMSIZE_TINY nutriment_amt = 1 @@ -3066,6 +3122,34 @@ /obj/item/weapon/reagent_containers/food/snacks/slice/margherita/filled filled = TRUE +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pineapple + name = "Hawaiian" + desc = "The accursed wheel from ancient times." + icon_state = "pizzamargherita" + slice_path = /obj/item/weapon/reagent_containers/food/snacks/slice/pineapple + slices_num = 6 + center_of_mass = list("x"=16, "y"=11) + nutriment_desc = list("pizza crust" = 5, "tomato" = 5, "cheese" = 5, "pineapple" = 20) + nutriment_amt = 35 + +/obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pineapple/Initialize() + . = ..() + reagents.add_reagent("protein", 5) + reagents.add_reagent("pineapplejuice", 6) + bitesize = 2 + +/obj/item/weapon/reagent_containers/food/snacks/slice/pineapple + name = "Hawaiian slice" + desc = "A slice of the accursed pizza." + icon_state = "pizzamargheritaslice" + filling_color = "#BAA14C" + bitesize = 2 + center_of_mass = list("x"=16, "y"=13) + whole_path = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pineapple + +/obj/item/weapon/reagent_containers/food/snacks/slice/pineapple/filled + filled = TRUE + /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza name = "Meatpizza" desc = "A pizza with meat topping." @@ -3579,7 +3663,11 @@ /obj/item/weapon/reagent_containers/food/snacks/grown/attackby(obj/item/weapon/W, mob/user) if(seed && seed.kitchen_tag && seed.kitchen_tag == "potato" && istype(W,/obj/item/weapon/material/knife)) new /obj/item/weapon/reagent_containers/food/snacks/rawsticks(get_turf(src)) - user << "You cut the potato." + to_chat(user, "You cut the potato.") + qdel(src) + else if(seed && seed.kitchen_tag && seed.kitchen_tag == "sunflower" && istype(W,/obj/item/weapon/material/knife)) + new /obj/item/weapon/reagent_containers/food/snacks/rawsunflower(get_turf(src)) + to_chat(user, "You remove the seeds from the flower, slightly damaging them.") qdel(src) else ..() @@ -3597,6 +3685,39 @@ /obj/item/weapon/reagent_containers/food/snacks/rawsticks/Initialize() . = ..() +/obj/item/weapon/reagent_containers/food/snacks/rawsunflower + name = "sunflower seeds" + desc = "Raw sunflower seeds, alright. They look too damaged to plant." + icon = 'icons/obj/food_ingredients.dmi' + icon_state = "sunflowerseed" + bitesize = 1 + center_of_mass = list("x"=17, "y"=18) + nutriment_amt = 1 + nutriment_desc = list("starch" = 3) + +/obj/item/weapon/reagent_containers/food/snacks/rawsunflower/Initialize() + . = ..() + +/obj/item/weapon/reagent_containers/food/snacks/roastedsunflower + name = "sunflower seeds" + desc = "Sunflower seeds!" + icon = 'icons/obj/food.dmi' + icon_state = "sunflowerseed" + bitesize = 1 + center_of_mass = list("x"=15, "y"=17) + nutriment_amt = 2 + nutriment_desc = list("salt" = 3) + +/obj/item/weapon/reagent_containers/food/snacks/roastedpeanuts + name = "peanuts" + desc = "Stopped being the planetary airline food of Earth in 2120." + icon = 'icons/obj/food.dmi' + icon_state = "roastnuts" + bitesize = 1 + center_of_mass = list("x"=15, "y"=17) + nutriment_amt = 2 + nutriment_desc = list("salt" = 3) + /obj/item/weapon/reagent_containers/food/snacks/liquidfood name = "\improper LiquidFood Ration" desc = "A prepackaged grey slurry of all the essential nutrients for a spacefarer on the go. Should this be crunchy?" @@ -3613,6 +3734,33 @@ reagents.add_reagent("iron", 3) bitesize = 4 +/obj/item/weapon/reagent_containers/food/snacks/liquidprotein + name = "\improper LiquidProtein Ration" + desc = "A variant of the liquidfood ration, designed for obligate carnivore species. Only barely more appealing than regular liquidfood. Should this be crunchy?" + icon_state = "liquidprotein" + trash = /obj/item/trash/liquidprotein + filling_color = "#A8A8A8" + survivalfood = TRUE + center_of_mass = list("x"=16, "y"=15) + +/obj/item/weapon/reagent_containers/food/snacks/liquidprotein/Initialize() + ..() + reagents.add_reagent("protein", 30) + reagents.add_reagent("iron", 3) + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/meatcube + name = "cubed meat" + desc = "Fried, salted lean meat compressed into a cube. Not very appetizing." + icon_state = "meatcube" + filling_color = "#7a3d11" + center_of_mass = list("x"=16, "y"=16) + +/obj/item/weapon/reagent_containers/food/snacks/meatcube/Initialize() + . = ..() + reagents.add_reagent("protein", 15) + bitesize = 3 + /obj/item/weapon/reagent_containers/food/snacks/tastybread name = "bread tube" desc = "Bread in a tube. Chewy...and surprisingly tasty." @@ -3680,7 +3828,7 @@ /obj/item/weapon/reagent_containers/food/snacks/sashimi name = "carp sashimi" - desc = "Expertly prepared. Still toxic." + desc = "Expertly prepared. Hopefully toxin got removed though." filling_color = "#FFDEFE" icon_state = "sashimi" nutriment_amt = 6 @@ -3688,7 +3836,6 @@ /obj/item/weapon/reagent_containers/food/snacks/sashimi/Initialize() . = ..() reagents.add_reagent("protein", 2) - reagents.add_reagent("carpotoxin", 2) bitesize = 3 /obj/item/weapon/reagent_containers/food/snacks/benedict @@ -3770,6 +3917,21 @@ reagents.add_reagent("protein", 2) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/devilledegg + name = "devilled eggs" + desc = "Spicy homestyle favorite." + icon_state = "devilledegg" + filling_color = "#799ACE" + center_of_mass = list("x"=17, "y"=16) + nutriment_amt = 8 + nutriment_desc = list("egg" = 4, "chili" = 4) + +/obj/item/weapon/reagent_containers/food/snacks/devilledegg/Initialize() + . = ..() + reagents.add_reagent("nutriment", 6) + reagents.add_reagent("capsaicin", 2) + bitesize = 2 + /obj/item/weapon/reagent_containers/food/snacks/fruitsalad name = "fruit salad" desc = "Your standard fruit salad." @@ -3783,6 +3945,33 @@ reagents.add_reagent("nutriment", 10) bitesize = 4 +/obj/item/weapon/reagent_containers/food/snacks/flowerchildsalad + name = "flowerchild salad" + desc = "A fragrant salad." + icon_state = "flowerchildsalad" + filling_color = "#FF3867" + nutriment_amt = 10 + nutriment_desc = list("bittersweet" = 10) + +/obj/item/weapon/reagent_containers/food/snacks/flowerchildsalad/Initialize() + . = ..() + reagents.add_reagent("nutriment", 10) + bitesize = 4 + +/obj/item/weapon/reagent_containers/food/snacks/rosesalad + name = "flowerchild salad" + desc = "A fragrant salad." + icon_state = "rosesalad" + filling_color = "#FF3867" + nutriment_amt = 5 + nutriment_desc = list("bittersweet" = 10, "iron" = 5) + +/obj/item/weapon/reagent_containers/food/snacks/rosesalad/Initialize() + . = ..() + reagents.add_reagent("nutriment", 10) + reagents.add_reagent("stoxin", 2) + bitesize = 4 + /obj/item/weapon/reagent_containers/food/snacks/eggbowl name = "egg bowl" desc = "A bowl of fried rice with egg mixed in." @@ -3901,6 +4090,19 @@ reagents.add_reagent("capsaicin", 4) bitesize = 2 +/obj/item/weapon/reagent_containers/food/snacks/curryrice + name = "curry rice" + desc = "That's some dangerously spicy rice." + icon_state = "curryrice" + nutriment_amt = 6 + nutriment_desc = list("salt" = 1, "rice" = 2, "chili peppers" = 3) + +/obj/item/weapon/reagent_containers/food/snacks/curryrice/Initialize() + . = ..() + reagents.add_reagent("nutriment", 5) + reagents.add_reagent("capsaicin", 4) + bitesize = 2 + /obj/item/weapon/reagent_containers/food/snacks/piginblanket name = "pig in a blanket" desc = "A sausage embedded in soft, fluffy pastry. Free this pig from its blanket prison by eating it." @@ -3964,4 +4166,27 @@ /obj/item/weapon/reagent_containers/food/snacks/wormdeluxe/Initialize() . = ..() reagents.add_reagent("fishbait", 40) - bitesize = 5 \ No newline at end of file + bitesize = 5 + +/obj/item/weapon/reagent_containers/food/snacks/siffruit + name = "pulsing fruit" + desc = "A blue-ish sac encased in a tough black shell." + icon = 'icons/obj/flora/foraging.dmi' + icon_state = "siffruit" + nutriment_amt = 2 + nutriment_desc = list("tart" = 1) + w_class = ITEMSIZE_TINY + +/obj/item/weapon/reagent_containers/food/snacks/siffruit/Initialize() + . = ..() + reagents.add_reagent("sifsap", 2) + +/obj/item/weapon/reagent_containers/food/snacks/siffruit/afterattack(obj/O as obj, mob/user as mob, proximity) + if(istype(O,/obj/machinery/microwave)) + return ..() + if(!(proximity && O.is_open_container())) + return + to_chat(user, "You tear \the [src]'s sac open, pouring it into \the [O].") + reagents.trans_to(O, reagents.total_volume) + user.drop_from_inventory(src) + qdel(src) diff --git a/code/modules/food/food/snacks_vr.dm b/code/modules/food/food/snacks_vr.dm index 0321ca41bb6..a283a6bafe5 100644 --- a/code/modules/food/food/snacks_vr.dm +++ b/code/modules/food/food/snacks_vr.dm @@ -597,28 +597,13 @@ filled = TRUE /obj/item/pizzabox/margherita/Initialize() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/pizza/margfrozen(src) + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margcargo(src) /obj/item/pizzabox/vegetable/Initialize() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/pizza/vegfrozen(src) + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/vegcargo(src) /obj/item/pizzabox/mushroom/Initialize() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/pizza/mushfrozen(src) + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/mushcargo(src) /obj/item/pizzabox/meat/Initialize() - pizza = new /obj/item/weapon/reagent_containers/food/snacks/pizza/meatfrozen(src) - -/obj/item/weapon/reagent_containers/food/snacks/liquidprotein - name = "\improper LiquidProtein Ration" - desc = "A variant of the liquidfood ration, designed for obligate carnivore species. Only barely more appealing than regular liquidfood. Should this be crunchy?" - icon = 'icons/obj/food_vr.dmi' - icon_state = "liquidprotein" - trash = /obj/item/trash/liquidprotein - filling_color = "#A8A8A8" - center_of_mass = list("x"=16, "y"=15) - -/obj/item/weapon/reagent_containers/food/snacks/liquidprotein/Initialize() - ..() - reagents.add_reagent("protein", 20) - reagents.add_reagent("iron", 3) - bitesize = 4 + pizza = new /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatcargo(src) diff --git a/code/modules/food/kitchen/microwave.dm b/code/modules/food/kitchen/microwave.dm index 0eb0683ba80..bb40355d6cc 100644 --- a/code/modules/food/kitchen/microwave.dm +++ b/code/modules/food/kitchen/microwave.dm @@ -246,7 +246,7 @@ return start() if (reagents.total_volume==0 && !(locate(/obj) in ((contents - component_parts) - circuit))) //dry run - if (!wzhzhzh(10)) + if (!wzhzhzh(5)) //VOREStation Edit - Quicker Microwaves abort() return abort() @@ -257,17 +257,17 @@ if (!recipe) dirty += 1 if (prob(max(10,dirty*5))) - if (!wzhzhzh(4)) + if (!wzhzhzh(2)) //VOREStation Edit - Quicker Microwaves abort() return muck_start() - wzhzhzh(4) + wzhzhzh(2) //VOREStation Edit - Quicker Microwaves muck_finish() cooked = fail() cooked.loc = src.loc return else if (has_extra_item()) - if (!wzhzhzh(4)) + if (!wzhzhzh(2)) //VOREStation Edit - Quicker Microwaves abort() return broke() @@ -275,7 +275,7 @@ cooked.loc = src.loc return else - if (!wzhzhzh(10)) + if (!wzhzhzh(5)) //VOREStation Edit - Quicker Microwaves abort() return abort() @@ -283,7 +283,7 @@ cooked.loc = src.loc return else - var/halftime = round(recipe.time/10/2) + var/halftime = round(recipe.time/20/2) //VOREStation Edit - Quicker Microwaves if (!wzhzhzh(halftime)) abort() return @@ -303,7 +303,7 @@ if (stat & (NOPOWER|BROKEN)) return 0 use_power(500) - sleep(10) + sleep(5) //VOREStation Edit - Quicker Microwaves return 1 /obj/machinery/microwave/proc/has_extra_item() diff --git a/code/modules/food/recipes_microwave.dm b/code/modules/food/recipes_microwave.dm index f80fecdd9f0..55ecc2f6372 100644 --- a/code/modules/food/recipes_microwave.dm +++ b/code/modules/food/recipes_microwave.dm @@ -33,6 +33,15 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/boiledegg +/datum/recipe/devilledegg + fruit = list("chili" = 1) + reagents = list("sodiumchloride" = 2, "mayo" = 5) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/egg, + /obj/item/weapon/reagent_containers/food/snacks/egg + ) + result = /obj/item/weapon/reagent_containers/food/snacks/devilledegg + /datum/recipe/dionaroast fruit = list("apple" = 1) reagents = list("pacid" = 5) //It dissolves the carapace. Still poisonous, though. @@ -81,13 +90,6 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/monkeyburger -/datum/recipe/syntiburger - items = list( - /obj/item/weapon/reagent_containers/food/snacks/bun, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh - ) - result = /obj/item/weapon/reagent_containers/food/snacks/monkeyburger - /datum/recipe/brainburger items = list( /obj/item/weapon/reagent_containers/food/snacks/bun, @@ -205,20 +207,6 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread -/datum/recipe/syntibread - items = list( - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/dough, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/meatbread - /datum/recipe/xenomeatbread items = list( /obj/item/weapon/reagent_containers/food/snacks/dough, @@ -344,19 +332,11 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/human/kabob -/datum/recipe/monkeykabob +/datum/recipe/kabob //Do not put before humankabob items = list( /obj/item/stack/rods, - /obj/item/weapon/reagent_containers/food/snacks/meat/monkey, - /obj/item/weapon/reagent_containers/food/snacks/meat/monkey, - ) - result = /obj/item/weapon/reagent_containers/food/snacks/monkeykabob - -/datum/recipe/syntikabob - items = list( - /obj/item/stack/rods, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, + /obj/item/weapon/reagent_containers/food/snacks/meat, + /obj/item/weapon/reagent_containers/food/snacks/meat, ) result = /obj/item/weapon/reagent_containers/food/snacks/monkeykabob @@ -468,11 +448,6 @@ I said no! items = list(/obj/item/weapon/reagent_containers/food/snacks/meat) result = /obj/item/weapon/reagent_containers/food/snacks/meatsteak -/datum/recipe/syntisteak - reagents = list("sodiumchloride" = 1, "blackpepper" = 1) - items = list(/obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh) - result = /obj/item/weapon/reagent_containers/food/snacks/meatsteak - /datum/recipe/pizzamargherita fruit = list("tomato" = 1) items = list( @@ -484,6 +459,15 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/margherita +/datum/recipe/pizzahawaiian + fruit = list("tomato" = 1, "pineapple" = 1) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, + /obj/item/weapon/reagent_containers/food/snacks/cutlet, + /obj/item/weapon/reagent_containers/food/snacks/cheesewedge + ) + result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/pineapple + /datum/recipe/meatpizza fruit = list("tomato" = 1) items = list( @@ -495,17 +479,6 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza -/datum/recipe/syntipizza - fruit = list("tomato" = 1) - items = list( - /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/meat/syntiflesh, - /obj/item/weapon/reagent_containers/food/snacks/cheesewedge - ) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/pizza/meatpizza - /datum/recipe/mushroompizza fruit = list("mushroom" = 5, "tomato" = 1) items = list( @@ -665,6 +638,14 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/toastedsandwich +/datum/recipe/peanutbutterjellysandwich + reagents = list("berryjuice" = 5, "peanutbutter" = 5) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/slice/bread, + /obj/item/weapon/reagent_containers/food/snacks/slice/bread + ) + result = /obj/item/weapon/reagent_containers/food/snacks/jellysandwich/peanutbutter + /datum/recipe/grilledcheese items = list( /obj/item/weapon/reagent_containers/food/snacks/slice/bread, @@ -874,6 +855,30 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/fishfingers +/datum/recipe/zestfish + fruit = list("lemon" = 1) + reagents = list("sodiumchloride" = 3) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/carpmeat + ) + result = /obj/item/weapon/reagent_containers/food/snacks/zestfish + +/datum/recipe/limezestfish + fruit = list("lime" = 1) + reagents = list("sodiumchloride" = 3) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/carpmeat + ) + result = /obj/item/weapon/reagent_containers/food/snacks/zestfish + +/datum/recipe/kudzudonburi + fruit = list("kudzu" = 1) + reagents = list("rice" = 10) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/carpmeat + ) + result = /obj/item/weapon/reagent_containers/food/snacks/kudzudonburi + /datum/recipe/mysterysoup reagents = list("water" = 10) items = list( @@ -925,6 +930,20 @@ I said no! fruit = list("cabbage" = 2, "tomato" = 1, "carrot" = 1, "apple" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/tossedsalad +/datum/recipe/flowersalad + fruit = list("harebell" = 1, "poppy" = 1) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/roastedsunflower + ) + result = /obj/item/weapon/reagent_containers/food/snacks/flowerchildsalad + +/datum/recipe/rosesalad + fruit = list("harebell" = 1, "rose" = 1) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/roastedsunflower + ) + result = /obj/item/weapon/reagent_containers/food/snacks/rosesalad + /datum/recipe/aesirsalad fruit = list("goldapple" = 1, "ambrosiadeus" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/aesirsalad @@ -1019,6 +1038,25 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/fries +/datum/recipe/roastedsunflowerseeds + reagents = list("sodiumchloride" = 1, "cornoil" = 1) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/rawsunflower + ) + result = /obj/item/weapon/reagent_containers/food/snacks/roastedsunflower + +/datum/recipe/roastedpeanutsunflowerseeds + reagents = list("sodiumchloride" = 1, "peanutoil" = 1) + items = list( + /obj/item/weapon/reagent_containers/food/snacks/rawsunflower + ) + result = /obj/item/weapon/reagent_containers/food/snacks/roastedsunflower + +/datum/recipe/roastedpeanuts + fruit = list("peanut" = 2) + reagents = list("sodiumchloride" = 2, "cornoil" = 1) + result = /obj/item/weapon/reagent_containers/food/snacks/roastedpeanuts + /datum/recipe/mint reagents = list("sugar" = 5, "frostoil" = 5) result = /obj/item/weapon/reagent_containers/food/snacks/mint @@ -1156,6 +1194,11 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/cubannachos +/datum/recipe/curryrice + fruit = list("chili" = 1) + reagents = list("rice" = 10) + result = /obj/item/weapon/reagent_containers/food/snacks/curryrice + /datum/recipe/piginblanket items = list( /obj/item/weapon/reagent_containers/food/snacks/sliceable/flatdough, @@ -1163,10 +1206,9 @@ I said no! ) result = /obj/item/weapon/reagent_containers/food/snacks/piginblanket - // Cakes. /datum/recipe/cake - reagents = list("milk" = 5, "flour" = 15, "sugar" = 15, "egg" = 9) + reagents = list("milk" = 5, "flour" = 15, "sugar" = 15, "egg" = 9, "vanilla" = 1) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/plaincake /datum/recipe/cake/carrot @@ -1175,12 +1217,18 @@ I said no! result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/carrotcake /datum/recipe/cake/cheese + reagents = list("milk" = 5, "flour" = 15, "sugar" = 15, "egg" = 9) items = list( /obj/item/weapon/reagent_containers/food/snacks/cheesewedge, /obj/item/weapon/reagent_containers/food/snacks/cheesewedge ) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/cheesecake +/datum/recipe/cake/peanut + fruit = list("peanut" = 3) + reagents = list("milk" = 5, "flour" = 10, "sugar" = 5, "egg" = 6, "peanutbutter" = 5) + result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/peanutcake + /datum/recipe/cake/orange fruit = list("orange" = 1) reagents = list("milk" = 5, "flour" = 15, "egg" = 9,"sugar" = 5) @@ -1202,6 +1250,7 @@ I said no! result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/chocolatecake /datum/recipe/cake/birthday + reagents = list("milk" = 5, "flour" = 15, "sugar" = 15, "egg" = 9) items = list(/obj/item/clothing/head/cakehat) result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake @@ -1211,5 +1260,6 @@ I said no! result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/applecake /datum/recipe/cake/brain + reagents = list("milk" = 5, "flour" = 15, "sugar" = 15, "egg" = 9) items = list(/obj/item/organ/internal/brain) - result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake \ No newline at end of file + result = /obj/item/weapon/reagent_containers/food/snacks/sliceable/braincake diff --git a/code/modules/gamemaster/actions/action.dm b/code/modules/gamemaster/actions/action.dm index aa259ccc033..f8ea16994ec 100644 --- a/code/modules/gamemaster/actions/action.dm +++ b/code/modules/gamemaster/actions/action.dm @@ -7,6 +7,7 @@ var/observers_used = FALSE // Determines if the GM should check if ghosts are available before using this. var/length = 0 // Determines how long the event lasts, until end() is called. var/datum/game_master/gm = null + var/severity = 1 // The severity of the action. This is here to prevent continued future defining of this var on actions, un-used. /datum/gm_action/proc/set_up() return diff --git a/code/modules/gamemaster/actions/atmos_leak.dm b/code/modules/gamemaster/actions/atmos_leak.dm index ab3947cb151..34772bf1a81 100644 --- a/code/modules/gamemaster/actions/atmos_leak.dm +++ b/code/modules/gamemaster/actions/atmos_leak.dm @@ -13,7 +13,7 @@ /area/engineering/engine_room ) - var/severity + severity // Decide which area will be targeted! /datum/gm_action/atmos_leak/set_up() diff --git a/code/modules/gamemaster/actions/blob.dm b/code/modules/gamemaster/actions/blob.dm index 058f678c67c..31a4518a690 100644 --- a/code/modules/gamemaster/actions/blob.dm +++ b/code/modules/gamemaster/actions/blob.dm @@ -3,13 +3,59 @@ departments = list(ROLE_ENGINEERING, ROLE_SECURITY, ROLE_MEDICAL) chaotic = 25 + var/list/area/excluded = list( + /area/submap, + /area/shuttle, + /area/crew_quarters, + /area/holodeck, + /area/engineering/engine_room + ) + + var/area/target_area // Chosen target area + var/turf/target_turf // Chosen target turf in target_area + var/obj/structure/blob/core/Blob + var/spawn_blob_type = /obj/structure/blob/core/random_medium + +/datum/gm_action/blob/set_up() + severity = pickweight(EVENT_LEVEL_MUNDANE = 4, + EVENT_LEVEL_MODERATE = 2, + EVENT_LEVEL_MAJOR = 1 + ) + + var/list/area/grand_list_of_areas = get_station_areas(excluded) + + for(var/i in 1 to 10) + var/area/A = pick(grand_list_of_areas) + if(is_area_occupied(A)) + log_debug("Blob infestation event: Rejected [A] because it is occupied.") + continue + var/list/turfs = list() + for(var/turf/simulated/floor/F in A) + if(turf_clear(F)) + turfs += F + if(turfs.len == 0) + log_debug("Blob infestation event: Rejected [A] because it has no clear turfs.") + continue + target_area = A + target_turf = pick(turfs) + + if(!target_area) + log_debug("Blob infestation event: Giving up after too many failures to pick target area") /datum/gm_action/blob/start() ..() - var/turf/T = pick(blobstart) + var/turf/T - Blob = new /obj/structure/blob/core/random_medium(T) + if(severity == EVENT_LEVEL_MUNDANE || !target_area || !target_turf) + T = pick(blobstart) + else if(severity == EVENT_LEVEL_MODERATE) + T = target_turf + else + T = target_turf + spawn_blob_type = /obj/structure/blob/core/random_hard + + Blob = new spawn_blob_type(T) /datum/gm_action/blob/announce() spawn(rand(600, 3000)) // 1-5 minute leeway for the blob to go un-detected. diff --git a/code/modules/gamemaster/actions/camera_damage.dm b/code/modules/gamemaster/actions/camera_damage.dm index 0f1ef38e9cf..583e57096b8 100644 --- a/code/modules/gamemaster/actions/camera_damage.dm +++ b/code/modules/gamemaster/actions/camera_damage.dm @@ -10,7 +10,7 @@ ..() var/severity_range = 0 - var/severity = pickweight(EVENT_LEVEL_MUNDANE = 10, + severity = pickweight(EVENT_LEVEL_MUNDANE = 10, EVENT_LEVEL_MODERATE = 5, EVENT_LEVEL_MAJOR = 1 ) @@ -44,9 +44,9 @@ return acquire_random_camera(remaining_attempts--) /datum/gm_action/camera_damage/proc/is_valid_camera(var/obj/machinery/camera/C) - // Only return a functional camera, not installed in a silicon, and that exists somewhere players have access + // Only return a functional camera, not installed in a silicon/hardsuit/circuit/etc, and that exists somewhere players have access var/turf/T = get_turf(C) - return T && C.can_use() && !istype(C.loc, /mob/living/silicon) && (T.z in using_map.player_levels) + return T && C.can_use() && istype(C.loc, /turf) && (T.z in using_map.player_levels) /datum/gm_action/camera_damage/get_weight() return 40 + (metric.count_people_in_department(ROLE_ENGINEERING) * 20) + (metric.count_people_in_department(ROLE_SYNTHETIC) * 40) diff --git a/code/modules/gamemaster/actions/carp_migration.dm b/code/modules/gamemaster/actions/carp_migration.dm index b635ca6d5e8..eabb2ce79a6 100644 --- a/code/modules/gamemaster/actions/carp_migration.dm +++ b/code/modules/gamemaster/actions/carp_migration.dm @@ -8,14 +8,7 @@ length = 20 MINUTES /datum/gm_action/carp_migration/get_weight() - var/people_in_space = 0 - for(var/mob/living/L in player_list) - if(!(L.z in using_map.station_levels)) - continue // Not on the right z-level. - var/turf/T = get_turf(L) - if(istype(T, /turf/space) && istype(T.loc,/area/space)) - people_in_space++ - return 50 + (metric.count_people_in_department(ROLE_SECURITY) * 10) + (people_in_space * 20) + return 50 + (metric.count_people_in_department(ROLE_SECURITY) * 10) + (metric.count_all_space_mobs() * 20) /datum/gm_action/carp_migration/announce() var/announcement = "Unknown biological entities have been detected near [station_name()], please stand-by." diff --git a/code/modules/gamemaster/actions/electrified_door.dm b/code/modules/gamemaster/actions/electrified_door.dm index d5365d50aac..e11c72f3456 100644 --- a/code/modules/gamemaster/actions/electrified_door.dm +++ b/code/modules/gamemaster/actions/electrified_door.dm @@ -9,7 +9,6 @@ /area/shuttle, /area/crew_quarters ) - var/severity /datum/gm_action/electrified_door/set_up() var/list/area/grand_list_of_areas = get_station_areas(excluded) diff --git a/code/modules/gamemaster/actions/radiation_storm.dm b/code/modules/gamemaster/actions/radiation_storm.dm index ee4a3edca51..243af5dbee0 100644 --- a/code/modules/gamemaster/actions/radiation_storm.dm +++ b/code/modules/gamemaster/actions/radiation_storm.dm @@ -64,11 +64,4 @@ revoke_maint_all_access() /datum/gm_action/radiation_storm/get_weight() - var/people_in_space = 0 - for(var/mob/living/L in player_list) - if(!(L.z in using_map.station_levels)) - continue // Not on the right z-level. - var/turf/T = get_turf(L) - if(istype(T, /turf/space) && istype(T.loc,/area/space)) - people_in_space++ - return 20 + (metric.count_people_in_department(ROLE_MEDICAL) * 10) + (people_in_space * 40) + (metric.count_people_in_department(ROLE_EVERYONE) * 20) + return 20 + (metric.count_people_in_department(ROLE_MEDICAL) * 10) + (metric.count_all_space_mobs() * 40) + (metric.count_people_in_department(ROLE_EVERYONE) * 20) diff --git a/code/modules/gamemaster/actions/rogue_drones.dm b/code/modules/gamemaster/actions/rogue_drones.dm index 23e57f089de..983aa878424 100644 --- a/code/modules/gamemaster/actions/rogue_drones.dm +++ b/code/modules/gamemaster/actions/rogue_drones.dm @@ -60,11 +60,4 @@ command_announcement.Announce("We're disappointed at the loss of the drones, but the survivors have been recovered.", "Rogue drone alert") /datum/gm_action/rogue_drone/get_weight() - var/people_in_space = 0 - for(var/mob/living/L in player_list) - if(!(L.z in using_map.station_levels)) - continue // Not on the right z-level. - var/turf/T = get_turf(L) - if(istype(T, /turf/space) && istype(T.loc,/area/space)) - people_in_space++ - return 20 + (metric.count_people_in_department(ROLE_SECURITY) * 10) + (people_in_space * 30) + return 20 + (metric.count_people_in_department(ROLE_SECURITY) * 10) + (metric.count_all_space_mobs() * 30) diff --git a/code/modules/gamemaster/actions/solar_storm.dm b/code/modules/gamemaster/actions/solar_storm.dm index 5c5583328b8..046b93639b6 100644 --- a/code/modules/gamemaster/actions/solar_storm.dm +++ b/code/modules/gamemaster/actions/solar_storm.dm @@ -1,6 +1,6 @@ /datum/gm_action/solar_storm name = "solar storm" - var/const/rad_interval = 5 //Same interval period as radiation storms. + var/rad_interval = 1 SECOND var/base_solar_gen_rate length = 3 MINUTES var/duration // Duration for the storm @@ -21,30 +21,25 @@ if(isnull(base_solar_gen_rate)) base_solar_gen_rate = GLOB.solar_gen_rate GLOB.solar_gen_rate = mult * base_solar_gen_rate - /datum/gm_action/solar_storm/start() ..() length = duration command_announcement.Announce("The solar storm has reached the station. Please refain from EVA and remain inside the station until it has passed.", "Anomaly Alert") adjust_solar_output(5) - while(world.time <= world.time + duration) - if(duration % rad_interval == 0) + var/start_time = world.time + + spawn() + while(world.time <= start_time + duration) + sleep(rad_interval) radiate() /datum/gm_action/solar_storm/get_weight() - var/people_in_space = 0 - for(var/mob/living/L in player_list) - if(!(L.z in using_map.station_levels)) - continue // Not on the right z-level. - var/turf/T = get_turf(L) - if(istype(T, /turf/space) && istype(T.loc,/area/space)) - people_in_space++ - return 20 + (metric.count_people_in_department(ROLE_ENGINEERING) * 10) + (people_in_space * 30) + return 20 + (metric.count_people_in_department(ROLE_ENGINEERING) * 10) + (metric.count_all_space_mobs() * 30) /datum/gm_action/solar_storm/proc/radiate() // Note: Too complicated to be worth trying to use the radiation system for this. Its only in space anyway, so we make an exception in this case. - for(var/mob/living/L in living_mob_list) + for(var/mob/living/L in player_list) var/turf/T = get_turf(L) if(!T) continue diff --git a/code/modules/gamemaster/actions/spider_infestation.dm b/code/modules/gamemaster/actions/spider_infestation.dm index c98aa4de8b9..baba49c2e3b 100644 --- a/code/modules/gamemaster/actions/spider_infestation.dm +++ b/code/modules/gamemaster/actions/spider_infestation.dm @@ -3,7 +3,7 @@ departments = list(ROLE_SECURITY, ROLE_MEDICAL, ROLE_EVERYONE) chaotic = 30 - var/severity = 1 + severity = 1 var/spawncount = 1 diff --git a/code/modules/gamemaster/actions/surprise_carp_attack.dm b/code/modules/gamemaster/actions/surprise_carp_attack.dm index 14c4b03e0e0..dce6121b619 100644 --- a/code/modules/gamemaster/actions/surprise_carp_attack.dm +++ b/code/modules/gamemaster/actions/surprise_carp_attack.dm @@ -8,14 +8,7 @@ var/mob/living/victim = null /datum/gm_action/surprise_carp_attack/get_weight() - var/people_in_space = 0 - for(var/mob/living/L in player_list) - if(!(L.z in using_map.station_levels)) - continue // Not on the right z-level. - var/turf/T = get_turf(L) - if(istype(T, /turf/space) && istype(T.loc,/area/space)) - people_in_space++ - return people_in_space * 50 + return metric.count_all_space_mobs() * 50 /datum/gm_action/surprise_carp_attack/set_up() var/list/potential_victims = list() @@ -28,7 +21,8 @@ var/turf/T = get_turf(L) if(istype(T, /turf/space) && istype(T.loc,/area/space)) potential_victims.Add(L) - victim = pick(potential_victims) + if(potential_victims.len) + victim = pick(potential_victims) /datum/gm_action/surprise_carp_attack/start() diff --git a/code/modules/gamemaster/actions/viral_infection.dm b/code/modules/gamemaster/actions/viral_infection.dm index d33c4f52765..9b42e2df460 100644 --- a/code/modules/gamemaster/actions/viral_infection.dm +++ b/code/modules/gamemaster/actions/viral_infection.dm @@ -5,7 +5,7 @@ departments = list(ROLE_MEDICAL) chaotic = 5 var/list/viruses = list() - var/severity = 1 + severity = 1 /datum/gm_action/viral_infection/set_up() severity = pickweight(EVENT_LEVEL_MUNDANE = 20, diff --git a/code/modules/gamemaster/actions/viral_outbreak.dm b/code/modules/gamemaster/actions/viral_outbreak.dm index f7f1719e4a5..f0eb27b41ab 100644 --- a/code/modules/gamemaster/actions/viral_outbreak.dm +++ b/code/modules/gamemaster/actions/viral_outbreak.dm @@ -2,7 +2,7 @@ name = "viral outbreak" departments = list(ROLE_MEDICAL, ROLE_EVERYONE) chaotic = 30 - var/severity = 1 + severity = 1 var/list/candidates = list() /datum/gm_action/viral_outbreak/set_up() diff --git a/code/modules/gamemaster/actions/wallrot.dm b/code/modules/gamemaster/actions/wallrot.dm index e81a293aab2..e2c05aed74c 100644 --- a/code/modules/gamemaster/actions/wallrot.dm +++ b/code/modules/gamemaster/actions/wallrot.dm @@ -3,7 +3,7 @@ departments = list(ROLE_ENGINEERING) reusable = TRUE var/turf/simulated/wall/center - var/severity = 1 + severity = 1 /datum/gm_action/wallrot/set_up() severity = rand(1,3) diff --git a/code/modules/gamemaster/actions/wormholes.dm b/code/modules/gamemaster/actions/wormholes.dm index 15216746be2..f2a90f55395 100644 --- a/code/modules/gamemaster/actions/wormholes.dm +++ b/code/modules/gamemaster/actions/wormholes.dm @@ -3,7 +3,7 @@ chaotic = 70 length = 12 MINUTES departments = list(ROLE_EVERYONE) - var/severity = 1 + severity = 1 /datum/gm_action/wormholes/set_up() // 1 out of 5 will be full-duration wormholes, meaning up to a minute long. severity = pickweight(list( diff --git a/code/modules/holodeck/HolodeckObjects.dm b/code/modules/holodeck/HolodeckObjects.dm index 22b4b2e6c6d..c1c7ebedafa 100644 --- a/code/modules/holodeck/HolodeckObjects.dm +++ b/code/modules/holodeck/HolodeckObjects.dm @@ -126,6 +126,38 @@ slot_r_hand_str = 'icons/mob/items/righthand_gloves.dmi', ) item_state = "boxing" + special_attack_type = /datum/unarmed_attack/holopugilism + +datum/unarmed_attack/holopugilism + sparring_variant_type = /datum/unarmed_attack/holopugilism + +datum/unarmed_attack/holopugilism/unarmed_override(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/zone) + user.do_attack_animation(src) + var/damage = rand(0, 9) + if(!damage) + playsound(target.loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + target.visible_message("[user] has attempted to punch [target]!") + return TRUE + var/obj/item/organ/external/affecting = target.get_organ(ran_zone(user.zone_sel.selecting)) + var/armor_block = target.run_armor_check(affecting, "melee") + var/armor_soak = target.get_armor_soak(affecting, "melee") + + if(HULK in user.mutations) + damage += 5 + + playsound(target.loc, "punch", 25, 1, -1) + + target.visible_message("[user] has punched [target]!") + + if(armor_soak >= damage) + return TRUE + + target.apply_damage(damage, HALLOSS, affecting, armor_block, armor_soak) + if(damage >= 9) + target.visible_message("[user] has weakened [target]!") + target.apply_effect(4, WEAKEN, armor_block) + + return TRUE /obj/structure/window/reinforced/holowindow/attackby(obj/item/W as obj, mob/user as mob) if(!istype(W)) @@ -262,8 +294,8 @@ spark_system.set_up(5, 0, user.loc) spark_system.start() playsound(user.loc, 'sound/weapons/blade1.ogg', 50, 1) - return 1 - return 0 + return TRUE + return FALSE /obj/item/weapon/holo/esword/New() item_color = pick("red","blue","green","purple") diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 40236e42af1..81018de61ca 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -5,6 +5,7 @@ icon = 'icons/obj/hydroponics_products.dmi' icon_state = "blank" desc = "Nutritious! Probably." + flags = NOCONDUCT slot_flags = SLOT_HOLSTER var/plantname diff --git a/code/modules/hydroponics/grown_inedible.dm b/code/modules/hydroponics/grown_inedible.dm index aa054cae29d..2b02116478a 100644 --- a/code/modules/hydroponics/grown_inedible.dm +++ b/code/modules/hydroponics/grown_inedible.dm @@ -37,6 +37,7 @@ desc = "A reminder of meals gone by." icon = 'icons/obj/trash.dmi' icon_state = "corncob" + flags = NOCONDUCT w_class = ITEMSIZE_SMALL throwforce = 0 throw_speed = 4 @@ -55,6 +56,7 @@ desc = "A peel from a banana." icon = 'icons/obj/items.dmi' icon_state = "banana_peel" + flags = NOCONDUCT w_class = ITEMSIZE_SMALL throwforce = 0 throw_speed = 4 diff --git a/code/modules/hydroponics/seed.dm b/code/modules/hydroponics/seed.dm index 0ec87dca8a0..b2d4443c9c8 100644 --- a/code/modules/hydroponics/seed.dm +++ b/code/modules/hydroponics/seed.dm @@ -21,7 +21,9 @@ var/kitchen_tag // Used by the reagent grinder. var/trash_type // Garbage item produced when eaten. var/splat_type = /obj/effect/decal/cleanable/fruit_smudge // Graffiti decal. - var/has_mob_product + var/has_mob_product // Mob products. (Dionaea, Walking Mushrooms, Angry Tomatoes) + var/apply_color_to_mob = TRUE // Do we color the mob to match the plant? + var/has_item_product // Item products. (Eggy) var/force_layer /datum/seed/New() @@ -619,6 +621,7 @@ gene.values["[TRAIT_CONSUME_GASSES]"] = null if(GENE_METABOLISM) has_mob_product = gene.values["mob_product"] + has_item_product = gene.values["item_product"] gene.values["mob_product"] = null for(var/trait in gene.values) @@ -649,6 +652,7 @@ traits_to_copy = list(TRAIT_TOXINS_TOLERANCE,TRAIT_PEST_TOLERANCE,TRAIT_WEED_TOLERANCE,TRAIT_ENDURANCE) if(GENE_METABOLISM) P.values["mob_product"] = has_mob_product + P.values["item_product"] = has_item_product traits_to_copy = list(TRAIT_REQUIRES_NUTRIENTS,TRAIT_REQUIRES_WATER,TRAIT_ALTER_TEMP) if(GENE_VIGOUR) traits_to_copy = list(TRAIT_PRODUCTION,TRAIT_MATURATION,TRAIT_YIELD,TRAIT_SPREAD) @@ -709,6 +713,8 @@ var/obj/item/product if(has_mob_product) product = new has_mob_product(get_turf(user),name) + else if(has_item_product) + product = new has_item_product(get_turf(user)) else product = new /obj/item/weapon/reagent_containers/food/snacks/grown(get_turf(user),name) if(get_trait(TRAIT_PRODUCT_COLOUR)) @@ -752,6 +758,8 @@ new_seed.kitchen_tag = kitchen_tag new_seed.trash_type = trash_type new_seed.has_mob_product = has_mob_product + new_seed.has_item_product = has_item_product + //Copy over everything else. if(mutants) new_seed.mutants = mutants.Copy() if(chems) new_seed.chems = chems.Copy() diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm index eab78597b18..9e34611b7da 100644 --- a/code/modules/hydroponics/seed_datums.dm +++ b/code/modules/hydroponics/seed_datums.dm @@ -3,9 +3,9 @@ name = "chili" seed_name = "chili" display_name = "chili plants" + kitchen_tag = "chili" chems = list("capsaicin" = list(3,5), "nutriment" = list(1,25)) mutants = list("icechili") - kitchen_tag = "chili" /datum/seed/chili/New() ..() @@ -24,9 +24,9 @@ name = "icechili" seed_name = "ice pepper" display_name = "ice-pepper plants" + kitchen_tag = "icechili" mutants = null chems = list("frostoil" = list(3,5), "nutriment" = list(1,50)) - kitchen_tag = "icechili" /datum/seed/chili/ice/New() ..() @@ -39,9 +39,9 @@ name = "berries" seed_name = "berry" display_name = "berry bush" + kitchen_tag = "berries" mutants = list("glowberries","poisonberries") chems = list("nutriment" = list(1,10), "berryjuice" = list(10,10)) - kitchen_tag = "berries" /datum/seed/berry/New() ..() @@ -112,7 +112,6 @@ mutants = list("deathnettle") chems = list("nutriment" = list(1,50), "sacid" = list(0,1)) kitchen_tag = "nettle" - kitchen_tag = "nettle" /datum/seed/nettle/New() ..() @@ -130,9 +129,9 @@ name = "deathnettle" seed_name = "death nettle" display_name = "death nettles" + kitchen_tag = "deathnettle" mutants = null chems = list("nutriment" = list(1,50), "pacid" = list(0,1)) - kitchen_tag = "deathnettle" /datum/seed/nettle/death/New() ..() @@ -222,9 +221,9 @@ name = "eggplant" seed_name = "eggplant" display_name = "eggplants" - mutants = list("realeggplant") - chems = list("nutriment" = list(1,10)) kitchen_tag = "eggplant" + mutants = list("egg-plant") + chems = list("nutriment" = list(1,10)) /datum/seed/eggplant/New() ..() @@ -239,14 +238,24 @@ set_trait(TRAIT_IDEAL_HEAT, 298) set_trait(TRAIT_IDEAL_LIGHT, 7) +// Return of Eggy. Just makes purple eggs. If the reagents are separated from the egg production by xenobotany or RNG, it's still an Egg plant. +/datum/seed/eggplant/egg + name = "egg-plant" + seed_name = "egg-plant" + display_name = "egg-plants" + kitchen_tag = "egg-plant" + mutants = null + chems = list("nutriment" = list(1,5), "egg" = list(3,12)) + has_item_product = /obj/item/weapon/reagent_containers/food/snacks/egg/purple + //Apples/varieties. /datum/seed/apple name = "apple" seed_name = "apple" display_name = "apple tree" + kitchen_tag = "apple" mutants = list("poisonapple","goldapple") chems = list("nutriment" = list(1,10),"applejuice" = list(10,20)) - kitchen_tag = "apple" /datum/seed/apple/New() ..() @@ -270,9 +279,9 @@ name = "goldapple" seed_name = "golden apple" display_name = "gold apple tree" + kitchen_tag = "goldapple" mutants = null chems = list("nutriment" = list(1,10), "gold" = list(1,5)) - kitchen_tag = "goldapple" /datum/seed/apple/gold/New() ..() @@ -287,9 +296,9 @@ name = "ambrosia" seed_name = "ambrosia vulgaris" display_name = "ambrosia vulgaris" + kitchen_tag = "ambrosia" mutants = list("ambrosiadeus") chems = list("nutriment" = list(1), "space_drugs" = list(1,8), "kelotane" = list(1,8,1), "bicaridine" = list(1,10,1), "toxin" = list(1,10)) - kitchen_tag = "ambrosia" /datum/seed/ambrosia/New() ..() @@ -307,9 +316,9 @@ name = "ambrosiadeus" seed_name = "ambrosia deus" display_name = "ambrosia deus" + kitchen_tag = "ambrosiadeus" mutants = null chems = list("nutriment" = list(1), "bicaridine" = list(1,8), "synaptizine" = list(1,8,1), "hyperzine" = list(1,10,1), "space_drugs" = list(1,10)) - kitchen_tag = "ambrosiadeus" /datum/seed/ambrosia/deus/New() ..() @@ -450,6 +459,7 @@ display_name = "tower caps" chems = list("woodpulp" = list(10,1)) mutants = null + has_item_product = /obj/item/stack/material/log /datum/seed/mushroom/towercap/New() ..() @@ -502,6 +512,7 @@ name = "harebells" seed_name = "harebell" display_name = "harebells" + kitchen_tag = "harebell" chems = list("nutriment" = list(1,20)) /datum/seed/flower/New() @@ -519,8 +530,8 @@ name = "poppies" seed_name = "poppy" display_name = "poppies" - chems = list("nutriment" = list(1,20), "bicaridine" = list(1,10)) kitchen_tag = "poppy" + chems = list("nutriment" = list(1,20), "bicaridine" = list(1,10)) /datum/seed/flower/poppy/New() ..() @@ -539,6 +550,7 @@ name = "sunflowers" seed_name = "sunflower" display_name = "sunflowers" + kitchen_tag = "sunflower" /datum/seed/flower/sunflower/New() ..() @@ -554,6 +566,7 @@ name = "lavender" seed_name = "lavender" display_name = "lavender" + kitchen_tag = "lavender" chems = list("nutriment" = list(1,20), "bicaridine" = list(1,10)) /datum/seed/flower/lavender/New() @@ -569,11 +582,46 @@ set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.05) set_trait(TRAIT_WATER_CONSUMPTION, 0.5) +/datum/seed/flower/rose + name = "rose" + seed_name = "rose" + display_name = "rose" + kitchen_tag = "rose" + mutants = list("bloodrose") + chems = list("nutriment" = list(1,5), "stoxin" = list(0,2)) + +/datum/seed/flower/rose/New() + ..() + set_trait(TRAIT_MATURATION,7) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_PRODUCT_ICON,"flowers") + set_trait(TRAIT_PRODUCT_COLOUR,"#ce0e0e") + set_trait(TRAIT_PLANT_COLOUR,"#6B8C5E") + set_trait(TRAIT_PLANT_ICON,"bush5") + set_trait(TRAIT_IDEAL_LIGHT, 7) + set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.1) + set_trait(TRAIT_WATER_CONSUMPTION, 0.5) + set_trait(TRAIT_STINGS,1) + +/datum/seed/flower/rose/blood + name = "bloodrose" + display_name = "bleeding rose" + mutants = null + chems = list("nutriment" = list(1,5), "stoxin" = list(1,5), "blood" = list(0,2)) + +/datum/seed/flower/rose/blood/New() + ..() + set_trait(TRAIT_IDEAL_LIGHT, 1) + set_trait(TRAIT_PLANT_COLOUR,"#5e0303") + set_trait(TRAIT_CARNIVOROUS,1) + //Grapes/varieties /datum/seed/grapes name = "grapes" seed_name = "grape" display_name = "grapevines" + kitchen_tag = "grapes" mutants = list("greengrapes") chems = list("nutriment" = list(1,10), "sugar" = list(1,5), "grapejuice" = list(10,10)) @@ -602,12 +650,103 @@ ..() set_trait(TRAIT_PRODUCT_COLOUR,"42ed2f") +// Lettuce/varieties. +/datum/seed/lettuce + name = "lettuce" + seed_name = "lettuce" + display_name = "lettuce" + kitchen_tag = "cabbage" + chems = list("nutriment" = list(1,15)) + +/datum/seed/lettuce/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,4) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,6) + set_trait(TRAIT_POTENCY,8) + set_trait(TRAIT_PRODUCT_ICON,"lettuce") + set_trait(TRAIT_PRODUCT_COLOUR,"#A8D0A7") + set_trait(TRAIT_PLANT_COLOUR,"#6D9C6B") + set_trait(TRAIT_PLANT_ICON,"vine2") + set_trait(TRAIT_IDEAL_LIGHT, 6) + set_trait(TRAIT_WATER_CONSUMPTION, 8) + set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.13) + +/datum/seed/lettuce/ice + name = "siflettuce" + seed_name = "glacial lettuce" + display_name = "glacial lettuce" + kitchen_tag = "icelettuce" + chems = list("nutriment" = list(1,5), "paracetamol" = list(0,2)) + +/datum/seed/lettuce/ice/New() + ..() + set_trait(TRAIT_ALTER_TEMP, -5) + set_trait(TRAIT_PRODUCT_COLOUR,"#9ABCC9") + +//Wabback / varieties. +/datum/seed/wabback + name = "whitewabback" + seed_name = "white wabback" + seed_noun = "nodes" + display_name = "white wabback" + chems = list("nutriment" = list(1,10), "protein" = list(1,5), "enzyme" = list(0,3)) + kitchen_tag = "wabback" + mutants = list("blackwabback","wildwabback") + has_item_product = /obj/item/stack/material/cloth + +/datum/seed/wabback/New() + ..() + set_trait(TRAIT_IDEAL_LIGHT, 5) + set_trait(TRAIT_MATURATION,8) + set_trait(TRAIT_PRODUCTION,3) + set_trait(TRAIT_YIELD,2) + set_trait(TRAIT_POTENCY,5) + set_trait(TRAIT_PRODUCT_ICON,"carrot2") + set_trait(TRAIT_PRODUCT_COLOUR,"#E6EDFA") + set_trait(TRAIT_PLANT_ICON,"chute") + set_trait(TRAIT_PLANT_COLOUR, "#0650ce") + set_trait(TRAIT_WATER_CONSUMPTION, 10) + set_trait(TRAIT_ALTER_TEMP, -1) + set_trait(TRAIT_CARNIVOROUS,1) + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_SPREAD,1) + +/datum/seed/wabback/vine + name = "blackwabback" + seed_name = "black wabback" + display_name = "black wabback" + mutants = null + chems = list("nutriment" = list(1,3), "protein" = list(1,10), "serotrotium_v" = list(0,1)) + +/datum/seed/wabback/vine/New() + ..() + set_trait(TRAIT_PRODUCT_COLOUR,"#2E2F32") + set_trait(TRAIT_CARNIVOROUS,2) + +/datum/seed/wabback/wild + name = "wildwabback" + seed_name = "wild wabback" + display_name = "wild wabback" + mutants = list("whitewabback") + has_item_product = null + chems = list("nutriment" = list(1,15), "protein" = list(0,2), "enzyme" = list(0,1)) + +/datum/seed/wabback/wild/New() + ..() + set_trait(TRAIT_IDEAL_LIGHT, 3) + set_trait(TRAIT_WATER_CONSUMPTION, 7) + set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.1) + set_trait(TRAIT_YIELD,5) + //Everything else /datum/seed/peanuts name = "peanut" seed_name = "peanut" display_name = "peanut vines" - chems = list("nutriment" = list(1,10)) + kitchen_tag = "peanut" + chems = list("nutriment" = list(1,10), "peanutoil" = list(1,3)) /datum/seed/peanuts/New() ..() @@ -621,12 +760,32 @@ set_trait(TRAIT_PLANT_ICON,"bush2") set_trait(TRAIT_IDEAL_LIGHT, 6) +/datum/seed/vanilla + name = "vanilla" + seed_name = "vanilla" + display_name = "vanilla" + kitchen_tag = "vanilla" + chems = list("nutriment" = list(1,10), "vanilla" = list(0,3), "sugar" = list(0, 1)) + +/datum/seed/vanilla/New() + ..() + set_trait(TRAIT_MATURATION,7) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_PRODUCT_ICON,"chili") + set_trait(TRAIT_PRODUCT_COLOUR,"#B57EDC") + set_trait(TRAIT_PLANT_COLOUR,"#6B8C5E") + set_trait(TRAIT_PLANT_ICON,"bush5") + set_trait(TRAIT_IDEAL_LIGHT, 8) + set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.3) + set_trait(TRAIT_WATER_CONSUMPTION, 0.5) + /datum/seed/cabbage name = "cabbage" seed_name = "cabbage" display_name = "cabbages" - chems = list("nutriment" = list(1,10)) kitchen_tag = "cabbage" + chems = list("nutriment" = list(1,10)) /datum/seed/cabbage/New() ..() @@ -647,9 +806,9 @@ name = "banana" seed_name = "banana" display_name = "banana tree" + kitchen_tag = "banana" chems = list("banana" = list(10,10)) trash_type = /obj/item/weapon/bananapeel - kitchen_tag = "banana" /datum/seed/banana/New() ..() @@ -669,8 +828,8 @@ name = "corn" seed_name = "corn" display_name = "ears of corn" - chems = list("nutriment" = list(1,10), "cornoil" = list(1,10)) kitchen_tag = "corn" + chems = list("nutriment" = list(1,10), "cornoil" = list(1,10)) trash_type = /obj/item/weapon/corncob /datum/seed/corn/New() @@ -691,8 +850,8 @@ name = "potato" seed_name = "potato" display_name = "potatoes" - chems = list("nutriment" = list(1,10), "potatojuice" = list(10,10)) kitchen_tag = "potato" + chems = list("nutriment" = list(1,10), "potatojuice" = list(10,10)) /datum/seed/potato/New() ..() @@ -707,29 +866,29 @@ set_trait(TRAIT_WATER_CONSUMPTION, 6) /datum/seed/onion - name = "onion" - seed_name = "onion" - display_name = "onions" - chems = list("nutriment" = list(1,10)) - kitchen_tag = "onion" + name = "onion" + seed_name = "onion" + display_name = "onions" + kitchen_tag = "onion" + chems = list("nutriment" = list(1,10)) /datum/seed/onion/New() - ..() - set_trait(TRAIT_MATURATION,10) - set_trait(TRAIT_PRODUCTION,1) - set_trait(TRAIT_YIELD,4) - set_trait(TRAIT_POTENCY,10) - set_trait(TRAIT_PRODUCT_ICON,"onion") - set_trait(TRAIT_PRODUCT_COLOUR,"#E0C367") - set_trait(TRAIT_PLANT_ICON,"carrot") - set_trait(TRAIT_WATER_CONSUMPTION, 6) + ..() + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_PRODUCTION,1) + set_trait(TRAIT_YIELD,4) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"onion") + set_trait(TRAIT_PRODUCT_COLOUR,"#E0C367") + set_trait(TRAIT_PLANT_ICON,"carrot") + set_trait(TRAIT_WATER_CONSUMPTION, 6) /datum/seed/soybean name = "soybean" seed_name = "soybean" display_name = "soybeans" - chems = list("nutriment" = list(1,20), "soymilk" = list(10,20)) kitchen_tag = "soybeans" + chems = list("nutriment" = list(1,20), "soymilk" = list(10,20)) /datum/seed/soybean/New() ..() @@ -746,8 +905,8 @@ name = "wheat" seed_name = "wheat" display_name = "wheat stalks" - chems = list("nutriment" = list(1,25), "flour" = list(15,15)) kitchen_tag = "wheat" + chems = list("nutriment" = list(1,25), "flour" = list(15,15)) /datum/seed/wheat/New() ..() @@ -766,8 +925,8 @@ name = "rice" seed_name = "rice" display_name = "rice stalks" - chems = list("nutriment" = list(1,25), "rice" = list(10,15)) kitchen_tag = "rice" + chems = list("nutriment" = list(1,25), "rice" = list(10,15)) /datum/seed/rice/New() ..() @@ -786,8 +945,8 @@ name = "carrot" seed_name = "carrot" display_name = "carrots" - chems = list("nutriment" = list(1,20), "imidazoline" = list(3,5), "carrotjuice" = list(10,20)) kitchen_tag = "carrot" + chems = list("nutriment" = list(1,20), "imidazoline" = list(3,5), "carrotjuice" = list(10,20)) /datum/seed/carrots/New() ..() @@ -821,8 +980,8 @@ name = "whitebeet" seed_name = "white-beet" display_name = "white-beets" - chems = list("nutriment" = list(0,20), "sugar" = list(1,5)) kitchen_tag = "whitebeet" + chems = list("nutriment" = list(0,20), "sugar" = list(1,5)) /datum/seed/whitebeets/New() ..() @@ -840,6 +999,7 @@ name = "sugarcane" seed_name = "sugarcane" display_name = "sugarcanes" + kitchen_tag = "sugarcanes" chems = list("sugar" = list(4,5)) /datum/seed/sugarcane/New() @@ -855,12 +1015,93 @@ set_trait(TRAIT_PLANT_ICON,"stalk3") set_trait(TRAIT_IDEAL_HEAT, 298) +/datum/seed/rhubarb + name = "rhubarb" + seed_name = "rhubarb" + display_name = "rhubarb" + kitchen_tag = "rhubarb" + chems = list("nutriment" = list(1,15)) + +/datum/seed/rhubarb/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,3) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,5) + set_trait(TRAIT_POTENCY,6) + set_trait(TRAIT_PRODUCT_ICON,"stalk") + set_trait(TRAIT_PRODUCT_COLOUR,"#FD5656") + set_trait(TRAIT_PLANT_ICON,"stalk3") + +/datum/seed/celery + name = "celery" + seed_name = "celery" + display_name = "celery" + kitchen_tag = "celery" + chems = list("nutriment" = list(5,20)) + +/datum/seed/celery/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,4) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,8) + set_trait(TRAIT_PRODUCT_ICON,"stalk") + set_trait(TRAIT_PRODUCT_COLOUR,"#56FD56") + set_trait(TRAIT_PLANT_ICON,"stalk3") + +/datum/seed/spineapple + name = "spineapple" + seed_name = "spineapple" + display_name = "spineapple" + kitchen_tag = "pineapple" + chems = list("nutriment" = list(1,5), "enzyme" = list(1,5), "pineapplejuice" = list(1, 20)) + +/datum/seed/spineapple/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,10) + set_trait(TRAIT_PRODUCTION,6) + set_trait(TRAIT_YIELD,1) + set_trait(TRAIT_POTENCY,13) + set_trait(TRAIT_PRODUCT_ICON,"pineapple") + set_trait(TRAIT_PRODUCT_COLOUR,"#FFF23B") + set_trait(TRAIT_PLANT_COLOUR,"#87C969") + set_trait(TRAIT_PLANT_ICON,"corn") + set_trait(TRAIT_IDEAL_HEAT, 298) + set_trait(TRAIT_IDEAL_LIGHT, 4) + set_trait(TRAIT_WATER_CONSUMPTION, 8) + set_trait(TRAIT_STINGS,1) + +/datum/seed/durian + name = "durian" + seed_name = "durian" + seed_noun = "pits" + display_name = "durian" + kitchen_tag = "durian" + chems = list("nutriment" = list(1,5), "durianpaste" = list(1, 20)) + +/datum/seed/durian/New() + ..() + set_trait(TRAIT_HARVEST_REPEAT,1) + set_trait(TRAIT_MATURATION,6) + set_trait(TRAIT_PRODUCTION,5) + set_trait(TRAIT_YIELD,3) + set_trait(TRAIT_POTENCY,10) + set_trait(TRAIT_PRODUCT_ICON,"spinefruit") + set_trait(TRAIT_PRODUCT_COLOUR,"#757631") + set_trait(TRAIT_PLANT_COLOUR,"#87C969") + set_trait(TRAIT_PLANT_ICON,"tree") + set_trait(TRAIT_IDEAL_LIGHT, 8) + set_trait(TRAIT_WATER_CONSUMPTION, 8) + /datum/seed/watermelon name = "watermelon" seed_name = "watermelon" display_name = "watermelon vine" - chems = list("nutriment" = list(1,6), "watermelonjuice" = list(10,6)) kitchen_tag = "watermelon" + chems = list("nutriment" = list(1,6), "watermelonjuice" = list(10,6)) /datum/seed/watermelon/New() ..() @@ -883,8 +1124,8 @@ name = "pumpkin" seed_name = "pumpkin" display_name = "pumpkin vine" - chems = list("nutriment" = list(1,6)) kitchen_tag = "pumpkin" + chems = list("nutriment" = list(1,6)) /datum/seed/pumpkin/New() ..() @@ -903,8 +1144,8 @@ name = "lime" seed_name = "lime" display_name = "lime trees" - chems = list("nutriment" = list(1,20), "limejuice" = list(10,20)) kitchen_tag = "lime" + chems = list("nutriment" = list(1,20), "limejuice" = list(10,20)) /datum/seed/citrus/New() ..() @@ -923,8 +1164,8 @@ name = "lemon" seed_name = "lemon" display_name = "lemon trees" - chems = list("nutriment" = list(1,20), "lemonjuice" = list(10,20)) kitchen_tag = "lemon" + chems = list("nutriment" = list(1,20), "lemonjuice" = list(10,20)) /datum/seed/citrus/lemon/New() ..() @@ -950,8 +1191,8 @@ name = "grass" seed_name = "grass" display_name = "grass" - chems = list("nutriment" = list(1,20)) kitchen_tag = "grass" + chems = list("nutriment" = list(1,20)) /datum/seed/grass/New() ..() @@ -970,6 +1211,7 @@ name = "cocoa" seed_name = "cacao" display_name = "cacao tree" + kitchen_tag = "cocoa" chems = list("nutriment" = list(1,10), "coco" = list(4,5)) /datum/seed/cocoa/New() @@ -990,8 +1232,8 @@ seed_name = "cherry" seed_noun = "pits" display_name = "cherry tree" - chems = list("nutriment" = list(1,15), "sugar" = list(1,15), "cherryjelly" = list(10,15)) kitchen_tag = "cherries" + chems = list("nutriment" = list(1,15), "sugar" = list(1,15), "cherryjelly" = list(10,15)) /datum/seed/cherries/New() ..() @@ -1010,6 +1252,7 @@ name = "kudzu" seed_name = "kudzu" display_name = "kudzu vines" + kitchen_tag = "kudzu" chems = list("nutriment" = list(1,50), "anti_toxin" = list(1,25)) /datum/seed/kudzu/New() @@ -1031,6 +1274,7 @@ seed_noun = "nodes" display_name = "replicant pods" can_self_harvest = 1 + apply_color_to_mob = FALSE has_mob_product = /mob/living/carbon/alien/diona /datum/seed/diona/New() @@ -1050,8 +1294,8 @@ name = "shand" seed_name = "Selem's hand" display_name = "Selem's hand leaves" - chems = list("bicaridine" = list(0,10)) kitchen_tag = "shand" + chems = list("bicaridine" = list(0,10)) /datum/seed/shand/New() ..() @@ -1070,8 +1314,8 @@ name = "mtear" seed_name = "Malani's tear" display_name = "Malani's tear leaves" - chems = list("honey" = list(1,10), "kelotane" = list(3,5)) kitchen_tag = "mtear" + chems = list("honey" = list(1,10), "kelotane" = list(3,5)) /datum/seed/mtear/New() ..() @@ -1090,11 +1334,13 @@ name = "telriis" seed_name = "telriis" display_name = "telriis grass" + kitchen_tag = "telriis" chems = list("pwine" = list(1,5), "nutriment" = list(1,6)) /datum/seed/telriis/New() ..() - set_trait(TRAIT_PLANT_ICON,"telriis") + set_trait(TRAIT_PLANT_ICON,"ambrosia") + set_trait(TRAIT_PRODUCT_ICON,"ambrosia") set_trait(TRAIT_ENDURANCE,50) set_trait(TRAIT_MATURATION,5) set_trait(TRAIT_PRODUCTION,5) @@ -1105,11 +1351,13 @@ name = "thaadra" seed_name = "thaa'dra" display_name = "thaa'dra lichen" + kitchen_tag = "thaadra" chems = list("frostoil" = list(1,5),"nutriment" = list(1,5)) /datum/seed/thaadra/New() ..() - set_trait(TRAIT_PLANT_ICON,"thaadra") + set_trait(TRAIT_PLANT_ICON,"grass") + set_trait(TRAIT_PLANT_COLOUR,"#ABC7D2") set_trait(TRAIT_ENDURANCE,10) set_trait(TRAIT_MATURATION,5) set_trait(TRAIT_PRODUCTION,9) @@ -1120,11 +1368,12 @@ name = "jurlmah" seed_name = "jurl'mah" display_name = "jurl'mah reeds" + kitchen_tag = "jurlmah" chems = list("serotrotium" = list(1,5),"nutriment" = list(1,5)) /datum/seed/jurlmah/New() ..() - set_trait(TRAIT_PLANT_ICON,"jurlmah") + set_trait(TRAIT_PLANT_ICON,"mushroom9") set_trait(TRAIT_ENDURANCE,12) set_trait(TRAIT_MATURATION,8) set_trait(TRAIT_PRODUCTION,9) @@ -1135,11 +1384,12 @@ name = "amauri" seed_name = "amauri" display_name = "amauri plant" + kitchen_tag = "amauri" chems = list("zombiepowder" = list(1,10),"condensedcapsaicin" = list(1,5),"nutriment" = list(1,5)) /datum/seed/amauri/New() ..() - set_trait(TRAIT_PLANT_ICON,"amauri") + set_trait(TRAIT_PLANT_ICON,"bush4") set_trait(TRAIT_ENDURANCE,10) set_trait(TRAIT_MATURATION,8) set_trait(TRAIT_PRODUCTION,9) @@ -1150,11 +1400,12 @@ name = "gelthi" seed_name = "gelthi" display_name = "gelthi plant" + kitchen_tag = "gelthi" chems = list("stoxin" = list(1,5),"capsaicin" = list(1,5),"nutriment" = list(1,5)) /datum/seed/gelthi/New() ..() - set_trait(TRAIT_PLANT_ICON,"gelthi") + set_trait(TRAIT_PLANT_ICON,"mushroom3") set_trait(TRAIT_ENDURANCE,15) set_trait(TRAIT_MATURATION,6) set_trait(TRAIT_PRODUCTION,6) @@ -1165,11 +1416,12 @@ name = "vale" seed_name = "vale" display_name = "vale bush" + kitchen_tag = "vale" chems = list("paracetamol" = list(1,5),"dexalin" = list(1,2),"nutriment"= list(1,5)) /datum/seed/vale/New() ..() - set_trait(TRAIT_PLANT_ICON,"vale") + set_trait(TRAIT_PLANT_ICON,"flower4") set_trait(TRAIT_ENDURANCE,15) set_trait(TRAIT_MATURATION,8) set_trait(TRAIT_PRODUCTION,10) @@ -1180,11 +1432,12 @@ name = "surik" seed_name = "surik" display_name = "surik vine" + kitchen_tag = "surik" chems = list("impedrezene" = list(1,3),"synaptizine" = list(1,2),"nutriment" = list(1,5)) /datum/seed/surik/New() ..() - set_trait(TRAIT_PLANT_ICON,"surik") + set_trait(TRAIT_PLANT_ICON,"bush6") set_trait(TRAIT_ENDURANCE,18) set_trait(TRAIT_MATURATION,7) set_trait(TRAIT_PRODUCTION,7) diff --git a/code/modules/hydroponics/seed_gene_mut.dm b/code/modules/hydroponics/seed_gene_mut.dm index cdb7048957c..09147c72b90 100644 --- a/code/modules/hydroponics/seed_gene_mut.dm +++ b/code/modules/hydroponics/seed_gene_mut.dm @@ -6,24 +6,24 @@ var/datum/seed/S = diverge() //Let's not modify all of the seeds. T.visible_message("\The [S.display_name] quivers!") //Mimicks the normal mutation. G.mutate(S, T) - + return S - + /decl/plantgene var/gene_tag - + /decl/plantgene/biochem gene_tag = GENE_BIOCHEMISTRY - + /decl/plantgene/hardiness gene_tag = GENE_HARDINESS - + /decl/plantgene/environment gene_tag = GENE_ENVIRONMENT /decl/plantgene/metabolism gene_tag = GENE_METABOLISM - + /decl/plantgene/structure gene_tag = GENE_STRUCTURE @@ -38,7 +38,7 @@ /decl/plantgene/atmosphere gene_tag = GENE_ATMOSPHERE - + /decl/plantgene/vigour gene_tag = GENE_VIGOUR @@ -53,7 +53,7 @@ /decl/plantgene/biochem/mutate(var/datum/seed/S) S.set_trait(TRAIT_POTENCY, S.get_trait(TRAIT_POTENCY)+rand(-20,20),200, 0) - + /decl/plantgene/hardiness/mutate(var/datum/seed/S) if(prob(60)) S.set_trait(TRAIT_TOXINS_TOLERANCE, S.get_trait(TRAIT_TOXINS_TOLERANCE)+rand(-2,2),10,0) @@ -63,7 +63,7 @@ S.set_trait(TRAIT_WEED_TOLERANCE, S.get_trait(TRAIT_WEED_TOLERANCE)+rand(-2,2),10,0) if(prob(60)) S.set_trait(TRAIT_ENDURANCE, S.get_trait(TRAIT_ENDURANCE)+rand(-5,5),100,0) - + /decl/plantgene/environment/mutate(var/datum/seed/S) if(prob(60)) S.set_trait(TRAIT_IDEAL_HEAT, S.get_trait(TRAIT_IDEAL_HEAT)+rand(-2,2),10,0) @@ -71,7 +71,7 @@ S.set_trait(TRAIT_IDEAL_LIGHT, S.get_trait(TRAIT_IDEAL_LIGHT)+rand(-2,2),10,0) if(prob(60)) S.set_trait(TRAIT_LIGHT_TOLERANCE, S.get_trait(TRAIT_LIGHT_TOLERANCE)+rand(-5,5),100,0) - + /decl/plantgene/metabolism/mutate(var/datum/seed/S) if(prob(65)) S.set_trait(TRAIT_REQUIRES_NUTRIENTS, S.get_trait(TRAIT_REQUIRES_NUTRIENTS)+rand(-2,2),10,0) @@ -79,7 +79,7 @@ S.set_trait(TRAIT_REQUIRES_WATER, S.get_trait(TRAIT_REQUIRES_WATER)+rand(-2,2),10,0) if(prob(40)) S.set_trait(TRAIT_ALTER_TEMP, S.get_trait(TRAIT_ALTER_TEMP)+rand(-5,5),100,0) - + /decl/plantgene/diet/mutate(var/datum/seed/S) if(prob(60)) S.set_trait(TRAIT_CARNIVOROUS, S.get_trait(TRAIT_CARNIVOROUS)+rand(-1,1),2,0) @@ -102,17 +102,15 @@ T.visible_message("\The [S.display_name]'s glow dims...") if(prob(60)) S.set_trait(TRAIT_PRODUCES_POWER, !S.get_trait(TRAIT_PRODUCES_POWER)) - + /decl/plantgene/atmosphere/mutate(var/datum/seed/S) if(prob(60)) - S.set_trait(TRAIT_TOXINS_TOLERANCE, S.get_trait(TRAIT_TOXINS_TOLERANCE)+rand(-2,2),10,0) + S.set_trait(TRAIT_HEAT_TOLERANCE, S.get_trait(TRAIT_HEAT_TOLERANCE)+rand(-2,2),40,0) if(prob(60)) - S.set_trait(TRAIT_PEST_TOLERANCE, S.get_trait(TRAIT_PEST_TOLERANCE)+rand(-2,2),10,0) + S.set_trait(TRAIT_LOWKPA_TOLERANCE, S.get_trait(TRAIT_LOWKPA_TOLERANCE)+rand(-10,10),100,10) if(prob(60)) - S.set_trait(TRAIT_WEED_TOLERANCE, S.get_trait(TRAIT_WEED_TOLERANCE)+rand(-2,2),10,0) - if(prob(60)) - S.set_trait(TRAIT_ENDURANCE, S.get_trait(TRAIT_ENDURANCE)+rand(-5,5),100,0) - + S.set_trait(TRAIT_HIGHKPA_TOLERANCE, S.get_trait(TRAIT_HIGHKPA_TOLERANCE)+rand(-10,10),500,100) + /decl/plantgene/vigour/mutate(var/datum/seed/S, var/turf/T) if(prob(65)) S.set_trait(TRAIT_PRODUCTION, S.get_trait(TRAIT_PRODUCTION)+rand(-1,1),10,0) @@ -121,7 +119,7 @@ if(prob(55)) S.set_trait(TRAIT_SPREAD, S.get_trait(TRAIT_SPREAD)+rand(-1,1),2,0) T.visible_message("\The [S.display_name] spasms visibly, shifting in the tray.") - + /decl/plantgene/fruit/mutate(var/datum/seed/S) if(prob(65)) S.set_trait(TRAIT_STINGS, !S.get_trait(TRAIT_STINGS)) @@ -129,7 +127,7 @@ S.set_trait(TRAIT_EXPLOSIVE, !S.get_trait(TRAIT_EXPLOSIVE)) if(prob(65)) S.set_trait(TRAIT_JUICY, !S.get_trait(TRAIT_JUICY)) - + /decl/plantgene/special/mutate(var/datum/seed/S) if(prob(65)) S.set_trait(TRAIT_TELEPORTING, !S.get_trait(TRAIT_TELEPORTING)) diff --git a/code/modules/hydroponics/seed_mobs.dm b/code/modules/hydroponics/seed_mobs.dm index 88462acb47a..0c9441dbaca 100644 --- a/code/modules/hydroponics/seed_mobs.dm +++ b/code/modules/hydroponics/seed_mobs.dm @@ -3,6 +3,9 @@ if(!host || !istype(host)) return + if(apply_color_to_mob) + host.color = traits[TRAIT_PRODUCT_COLOUR] + var/datum/ghosttrap/plant/P = get_ghost_trap("living plant") P.request_player(host, "Someone is harvesting [display_name]. ") diff --git a/code/modules/hydroponics/seed_packets.dm b/code/modules/hydroponics/seed_packets.dm index f4b8b951a59..047a7d895a8 100644 --- a/code/modules/hydroponics/seed_packets.dm +++ b/code/modules/hydroponics/seed_packets.dm @@ -283,3 +283,42 @@ GLOBAL_LIST_BOILERPLATE(all_seed_packs, /obj/item/seeds) /obj/item/seeds/thaadra seed_type = "thaadra" + +/obj/item/seeds/celery + seed_type = "celery" + +/obj/item/seeds/rhubarb + seed_type = "rhubarb" + +/obj/item/seeds/wabback + seed_type = "whitewabback" + +/obj/item/seeds/blackwabback + seed_type = "blackwabback" + +/obj/item/seeds/wildwabback + seed_type = "wildwabback" + +/obj/item/seeds/lettuce + seed_type = "lettuce" + +/obj/item/seeds/siflettuce + seed_type = "siflettuce" + +/obj/item/seeds/eggyplant + seed_type = "egg-plant" + +/obj/item/seeds/spineapple + seed_type = "spineapple" + +/obj/item/seeds/durian + seed_type = "durian" + +/obj/item/seeds/vanilla + seed_type = "vanilla" + +/obj/item/seeds/rose + seed_type = "rose" + +/obj/item/seeds/rose/blood + seed_type = "bloodrose" diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm index 135dc09a4c1..be7d253659e 100644 --- a/code/modules/hydroponics/seed_storage.dm +++ b/code/modules/hydroponics/seed_storage.dm @@ -54,7 +54,7 @@ /obj/item/seeds/ambrosiavulgarisseed = 3, /obj/item/seeds/plastiseed = 3, /obj/item/seeds/kudzuseed = 2, - /obj/item/seeds/nettleseed = 1 + /obj/item/seeds/rose/blood = 1 ), list( /obj/item/seeds/ambrosiavulgarisseed = 3, @@ -69,6 +69,7 @@ /obj/item/seeds/bluetomatoseed = 1 ), list( + /obj/item/seeds/durian = 2, /obj/item/seeds/ambrosiadeusseed = 1, /obj/item/seeds/killertomatoseed = 1 ), @@ -99,17 +100,20 @@ /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, + /obj/item/seeds/celery = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, + /obj/item/seeds/durian = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/grapeseed = 3, /obj/item/seeds/grassseed = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/lavenderseed = 3, /obj/item/seeds/lemonseed = 3, + /obj/item/seeds/lettuce = 3, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, /obj/item/seeds/orangeseed = 3, @@ -119,14 +123,18 @@ /obj/item/seeds/poppyseed = 3, /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, + /obj/item/seeds/rhubarb = 3, /obj/item/seeds/riceseed = 3, + /obj/item/seeds/rose = 3, /obj/item/seeds/soyaseed = 3, + /obj/item/seeds/spineapple = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, + /obj/item/seeds/vanilla = 3, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3 @@ -144,11 +152,13 @@ /obj/item/seeds/berryseed = 3, /obj/item/seeds/cabbageseed = 3, /obj/item/seeds/carrotseed = 3, + /obj/item/seeds/celery = 3, /obj/item/seeds/chantermycelium = 3, /obj/item/seeds/cherryseed = 3, /obj/item/seeds/chiliseed = 3, /obj/item/seeds/cocoapodseed = 3, /obj/item/seeds/cornseed = 3, + /obj/item/seeds/durian = 3, /obj/item/seeds/replicapod = 3, /obj/item/seeds/eggplantseed = 3, /obj/item/seeds/glowshroom = 2, @@ -156,6 +166,7 @@ /obj/item/seeds/grassseed = 3, /obj/item/seeds/lavenderseed = 3, /obj/item/seeds/lemonseed = 3, + /obj/item/seeds/lettuce = 3, /obj/item/seeds/libertymycelium = 2, /obj/item/seeds/limeseed = 3, /obj/item/seeds/mtearseed = 2, @@ -168,14 +179,19 @@ /obj/item/seeds/potatoseed = 3, /obj/item/seeds/pumpkinseed = 3, /obj/item/seeds/reishimycelium = 2, + /obj/item/seeds/rhubarb = 3, /obj/item/seeds/riceseed = 3, + /obj/item/seeds/rose = 3, /obj/item/seeds/soyaseed = 3, + /obj/item/seeds/spineapple = 3, /obj/item/seeds/sugarcaneseed = 3, /obj/item/seeds/sunflowerseed = 3, /obj/item/seeds/shandseed = 2, /obj/item/seeds/tobaccoseed = 3, /obj/item/seeds/tomatoseed = 3, /obj/item/seeds/towermycelium = 3, + /obj/item/seeds/vanilla = 3, + /obj/item/seeds/wabback = 2, /obj/item/seeds/watermelonseed = 3, /obj/item/seeds/wheatseed = 3, /obj/item/seeds/whitebeetseed = 3 diff --git a/code/modules/integrated_electronics/core/printer.dm b/code/modules/integrated_electronics/core/printer.dm index c2c70985c51..cdf4652d5ee 100644 --- a/code/modules/integrated_electronics/core/printer.dm +++ b/code/modules/integrated_electronics/core/printer.dm @@ -44,7 +44,7 @@ if(num < 1) to_chat(user, span("warning", "\The [src] is too full to add more metal.")) return - if(stack.use(num)) + if(stack.use(max(1, round(num)))) // We don't want to create stacks that aren't whole numbers to_chat(user, span("notice", "You add [num] sheet\s to \the [src].")) metal += num * metal_per_sheet interact(user) @@ -148,7 +148,7 @@ else var/obj/item/I = build_type cost = initial(I.w_class) - if(!build_type in SScircuit.circuit_fabricator_recipe_list[current_category]) + if(!(build_type in SScircuit.circuit_fabricator_recipe_list[current_category])) return if(!debug) diff --git a/code/modules/integrated_electronics/subtypes/input.dm b/code/modules/integrated_electronics/subtypes/input.dm index c11c7e963ab..e3fcb5d9855 100644 --- a/code/modules/integrated_electronics/subtypes/input.dm +++ b/code/modules/integrated_electronics/subtypes/input.dm @@ -540,7 +540,57 @@ if(translated) activate_pin(2) +/obj/item/integrated_circuit/input/microphone/sign + name = "sign-language translator" + desc = "Useful for spying on people or for sign activated machines." + extended_desc = "This will automatically translate galactic standard sign language it sees to Galactic Common. \ + The first activation pin is always pulsed when the circuit sees someone speak sign, while the second one \ + is only triggered if it sees someone speaking a language other than sign language, which it will attempt to \ + lip-read." + icon_state = "video_camera" + complexity = 12 + inputs = list() + outputs = list( + "speaker" = IC_PINTYPE_STRING, + "message" = IC_PINTYPE_STRING + ) + activators = list("on message received" = IC_PINTYPE_PULSE_OUT, "on translation" = IC_PINTYPE_PULSE_OUT) + spawn_flags = IC_SPAWN_RESEARCH + power_draw_per_use = 30 + var/list/my_langs = list() + var/list/readable_langs = list( + LANGUAGE_GALCOM, + LANGUAGE_SOL_COMMON, + LANGUAGE_TRADEBAND, + LANGUAGE_GUTTER, + LANGUAGE_TERMINUS + ) + +/obj/item/integrated_circuit/input/microphone/sign/Initialize() + ..() + for(var/lang in readable_langs) + var/datum/language/newlang = all_languages[lang] + my_langs |= newlang + +/obj/item/integrated_circuit/input/microphone/sign/hear_talk(mob/living/M, msg, var/verb="says", datum/language/speaking=null) + var/translated = FALSE + if(M && msg) + if(speaking) + if(!((speaking.flags & NONVERBAL) || (speaking.flags & SIGNLANG))) + translated = TRUE + msg = speaking.scramble(msg, my_langs) + set_pin_data(IC_OUTPUT, 1, M.GetVoice()) + set_pin_data(IC_OUTPUT, 2, msg) + + push_data() + activate_pin(1) + if(translated) + activate_pin(2) + +/obj/item/integrated_circuit/input/microphone/sign/hear_signlang(text, verb, datum/language/speaking, mob/M as mob) + hear_talk(M, text, verb, speaking) + return /obj/item/integrated_circuit/input/sensor name = "sensor" diff --git a/code/modules/integrated_electronics/subtypes/output.dm b/code/modules/integrated_electronics/subtypes/output.dm index 1e7ad6c31a5..3ddc3458d7c 100644 --- a/code/modules/integrated_electronics/subtypes/output.dm +++ b/code/modules/integrated_electronics/subtypes/output.dm @@ -136,6 +136,33 @@ var/obj/O = assembly ? loc : assembly audible_message("\icon[O] \The [O.name] states, \"[text]\"") +/obj/item/integrated_circuit/output/text_to_speech/advanced + name = "advanced text-to-speech circuit" + desc = "A miniature speaker is attached to this component. It is able to transpose any valid text to speech, matching a scanned target's voice." + complexity = 15 + cooldown_per_use = 6 SECONDS + inputs = list("text" = IC_PINTYPE_STRING, "mimic target" = IC_PINTYPE_REF) + power_draw_per_use = 100 + + spawn_flags = IC_SPAWN_RESEARCH + origin_tech = list(TECH_ENGINEERING = 3, TECH_DATA = 4, TECH_ILLEGAL = 1) + + var/mob/living/voice/my_voice + +/obj/item/integrated_circuit/output/text_to_speech/advanced/Initialize() + ..() + my_voice = new (src) + my_voice.name = "TTS Circuit" + +/obj/item/integrated_circuit/output/text_to_speech/advanced/do_work() + text = get_pin_data(IC_INPUT, 1) + var/mob/living/target_mob = get_pin_data(IC_INPUT, 2) + my_voice.transfer_identity(target_mob) + if(!isnull(text) && !isnull(my_voice) && !isnull(my_voice.name)) + my_voice.forceMove(get_turf(src)) + my_voice.say("[text]") + my_voice.forceMove(src) + /obj/item/integrated_circuit/output/sound name = "speaker circuit" desc = "A miniature speaker is attached to this component." @@ -244,7 +271,7 @@ activators = list() spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH power_draw_idle = 5 // Raises to 80 when on. - var/obj/machinery/camera/network/research/camera + var/obj/machinery/camera/network/circuits/camera /obj/item/integrated_circuit/output/video_camera/New() ..() diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index 734a2bcfa59..3c7ebec3779 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -141,6 +141,7 @@ icon_state ="book" throw_speed = 1 throw_range = 5 + flags = NOCONDUCT w_class = ITEMSIZE_NORMAL //upped to three because books are, y'know, pretty big. (and you could hide them inside eachother recursively forever) attack_verb = list("bashed", "whacked", "educated") var/dat // Actual page content diff --git a/code/modules/lore_codex/news_data/main.dm b/code/modules/lore_codex/news_data/main.dm index ee41280d6fb..a2f5f430433 100644 --- a/code/modules/lore_codex/news_data/main.dm +++ b/code/modules/lore_codex/news_data/main.dm @@ -4,6 +4,27 @@ region. Each is labeled by date of publication and title. This list is self-updating, and from time to time the publisher will push new \ articles. You are encouraged to check back frequently." children = list( + /datum/lore/codex/page/article53, + /datum/lore/codex/page/article52, + /datum/lore/codex/page/article51, + /datum/lore/codex/page/article50, + /datum/lore/codex/page/article49, + /datum/lore/codex/page/article48, + /datum/lore/codex/page/article47, + /datum/lore/codex/page/article46, + /datum/lore/codex/page/article45, + /datum/lore/codex/page/article44, + /datum/lore/codex/page/article43, + /datum/lore/codex/page/article42, + /datum/lore/codex/page/article41, + /datum/lore/codex/page/article40, + /datum/lore/codex/page/article39, + /datum/lore/codex/page/keldowinterview, + /datum/lore/codex/category/article38, + /datum/lore/codex/page/article37, + /datum/lore/codex/page/article36, + /datum/lore/codex/page/article35, + /datum/lore/codex/page/article34, /datum/lore/codex/page/article33, /datum/lore/codex/page/article32, /datum/lore/codex/page/bjornretirement, @@ -401,3 +422,232 @@ Vani Jee is running on a platform of free access to education, Sivian self-determination, and isolationist foreign policy. She has refused to make any strong statements regarding hot-button issues such as the Five Points.\

      \ She intends to resume her scheduled tour after a three day break." + +/datum/lore/codex/page/article34 + name = "02/05/63 - Angessa Martei to Take Control of Eponymous Colony" + data = "Coming out of retirement and displacing the nameless Exalt of the Starlit Path, religious demagogue Angessa Martei has returned to the throne of the colony that bears her name. \ +

      \ + 'I had retired because of senescence brought on by my old age, high-stress lifestyle, and multiple resurrective clonings. As you may know, I recently had a procedure that renders these difficulties obsolete. Hereafter I will continue to control the automated facilities of the Pearl and claim responsibility for the collective action of my followers. Those who oppose my decision may oppose all they want. Feelings do not move mountains. I do. We shall seize the stars in our own hands. May you become who you wish to be, and grind all obstacles to dust, as I have done.'\ +

      \ + Purportedly, this address was met with a standing ovation from the population of Angessa's Pearl. In a separate dispatch, Martei stated her intention to tour SolGov as a foreign dignitary protected by the Respect for Diplomats Act." + +/datum/lore/codex/page/article35 + name = "02/07/63 - Vir Gubernatorial Candidate Barred from Breakfast TV" + data = "Infamously hot-headed Shadow Coalition candidate Phaedrus has reportedly been blacklisted from future appearances on morning television by several major networks. The ban comes after an advertised chat segment between Phaedrus and hosts of the West Sif Wakeup breakfast programme had to be pulled from broadcast after the candidate 'Flew into a expletive-laden mercurial rant' at the expense of rival candidate Mehmet Sao of the Icarus Front.\ +

      \ + Recordings of the outburst quickly made their way onto social media, sparking outrage from opponents and network executives alike, prompting Occulum Media to issue a rare blacklist from major media outlets, restricting Phaedrus to 'appearances on alternative news sources' owned by the company.\ +

      \ + Phaedrus, a long-time Vir Mercurial Progress Party member running for a major party for the first time, is said to have taken issue with candidate Sao's 'Blatant anti-synthetic' policies, though he did not use the word 'policies'." + +/datum/lore/codex/page/article36 + name = "02/09/63 - SEO Candidate Embarks on Wilderness Tour" + data = "In an effort to stir up support for his promotion of natural resource extraction industries, Sol Economic Organization candidate Mason Keldow has embarked on an unorthodox tour of resource-rich sites across central Sif. Keldow has described the tour as an 'Old fashioned expedition', invoking images of hardy prospectors of centuries past, and intends to make the journey entirely by ground with only a small party of 'Adventurous outdoorspeople' to support his trek.\ +

      \ + Critics of the plan have pointed out that the earliest surveys of Sif were largely performed by aerial drones, and the idea of ground-based survey teams is 'Frankly anachronistic'. Rival Shadow Coalition candidate Selma Jorg - a staunch planetary environmentalist - has described the tour as 'Irresponsible and insane'.\ +

      \ + The candidate intends to visit both unexploited sites and current corporate extraction facilities in order to 'Better understand the folks helping dig out Sif's hidden wealth' over the coming two weeks." + +/datum/lore/codex/page/article37 + name = "02/09/63 - Zaddat Colony 'Bright' To Enter Vir" + data = "After several months of talks with Nanotrasen and other corporations in the system, the Colony Bright is to begin orbiting Sif and hardsuited Zaddat are to enter the Virite workforce. Executives in Nanotrasen Vir cite the reduction of their drone-automated and positronic workforce as a result of the Gray Hour as cause for them to reverse their previous decision against allowing the migrants into the system. Icarus officials within VGA are concerned that, if other Colonies are to follow the Bright, the native industry of Sif may be disrupted or suborned by Zaddat and Hegemony interests, and have made it clear that the Bright's presence in the system is highly conditional." + +/datum/lore/codex/category/article38 + name = "02/11/63 - Mason Keldow in Ullran Expanse Close Call" + data = "Sol Economic Organization candidate Mason Keldow was rushed to nearby corporate medical facilities after a death-defying encounter with local wildlife in the Ullran Expanse this morning. The candidate had been planning to visit the nearby NanoTrasen mining facilities as part of his much publicized 'Wilderness Tour' when he and a local guide were set upon by the notoriously savage Sivian Savik. The animal was killed in the encounter, but not before Mr. Keldow suffered life-threatening injuries and had to be recovered by crew from the NLS Southern Cross, the closest facility on hand.\ +

      \ + Following emergency surgery, Keldow was happy to provide news sources with a 'Good-natured' interview, in which he highlighted the dangers faced by rural workers on Sif and his plans to tackle them, as well as slamming rival Shadow Coalition candidate Selma Jorg for lacking tangible plans for the future.\ +

      \ + Candidate Keldow is reported to have made a miraculous recovery, and is 'in good spirits'. Aides state that he is unlikely to suffer any long term effects from the injuries, in part thanks for the skilful work of NanoTrasen's Dr. Fuerte.\ +

      \ + A full transcript of the interview follows:" + children = list( + /datum/lore/codex/page/keldowinterview + ) + +/datum/lore/codex/page/keldowinterview + name = "Mason Keldow Interview Transcript" + data = "Blip asks, 'Subject Keldow. Pleasantries first. How do you feel after your ordeal on the planet's surface?'\ +

      \ + Mason Keldow says, 'Ah that? You know I'd love to downplay it and pretend that it was just a walk in the park... But NT's medical staff probably will tell you otherwise, so there's no reason to hide it; things went pretty far south.'\ +

      \ + Mason Keldow says, 'But that's how it goes, working on the surface of Sif isn't pleasant at times.'\ +

      \ + Blip asks, 'Candidate Keldow, you have placed yourself quite firmly in the boots of the local TSC's explorer contingents today. Do you feel you will be attempting to live the life of any other labour intensive roles in the near future?'\ +

      \ + Mason Keldow says, 'Blip, Let me tell you I do try to get a taste for a lot of the work done by these people... But admittedly this isn't the job I do every day. These are hard working fellows who do there damnedest day in and day out... I could try spending a week just working the mines, But-'\ +

      \ + Mason Keldow says, 'As I was saying.. Many of the folks, Miners, Explorers, The work in and around the Ullran Expanse. They work in the mountains, Out in the fields.. It's a dangerous place and frankly its not a place average people wanna go too.'\ +

      \ + Mason Keldow says, 'They told me on the way here. 'Keldow you're an idiot''\ +

      \ + Mason Keldow says, 'Hell, Even Basman over here was wondering why I didn't ask for a detail.'\ +

      \ + Mason Keldow says, 'So it's not a safe route... But when's the last time any of the other candidates actually came down to these outer stretches and tried earning their sweat.'\ +

      \ + Blip asks, 'You indeed seem to be attempting to gain a unique, and firm understanding of the daily struggles of the working populace. How do you intend to translate this newfound knowledge into policy and direction if you take the Governorship in Vir?'\ +

      \ + Mason Keldow says, 'You see, getting a grasp of the struggle is only step one, I paint myself as an every-man but that doesn't mean core issues aren't the problem either; Vir's economics, The small pay that sometimes offered. There is a lot to be tapped into.'\ +

      \ + Mason Keldow says, 'Let's take for instance the spiders I've been hearing about.'\ +

      \ + Mason Keldow says, 'People working in orbit say 'Don't go to the surface, Spiders are down there.''\ +

      \ + Mason Keldow says, 'And apparently there was a big ol' purple one sitting right by a camp we had set up. A giant mother who'd - if I hadn't met that lovely mass of fur and ice instead - would have probably said its “hello” in the worst possible way.'\ +

      \ + Mason Keldow says, 'They are a species that prevents anyone from actually working or otherwise making use of all that land. If I were in office, I'd make an effort to clear out the dangerous species that surround the outer regions of Sif – relocate them if possible - and use that territory for something productive.'\ +

      \ + Mason Keldow says, 'New forms of Transit, new buildings, new jobs.'\ +

      \ + Blip asks, 'Such implementation of infrastructure and security is not a cheap measure. How do you intend to find funds for such an endeavour?'\ +

      \ + Mason Keldow says, 'Now obviously Vir is in a very interesting position, But thankfully it's in a wonderful position where business and partnerships are more than happy to come in and assist. The bottom line would make sure the average Taxpayer doesn't feel a dent, only the dividends.'\ +

      \ + Mason Keldow says, 'If we break this down into economic plans, using new yet relatively safe tools being put out by Hepheastus, you could safely clear swaths of territory in the Expanse.'\ +

      \ + Blip says, 'Thank you for your insight into your economic policies and plans. As a final question;'\ +

      \ + Blip asks, 'A puff-piece question. Do you have anything positive to say about your rivals in the political race?'\ +

      \ + Mason Keldow says, 'Ah yes, yes well... As for any candidate they need to show they're worth. Not simply as a politician but as a person who believes what they will do for for the betterment of Sif, And Vir as a whole.'\ +

      \ + Mason Keldow says, 'Let's take a look Ms. Jorg.'\ +

      \ + Mason Keldow says, 'She has LONG called me a Corporate sell-out, Saying I would poison the planet and other awful mudslinging.'\ +

      \ + Mason Keldow says, 'She loves to claim she's here for the better of the misrepresented.'\ +

      \ + Mason Keldow says, 'But when is the last time she's talked to a Tajaran and told them how they will help put food on the table, and money into their pockets.'\ +

      \ + Mason Keldow says, 'When has she came and told the Unathi Exile, Your worth more than what the Hegemony is trying to convince you you're worth.'\ +

      \ + Mason Keldow says, 'There's blood in the grass out there showing what I'm willing to do to make Sif and Vir a better more prosperous system. I wanna see what the other Candidates will do.'\ +

      \ + Blip pings!\ +

      \ + Blip says, 'Thank you for your time, Candidate Keldow. Unit looks forward to seeing where this race ends, and wishes Candidate the best of luck in his endeavours.'\ +

      \ + Mason Keldow says, 'It's been a pleasure Blip.'" + +/datum/lore/codex/page/article39 + name = "02/12/63 - VirGov Launches Election Website" + data = "The Vir Governmental Authority has launched this year's election information exonet site, unusually several months after campaigning began. The government election agency states that the delay was caused by an usually long process of finalizing candidates this cycle, and did not want to confuse voters with incorrect or outdated information.\ +

      \ + The newly updated site includes information on candidates and political parties, and is planned to include information on local voting rights at a future date. It can be found at:\ +

      \ + your-choice-vir.virgov.xo.vr\ +

      \ + (( https://your-choice-vir.weebly.com/ ))" + +/datum/lore/codex/page/article40 + name = "02/14/63 - Ultimatum Unmet: War With Almach!" + data = "The Solar Confederate Government has resumed a state of war against the secessionist Almach Association, after 4 months of tense ceasefire. The re-declaration comes after the Association failed to meet requirements set forth by the Colonial Assembly last November, which called for the cessation and destruction of all research that did not meet standards established by the Five Points of Human Sanctity.\ +

      \ + The past few weeks have been marked by an increasing buildup of military forces on the Almach border as it became apparent that Almach had no intention of meeting Sol's demands. At 9am this morning, the deadline was met and initial reports from the frontline suggest relatively little action besides the destruction of pre-existing Almach scout drones that had been placed on the border several months prior. The exact plans of the fleet going forward have not been made public, but civilian traffic to and from the Saint Columbia system has been entirely suspended.\ +

      \ + How this development will influence the coming Vir election remains to be seen, though SEO candidate Mason Keldow has reportedly ended his planetary tour 10 days earlier than planned due to the tense political situation." + +/datum/lore/codex/page/article41 + name = "02/22/63 - Militia Retreats: First Solar Victory" + data = "After a week of tense stand-offs and increasingly frequent skirmishes, the Association Militia has begun moving from their position around Saint Columbia further into the Almach Rim. The inciting incident for this shift seems to have been the first use of the MJOLNIR system, which instantly destroyed a large Almachi warship from half a system away. This demonstration was met with a standing ovation from much of Iserlohn, and Militia forces disengaged almost immediately. Admiral McMullen is unwilling to elaborate on pursuit or invasion plans at this moment, but 'hope(s) the MJOLNIR will continue to be a valuable asset for national defense.'" + +/datum/lore/codex/page/article42 + name = "03/04/63 - Savik Slams Local Chat Host" + data = "Television sweetheart Sally, host of Chat With Sally has come under harsh criticism from independent Vir gubernatorial candidate Yole Savik after his 'humiliating' appearance on the show yesterday morning alongside Sol Economic Organization candidate Calvert Moravec. Savik - who is campaigning for Vir independence from both the SCG and corporate interests - alleges that the show, which has run for 13 years on select networks, is 'little more than a propaganda piece for high powered executives.' and that his appearance had been part of a 'smear campaign' against non-SEO candidates.\ +

      \ + NanoTrasen, who have openly sponsored Sally since her inception deny these accusations. Jan Bhatt of the NT marketing division stated 'Chat With Sally has always been intended as light morning entertainment, and Sally a personality we can all relate to. The fact that Mr. Savik was unable to have a sense of humour about the whole thing and took the show as an opportunity to bloviate about dry politics is not an indictment of Sally, nor the corporation but rather a simple misunderstanding of the purpose of the segment. We had hoped Mr. Savik's appearance would help dismiss any claims of political bias in our programming and hope to host more civil candidates in the future.'\ +

      \ + Catch Chat With Sally weekly at 5am SST." + +/datum/lore/codex/page/article43 + name = "03/06/63 - Dark Triangle Goes Dark!" + data = "As of 0352 this morning, New Reykjavik time, SolGov officials confirmed that all communications coming from the so-called 'Dark Triangle' had ceased. The Dark Triangle is a disputed region of space home to the independent world Natuna, which has maintained a more or less neutral relationship with SolGov for a little more than a decade.\ +

      \ + The announcement gives no cause for the communications blackout, though sources with inside knowledge claim that it was completely unforeseen. Some speculate that Natuna, who became an 'observer nation' of the Almach Association last November, is making a political statement, though experts in the telecommunications field are uncertain as to how such a complete blackout is possible.\ +

      \ + Dr. Ina Lai from the Kara Interstellar Observatory states, 'we've never seen anything like this outside of the (Skrellian) Far Kingdoms, and frankly we're at a loss for who might be responsible,' adding that 'the tachyon signatures from the whole region are masked, even those from stellar phenomena or normal bluespace travel.' Independent explorers from the FTU have set out to the region in an attempt to re-establish communication with Natuna and smaller human settlements nearby." + +/datum/lore/codex/page/article44 + name = "03/08/63 - Dark Triangle Overrun By Hegemony" + data = "FTU explorers have re-established exonet communications with the ruling bodies of Natuna and the Dark Triangle. Unfortunately, they also discovered that Natuna's previously autonomous townships have been subsumed into the Moghes Hegemony. \ +

      \ + Bluespace-lensed telescopes throughout SolGov, including the Vir-based Kara Interstellar Observatory, can once again pick up on tachyon signatures in the region. Traffic has been described as 'lower than usual' and no significant fleet assets are believed to be present in the region, though fixed-placement Hegemony installations now litter the Triangle's major star systems. Systems with significant Hegemony presence include Natuna and Ukupanipo, home to the primitive Uehshad species. Some have speculated that the presence of the Uehshad is the reason for the unexpected Hegemony takeover, though Icarus Front General Secretary Mackenzie West was quick to decry the move as 'an obvious imperial land-grab.'\ +

      \ + Hegemony diplomats on Luna and elsewhere have been quick to justify their actions. 'The Dark Triangle has been home to various criminal elements for several centuries,' says Aksere Eko Azaris, a major Hegemony diplomat since the early post-war years. 'Neither the Skrell nor the Solar Confederacy have proven any willingness to bring stability to the region. Local governments such as Natuna have actively encouraged piracy, smuggling, and other acts of banditry, instead of making any moves to legitimize themselves. This instability proved detrimental to the health and wellbeing of all living within striking distance of the pirates of Ue-Orsi, and it was deemed unfortunate, but necessary, that we step in and provide the guiding hand by which this region might be brought back into the fold of civilization, as is our duty as sapients.'\ +

      \ + In a statement closer to home,Commander Iheraer Saelho of the Zaddat Escort Fleet has assured VirGov that 'we only took action to protect the innocents of the Dark Triangle and of neighboring systems'.He asserts that Hegemony rule will ultimately benefit all races of people within the Triangle, and promises that, 'the people of Vir, of Oasis, of the Golden Crescent writ large, have nothing to fear from our clients the Zaddat, or from the Hegemony vessels assigned to their protection.'\ +

      \ + Only time will tell if Saelho's promised peace and stability will manifest in truth. \ +

      \ + This newfound militancy of the Hegemony is likely to become a major campaign issue in the upcoming Vir elections, alongside involvement in the war with the Almach Association and traditionally Virite issues of corporate authority, minority-friendly infrastructure, and taxation." + +/datum/lore/codex/page/article45 + name = "03/12/63 - Ue-Orsi Escapes Hegemony Triangle" + data = "The lawless 'Ue-Orsi' flotilla, home to hundreds of thousands of outcast Skrellian pirates, has departed from the Hegemony-controlled Dark Triangle after what appears to be a brief battle with several Unathi warships. The action damaged several important Orsian ships, including their massive and venerable solar array 'Suqot-Thoo'm', a development which is likely to increase the pirates' aggression in the coming months as they search for additional power sources. It is unclear exactly where the flotilla has fled, though best guesses indicate that they are presently in Skrell space, likely near the lightly-patrolled Xe'Teq system. The Moghes Hegemony is in negotiations with several Skrellian states to arrange for military action against their escaped subjects, but little headway has been made thus far.\ +

      \ + This revelation has added more fuel to already heated Assembly arguments about SolGov response to the Unathi takeover. 'This is a prelude to invasion, nothing more and nothing less,' says New Seoul Representative Collin So-Yung, a noted Iconoclast. 'We must make it absolutely clear to the Hegemony that this is a threat we will not bow to, even in our present state of internal weakness. I suggest we pursue a fair peace with the Association, one where we can keep them as allies against this sort of encroachment instead of shattering our fleets during such a pivotal moment.'\ +

      \ + Others took a more nuanced approach, including VGA Governor Bjorn Arielsson. 'What we have here is our punishment for how badly we've treated the people of the Triangle. I don't really see why we should have let the tired old racism of some Qerr-Katish oligarchs stop us from offering aid to their tired and huddled masses, such as it is. And because we have had a full century of ignoring their plight, they were defenceless to resist the Hegemony. I say we fling the doors open, let (the Orsians) settle some rock here, and show the unaligned powers of the galaxy that the Hegemony's way isn't the only way.'\ +

      \ + Even more conciliatory was Speaker ISA-5, who Arielsson blames for mistreatment of the Ue-Katish. 'Our policy has always been that our defence budget cannot adequately defend the Dark Triangle from internal piracy, that Ue-Orsi is a criminal organization using their refugee status as a shield, and that we cannot lift the blockade of Natuna until they stop hosting these criminals and transition to a more sustainable economy. If Moghes has the power and the inclination to administer the Triangle, I see no reason why this state of affairs isn't better than the alternatives.'" + +/datum/lore/codex/page/article46 + name = "03/26/63 - Almach Routed from Saint Columbia" + data = "The Saint Columbia system has been declared free of Association forces following a renewed SCG offensive in the region. Admiral McMullen of the Saint Columbia garrison - who has reportedly reclaimed his post at the system's naval base despite the facility suffering moderate damage in this week's fighting - says that the last secessionist vessels were driven from the system just over 24 hours ago, and remaining pockets of resistance have been quick to lay down their arms. At least 20 enemy vessels - mostly converted civilian ships - have been confirmed disabled or destroyed in-system, thanks in no small part to the deployment of the state-of-the-art MJOLNIR weapons system.\ +

      \ + This more aggressive approach to the Almach front comes on the tail of aggressive Hegemony deployments in the Dark Triangle, which SolGov has conceded was 'Immediately threatening, but after some deliberation, has brought some form of policing to a lawless region.'.\ +

      \ + Despite assurances, this recent action would appear to many to be an effort to quash the Association threat and return fleet forces to the now extended Hegemony border, and some critics of the Almach War have called for a second ceasefire 'In order to focus on the real threat to mankind.'" + +/datum/lore/codex/page/article47 + name = "04/28/63 - Representative Hainirsdottir Reaffirms Pro-Vey Medical Manifesto" + data = "Incumbent Vir Representative Lusia Hainirsdottir has restated her dedication to advanced medical research at a public appearance at a Vey Medical facility in downtown New Reykjavik. Vey Medical has come under some criticism locally in the past year due to its 'accelerated' sapient trials, which Representative Hainirsdottir has strongly endorsed in her current term of office.\ +

      \ + In her statement to staff at the New Reykjavik facility, Lusia promised that under her governorship, the company would not be reprimanded for the deadly Holburn's Disease outbreak in rural Sif this past June which claimed fifteen lives, and in which Vey-Med's involvement was only confirmed this week - as the outbreak 'directly lead' to the development of a new life-saving inoculation which has seen success galaxy-wide.\ +

      \ + Hainirsdottir has long advocated for the promotion of scientific achievements that have taken place in, and undertaken by the people of Vir." + +/datum/lore/codex/page/article48 + name = "05/06/63 - Isak Spar Withdraws from Vir Election" + data = "Independent gubernatorial candidate Isak Spar has withdrawn his name from the running following a 'Public Relations disaster' aboard an orbital NanoTrasen logistics facility. According to witnesses, Spar acted belligerently towards staff members and engaged in vandalism and assault with a deadly weapon during his scheduled visit to the station, which the candidate had opted to undertake alone due to the temporary illness of his campaign manager.\ +

      \ + In a statement just hours after the alleged incident, Isak announced that he would no longer be pursuing Vir Governorship, due to 'The unexpected stresses of a political career.' before plugging his upcoming album, C*** End Savage Turbo Death A** Destruction. The NanoTrasen corporation has decided not to press charges due to Mr. Spar 'Suffering the consequences on a far more significant level than a mere fine.' but will not be inviting Spar back for future visitation.\ +

      \ + Spar's label, Skull Wreck Music has declined to comment at this time but has agreed to pay damages to the victims on behalf of the self-described 'post-pseudo electro-death superstar'." + +/datum/lore/codex/page/article49 + name = "05/15/63 - Solar Fleet Launches Offensive Against Almach" + data = "The first vessels of an SCG Fleet invasion force arrived in the Relan system this morning after a month-long intelligence operation to establish the Almach Association's most vulnerable positions, according to an announcement by Admiral McMullen just hours ago. Relan, which has long been fragmented between the neutral Republic of Taron and the once insurrectory Free Relan Federation - who now control the majority of the system and declared allegiance with Almach early in the crisis - is expected to fall to Confederate forces within 'a matter of weeks' due to its fractious political situation, and relative insignificance to Almach interests.\ +

      \ + According to McMullen, the system's most populous habitat, the Carter Interstellar Spaceport is already under blockade and local resistance has thus far been minimal. The capture of Relan is expected to provide our forces with a major foothold in Almach territory and further advances are expected to be 'trivial', bypassing the Association's defensive positions in Angessa's Pearl.\ +

      \ + The offensive comes weeks after sizable portions of the Fleet were publicly withdrawn from the frontline in order to reinforce the extended border with the Hegemony following their annexation of the Dark Triangle, and is a clear sign that - despite reduced numbers - Fleet command remains confident of Solar victory against the Mercurial rogue state." + +/datum/lore/codex/page/article50 + name = "05/19/63 - 'Drone Operated' Shelfican Ships Storm Sol Siege" + data = "Blockading Solar vessels in the Relan system came under fire today from automated craft originating from the Shelf fleet. The flotilla of drones, described by one survivor as a 'swarm', launched electromagnetic pulse and so-called 'hatch buster' precision missiles against three SCG Defense vessels, inflicting systems damage, and casualties 'in the hundreds' with at least eight service people already confirmed killed in action. The drones are reported to have withdrawn after 'only a few minutes of protracted fire from both sides.'\ +

      \ + The Shelf telops fleet, which was spotted by Fleet forces but not identified as an immediate threat, entered the system early this morning and were understood to be acting as observers to the ongoing battle for the Relan system due to Shelf's official stance of non-aggression -- despite aligning itself with the Association. Shelf has reportedly been unable to be reached for comment on their actions, and their alleged neutrality in matters of war has been seriously called into question by many in the Colonial Assembly.\ +

      \ + The SCG-D Krishna and SCG-D Mogwai of the SCG fleet, and the assisting Oasis logistical vessel, the OG-L Cloud Nine have been withdrawn to an unspecified location for immediate medical assistance and repairs." + +/datum/lore/codex/page/article51 + name = "05/20/63 - Fleet Withdraws - Sol On The Back Foot?" + data = "The Solar Colonial Assembly has confirmed that the Solar Fleet has withdrawn from the contested Relan system due to 'unexpected resistance' from Shelf tele-operated forces. This comes less than 24 hours after three Solar vessels were seriously damaged in an 'ambush' by a large number of Almach-aligned military drones. According to the Fleet, they were unprepared for any significant ship-to-ship combat in the system and will be consolidating their forces. 'This is not a defeat', according to Captain Silvain Astier of the SCG-R Hanoi, speaking unofficially to Occulum News sources 'This is merely a tactical withdrawal in order to reconvene and reassess our plans to restore order to the Almach Rim.'\ +

      \ + A spokesperson for Shelf was quick to contact Fleet forces following the withdrawal with a formal apology for yesterday's incident, describing the previous day's attack as 'A terrible mistake.', blaming 'a miscommunication between our people in telops and the trigger-happy robots', though the veracity of their claims cannot be confirmed." + +/datum/lore/codex/page/article52 + name = "05/21/63 - NanoTrasen Station to Host Major Election Debate" + data = "As the Vir Gubernatorial elections approach, and with several high-profile debates lined up between the leading candidates in the polls, the NanoTrasen corporation is set to host its very own televised event live from one of its major logistical stations in Vir. The NLS Southern Cross, primarily a traffic control outpost managing shipping in Sif orbit, has been selected by the company to host the debate - funded in full by the corporation - due to a series of minor political scandals that have taken place on the platform, and the suitability of unused space onboard.\ +

      \ + Early in the election cycle, NanoTrasen came under fire for its alleged 'manhandling' of Icarus Front candidate Vani Jee, and the confiscation of to-be-televised recordings taken by a party drone. While the company apologised for the incident shortly thereafter, the corporation hopes to mend ties with the potential future representatives by showing that they are capable of hosting civil discourse. More recently, the NLS Southern Cross played host to the 'breakdown' of disgraced former candidate Isak Spar - an episode which was not addressed in NanoTrasen's official statement on the planned debate event." + +/datum/lore/codex/page/article53 + name = "05/26/63 - SEO Candidate Advocates Murder On Live TV!" + data = "Sol Economic Organization candidate Freya Singh has been caught live on camera admitting that she would like to throw an innocent individual out of an airlock for a minor slight. During this afternoon's debate hosted aboard the NLS Southern Cross. Singh is quoted as having said that the event was 'the silliest concept for a debate I've encountered yet, and whoever came up with it should get a promotion, and then be fired out of an airlock.', a clear incitement of violence against Oculum Broadcast staff.\ +

      \ + Magnus Dugal, 48 works for the Oculum Broadcast corporation and is credited with creating the concept for today's debate, the highest rated for this cycle so far. The father of three, who enjoys hoverboarding in his free time, says that he feels 'Threatened' by Singh's comments, and hopes that she will, 'at the bare minimum', issue an official apology to the company and himself.\ +

      \ + Candidate Freya Singh, a career investment banker, spent much of today's debate advocating for reduced safety regulations and the apparent overturning of the Five Points, raising eyebrows across the system. Singh's office claims that her statements were 'a joke', but we do not feel that this is a laughing matter.\ +

      \ + In related news, Shadow Coalition candidate Phaedrus remains under a profanity filter 'house arrest' for the remainder of the election." \ No newline at end of file diff --git a/code/modules/maps/tg/map_template.dm b/code/modules/maps/tg/map_template.dm index 63a597ac8e6..132d76445c0 100644 --- a/code/modules/maps/tg/map_template.dm +++ b/code/modules/maps/tg/map_template.dm @@ -225,8 +225,8 @@ orientation = pick(list(0, 90, 180, 270)) chosen_template.preload_size(chosen_template.mappath, orientation) - var/width_border = TRANSITIONEDGE + SUBMAP_MAP_EDGE_PAD + round(((orientation%180) ? chosen_template.height : chosen_template.width) / 2) // %180 catches East/West (90,270) rotations on true, North/South (0,180) rotations on false - var/height_border = TRANSITIONEDGE + SUBMAP_MAP_EDGE_PAD + round(((orientation%180) ? chosen_template.width : chosen_template.height) / 2) + var/width_border = SUBMAP_MAP_EDGE_PAD + round(((orientation%180) ? chosen_template.height : chosen_template.width) / 2) // %180 catches East/West (90,270) rotations on true, North/South (0,180) rotations on false //VOREStation Edit + var/height_border = SUBMAP_MAP_EDGE_PAD + round(((orientation%180) ? chosen_template.width : chosen_template.height) / 2) //VOREStation Edit var/z_level = pick(z_levels) var/turf/T = locate(rand(width_border, world.maxx - width_border), rand(height_border, world.maxy - height_border), z_level) var/valid = TRUE diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index f45adba7873..465d4ecc39f 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -14,7 +14,6 @@ recipes += new/datum/stack_recipe("[display_name] grave marker", /obj/item/weapon/material/gravemarker, 5, time = 50, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] ring", /obj/item/clothing/gloves/ring/material, 1, on_floor = 1, supplied_material = "[name]") recipes += new/datum/stack_recipe("[display_name] bracelet", /obj/item/clothing/accessory/bracelet/material, 1, on_floor = 1, supplied_material = "[name]") - recipes += new/datum/stack_recipe("[display_name] deskbell", /obj/item/weapon/deskbell, 1, on_floor = 1, supplied_material = "[name]") if(integrity>=50) recipes += new/datum/stack_recipe("[display_name] door", /obj/structure/simple_door, 10, one_per_turf = 1, on_floor = 1, supplied_material = "[name]") @@ -101,6 +100,7 @@ new/datum/stack_recipe("tall filing cabinet", /obj/structure/filingcabinet/filingcabinet, 4, time = 20, one_per_turf = 1, on_floor = 1), \ new/datum/stack_recipe("chest drawer", /obj/structure/filingcabinet/chestdrawer, 4, time = 20, one_per_turf = 1, on_floor = 1), \ )) + recipes += new/datum/stack_recipe("desk bell", /obj/item/weapon/deskbell, 1, on_floor = 1, supplied_material = "[name]") /material/plasteel/generate_recipes() ..() @@ -197,8 +197,13 @@ /material/wood/sif/generate_recipes() ..() recipes += new/datum/stack_recipe("alien wood floor tile", /obj/item/stack/tile/wood/sif, 1, 4, 20) - recipes -= new/datum/stack_recipe("wood floor tile", /obj/item/stack/tile/wood, 1, 4, 20) - recipes -= new/datum/stack_recipe("wooden chair", /obj/structure/bed/chair/wood, 3, time = 10, one_per_turf = 1, on_floor = 1) + for(var/datum/stack_recipe/r_recipe in recipes) + if(r_recipe.title == "wood floor tile") + recipes -= r_recipe + continue + if(r_recipe.title == "wooden chair") + recipes -= r_recipe + continue /material/supermatter/generate_recipes() recipes = list() diff --git a/code/modules/materials/material_sheets.dm b/code/modules/materials/material_sheets.dm index 1fbecaec7e5..4ca50889ead 100644 --- a/code/modules/materials/material_sheets.dm +++ b/code/modules/materials/material_sheets.dm @@ -99,7 +99,7 @@ icon_state = "sheet-adamantine" default_type = "lead" apply_colour = 1 - no_variants = TRUE + no_variants = FALSE /obj/item/stack/material/sandstone name = "sandstone brick" diff --git a/code/modules/materials/materials.dm b/code/modules/materials/materials.dm index 5428e110dbe..c362054cfa3 100644 --- a/code/modules/materials/materials.dm +++ b/code/modules/materials/materials.dm @@ -107,7 +107,7 @@ var/list/name_to_material var/explosion_resistance = 5 // Only used by walls currently. var/negation = 0 // Objects that respect this will randomly absorb impacts with this var as the percent chance. var/spatial_instability = 0 // Objects that have trouble staying in the same physical space by sheer laws of nature have this. Percent for respecting items to cause teleportation. - var/conductive = 1 // Objects with this var add CONDUCTS to flags on spawn. + var/conductive = 1 // Objects without this var add NOCONDUCT to flags on spawn. var/conductivity = null // How conductive the material is. Iron acts as the baseline, at 10. var/list/composite_material // If set, object matter var will be a list containing these values. var/luminescence @@ -259,6 +259,7 @@ var/list/name_to_material icon_colour = "#00FFE1" opacity = 0.4 reflectivity = 0.6 + conductive = 0 conductivity = 1 shard_type = SHARD_SHARD tableslam_noise = 'sound/effects/Glasshit.ogg' @@ -350,6 +351,7 @@ var/list/name_to_material weight = 22 hardness = 55 protectiveness = 5 // 20% + conductive = 0 conductivity = 5 door_icon_base = "stone" sheet_singular_name = "brick" @@ -436,7 +438,7 @@ var/list/name_to_material // Very rare alloy that is reflective, should be used sparingly. /material/durasteel name = "durasteel" - stack_type = /obj/item/stack/material/durasteel + stack_type = /obj/item/stack/material/durasteel/hull integrity = 600 melting_point = 7000 icon_base = "metal" @@ -458,6 +460,9 @@ var/list/name_to_material explosion_resistance = 90 reflectivity = 0.9 +/material/durasteel/hull/place_sheet(var/turf/target) //Deconstructed into normal durasteel sheets. + new /obj/item/stack/material/durasteel(target) + /material/plasteel/titanium name = MAT_TITANIUM stack_type = /obj/item/stack/material/titanium @@ -473,6 +478,9 @@ var/list/name_to_material icon_base = "hull" icon_reinf = "reinf_mesh" +/material/plasteel/titanium/hull/place_sheet(var/turf/target) //Deconstructed into normal titanium sheets. + new /obj/item/stack/material/titanium(target) + /material/glass name = "glass" stack_type = /obj/item/stack/material/glass @@ -485,6 +493,7 @@ var/list/name_to_material hardness = 30 weight = 15 protectiveness = 0 // 0% + conductive = 0 conductivity = 1 // Glass shards don't conduct. door_icon_base = "stone" destruction_desc = "shatters" @@ -626,6 +635,7 @@ var/list/name_to_material hardness = 10 weight = 12 protectiveness = 5 // 20% + conductive = 0 conductivity = 2 // For the sake of material armor diversity, we're gonna pretend this plastic is a good insulator. melting_point = T0C+371 //assuming heat resistant plastic stack_origin_tech = list(TECH_MATERIAL = 3) @@ -643,6 +653,7 @@ var/list/name_to_material stack_origin_tech = list(TECH_MATERIAL = 5) sheet_singular_name = "ingot" sheet_plural_name = "ingots" + conductivity = 100 /material/tritium name = "tritium" @@ -652,6 +663,7 @@ var/list/name_to_material sheet_singular_name = "ingot" sheet_plural_name = "ingots" is_fusion_fuel = 1 + conductive = 0 /material/deuterium name = "deuterium" @@ -661,6 +673,7 @@ var/list/name_to_material sheet_singular_name = "ingot" sheet_plural_name = "ingots" is_fusion_fuel = 1 + conductive = 0 /material/mhydrogen name = "mhydrogen" @@ -730,6 +743,7 @@ var/list/name_to_material icon_reinf = "reinf_metal" protectiveness = 60 integrity = 300 + conductive = 0 conductivity = 1.5 hardness = 90 shard_type = SHARD_SHARD @@ -758,6 +772,7 @@ var/list/name_to_material weight = 30 hardness = 45 negation = 2 + conductive = 0 conductivity = 5 reflectivity = 0.5 radiation_resistance = 20 @@ -813,6 +828,7 @@ var/list/name_to_material melting_point = T0C+300 sheet_singular_name = "blob" sheet_plural_name = "blobs" + conductive = 0 /material/resin/can_open_material_door(var/mob/living/user) var/mob/living/carbon/M = user @@ -833,6 +849,7 @@ var/list/name_to_material hardness = 15 weight = 18 protectiveness = 8 // 28% + conductive = 0 conductivity = 1 melting_point = T0C+300 //okay, not melting in this case, but hot enough to destroy wood ignition_point = T0C+288 @@ -864,7 +881,7 @@ var/list/name_to_material /material/wood/sif name = MAT_SIFWOOD -// stack_type = /obj/item/stack/material/wood/sif + stack_type = /obj/item/stack/material/wood/sif icon_colour = "#0099cc" // Cyan-ish stack_origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 2) // Alien wood would presumably be more interesting to the analyzer. @@ -879,6 +896,7 @@ var/list/name_to_material hardness = 1 weight = 1 protectiveness = 0 // 0% + conductive = 0 ignition_point = T0C+232 //"the temperature at which book-paper catches fire, and burns." close enough melting_point = T0C+232 //temperature at which cardboard walls would be destroyed stack_origin_tech = list(TECH_MATERIAL = 1) @@ -930,6 +948,7 @@ var/list/name_to_material melting_point = T0C+300 protectiveness = 1 // 4% flags = MATERIAL_PADDING + conductive = 0 /material/cult name = "cult" @@ -940,6 +959,7 @@ var/list/name_to_material shard_type = SHARD_STONE_PIECE sheet_singular_name = "brick" sheet_plural_name = "bricks" + conductive = 0 /material/cult/place_dismantled_girder(var/turf/target) new /obj/structure/girder/cult(target, "cult") @@ -963,6 +983,7 @@ var/list/name_to_material ignition_point = T0C+300 melting_point = T0C+300 protectiveness = 3 // 13% + conductive = 0 /material/carpet name = "carpet" @@ -975,6 +996,7 @@ var/list/name_to_material sheet_singular_name = "tile" sheet_plural_name = "tiles" protectiveness = 1 // 4% + conductive = 0 /material/cotton name = "cotton" @@ -984,6 +1006,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 // This all needs to be OOP'd and use inheritence if its ever used in the future. /material/cloth_teal @@ -995,6 +1018,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 /material/cloth_black name = "black" @@ -1005,6 +1029,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 /material/cloth_green name = "green" @@ -1015,6 +1040,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 /material/cloth_puple name = "purple" @@ -1025,6 +1051,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 /material/cloth_blue name = "blue" @@ -1035,6 +1062,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 /material/cloth_beige name = "beige" @@ -1045,6 +1073,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 /material/cloth_lime name = "lime" @@ -1055,6 +1084,7 @@ var/list/name_to_material ignition_point = T0C+232 melting_point = T0C+300 protectiveness = 1 // 4% + conductive = 0 /material/toy_foam name = "foam" @@ -1067,3 +1097,4 @@ var/list/name_to_material hardness = 1 weight = 1 protectiveness = 0 // 0% + conductive = 0 diff --git a/code/modules/metric/count.dm b/code/modules/metric/count.dm index 430f2fdd93b..3900aaaa97e 100644 --- a/code/modules/metric/count.dm +++ b/code/modules/metric/count.dm @@ -11,11 +11,13 @@ num++ return num -/datum/metric/proc/count_all_space_mobs(var/cutoff = 75) +/datum/metric/proc/count_all_space_mobs(var/cutoff = 75, var/respect_z = TRUE) var/num = 0 for(var/mob/living/L in player_list) var/turf/T = get_turf(L) - if(istype(T, /turf/space)) + if(istype(T, /turf/space) && istype(T.loc, /area/space)) + if(respect_z && !(L.z in using_map.station_levels)) + continue if(assess_player_activity(L) >= cutoff) num++ return num diff --git a/code/modules/mining/drilling/scanner.dm b/code/modules/mining/drilling/scanner.dm index 56f371fe91c..bbcc65cc160 100644 --- a/code/modules/mining/drilling/scanner.dm +++ b/code/modules/mining/drilling/scanner.dm @@ -6,14 +6,18 @@ item_state = "electronic" origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1) matter = list(DEFAULT_WALL_MATERIAL = 150) + var/scan_time = 5 SECONDS /obj/item/weapon/mining_scanner/attack_self(mob/user as mob) user << "You begin sweeping \the [src] about, scanning for metal deposits." playsound(loc, 'sound/items/goggles_charge.ogg', 50, 1, -6) - if(!do_after(user, 50)) + if(!do_after(user, scan_time)) return + ScanTurf(user, get_turf(user)) + +/obj/item/weapon/mining_scanner/proc/ScanTurf(var/atom/target, var/mob/user, var/exact = FALSE) var/list/metals = list( "surface minerals" = 0, "precious metals" = 0, @@ -22,7 +26,9 @@ "anomalous matter" = 0 ) - for(var/turf/simulated/T in range(2, get_turf(user))) + var/turf/Turf = get_turf(target) + + for(var/turf/simulated/T in range(2, Turf)) if(!T.has_resources) continue @@ -39,14 +45,18 @@ if(ore_type) metals[ore_type] += T.resources[metal] - user << "\icon[src] The scanner beeps and displays a readout." + to_chat(user, "\icon[src] The scanner beeps and displays a readout.") for(var/ore_type in metals) var/result = "no sign" - switch(metals[ore_type]) - if(1 to 25) result = "trace amounts" - if(26 to 75) result = "significant amounts" - if(76 to INFINITY) result = "huge quantities" + if(!exact) + switch(metals[ore_type]) + if(1 to 25) result = "trace amounts" + if(26 to 75) result = "significant amounts" + if(76 to INFINITY) result = "huge quantities" - user << "- [result] of [ore_type]." \ No newline at end of file + else + result = metals[ore_type] + + to_chat(user, "- [result] of [ore_type].") diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index d07a52a2f22..fa5fcc7397d 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -9,7 +9,7 @@ var/global/list/total_extraction_beacons = list() var/obj/structure/extraction_point/beacon var/list/beacon_networks = list("station") var/uses_left = 3 - var/can_use_indoors + var/can_use_indoors = FALSE var/safe_for_living_creatures = 1 /obj/item/extraction_pack/examine() @@ -145,7 +145,9 @@ var/global/list/total_extraction_beacons = list() icon_state = "subspace_amplifier" /obj/item/fulton_core/attack_self(mob/user) - if(do_after(user,15,target = user) && !QDELETED(src)) + var/turf/T = get_turf(user) + var/outdoors = T.outdoors + if(do_after(user,15,target = user) && !QDELETED(src) && outdoors) new /obj/structure/extraction_point(get_turf(user)) qdel(src) diff --git a/code/modules/mining/mine_outcrops.dm b/code/modules/mining/mine_outcrops.dm new file mode 100644 index 00000000000..5ce5c5bc942 --- /dev/null +++ b/code/modules/mining/mine_outcrops.dm @@ -0,0 +1,117 @@ +/obj/structure/outcrop + name = "outcrop" + desc = "A boring rocky outcrop." + icon = 'icons/obj/outcrop.dmi' + density = 1 + throwpass = 1 + climbable = 1 + anchored = 1 + icon_state = "outcrop" + var/mindrop = 5 + var/upperdrop = 10 + var/outcropdrop = /obj/item/weapon/ore/glass + +/obj/structure/outcrop/Initialize() + . = ..() + if(prob(1)) + overlays += image(icon, "[initial(icon_state)]-egg") + +/obj/structure/outcrop/diamond + name = "shiny outcrop" + desc = "A shiny rocky outcrop." + icon_state = "outcrop-diamond" + mindrop = 2 + upperdrop = 4 + outcropdrop = /obj/item/weapon/ore/diamond + +/obj/structure/outcrop/phoron + name = "shiny outcrop" + desc = "A shiny rocky outcrop." + icon_state = "outcrop-phoron" + mindrop = 4 + upperdrop = 8 + outcropdrop = /obj/item/weapon/ore/phoron + +/obj/structure/outcrop/iron + name = "rugged outcrop" + desc = "A rugged rocky outcrop." + icon_state = "outcrop-iron" + mindrop = 10 + upperdrop = 20 + outcropdrop = /obj/item/weapon/ore/iron + +/obj/structure/outcrop/coal + name = "rugged outcrop" + desc = "A rugged rocky outcrop." + icon_state = "outcrop-coal" + mindrop = 10 + upperdrop = 20 + outcropdrop = /obj/item/weapon/ore/coal + +/obj/structure/outcrop/lead + name = "rugged outcrop" + desc = "A rugged rocky outcrop." + icon_state = "outcrop-lead" + mindrop = 2 + upperdrop = 5 + outcropdrop = /obj/item/weapon/ore/lead + +/obj/structure/outcrop/gold + name = "hollow outcrop" + desc = "A hollow rocky outcrop." + icon_state = "outcrop-gold" + mindrop = 4 + upperdrop = 6 + outcropdrop = /obj/item/weapon/ore/gold + +/obj/structure/outcrop/silver + name = "hollow outcrop" + desc = "A hollow rocky outcrop." + icon_state = "outcrop-silver" + mindrop = 6 + upperdrop = 8 + outcropdrop = /obj/item/weapon/ore/silver + +/obj/structure/outcrop/platinum + name = "hollow outcrop" + desc = "A hollow rocky outcrop." + icon_state = "outcrop-platinum" + mindrop = 2 + upperdrop = 5 + outcropdrop = /obj/item/weapon/ore/osmium + +/obj/structure/outcrop/uranium + name = "spiky outcrop" + desc = "A spiky rocky outcrop, it glows faintly." + icon_state = "outcrop-uranium" + mindrop = 4 + upperdrop = 8 + outcropdrop = /obj/item/weapon/ore/uranium + +/obj/structure/outcrop/attackby(obj/item/W as obj, mob/user as mob) + if (istype(W, /obj/item/weapon/pickaxe)) + to_chat(user, "[user] begins to hack away at \the [src].") + if(do_after(user,40)) + to_chat(user, "You have finished digging!") + for(var/i=0;i<(rand(mindrop,upperdrop));i++) + new outcropdrop(get_turf(src)) + qdel(src) + return + +/obj/random/outcrop //In case you want an outcrop without pre-determining the type of ore. + name = "random rock outcrop" + desc = "This is a random rock outcrop." + icon = 'icons/obj/outcrop.dmi' + icon_state = "outcrop-random" + +/obj/random/outcrop/item_to_spawn() + return pick(prob(100);/obj/structure/outcrop, + prob(100);/obj/structure/outcrop/iron, + prob(100);/obj/structure/outcrop/coal, + prob(65);/obj/structure/outcrop/silver, + prob(50);/obj/structure/outcrop/gold, + prob(30);/obj/structure/outcrop/uranium, + prob(30);/obj/structure/outcrop/phoron, + prob(7);/obj/structure/outcrop/diamond, + prob(15);/obj/structure/outcrop/platinum, + prob(15);/obj/structure/outcrop/lead) \ No newline at end of file diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 4d3e2c0ca72..3da050bacb8 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -11,6 +11,10 @@ var/list/mining_overlay_cache = list() name = "rock" icon = 'icons/turf/walls.dmi' icon_state = "rock" + var/rock_side_icon_state = "rock_side" + var/sand_icon_state = "asteroid" + var/rock_icon_state = "rock" + var/random_icon = 0 oxygen = 0 nitrogen = 0 opacity = 1 @@ -54,6 +58,14 @@ var/list/mining_overlay_cache = list() has_resources = 1 +// Alternative rock wall sprites. +/turf/simulated/mineral/light + icon_state = "rock-light" + rock_side_icon_state = "rock_side-light" + sand_icon_state = "sand-light" + rock_icon_state = "rock-light" + random_icon = 1 + /turf/simulated/mineral/ignore_mapgen ignore_mapgen = 1 @@ -66,6 +78,23 @@ var/list/mining_overlay_cache = list() blocks_air = 0 can_build_into_floor = TRUE +//Alternative sand floor sprite. +turf/simulated/mineral/floor/light + icon_state = "sand-light" + sand_icon_state = "sand-light" + +turf/simulated/mineral/floor/light_border + icon_state = "sand-light-border" + sand_icon_state = "sand-light-border" + +turf/simulated/mineral/floor/light_nub + icon_state = "sand-light-nub" + sand_icon_state = "sand-light-nub" + +turf/simulated/mineral/floor/light_corner + icon_state = "sand-light-corner" + sand_icon_state = "sand-light-corner" + /turf/simulated/mineral/floor/ignore_mapgen ignore_mapgen = 1 @@ -130,6 +159,9 @@ var/list/mining_overlay_cache = list() update_icon(1) if(density && mineral) . = INITIALIZE_HINT_LATELOAD + if(random_icon) + dir = pick(alldirs) + . = INITIALIZE_HINT_LATELOAD /turf/simulated/mineral/LateInitialize() if(density && mineral) @@ -147,13 +179,13 @@ var/list/mining_overlay_cache = list() name = "rock" icon = 'icons/turf/walls.dmi' - icon_state = "rock" + icon_state = rock_icon_state //Apply overlays if we should have borders for(var/direction in cardinal) var/turf/T = get_step(src,direction) if(istype(T) && !T.density) - add_overlay(get_cached_border("rock_side",direction,icon,"rock_side")) + add_overlay(get_cached_border(rock_side_icon_state,direction,icon,rock_side_icon_state)) if(archaeo_overlay) add_overlay(archaeo_overlay) @@ -165,7 +197,7 @@ var/list/mining_overlay_cache = list() else name = "sand" icon = 'icons/turf/flooring/asteroid.dmi' - icon_state = "asteroid" + icon_state = sand_icon_state if(sand_dug) add_overlay("dug_overlay") @@ -179,7 +211,7 @@ var/list/mining_overlay_cache = list() else var/turf/T = get_step(src, direction) if(istype(T) && T.density) - add_overlay(get_cached_border("rock_side",direction,'icons/turf/walls.dmi',"rock_side")) + add_overlay(get_cached_border(rock_side_icon_state,direction,'icons/turf/walls.dmi',rock_side_icon_state)) if(overlay_detail) add_overlay('icons/turf/flooring/decals.dmi',overlay_detail) @@ -559,9 +591,9 @@ var/list/mining_overlay_cache = list() if(is_clean) X = new /obj/item/weapon/archaeological_find(src, new_item_type = F.find_type) else - X = new /obj/item/weapon/ore/strangerock(src, inside_item_type = F.find_type) + X = new /obj/item/weapon/strangerock(src, inside_item_type = F.find_type) geologic_data.UpdateNearbyArtifactInfo(src) - var/obj/item/weapon/ore/strangerock/SR = X + var/obj/item/weapon/strangerock/SR = X SR.geologic_data = geologic_data //some find types delete the /obj/item/weapon/archaeological_find and replace it with something else, this handles when that happens diff --git a/code/modules/mining/ore_datum_vr.dm b/code/modules/mining/ore_datum_vr.dm new file mode 100644 index 00000000000..e55bc9e599c --- /dev/null +++ b/code/modules/mining/ore_datum_vr.dm @@ -0,0 +1,2 @@ +/ore/coal + compresses_to = "carbon" \ No newline at end of file diff --git a/code/modules/mining/ore_redemption_machine/construction.dm b/code/modules/mining/ore_redemption_machine/construction.dm index dbf8a96ffb7..3880ef5cb8a 100644 --- a/code/modules/mining/ore_redemption_machine/construction.dm +++ b/code/modules/mining/ore_redemption_machine/construction.dm @@ -10,3 +10,12 @@ req_components = list( /obj/item/weapon/stock_parts/console_screen = 1, /obj/item/weapon/stock_parts/matter_bin = 3) + +/obj/item/weapon/circuitboard/exploration_equipment_vendor + name = T_BOARD("Exploration Equipment Vendor") + board_type = new /datum/frame/frame_types/machine + build_path = /obj/machinery/mineral/equipment_vendor/survey + origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 2) + req_components = list( + /obj/item/weapon/stock_parts/console_screen = 1, + /obj/item/weapon/stock_parts/matter_bin = 3) diff --git a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm index 418ec44a8a4..3d9651c044f 100644 --- a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm +++ b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm @@ -10,7 +10,7 @@ circuit = /obj/item/weapon/circuitboard/mining_equipment_vendor var/icon_deny = "mining-deny" var/obj/item/weapon/card/id/inserted_id - //VOREStation Edit - Heavily modified list + //VOREStation Edit Start - Heavily modified list var/list/prize_list = list( new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10), new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 100), @@ -20,11 +20,14 @@ new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 150), new /datum/data/mining_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 200), new /datum/data/mining_equipment("Laser Pointer", /obj/item/device/laser_pointer, 900), + new /datum/data/mining_equipment("Geiger Counter", /obj/item/device/geiger, 750), new /datum/data/mining_equipment("Plush Toy", /obj/random/plushie, 300), + new /datum/data/mining_equipment("GPS Device", /obj/item/device/gps/mining, 100), // TODO new /datum/data/mining_equipment("Advanced Scanner", /obj/item/device/t_scanner/adv_mining_scanner, 800), new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 500), new /datum/data/mining_equipment("Shelter Capsule", /obj/item/device/survivalcapsule, 500), // TODO new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/storage/belt/mining, 500), + new /datum/data/mining_equipment("Umbrella", /obj/item/weapon/melee/umbrella/random, 200), new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500), new /datum/data/mining_equipment("Survival Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/miner, 500), new /datum/data/mining_equipment("Mini-Translocator", /obj/item/device/perfect_tele/one_beacon, 1200), @@ -33,15 +36,21 @@ new /datum/data/mining_equipment("Resonator", /obj/item/resonator, 900), new /datum/data/mining_equipment("Fulton Pack", /obj/item/extraction_pack, 1200), new /datum/data/mining_equipment("Silver Pickaxe", /obj/item/weapon/pickaxe/silver, 1200), - //new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffelbag/mining_conscript, 1000), + // new /datum/data/mining_equipment("Mining Conscription Kit", /obj/item/storage/backpack/duffelbag/mining_conscript, 1000), new /datum/data/mining_equipment("Space Cash", /obj/item/weapon/spacecash/c100, 1000), - new /datum/data/mining_equipment("Industrial Hardsuit - Control Module", /obj/item/weapon/rig/industrial, 2000), - new /datum/data/mining_equipment("Industrial Hardsuit - Plasma Cutter", /obj/item/rig_module/device/plasmacutter, 800), - new /datum/data/mining_equipment("Industrial Hardsuit - Drill", /obj/item/rig_module/device/drill, 2000), - new /datum/data/mining_equipment("Industrial Hardsuit - Ore Scanner", /obj/item/rig_module/device/orescanner, 1000), - new /datum/data/mining_equipment("Industrial Hardsuit - Material Scanner", /obj/item/rig_module/vision/material, 500), - new /datum/data/mining_equipment("Industrial Hardsuit - Maneuvering Jets", /obj/item/rig_module/maneuvering_jets, 1250), - new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000), + new /datum/data/mining_equipment("Hardsuit - Control Module", /obj/item/weapon/rig/industrial, 2000), + new /datum/data/mining_equipment("Hardsuit - Plasma Cutter", /obj/item/rig_module/device/plasmacutter, 800), + new /datum/data/mining_equipment("Hardsuit - Drill", /obj/item/rig_module/device/drill, 5000), + new /datum/data/mining_equipment("Hardsuit - Ore Scanner", /obj/item/rig_module/device/orescanner, 1000), + new /datum/data/mining_equipment("Hardsuit - Material Scanner", /obj/item/rig_module/vision/material, 500), + new /datum/data/mining_equipment("Hardsuit - Maneuvering Jets", /obj/item/rig_module/maneuvering_jets, 1250), + new /datum/data/mining_equipment("Hardsuit - Intelligence Storage", /obj/item/rig_module/ai_container, 2500), + new /datum/data/mining_equipment("Hardsuit - Smoke Bomb Deployer", /obj/item/rig_module/grenade_launcher/smoke, 2000), + new /datum/data/mining_equipment("Industrial Equipment - Phoron Bore", /obj/item/weapon/gun/magnetic/matfed, 3000), + new /datum/data/mining_equipment("Industrial Equipment - Sheet-Snatcher",/obj/item/weapon/storage/bag/sheetsnatcher, 500), + new /datum/data/mining_equipment("Digital Tablet - Standard", /obj/item/modular_computer/tablet/preset/custom_loadout/standard, 500), + new /datum/data/mining_equipment("Digital Tablet - Advanced", /obj/item/modular_computer/tablet/preset/custom_loadout/advanced, 1000), + // new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000), new /datum/data/mining_equipment("Super Resonator", /obj/item/resonator/upgraded, 2500), new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 2500), new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/device/survivalcapsule/luxury, 3100), @@ -54,6 +63,18 @@ new /datum/data/mining_equipment("KA Efficiency Increase", /obj/item/borg/upgrade/modkit/efficiency, 1200), new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000), new /datum/data/mining_equipment("KA Holster", /obj/item/clothing/accessory/holster/waist/kinetic_accelerator, 350), + new /datum/data/mining_equipment("Fine Excavation Kit - Chisels",/obj/item/weapon/storage/excavation, 500), + new /datum/data/mining_equipment("Fine Excavation Kit - Measuring Tape",/obj/item/device/measuring_tape, 125), + new /datum/data/mining_equipment("Fine Excavation Kit - Hand Pick",/obj/item/weapon/pickaxe/hand, 375), + new /datum/data/mining_equipment("Explosive Excavation Kit - Plastic Charge",/obj/item/weapon/plastique/seismic/locked, 1500), + new /datum/data/mining_equipment("Injector (L) - Glucose",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose, 500), + new /datum/data/mining_equipment("Injector (L) - Panacea",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity, 500), + new /datum/data/mining_equipment("Injector (L) - Trauma",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute, 500), + new /datum/data/mining_equipment("Nanopaste Tube", /obj/item/stack/nanopaste, 1000), + new /datum/data/mining_equipment("Defense Equipment - Smoke Bomb",/obj/item/weapon/grenade/smokebomb, 100), + new /datum/data/mining_equipment("Defense Equipment - Razor Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked, 1000), + new /datum/data/mining_equipment("Defense Equipment - Sentry Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/ward, 1500), + new /datum/data/mining_equipment("Defense Equipment - Plasteel Machete", /obj/item/weapon/material/knife/machete, 500), new /datum/data/mining_equipment("Fishing Net", /obj/item/weapon/material/fishing_net, 500), new /datum/data/mining_equipment("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 1000), new /datum/data/mining_equipment("Durasteel Fishing Rod", /obj/item/weapon/material/fishing_rod/modern/strong, 7500) diff --git a/code/modules/mining/ore_redemption_machine/mine_point_items.dm b/code/modules/mining/ore_redemption_machine/mine_point_items.dm index da4463842a5..a6a90a3bd6f 100644 --- a/code/modules/mining/ore_redemption_machine/mine_point_items.dm +++ b/code/modules/mining/ore_redemption_machine/mine_point_items.dm @@ -15,19 +15,33 @@ name = "mining point card" desc = "A small card preloaded with mining points. Swipe your ID card over it to transfer the points, then discard." icon_state = "data" - var/points = 500 + var/mine_points = 500 + var/survey_points = 0 /obj/item/weapon/card/mining_point_card/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/weapon/card/id)) - if(points) - var/obj/item/weapon/card/id/C = I - C.mining_points += points - to_chat(user, "You transfer [points] points to [C].") - points = 0 + var/obj/item/weapon/card/id/C = I + if(mine_points) + C.mining_points += mine_points + to_chat(user, "You transfer [mine_points] excavation points to [C].") + mine_points = 0 else - to_chat(user, "There's no points left on [src].") + to_chat(user, "There's no excavation points left on [src].") + + if(survey_points) + C.survey_points += survey_points + to_chat(user, "You transfer [survey_points] survey points to [C].") + survey_points = 0 + else + to_chat(user, "There's no survey points left on [src].") + ..() /obj/item/weapon/card/mining_point_card/examine(mob/user) ..(user) - to_chat(user, "There's [points] points on the card.") + to_chat(user, "There's [mine_points] excavation points on the card.") + to_chat(user, "There's [survey_points] survey points on the card.") + +/obj/item/weapon/card/mining_point_card/survey + mine_points = 0 + survey_points = 50 diff --git a/code/modules/mining/ore_redemption_machine/survey_vendor.dm b/code/modules/mining/ore_redemption_machine/survey_vendor.dm new file mode 100644 index 00000000000..61f5a269622 --- /dev/null +++ b/code/modules/mining/ore_redemption_machine/survey_vendor.dm @@ -0,0 +1,110 @@ +/obj/machinery/mineral/equipment_vendor/survey + name = "exploration equipment vendor" + desc = "An equipment vendor for explorers, points collected with a survey scanner can be spent here." + icon = 'icons/obj/machines/mining_machines_vr.dmi' //VOREStation Edit + icon_state = "exploration" //VOREStation Edit + density = TRUE + anchored = TRUE + circuit = /obj/item/weapon/circuitboard/exploration_equipment_vendor + icon_deny = "exploration-deny" //VOREStation Edit + var/icon_vend = "exploration-vend" //VOREStation Add + //VOREStation Edit Start - Heavily modified list + prize_list = list( + new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 1), + new /datum/data/mining_equipment("10 Marker Beacons", /obj/item/stack/marker_beacon/ten, 10), + new /datum/data/mining_equipment("30 Marker Beacons", /obj/item/stack/marker_beacon/thirty, 30), + new /datum/data/mining_equipment("GPS Device", /obj/item/device/gps/explorer, 10), + new /datum/data/mining_equipment("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 10), + new /datum/data/mining_equipment("Absinthe", /obj/item/weapon/reagent_containers/food/drinks/bottle/absinthe, 10), + new /datum/data/mining_equipment("Cigar", /obj/item/clothing/mask/smokable/cigarette/cigar/havana, 15), + new /datum/data/mining_equipment("Soap", /obj/item/weapon/soap/nanotrasen, 20), + new /datum/data/mining_equipment("Laser Pointer", /obj/item/device/laser_pointer, 90), + new /datum/data/mining_equipment("Geiger Counter", /obj/item/device/geiger, 75), + new /datum/data/mining_equipment("Plush Toy", /obj/random/plushie, 30), + new /datum/data/mining_equipment("Extraction Equipment - Fulton Beacon", /obj/item/fulton_core, 300), + new /datum/data/mining_equipment("Extraction Equipment - Fulton Pack", /obj/item/extraction_pack, 125), + new /datum/data/mining_equipment("Umbrella", /obj/item/weapon/melee/umbrella/random, 20), + new /datum/data/mining_equipment("Shelter Capsule", /obj/item/device/survivalcapsule, 50), + new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card/survey, 50), + new /datum/data/mining_equipment("Survival Medipen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/miner, 50), + new /datum/data/mining_equipment("Injector (L) - Glucose",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/glucose, 50), + new /datum/data/mining_equipment("Injector (L) - Panacea",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/purity, 50), + new /datum/data/mining_equipment("Injector (L) - Trauma",/obj/item/weapon/reagent_containers/hypospray/autoinjector/biginjector/brute, 50), + new /datum/data/mining_equipment("Digital Tablet - Standard", /obj/item/modular_computer/tablet/preset/custom_loadout/standard, 50), + new /datum/data/mining_equipment("Digital Tablet - Advanced", /obj/item/modular_computer/tablet/preset/custom_loadout/advanced, 100), + new /datum/data/mining_equipment("Nanopaste Tube", /obj/item/stack/nanopaste, 100), + new /datum/data/mining_equipment("Mini-Translocator", /obj/item/device/perfect_tele/one_beacon, 120), + new /datum/data/mining_equipment("Space Cash", /obj/item/weapon/spacecash/c100, 100), + new /datum/data/mining_equipment("Jump Boots", /obj/item/clothing/shoes/bhop, 250), + new /datum/data/mining_equipment("Luxury Shelter Capsule", /obj/item/device/survivalcapsule/luxury, 310), + new /datum/data/mining_equipment("Industrial Equipment - Phoron Bore", /obj/item/weapon/gun/magnetic/matfed, 300), + new /datum/data/mining_equipment("Survey Tools - Shovel", /obj/item/weapon/shovel, 40), + new /datum/data/mining_equipment("Survey Tools - Mechanical Trap", /obj/item/weapon/beartrap, 50), + new /datum/data/mining_equipment("Defense Equipment - Smoke Bomb",/obj/item/weapon/grenade/smokebomb, 10), + new /datum/data/mining_equipment("Defense Equipment - Razor Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/manhacks/station/locked, 100), + new /datum/data/mining_equipment("Defense Equipment - Sentry Drone Deployer",/obj/item/weapon/grenade/spawnergrenade/ward, 150), + new /datum/data/mining_equipment("Defense Equipment - Steel Machete", /obj/item/weapon/material/knife/machete, 75), + new /datum/data/mining_equipment("Fishing Net", /obj/item/weapon/material/fishing_net, 50), + new /datum/data/mining_equipment("Titanium Fishing Rod", /obj/item/weapon/material/fishing_rod/modern, 100), + new /datum/data/mining_equipment("Durasteel Fishing Rod", /obj/item/weapon/material/fishing_rod/modern/strong, 750) + ) + //VOREStation Edit End + +/obj/machinery/mineral/equipment_vendor/survey/interact(mob/user) + user.set_machine(src) + + var/dat + dat +="
      " + if(istype(inserted_id)) + dat += "You have [inserted_id.survey_points] survey points collected. Eject ID.
      " + else + dat += "No ID inserted. Insert ID.
      " + dat += "
      " + dat += "
      Equipment point cost list:
      " + for(var/datum/data/mining_equipment/prize in prize_list) + dat += "" + dat += "
      [prize.equipment_name][prize.cost]Purchase
      " + var/datum/browser/popup = new(user, "miningvendor", "Survey Equipment Vendor", 400, 600) + popup.set_content(dat) + popup.open() + +/obj/machinery/mineral/equipment_vendor/survey/Topic(href, href_list) + if(..()) + return 1 + + if(href_list["choice"]) + if(istype(inserted_id)) + if(href_list["choice"] == "eject") + to_chat(usr, "You eject the ID from [src]'s card slot.") + usr.put_in_hands(inserted_id) + inserted_id = null + else if(href_list["choice"] == "insert") + var/obj/item/weapon/card/id/I = usr.get_active_hand() + if(istype(I) && !inserted_id && usr.unEquip(I)) + I.forceMove(src) + inserted_id = I + interact(usr) + to_chat(usr, "You insert the ID into [src]'s card slot.") + else + to_chat(usr, "No valid ID.") + flick(icon_deny, src) + + if(href_list["purchase"]) + if(istype(inserted_id)) + var/datum/data/mining_equipment/prize = locate(href_list["purchase"]) + if (!prize || !(prize in prize_list)) + to_chat(usr, "Error: Invalid choice!") + flick(icon_deny, src) + return + if(prize.cost > inserted_id.survey_points) + to_chat(usr, "Error: Insufficent points for [prize.equipment_name]!") + flick(icon_deny, src) + else + inserted_id.survey_points -= prize.cost + to_chat(usr, "[src] clanks to life briefly before vending [prize.equipment_name]!") + flick(icon_vend, src) //VOREStation Add + new prize.equipment_path(drop_location()) + else + to_chat(usr, "Error: Please insert a valid ID!") + flick(icon_deny, src) + updateUsrDialog() diff --git a/code/modules/mob/_modifiers/medical.dm b/code/modules/mob/_modifiers/medical.dm new file mode 100644 index 00000000000..46a8877d1f2 --- /dev/null +++ b/code/modules/mob/_modifiers/medical.dm @@ -0,0 +1,17 @@ +/* + * Modifiers caused by chemicals or organs specifically. + */ + +/datum/modifier/cryogelled + name = "cryogelled" + desc = "Your body begins to freeze." + mob_overlay_state = "chilled" + + on_created_text = "You feel like you're going to freeze! It's hard to move." + on_expired_text = "You feel somewhat warmer and more mobile now." + stacks = MODIFIER_STACK_ALLOWED + + slowdown = 0.1 + evasion = -5 + attack_speed_percent = 1.1 + disable_duration_percent = 1.05 diff --git a/code/modules/mob/_modifiers/modifiers_misc.dm b/code/modules/mob/_modifiers/modifiers_misc.dm index e81cf0aaa86..800429de257 100644 --- a/code/modules/mob/_modifiers/modifiers_misc.dm +++ b/code/modules/mob/_modifiers/modifiers_misc.dm @@ -43,7 +43,7 @@ the artifact triggers the rage. /datum/modifier/berserk name = "berserk" desc = "You are filled with an overwhelming rage." - client_color = "#FF0000" // Make everything red! + client_color = "#FF5555" // Make everything red! mob_overlay_state = "berserk" on_created_text = "You feel an intense and overwhelming rage overtake you as you go berserk!" @@ -293,4 +293,29 @@ the artifact triggers the rage. on_expired_text = "You feel.. different." stacks = MODIFIER_STACK_EXTEND - pulse_set_level = PULSE_NORM \ No newline at end of file + pulse_set_level = PULSE_NORM + +/datum/modifier/slow_pulse + name = "slow pulse" + desc = "Your blood flows slower." + + on_created_text = "You feel sluggish." + on_expired_text = "You feel energized." + stacks = MODIFIER_STACK_EXTEND + + bleeding_rate_percent = 0.8 + + pulse_set_level = PULSE_SLOW + +// Temperature Normalizer. +/datum/modifier/homeothermic + name = "temperature resistance" + desc = "Your body normalizes to room temperature." + + on_created_text = "You feel comfortable." + on_expired_text = "You feel.. still probably comfortable." + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/homeothermic/tick() + ..() + holder.bodytemperature = round((holder.bodytemperature + T20C) / 2) diff --git a/code/modules/mob/_modifiers/unholy.dm b/code/modules/mob/_modifiers/unholy.dm index 0b6f69a21b9..730e57691c2 100644 --- a/code/modules/mob/_modifiers/unholy.dm +++ b/code/modules/mob/_modifiers/unholy.dm @@ -146,3 +146,55 @@ if(prob(10)) to_chat(H, "It feels as though your body is being torn apart!") L.updatehealth() + +/datum/modifier/gluttonyregeneration + name = "gluttonous regeneration" + desc = "You are filled with an overwhelming hunger." + mob_overlay_state = "electricity" + + on_created_text = "You feel an intense and overwhelming hunger overtake you as your body regenerates!" + on_expired_text = "The blaze of hunger inside you has been snuffed." + stacks = MODIFIER_STACK_EXTEND + +/datum/modifier/gluttonyregeneration/can_apply(var/mob/living/L) + if(L.stat == DEAD) + to_chat(L, "You can't be dead to consume.") + return FALSE + + if(!L.is_sentient()) + return FALSE // Drones don't feel anything, not even hunger. + + if(L.has_modifier_of_type(/datum/modifier/berserk_exhaustion)) + to_chat(L, "You recently berserked, so you are too tired to consume.") + return FALSE + + if(!ishuman(L)) // Only humanoids feel hunger. Totally. + return FALSE + + else + var/mob/living/carbon/human/H = L + if(H.species.name == "Diona") + to_chat(L, "You feel strange for a moment, but it passes.") + return FALSE // Happy trees aren't affected by incredible hunger. + + return ..() + +/datum/modifier/gluttonyregeneration/tick() + spawn() + if(ishuman(holder)) + var/mob/living/carbon/human/H = holder + var/starting_nutrition = H.nutrition + H.nutrition = max(0, H.nutrition - 10) + var/healing_amount = starting_nutrition - H.nutrition + if(healing_amount < 0) // If you are eating enough to somehow outpace this, congratulations, you are gluttonous enough to gain a boon. + healing_amount *= -2 + + H.adjustBruteLoss(-healing_amount * 0.25) + + H.adjustFireLoss(-healing_amount * 0.25) + + H.adjustOxyLoss(-healing_amount * 0.25) + + H.adjustToxLoss(-healing_amount * 0.25) + + ..() \ No newline at end of file diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index a3bf0d5465e..2c74029eb8a 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -389,17 +389,17 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return (T && T.holy) && (is_manifest || (mind in cult.current_antagonists)) -/mob/observer/dead/verb/jumptomob(target in getmobs()) //Moves the ghost instead of just changing the ghosts's eye -Nodrak +/mob/observer/dead/verb/jumptomob(input in getmobs()) //Moves the ghost instead of just changing the ghosts's eye -Nodrak set category = "Ghost" set name = "Jump to Mob" set desc = "Teleport to a mob" set popup_menu = FALSE //VOREStation Edit - Declutter. if(istype(usr, /mob/observer/dead)) //Make sure they're an observer! - + var/target = getmobs()[input] if (!target)//Make sure we actually have a target return else - var/mob/M = getmobs()[target] //Destination mob + var/mob/M = target //Destination mob var/turf/T = get_turf(M) //Turf of the destination mob if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination. diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm index 54087426547..693b2129e11 100644 --- a/code/modules/mob/hear_say.dm +++ b/code/modules/mob/hear_say.dm @@ -33,7 +33,7 @@ if(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages if(!say_understands(speaker,language)) if(language) - message = language.scramble(message) + message = language.scramble(message, languages) else message = stars(message) @@ -165,7 +165,7 @@ if(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages if(!say_understands(speaker,language)) if(language) - message = language.scramble(message) + message = language.scramble(message, languages) else message = stars(message) diff --git a/code/modules/mob/language/generic.dm b/code/modules/mob/language/generic.dm index 5a46a720389..8fa9efcd730 100644 --- a/code/modules/mob/language/generic.dm +++ b/code/modules/mob/language/generic.dm @@ -32,6 +32,7 @@ syllables = list( "vol", "zum", "coo","zoo","bi","do","ooz","ite","og","re","si","ite","ish", "ar","at","on","ee","east","ma","da", "rim") + partial_understanding = list(LANGUAGE_SKRELLIAN = 30, LANGUAGE_SOL_COMMON = 30) //TODO flag certain languages to use the mob-type specific say_quote and then get rid of these. /datum/language/common/get_spoken_verb(var/msg_end) @@ -64,6 +65,7 @@ colour = "terminus" key = "4" // flags = WHITELISTED (VOREstation edit) + // partial_understanding = list(LANGUAGE_SOL_COMMON = 20) (VOREStation Edit: It is a Zorren language now) syllables = list (".a", "spa", "pan", "blaif", "stra", "!u", "!ei", "!am", "by", ".y", "gry", "zbly", "!y", "fl", "sm", "rn", "cpi", "ku", "koi", "pr", "glau", "stu", "ved", "ki", "tsa", "xau", "jbu", "sny", "stro", "nu", "uan", "ju", "!i", "ge", "luk", "an", "ar", "at", "es", "et", "bel", "ki", "jaa", "ch", "ki", "gh", "ll", "uu", "wat") @@ -76,6 +78,7 @@ colour = "rough" key = "3" space_chance = 45 + partial_understanding = list(LANGUAGE_GALCOM = 10, LANGUAGE_TRADEBAND = 20, LANGUAGE_SOL_COMMON = 20) syllables = list ( "gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh", "gra", "a", "ai", "an", "ang", "ao", "ba", "bai", "ban", "bang", "bao", "bei", "ben", "beng", "bi", "bian", "biao", @@ -211,4 +214,4 @@ ) /datum/language/gibberish/can_speak_special(var/mob/speaker) - return TRUE //Anyone can speak gibberish \ No newline at end of file + return TRUE //Anyone can speak gibberish diff --git a/code/modules/mob/language/language.dm b/code/modules/mob/language/language.dm index 4822f46a164..f558301b151 100644 --- a/code/modules/mob/language/language.dm +++ b/code/modules/mob/language/language.dm @@ -19,6 +19,7 @@ var/list/syllables // Used when scrambling text for a non-speaker. var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string var/machine_understands = 1 // Whether machines can parse and understand this language + var/list/partial_understanding // List of languages that can /somehwat/ understand it, format is: name = chance of understanding a word /datum/language/proc/get_random_name(var/gender, name_count=2, syllable_count=4, syllable_divisor=2) if(!syllables || !syllables.len) @@ -41,8 +42,42 @@ /datum/language var/list/scramble_cache = list() -/datum/language/proc/scramble(var/input) +/datum/language/proc/scramble(var/input, var/list/known_languages) + var/understand_chance = 0 + for(var/datum/language/L in known_languages) + if(partial_understanding && partial_understanding[L.name]) + understand_chance += partial_understanding[L.name] + if(L.partial_understanding && L.partial_understanding[name]) + understand_chance += L.partial_understanding[name] * 0.5 + var/scrambled_text = "" + var/list/words = splittext(input, " ") + for(var/w in words) + if(prob(understand_chance)) + scrambled_text += " [w] " + else + var/nword = scramble_word(w) + var/ending = copytext(scrambled_text, length(scrambled_text)-1) + if(findtext(ending,".")) + nword = capitalize(nword) + else if(findtext(ending,"!")) + nword = capitalize(nword) + else if(findtext(ending,"?")) + nword = capitalize(nword) + scrambled_text += nword + scrambled_text = replacetext(scrambled_text," "," ") + scrambled_text = capitalize(scrambled_text) + scrambled_text = trim(scrambled_text) + var/ending = copytext(scrambled_text, length(scrambled_text)) + if(ending == ".") + scrambled_text = copytext(scrambled_text,1,length(scrambled_text)-1) + var/input_ending = copytext(input, length(input)) + if(input_ending in list("!","?",".")) + scrambled_text += input_ending + + return scrambled_text + +/datum/language/proc/scramble_word(var/input) if(!syllables || !syllables.len) return stars(input) @@ -55,7 +90,7 @@ var/input_size = length(input) var/scrambled_text = "" - var/capitalize = 1 + var/capitalize = 0 while(length(scrambled_text) < input_size) var/next = pick(syllables) @@ -70,14 +105,6 @@ else if(chance > 5 && chance <= space_chance) scrambled_text += " " - scrambled_text = trim(scrambled_text) - var/ending = copytext(scrambled_text, length(scrambled_text)) - if(ending == ".") - scrambled_text = copytext(scrambled_text,1,length(scrambled_text)-1) - var/input_ending = copytext(input, input_size) - if(input_ending in list("!","?",".")) - scrambled_text += input_ending - // Add it to cache, cutting old entries if the list is too long scramble_cache[input] = scrambled_text if(scramble_cache.len > SCRAMBLE_CACHE_LEN) diff --git a/code/modules/mob/language/monkey.dm b/code/modules/mob/language/monkey.dm index c6024d346b7..782c5bcf24e 100644 --- a/code/modules/mob/language/monkey.dm +++ b/code/modules/mob/language/monkey.dm @@ -5,24 +5,28 @@ ask_verb = "chimpers" exclaim_verb = "screeches" key = "6" + syllables = list("ook","eek") machine_understands = 0 /datum/language/skrell/monkey name = "Neaera" desc = "Squik squik squik." key = "8" + syllables = list("hiss","gronk") machine_understands = 0 /datum/language/unathi/monkey name = "Stok" desc = "Hiss hiss hiss." key = "7" + syllables = list("squick","croak") machine_understands = 0 /datum/language/tajaran/monkey name = "Farwa" desc = "Meow meow meow." key = "9" + syllables = list("meow","mew") machine_understands = 0 /datum/language/corgi diff --git a/code/modules/mob/living/bot/SLed209bot.dm b/code/modules/mob/living/bot/SLed209bot.dm new file mode 100644 index 00000000000..7b5bbc76e5d --- /dev/null +++ b/code/modules/mob/living/bot/SLed209bot.dm @@ -0,0 +1,172 @@ +/mob/living/bot/secbot/ed209/slime + name = "SL-ED-209 Security Robot" + desc = "A security robot. He looks less than thrilled." + icon = 'icons/obj/aibots.dmi' + icon_state = "sled2090" + density = 1 + health = 200 + maxHealth = 200 + + is_ranged = 1 + preparing_arrest_sounds = new() + + a_intent = I_HURT + mob_bump_flag = HEAVY + mob_swap_flags = ~HEAVY + mob_push_flags = HEAVY + + used_weapon = /obj/item/weapon/gun/energy/taser/xeno + + stun_strength = 10 + xeno_harm_strength = 9 + req_one_access = list(access_research, access_robotics) + botcard_access = list(access_research, access_robotics, access_xenobiology, access_xenoarch, access_tox, access_tox_storage, access_maint_tunnels) + var/xeno_stun_strength = 6 + +/mob/living/bot/secbot/ed209/slime/update_icons() + if(on && busy) + icon_state = "sled209-c" + else + icon_state = "sled209[on]" + +/mob/living/bot/secbot/ed209/slime/RangedAttack(var/atom/A) + if(last_shot + shot_delay > world.time) + to_chat(src, "You are not ready to fire yet!") + return + + last_shot = world.time + + var/projectile = /obj/item/projectile/beam/stun/xeno + if(emagged) + projectile = /obj/item/projectile/beam/shock + + playsound(loc, emagged ? 'sound/weapons/laser3.ogg' : 'sound/weapons/Taser.ogg', 50, 1) + var/obj/item/projectile/P = new projectile(loc) + + P.firer = src + P.old_style_target(A) + P.fire() + +/mob/living/bot/secbot/ed209/slime/UnarmedAttack(var/mob/living/L, var/proximity) + ..() + + if(istype(L, /mob/living/simple_mob/slime/xenobio)) + var/mob/living/simple_mob/slime/xenobio/S = L + S.slimebatoned(src, xeno_stun_strength) + +// Assembly + +/obj/item/weapon/secbot_assembly/ed209_assembly/slime + name = "SL-ED-209 assembly" + desc = "Some sort of bizarre assembly." + icon = 'icons/obj/aibots.dmi' + icon_state = "ed209_frame" + item_state = "buildpipe" + created_name = "SL-ED-209 Security Robot" + +/obj/item/weapon/secbot_assembly/ed209_assembly/slime/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) // Here in the event it's added into a PoI or some such. Standard construction relies on the standard ED up until taser. + if(istype(W, /obj/item/weapon/pen)) + var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN) + if(!t) + return + if(!in_range(src, usr) && src.loc != usr) + return + created_name = t + return + + switch(build_step) + if(0, 1) + if(istype(W, /obj/item/robot_parts/l_leg) || istype(W, /obj/item/robot_parts/r_leg) || (istype(W, /obj/item/organ/external/leg) && ((W.name == "robotic right leg") || (W.name == "robotic left leg")))) + user.drop_item() + qdel(W) + build_step++ + to_chat(user, "You add the robot leg to [src].") + name = "legs/frame assembly" + if(build_step == 1) + icon_state = "ed209_leg" + else + icon_state = "ed209_legs" + + if(2) + if(istype(W, /obj/item/clothing/suit/storage/vest)) + user.drop_item() + qdel(W) + build_step++ + to_chat(user, "You add the armor to [src].") + name = "vest/legs/frame assembly" + item_state = "ed209_shell" + icon_state = "ed209_shell" + + if(3) + if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + build_step++ + name = "shielded frame assembly" + to_chat(user, "You welded the vest to [src].") + if(4) + if(istype(W, /obj/item/clothing/head/helmet)) + user.drop_item() + qdel(W) + build_step++ + to_chat(user, "You add the helmet to [src].") + name = "covered and shielded frame assembly" + item_state = "ed209_hat" + icon_state = "ed209_hat" + + if(5) + if(isprox(W)) + user.drop_item() + qdel(W) + build_step++ + to_chat(user, "You add the prox sensor to [src].") + name = "covered, shielded and sensored frame assembly" + item_state = "ed209_prox" + icon_state = "ed209_prox" + + if(6) + if(istype(W, /obj/item/stack/cable_coil)) + var/obj/item/stack/cable_coil/C = W + if (C.get_amount() < 1) + to_chat(user, "You need one coil of wire to wire [src].") + return + to_chat(user, "You start to wire [src].") + if(do_after(user, 40) && build_step == 6) + if(C.use(1)) + build_step++ + to_chat(user, "You wire the ED-209 assembly.") + name = "wired ED-209 assembly" + return + + if(7) + if(istype(W, /obj/item/weapon/gun/energy/taser/xeno)) + name = "xenotaser SL-ED-209 assembly" + item_state = "sled209_taser" + icon_state = "sled209_taser" + build_step++ + to_chat(user, "You add [W] to [src].") + user.drop_item() + qdel(W) + + if(8) + if(W.is_screwdriver()) + playsound(src, W.usesound, 100, 1) + var/turf/T = get_turf(user) + to_chat(user, "Now attaching the gun to the frame...") + sleep(40) + if(get_turf(user) == T && build_step == 8) + build_step++ + name = "armed [name]" + to_chat(user, "Taser gun attached.") + + if(9) + if(istype(W, /obj/item/weapon/cell)) + build_step++ + to_chat(user, "You complete the ED-209.") + var/turf/T = get_turf(src) + new /mob/living/bot/secbot/ed209/slime(T,created_name,lasercolor) + user.drop_item() + qdel(W) + user.drop_from_inventory(src) + qdel(src) + diff --git a/code/modules/mob/living/bot/bot.dm b/code/modules/mob/living/bot/bot.dm index ff35a795b5a..6d89980bae8 100644 --- a/code/modules/mob/living/bot/bot.dm +++ b/code/modules/mob/living/bot/bot.dm @@ -53,6 +53,9 @@ access_scanner.req_access = req_access.Copy() access_scanner.req_one_access = req_one_access.Copy() + if(!using_map.bot_patrolling) + will_patrol = FALSE + // Make sure mapped in units start turned on. /mob/living/bot/Initialize() . = ..() @@ -88,13 +91,13 @@ /mob/living/bot/attackby(var/obj/item/O, var/mob/user) if(O.GetID()) - if(access_scanner.allowed(user) && !open && !emagged) + if(access_scanner.allowed(user) && !open) locked = !locked to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]") attack_hand(user) - else if(emagged) - to_chat(user, "ERROR") + to_chat(user, "ERROR! SYSTEMS COMPROMISED!") + else if(open) to_chat(user, "Please close the access panel before locking it.") else @@ -111,7 +114,15 @@ else if(istype(O, /obj/item/weapon/weldingtool)) if(health < getMaxHealth()) if(open) - health = min(getMaxHealth(), health + 10) + if(getBruteLoss() < 10) + bruteloss = 0 + else + bruteloss = bruteloss - 10 + if(getFireLoss() < 10) + fireloss = 0 + else + fireloss = fireloss - 10 + updatehealth() user.visible_message("[user] repairs [src].","You repair [src].") playsound(src, O.usesound, 50, 1) else @@ -119,6 +130,13 @@ else to_chat(user, "[src] does not need a repair.") return + else if(istype(O, /obj/item/device/assembly/prox_sensor) && emagged) + if(open) + to_chat(user, "You repair the bot's systems.") + emagged = 0 + qdel(O) + else + to_chat(user, "Unable to repair with the maintenance panel closed.") else ..() diff --git a/code/modules/mob/living/bot/cleanbot.dm b/code/modules/mob/living/bot/cleanbot.dm index eb2371c3293..b620ca3e1a4 100644 --- a/code/modules/mob/living/bot/cleanbot.dm +++ b/code/modules/mob/living/bot/cleanbot.dm @@ -113,7 +113,8 @@ dat += "Maintenance panel is [open ? "opened" : "closed"]" if(!locked || issilicon(user)) dat += "
      Cleans Blood: [blood ? "Yes" : "No"]
      " - dat += "
      Patrol station: [will_patrol ? "Yes" : "No"]
      " + if(using_map.bot_patrolling) + dat += "
      Patrol station: [will_patrol ? "Yes" : "No"]
      " if(open && !locked) dat += "Odd looking screw twiddled: [screwloose ? "Yes" : "No"]
      " dat += "Weird button pressed: [oddbutton ? "Yes" : "No"]" diff --git a/code/modules/mob/living/bot/ed209bot.dm b/code/modules/mob/living/bot/ed209bot.dm index b8f1c854855..4db5978d0dd 100644 --- a/code/modules/mob/living/bot/ed209bot.dm +++ b/code/modules/mob/living/bot/ed209bot.dm @@ -160,12 +160,30 @@ return if(7) - if(istype(W, /obj/item/weapon/gun/energy/taser)) - name = "taser ED-209 assembly" + if(istype(W, /obj/item/weapon/gun/energy/taser/xeno)) + name = "xenotaser SL-ED-209 assembly" + item_state = "sled209_taser" + icon_state = "sled209_taser" build_step++ to_chat(user, "You add [W] to [src].") + user.drop_item() + qdel(W) + var/turf/T = get_turf(src) + var/obj/item/weapon/secbot_assembly/ed209_assembly/slime/S = new /obj/item/weapon/secbot_assembly/ed209_assembly/slime(T) + S.name = name + S.item_state = item_state + S.icon_state = icon_state + S.build_step = build_step + S.created_name = created_name + user.drop_from_inventory(src) + qdel(src) + + else if(istype(W, /obj/item/weapon/gun/energy/taser)) + name = "taser ED-209 assembly" item_state = "ed209_taser" icon_state = "ed209_taser" + build_step++ + to_chat(user, "You add [W] to [src].") user.drop_item() qdel(W) diff --git a/code/modules/mob/living/bot/edCLNbot.dm b/code/modules/mob/living/bot/edCLNbot.dm index 9b846511659..08d7d9ace62 100644 --- a/code/modules/mob/living/bot/edCLNbot.dm +++ b/code/modules/mob/living/bot/edCLNbot.dm @@ -82,7 +82,8 @@ dat += "Maintenance panel is [open ? "opened" : "closed"]" if(!locked || issilicon(user)) dat += "
      Cleans Blood: [blood ? "Yes" : "No"]
      " - dat += "
      Patrol station: [will_patrol ? "Yes" : "No"]
      " + if(using_map.bot_patrolling) + dat += "
      Patrol station: [will_patrol ? "Yes" : "No"]
      " if(open && !locked) dat += "
      Red Switch: [red_switch ? "On" : "Off"]
      " dat += "
      Green Switch: [green_switch ? "On" : "Off"]
      " diff --git a/code/modules/mob/living/bot/farmbot.dm b/code/modules/mob/living/bot/farmbot.dm index 1abc85e8703..44aaae7ee1b 100644 --- a/code/modules/mob/living/bot/farmbot.dm +++ b/code/modules/mob/living/bot/farmbot.dm @@ -10,7 +10,7 @@ icon_state = "farmbot0" health = 50 maxHealth = 50 - req_one_access = list(access_robotics, access_hydroponics) + req_one_access = list(access_robotics, access_hydroponics, access_xenobiology) //TFF 11/7/19 - adds Xenobio access on behalf of Nalarac var/action = "" // Used to update icon var/waters_trays = 1 @@ -297,7 +297,7 @@ if(tray.dead && removes_dead || tray.harvest && collects_produce) return FARMBOT_COLLECT - else if(refills_water && tray.waterlevel < 40 && !tray.reagents.has_reagent("water")) + else if(refills_water && tray.waterlevel < 40 && !tray.reagents.has_reagent("water") && tank.reagents.total_volume > 0) return FARMBOT_WATER else if(uproots_weeds && tray.weedlevel > 3) diff --git a/code/modules/mob/living/bot/medbot.dm b/code/modules/mob/living/bot/medbot.dm index 4958d607948..f7bac5b82b9 100644 --- a/code/modules/mob/living/bot/medbot.dm +++ b/code/modules/mob/living/bot/medbot.dm @@ -279,6 +279,9 @@ if(!..()) return 0 + if(H.isSynthetic()) // Don't treat FBPs + return 0 + if(H.stat == DEAD) // He's dead, Jim return 0 diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index 2372def546d..1210d41e910 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -1,4 +1,4 @@ -#define SECBOT_WAIT_TIME 5 //number of in-game seconds to wait for someone to surrender +#define SECBOT_WAIT_TIME 3 //Around number*2 real seconds to surrender. #define SECBOT_THREAT_ARREST 4 //threat level at which we decide to arrest someone #define SECBOT_THREAT_ATTACK 8 //threat level at which was assume immediate danger and attack right away @@ -9,18 +9,20 @@ maxHealth = 100 health = 100 req_one_access = list(access_security, access_forensics_lockers) - botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels) + botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_maint_tunnels) patrol_speed = 2 target_speed = 3 var/default_icon_state = "secbot" - var/idcheck = 0 // If true, arrests for having weapons without authorization. - var/check_records = 0 // If true, arrests people without a record. - var/check_arrest = 1 // If true, arrests people who are set to arrest. - var/arrest_type = 0 // If true, doesn't handcuff. You monster. - var/declare_arrests = 0 // If true, announces arrests over sechuds. + var/idcheck = FALSE // If true, arrests for having weapons without authorization. + var/check_records = FALSE // If true, arrests people without a record. + var/check_arrest = TRUE // If true, arrests people who are set to arrest. + var/arrest_type = FALSE // If true, doesn't handcuff. You monster. + var/declare_arrests = FALSE // If true, announces arrests over sechuds. + var/threat = 0 // How much of a threat something is. Set upon acquiring a target. + var/attacked = FALSE // If true, gives the bot enough threat assessment to attack immediately. - var/is_ranged = 0 + var/is_ranged = FALSE var/awaiting_surrender = 0 var/can_next_insult = 0 // Uses world.time var/stun_strength = 60 // For humans. @@ -32,20 +34,25 @@ var/list/threat_found_sounds = list('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg') var/list/preparing_arrest_sounds = list('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bcreep.ogg') var/list/fighting_sounds = list('sound/voice/biamthelaw.ogg', 'sound/voice/bradio.ogg', 'sound/voice/bjustice.ogg') -//VOREStation Add - They don't like being pulled. This is going to fuck with slimesky, but meh. +//VOREStation Add - They don't like being pulled. This is going to fuck with slimesky, but meh. //Screw you. Just screw you and your 'meh' /mob/living/bot/secbot/Life() ..() if(health > 0 && on && pulledby) if(isliving(pulledby)) - var/mob/living/L = pulledby - UnarmedAttack(L) - say("Do not interfere with active law enforcement routines!") - global_announcer.autosay("[src] was interfered with in [get_area(src)], activating defense routines.", "[src]", "Security") + var/pull_allowed = FALSE + for(var/A in req_one_access) + if(A in pulledby.GetAccess()) + pull_allowed = TRUE + if(!pull_allowed) + var/mob/living/L = pulledby + UnarmedAttack(L) + say("Do not interfere with active law enforcement routines!") + global_announcer.autosay("[src] was interfered with in [get_area(src)], activating defense routines.", "[src]", "Security") //VOREStation Add End /mob/living/bot/secbot/beepsky name = "Officer Beepsky" desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey." - will_patrol = 1 + will_patrol = TRUE /mob/living/bot/secbot/slime name = "Slime Securitron" @@ -88,7 +95,8 @@ dat += "Check Arrest Status: [check_arrest ? "Yes" : "No"]
      " dat += "Operating Mode: [arrest_type ? "Detain" : "Arrest"]
      " dat += "Report Arrests: [declare_arrests ? "Yes" : "No"]
      " - dat += "Auto Patrol: [will_patrol ? "On" : "Off"]" + if(using_map.bot_patrolling) + dat += "Auto Patrol: [will_patrol ? "On" : "Off"]" var/datum/browser/popup = new(user, "autosec", "Securitron controls") popup.set_content(jointext(dat,null)) popup.open() @@ -126,18 +134,18 @@ . = ..() if(!emagged) if(user) - user << "\The [src] buzzes and beeps." - emagged = 1 + to_chat(user, "\The [src] buzzes and beeps.") + emagged = TRUE patrol_speed = 3 target_speed = 4 - return 1 + return TRUE else - user << "\The [src] is already corrupt." + to_chat(user, "\The [src] is already corrupt.") /mob/living/bot/secbot/attackby(var/obj/item/O, var/mob/user) var/curhealth = health . = ..() - if(health < curhealth && on == 1) + if(health < curhealth && on == TRUE) react_to_attack(user) /mob/living/bot/secbot/bullet_act(var/obj/item/projectile/P) @@ -154,18 +162,21 @@ ..() /mob/living/bot/secbot/proc/react_to_attack(mob/attacker) + if(!on) // We don't want it to react if it's off + return + if(!target) playsound(src.loc, pick(threat_found_sounds), 50) global_announcer.autosay("[src] was attacked by a hostile [target_name(attacker)] in [get_area(src)].", "[src]", "Security") target = attacker - awaiting_surrender = INFINITY // Don't try and wait for surrender + attacked = TRUE // Say "freeze!" and demand surrender /mob/living/bot/secbot/proc/demand_surrender(mob/target, var/threat) var/suspect_name = target_name(target) if(declare_arrests) global_announcer.autosay("[src] is [arrest_type ? "detaining" : "arresting"] a level [threat] suspect [suspect_name] in [get_area(src)].", "[src]", "Security") - say("Down on the floor, [suspect_name]! You have [SECBOT_WAIT_TIME] seconds to comply.") + say("Down on the floor, [suspect_name]! You have [SECBOT_WAIT_TIME*2] seconds to comply.") playsound(src.loc, pick(preparing_arrest_sounds), 50) // Register to be told when the target moves GLOB.moved_event.register(target, src, /mob/living/bot/secbot/proc/target_moved) @@ -179,7 +190,8 @@ /mob/living/bot/secbot/resetTarget() ..() GLOB.moved_event.unregister(target, src) - awaiting_surrender = -1 + awaiting_surrender = 0 + attacked = FALSE walk_to(src, 0) /mob/living/bot/secbot/startPatrol() @@ -189,17 +201,18 @@ /mob/living/bot/secbot/confirmTarget(var/atom/A) if(!..()) - return 0 - return (check_threat(A) >= SECBOT_THREAT_ARREST) + return FALSE + check_threat(A) + if(threat >= SECBOT_THREAT_ARREST) + return TRUE /mob/living/bot/secbot/lookForTargets() for(var/mob/living/M in view(src)) if(M.stat == DEAD) continue if(confirmTarget(M)) - var/threat = check_threat(M) target = M - awaiting_surrender = -1 + awaiting_surrender = 0 say("Level [threat] infraction alert!") custom_emote(1, "points at [M.name]!") playsound(src.loc, pick(threat_found_sounds), 50) @@ -207,15 +220,15 @@ /mob/living/bot/secbot/handleAdjacentTarget() var/mob/living/carbon/human/H = target - var/threat = check_threat(target) + check_threat(target) if(awaiting_surrender < SECBOT_WAIT_TIME && istype(H) && !H.lying && threat < SECBOT_THREAT_ATTACK) - if(awaiting_surrender == -1) // On first tick of awaiting... + if(awaiting_surrender == 0) // On first tick of awaiting... demand_surrender(target, threat) ++awaiting_surrender else if(declare_arrests) var/action = arrest_type ? "detaining" : "arresting" - if(istype(target, /mob/living/simple_mob)) + if(!ishuman(target)) action = "fighting" global_announcer.autosay("[src] is [action] a level [threat] [action != "fighting" ? "suspect" : "threat"] [target_name(target)] in [get_area(src)].", "[src]", "Security") UnarmedAttack(target) @@ -224,7 +237,6 @@ /mob/living/bot/secbot/proc/insult(var/mob/living/L) if(can_next_insult > world.time) return - var/threat = check_threat(L) if(threat >= 10) playsound(src.loc, 'sound/voice/binsult.ogg', 75) can_next_insult = world.time + 20 SECONDS @@ -240,47 +252,47 @@ if(!istype(M)) return - if(istype(M, /mob/living/carbon)) - var/mob/living/carbon/C = M - var/cuff = 1 - if(istype(C, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = C - if(istype(H.back, /obj/item/weapon/rig) && istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig)) - cuff = 0 - if(!C.lying || C.handcuffed || arrest_type) - cuff = 0 + if(ishuman(M)) + var/mob/living/carbon/human/H = M + var/cuff = TRUE + + if(!H.lying || H.handcuffed || arrest_type) + cuff = FALSE if(!cuff) - C.stun_effect_act(0, stun_strength, null) + H.stun_effect_act(0, stun_strength, null) playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1) - do_attack_animation(C) - busy = 1 + do_attack_animation(H) + busy = TRUE update_icons() spawn(2) - busy = 0 + busy = FALSE update_icons() - visible_message("\The [C] was prodded by \the [src] with a stun baton!") - insult(C) + visible_message("\The [H] was prodded by \the [src] with a stun baton!") + insult(H) else playsound(loc, 'sound/weapons/handcuffs.ogg', 30, 1, -2) - visible_message("\The [src] is trying to put handcuffs on \the [C]!") - busy = 1 - if(do_mob(src, C, 60)) - if(!C.handcuffed) - C.handcuffed = new /obj/item/weapon/handcuffs(C) - C.update_inv_handcuffed() - busy = 0 - else if(istype(M, /mob/living/simple_mob)) - var/mob/living/simple_mob/S = M - S.adjustBruteLoss(xeno_harm_strength) + visible_message("\The [src] is trying to put handcuffs on \the [H]!") + busy = TRUE + if(do_mob(src, H, 60)) + if(!H.handcuffed) + if(istype(H.back, /obj/item/weapon/rig) && istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig)) + H.handcuffed = new /obj/item/weapon/handcuffs/cable(H) // Better to be cable cuffed than stun-locked + else + H.handcuffed = new /obj/item/weapon/handcuffs(H) + H.update_inv_handcuffed() + busy = FALSE + else if(istype(M, /mob/living)) + var/mob/living/L = M + L.adjustBruteLoss(xeno_harm_strength) do_attack_animation(M) playsound(loc, "swing_hit", 50, 1, -1) - busy = 1 + busy = TRUE update_icons() spawn(2) - busy = 0 + busy = FALSE update_icons() visible_message("\The [M] was beaten by \the [src] with a stun baton!") - insult(S) + insult(L) /mob/living/bot/secbot/slime/UnarmedAttack(var/mob/living/L, var/proximity) ..() @@ -289,8 +301,6 @@ var/mob/living/simple_mob/slime/xenobio/S = L S.slimebatoned(src, xeno_stun_strength) - - /mob/living/bot/secbot/explode() visible_message("[src] blows apart!") var/turf/Tsec = get_turf(src) @@ -319,12 +329,15 @@ /mob/living/bot/secbot/proc/check_threat(var/mob/living/M) if(!M || !istype(M) || M.stat == DEAD || src == M) - return 0 + threat = 0 - if(emagged && !M.incapacitated()) //check incapacitated so emagged secbots don't keep attacking the same target forever - return 10 + else if(emagged && !M.incapacitated()) //check incapacitated so emagged secbots don't keep attacking the same target forever + threat = 10 - return M.assess_perp(access_scanner, 0, idcheck, check_records, check_arrest) + else + threat = M.assess_perp(access_scanner, 0, idcheck, check_records, check_arrest) // Set base threat level + if(attacked) + threat += SECBOT_THREAT_ATTACK // Increase enough so we can attack immediately in return //Secbot Construction @@ -367,12 +380,12 @@ if(WT.remove_fuel(0, user)) build_step = 1 overlays += image('icons/obj/aibots.dmi', "hs_hole") - user << "You weld a hole in \the [src]." + to_chat(user, "You weld a hole in \the [src].") else if(isprox(W) && (build_step == 1)) user.drop_item() build_step = 2 - user << "You add \the [W] to [src]." + to_chat(user, "You add \the [W] to [src].") overlays += image('icons/obj/aibots.dmi', "hs_eye") name = "helmet/signaler/prox sensor assembly" qdel(W) @@ -380,14 +393,14 @@ else if((istype(W, /obj/item/robot_parts/l_arm) || istype(W, /obj/item/robot_parts/r_arm) || (istype(W, /obj/item/organ/external/arm) && ((W.name == "robotic right arm") || (W.name == "robotic left arm")))) && build_step == 2) user.drop_item() build_step = 3 - user << "You add \the [W] to [src]." + to_chat(user, "You add \the [W] to [src].") name = "helmet/signaler/prox sensor/robot arm assembly" overlays += image('icons/obj/aibots.dmi', "hs_arm") qdel(W) else if(istype(W, /obj/item/weapon/melee/baton) && build_step == 3) user.drop_item() - user << "You complete the Securitron! Beep boop." + to_chat(user, "You complete the Securitron! Beep boop.") if(istype(W, /obj/item/weapon/melee/baton/slime)) var/mob/living/bot/secbot/slime/S = new /mob/living/bot/secbot/slime(get_turf(src)) S.name = created_name @@ -401,6 +414,6 @@ var/t = sanitizeSafe(input(user, "Enter new robot name", name, created_name), MAX_NAME_LEN) if(!t) return - if(!in_range(src, usr) && loc != usr) + if(!in_range(src, user) && loc != user) return - created_name = t + created_name = t \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm new file mode 100644 index 00000000000..431b7c44561 --- /dev/null +++ b/code/modules/mob/living/carbon/human/ai_controlled/ai_controlled.dm @@ -0,0 +1,143 @@ +/mob/living/carbon/human/ai_controlled + name = "Nameless Joe" + + ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive + + var/generate_species = SPECIES_HUMAN + var/generate_dead = FALSE + + var/generate_gender = FALSE + var/generate_id_gender = FALSE + + var/to_wear_hair = "Bald" + + var/to_wear_helmet = /obj/item/clothing/head/welding + var/to_wear_glasses = /obj/item/clothing/glasses/threedglasses + var/to_wear_mask = /obj/item/clothing/mask/gas + var/to_wear_l_radio = /obj/item/device/radio/headset + var/to_wear_r_radio = null + var/to_wear_uniform = /obj/item/clothing/under/color/grey + var/to_wear_suit = /obj/item/clothing/suit/armor/material/makeshift/glass + var/to_wear_gloves = /obj/item/clothing/gloves/ring/material/platinum + var/to_wear_shoes = /obj/item/clothing/shoes/galoshes + var/to_wear_belt = /obj/item/weapon/storage/belt/utility/full + var/to_wear_l_pocket = /obj/item/weapon/soap + var/to_wear_r_pocket = /obj/item/device/pda + var/to_wear_back = /obj/item/weapon/storage/backpack + var/to_wear_id_type = /obj/item/weapon/card/id + var/to_wear_id_job = "Assistant" + + var/to_wear_l_hand = null + var/to_wear_r_hand = /obj/item/weapon/melee/baton + +/mob/living/carbon/human/ai_controlled/Initialize() + if(generate_gender) + gender = pick(list(MALE, FEMALE, PLURAL, NEUTER)) + + if(generate_id_gender) + identifying_gender = pick(list(MALE, FEMALE, PLURAL, NEUTER)) + + ..(loc, generate_species) + + h_style = to_wear_hair + + if(to_wear_uniform) + equip_to_slot_or_del(new to_wear_uniform(src), slot_w_uniform) + + if(to_wear_suit) + equip_to_slot_or_del(new to_wear_suit(src), slot_wear_suit) + + if(to_wear_shoes) + equip_to_slot_or_del(new to_wear_shoes(src), slot_shoes) + + if(to_wear_gloves) + equip_to_slot_or_del(new to_wear_gloves(src), slot_gloves) + + if(to_wear_l_radio) + equip_to_slot_or_del(new to_wear_l_radio(src), slot_l_ear) + + if(to_wear_r_radio) + equip_to_slot_or_del(new to_wear_r_radio(src), slot_r_ear) + + if(to_wear_glasses) + equip_to_slot_or_del(new to_wear_glasses(src), slot_glasses) + + if(to_wear_mask) + equip_to_slot_or_del(new to_wear_mask(src), slot_wear_mask) + + if(to_wear_helmet) + equip_to_slot_or_del(new to_wear_helmet(src), slot_head) + + if(to_wear_belt) + equip_to_slot_or_del(new to_wear_belt(src), slot_belt) + + if(to_wear_r_pocket) + equip_to_slot_or_del(new to_wear_r_pocket(src), slot_r_store) + + if(to_wear_l_pocket) + equip_to_slot_or_del(new to_wear_l_pocket(src), slot_l_store) + + if(to_wear_back) + equip_to_slot_or_del(new to_wear_back(src), slot_back) + + if(to_wear_l_hand) + equip_to_slot_or_del(new to_wear_l_hand(src), slot_l_hand) + + if(to_wear_r_hand) + equip_to_slot_or_del(new to_wear_r_hand(src), slot_r_hand) + + if(to_wear_id_type) + var/obj/item/weapon/card/id/W = new to_wear_id_type(src) + W.name = "[real_name]'s ID Card" + var/datum/job/jobdatum + for(var/jobtype in typesof(/datum/job)) + var/datum/job/J = new jobtype + if(J.title == to_wear_id_job) + jobdatum = J + break + if(jobdatum) + W.access = jobdatum.get_access() + else + W.access = list() + if(to_wear_id_job) + W.assignment = to_wear_id_job + W.registered_name = real_name + equip_to_slot_or_del(W, slot_wear_id) + + if(generate_dead) + death() + +/* + * Subtypes. + */ + +/mob/living/carbon/human/ai_controlled/replicant + generate_species = SPECIES_REPLICANT_BETA + + generate_gender = TRUE + identifying_gender = NEUTER + + faction = "xeno" + + to_wear_helmet = /obj/item/clothing/head/helmet/dermal + to_wear_glasses = /obj/item/clothing/glasses/goggles + to_wear_mask = /obj/item/clothing/mask/gas/half + to_wear_l_radio = /obj/item/device/radio/headset/headset_rob + to_wear_r_radio = null + to_wear_uniform = /obj/item/clothing/under/color/grey + to_wear_suit = /obj/item/clothing/suit/armor/vest + to_wear_gloves = null + to_wear_shoes = /obj/item/clothing/shoes/boots/combat/changeling + to_wear_belt = /obj/item/weapon/storage/belt/utility/full + to_wear_l_pocket = /obj/item/weapon/grenade/explosive/mini + to_wear_r_pocket = /obj/item/weapon/grenade/explosive/mini + to_wear_back = /obj/item/device/radio/electropack + to_wear_id_type = /obj/item/weapon/card/id + to_wear_id_job = "Experiment" + + to_wear_r_hand = null + +/mob/living/carbon/human/ai_controlled/replicant/Initialize() + ..() + name = species.get_random_name(gender) + add_modifier(/datum/modifier/homeothermic, 0, null) diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index ad0ceb7f624..bee85326fcb 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -8,6 +8,14 @@ return soft_type return src.default_attack // VOREStation Edit - End + if(src.gloves) + var/obj/item/clothing/gloves/G = src.gloves + if(istype(G) && G.special_attack && G.special_attack.is_usable(src, target, hit_zone)) + if(pulling_punches) + var/datum/unarmed_attack/soft_type = G.special_attack.get_sparring_variant() + if(soft_type) + return soft_type + return G.special_attack for(var/datum/unarmed_attack/u_attack in species.unarmed_attacks) if(u_attack.is_usable(src, target, hit_zone)) if(pulling_punches) @@ -41,39 +49,11 @@ H.do_attack_animation(src) playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) visible_message("[H] reaches for [src], but misses!") - return 0 + return FALSE if(H != src && check_shields(0, null, H, H.zone_sel.selecting, H.name)) H.do_attack_animation(src) - return 0 - - if(istype(H.gloves, /obj/item/clothing/gloves/boxing/hologlove)) - H.do_attack_animation(src) - var/damage = rand(0, 9) - if(!damage) - playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - visible_message("[H] has attempted to punch [src]!") - return 0 - var/obj/item/organ/external/affecting = get_organ(ran_zone(H.zone_sel.selecting)) - var/armor_block = run_armor_check(affecting, "melee") - var/armor_soak = get_armor_soak(affecting, "melee") - - if(HULK in H.mutations) - damage += 5 - - playsound(loc, "punch", 25, 1, -1) - - visible_message("[H] has punched [src]!") - - if(armor_soak >= damage) - return - - apply_damage(damage, HALLOSS, affecting, armor_block, armor_soak) - if(damage >= 9) - visible_message("[H] has weakened [src]!") - apply_effect(4, WEAKEN, armor_block) - - return + return FALSE if(istype(M,/mob/living/carbon)) var/mob/living/carbon/C = M @@ -122,7 +102,7 @@ else if(!(M == src && apply_pressure(M, M.zone_sel.selecting))) help_shake_act(M) - return 1 + return TRUE if(I_GRAB) if(M == src || anchored) @@ -149,7 +129,7 @@ //VORESTATION EDIT visible_message("[M] has grabbed [src] [(M.zone_sel.selecting == BP_L_HAND || M.zone_sel.selecting == BP_R_HAND)? "by [(gender==FEMALE)? "her" : ((gender==MALE)? "his": "their")] hands": "passively"]!") //VORESTATION END END - return 1 + return TRUE if(I_HURT) @@ -175,7 +155,7 @@ if(!affecting || affecting.is_stump()) M << "They are missing that limb!" - return 1 + return TRUE switch(src.a_intent) if(I_HELP) @@ -245,7 +225,10 @@ // See what attack they use var/datum/unarmed_attack/attack = H.get_unarmed_attack(src, hit_zone) if(!attack) - return 0 + return FALSE + + if(attack.unarmed_override(H, src, hit_zone)) + return FALSE H.do_attack_animation(src) if(!attack_message) @@ -258,7 +241,7 @@ add_attack_logs(H,src,"Melee attacked with fists (miss/block)") if(miss_type) - return 0 + return FALSE var/real_damage = rand_damage var/hit_dam_type = attack.damage_type @@ -268,7 +251,7 @@ var/obj/item/clothing/gloves/G = H.gloves real_damage += G.punch_force hit_dam_type = G.punch_damtype - if(H.pulling_punches) //SO IT IS DECREED: PULLING PUNCHES WILL PREVENT THE ACTUAL DAMAGE FROM RINGS AND KNUCKLES, BUT NOT THE ADDED PAIN + if(H.pulling_punches && !attack.sharp && !attack.edge) //SO IT IS DECREED: PULLING PUNCHES WILL PREVENT THE ACTUAL DAMAGE FROM RINGS AND KNUCKLES, BUT NOT THE ADDED PAIN, BUT YOU CAN'T "PULL" A KNIFE hit_dam_type = AGONY real_damage *= damage_multiplier rand_damage *= damage_multiplier @@ -359,7 +342,7 @@ var/armor_soak = get_armor_soak(affecting, armor_type, armor_pen) apply_damage(damage, BRUTE, affecting, armor_block, armor_soak, sharp = a_sharp, edge = a_edge) updatehealth() - return 1 + return TRUE //Used to attack a joint through grabbing /mob/living/carbon/human/proc/grab_joint(var/mob/living/user, var/def_zone) @@ -370,43 +353,43 @@ break if(!has_grab) - return 0 + return FALSE if(!def_zone) def_zone = user.zone_sel.selecting var/target_zone = check_zone(def_zone) if(!target_zone) - return 0 + return FALSE var/obj/item/organ/external/organ = get_organ(check_zone(target_zone)) if(!organ || organ.dislocated > 0 || organ.dislocated == -1) //don't use is_dislocated() here, that checks parent - return 0 + return FALSE user.visible_message("[user] begins to dislocate [src]'s [organ.joint]!") if(do_after(user, 100)) organ.dislocate(1) src.visible_message("[src]'s [organ.joint] [pick("gives way","caves in","crumbles","collapses")]!") - return 1 - return 0 + return TRUE + return FALSE //Breaks all grips and pulls that the mob currently has. /mob/living/carbon/human/proc/break_all_grabs(mob/living/carbon/user) - var/success = 0 + var/success = FALSE if(pulling) visible_message("[user] has broken [src]'s grip on [pulling]!") - success = 1 + success = TRUE stop_pulling() if(istype(l_hand, /obj/item/weapon/grab)) var/obj/item/weapon/grab/lgrab = l_hand if(lgrab.affecting) visible_message("[user] has broken [src]'s grip on [lgrab.affecting]!") - success = 1 + success = TRUE spawn(1) qdel(lgrab) if(istype(r_hand, /obj/item/weapon/grab)) var/obj/item/weapon/grab/rgrab = r_hand if(rgrab.affecting) visible_message("[user] has broken [src]'s grip on [rgrab.affecting]!") - success = 1 + success = TRUE spawn(1) qdel(rgrab) return success @@ -421,11 +404,11 @@ /mob/living/carbon/human/proc/apply_pressure(mob/living/user, var/target_zone) var/obj/item/organ/external/organ = get_organ(target_zone) if(!organ || !(organ.status & ORGAN_BLEEDING) || (organ.robotic >= ORGAN_ROBOT)) - return 0 + return FALSE if(organ.applied_pressure) user << "Someone is already applying pressure to [user == src? "your [organ.name]" : "[src]'s [organ.name]"]." - return 0 + return FALSE var/datum/gender/TU = gender_datums[user.get_visible_gender()] @@ -446,4 +429,4 @@ else user.visible_message("\The [user] stops applying pressure to [src]'s [organ.name]!", "You stop applying pressure to [src]'s [organ.name]!") - return 1 + return TRUE diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 28de4d6d933..1f211fe95b7 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -1,5 +1,6 @@ //Updates the mob's health from organs and mob damage variables /mob/living/carbon/human/updatehealth() + var/huskmodifier = 1.5 // With 1.5, you need 250 burn instead of 200 to husk a human. if(status_flags & GODMODE) health = getMaxHealth() @@ -17,7 +18,7 @@ health = getMaxHealth() - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute //TODO: fix husking - if( ((getMaxHealth() - total_burn) < config.health_threshold_dead) && stat == DEAD) + if( ((getMaxHealth() - total_burn) < config.health_threshold_dead * huskmodifier) && stat == DEAD) ChangeToHusk() return diff --git a/code/modules/mob/living/carbon/human/human_defines_vr.dm b/code/modules/mob/living/carbon/human/human_defines_vr.dm index f856e4ab399..0af0b1f7d18 100644 --- a/code/modules/mob/living/carbon/human/human_defines_vr.dm +++ b/code/modules/mob/living/carbon/human/human_defines_vr.dm @@ -7,3 +7,6 @@ var/flapping = 0 var/vantag_pref = VANTAG_NONE //What's my status? var/impersonate_bodytype //For impersonating a bodytype + + //TFF 5/8/19 - add and set suit sensor setting define to 5 for random setting + var/sensorpref = 5 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 6c1311fa417..96005d74075 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -86,7 +86,7 @@ var/obj/item/organ/external/E = organs_by_name[limb_tag] if(!E || !E.is_usable()) stance_damage += 2 // let it fail even if just foot&leg - else if (E.is_malfunctioning()) + else if (E.is_malfunctioning() && !(lying || resting)) //malfunctioning only happens intermittently so treat it as a missing limb when it procs stance_damage += 2 if(isturf(loc) && prob(10)) diff --git a/code/modules/mob/living/carbon/human/human_powers.dm b/code/modules/mob/living/carbon/human/human_powers.dm index 809a5ef8ade..a3c5e654701 100644 --- a/code/modules/mob/living/carbon/human/human_powers.dm +++ b/code/modules/mob/living/carbon/human/human_powers.dm @@ -286,8 +286,11 @@ nutrition -= 200 for(var/obj/item/organ/I in internal_organs) + if(I.robotic >= ORGAN_ROBOT) // No free robofix. + continue if(I.damage > 0) I.damage = max(I.damage - 30, 0) //Repair functionally half of a dead internal organ. + I.status = 0 // Wipe status, as it's being regenerated from possibly dead. to_chat(src, "You feel a soothing sensation within your [I.name]...") // Replace completely missing limbs. @@ -310,6 +313,15 @@ var/agony_to_apply = round(0.66 * O.max_damage) // 66% of the limb's health is converted into pain. src.apply_damage(agony_to_apply, HALLOSS) + for(var/organtype in species.has_organ) // Replace completely missing internal organs. -After- external ones, so they all should exist. + if(!src.internal_organs_by_name[organtype]) + var/organpath = species.has_organ[organtype] + var/obj/item/organ/Int = new organpath(src, TRUE) + + Int.rejuvenate(TRUE) + + handle_organs() // Update everything + update_icons_body() active_regen = FALSE else diff --git a/code/modules/mob/living/carbon/human/species/species_vr.dm b/code/modules/mob/living/carbon/human/species/species_vr.dm index 63f02a5af8e..1d0a73d6692 100644 --- a/code/modules/mob/living/carbon/human/species/species_vr.dm +++ b/code/modules/mob/living/carbon/human/species/species_vr.dm @@ -17,6 +17,7 @@ var/wing var/wing_animation var/icobase_wing + var/wikilink = null //link to wiki page for species /datum/species/proc/update_attack_types() unarmed_attacks = list() diff --git a/code/modules/mob/living/carbon/human/species/station/alraune.dm b/code/modules/mob/living/carbon/human/species/station/alraune.dm index e8f503fe4fb..a26c15ad469 100644 --- a/code/modules/mob/living/carbon/human/species/station/alraune.dm +++ b/code/modules/mob/living/carbon/human/species/station/alraune.dm @@ -17,7 +17,7 @@ selects_bodytype = TRUE body_temperature = T20C - breath_type = "carbon_dioxide" + breath_type = "oxygen" poison_type = "phoron" exhale_type = "oxygen" @@ -170,7 +170,7 @@ var/failed_inhale = 0 var/failed_exhale = 0 - inhaling = breath.gas[breath_type] + inhaling = breath.gas["carbon_dioxide"] poison = breath.gas[poison_type] exhaling = breath.gas[exhale_type] @@ -194,7 +194,7 @@ H.oxygen_alert = 0 inhaled_gas_used = inhaling/6 - breath.adjust_gas(breath_type, -inhaled_gas_used, update = 0) //update afterwards + breath.adjust_gas("carbon_dioxide", -inhaled_gas_used, update = 0) //update afterwards breath.adjust_gas_temp(exhale_type, inhaled_gas_used, H.bodytemperature, update = 0) //update afterwards //Now we handle CO2. diff --git a/code/modules/mob/living/carbon/human/species/station/prometheans.dm b/code/modules/mob/living/carbon/human/species/station/prometheans.dm index 7bf92177dd1..8c745c056e5 100644 --- a/code/modules/mob/living/carbon/human/species/station/prometheans.dm +++ b/code/modules/mob/living/carbon/human/species/station/prometheans.dm @@ -74,7 +74,13 @@ var/datum/species/shapeshifter/promethean/prometheans genders = list(MALE, FEMALE, NEUTER, PLURAL) unarmed_types = list(/datum/unarmed_attack/slime_glomp) - has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime) // Slime core. + + has_organ = list(O_BRAIN = /obj/item/organ/internal/brain/slime, + O_HEART = /obj/item/organ/internal/heart/grey/colormatch/slime, + O_REGBRUTE = /obj/item/organ/internal/regennetwork, + O_REGBURN = /obj/item/organ/internal/regennetwork/burn, + O_REGOXY = /obj/item/organ/internal/regennetwork/oxy, + O_REGTOX = /obj/item/organ/internal/regennetwork/tox) dispersed_eyes = TRUE @@ -125,11 +131,7 @@ var/datum/species/shapeshifter/promethean/prometheans /obj/item/weapon/storage/toolbox/lunchbox/nymph, /obj/item/weapon/storage/toolbox/lunchbox/syndicate)) //Only pick the empty types var/obj/item/weapon/storage/toolbox/lunchbox/L = new boxtype(get_turf(H)) - var/mob/living/simple_mob/animal/passive/mouse/mouse = new (L) - var/obj/item/weapon/holder/holder = new (L) - holder.held_mob = mouse - mouse.forceMove(holder) - holder.sync(mouse) + new /obj/item/weapon/reagent_containers/food/snacks/candy/proteinbar(L) if(H.backbag == 1) H.equip_to_slot_or_del(L, slot_r_hand) else @@ -201,35 +203,71 @@ var/datum/species/shapeshifter/promethean/prometheans var/nutrition_cost = 0 // The total amount of nutrition drained every tick, when healing var/nutrition_debt = 0 // Holder variable used to store previous damage values prior to healing for use in the nutrition_cost equation. var/starve_mod = 1 // Lowering this lowers healing and increases agony multiplicatively. - if(H.nutrition <= 150) // This is when the icon goes red + + var/strain_negation = 0 // How much agony is being prevented by the + + if(H.nutrition <= 150) // This is when the icon goes red starve_mod = 0.75 if(H.nutrition <= 50) // Severe starvation. Damage repaired beyond this point will cause a stunlock if untreated. starve_mod = 0.5 + var/to_pay = 0 if(regen_brute) nutrition_debt = H.getBruteLoss() H.adjustBruteLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getBruteLoss() + + to_pay = nutrition_debt - H.getBruteLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/BrReg = H.internal_organs_by_name[O_REGBRUTE] + + if(BrReg) + strain_negation += to_pay * max(0, (1 - BrReg.get_strain_percent())) if(regen_burn) nutrition_debt = H.getFireLoss() H.adjustFireLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getFireLoss() + + to_pay = nutrition_debt - H.getFireLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/BuReg = H.internal_organs_by_name[O_REGBURN] + + if(BuReg) + strain_negation += to_pay * max(0, (1 - BuReg.get_strain_percent())) if(regen_oxy) nutrition_debt = H.getOxyLoss() H.adjustOxyLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getOxyLoss() + + to_pay = nutrition_debt - H.getOxyLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/OxReg = H.internal_organs_by_name[O_REGOXY] + + if(OxReg) + strain_negation += to_pay * max(0, (1 - OxReg.get_strain_percent())) if(regen_tox) nutrition_debt = H.getToxLoss() H.adjustToxLoss(-heal_rate * starve_mod) - nutrition_cost += nutrition_debt - H.getToxLoss() + + to_pay = nutrition_debt - H.getToxLoss() + + nutrition_cost += to_pay + + var/obj/item/organ/internal/regennetwork/ToxReg = H.internal_organs_by_name[O_REGTOX] + + if(ToxReg) + strain_negation += to_pay * max(0, (1 - ToxReg.get_strain_percent())) H.nutrition -= (3 * nutrition_cost) //Costs Nutrition when damage is being repaired, corresponding to the amount of damage being repaired. H.nutrition = max(0, H.nutrition) //Ensure it's not below 0. - var/agony_to_apply = ((1 / starve_mod) * nutrition_cost) //Regenerating damage causes minor pain over time. Small injures will be no issue, large ones will cause problems. + var/agony_to_apply = ((1 / starve_mod) * (nutrition_cost - strain_negation)) //Regenerating damage causes minor pain over time, if the organs responsible are nonexistant or too high on strain. Small injures will be no issue, large ones will cause problems. if((starve_mod <= 0.5 && (H.getHalLoss() + agony_to_apply) <= 90) || ((H.getHalLoss() + agony_to_apply) <= 70)) // Will max out at applying halloss at 70, unless they are starving; starvation regeneration will bring them up to a maximum of 120, the same amount of agony a human receives from three taser hits. H.apply_damage(agony_to_apply, HALLOSS) diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm index 69c461d767f..cb41200b707 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm @@ -41,6 +41,9 @@ blurb = "Some amalgamation of different species from across the universe,with extremely unstable DNA, making them unfit for regular cloners. \ Widely known for their voracious nature and violent tendencies when stressed or left unfed for long periods of time. \ Most, if not all chimeras possess the ability to undergo some type of regeneration process, at the cost of energy." + + wikilink = "https://wiki.vore-station.net/Xenochimera" + catalogue_data = list(/datum/category_item/catalogue/fauna/xenochimera) hazard_low_pressure = -1 //Prevents them from dying normally in space. Special code handled below. @@ -50,7 +53,7 @@ //primitive_form = "Farwa" - spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED //Whitelisted as restricted is broken. + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE//Whitelisted as restricted is broken. flags = NO_SCAN | NO_INFECT //Dying as a chimera is, quite literally, a death sentence. Well, if it wasn't for their revive, that is. appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR @@ -342,6 +345,9 @@ from their mandible lined mouths. They are a recent discovery by Nanotrasen, only being discovered roughly seven years ago. \ Before they were found they built great cities out of their silk, being united and subjugated in warring factions under great “Star Queens” \ Who forced the working class to build huge, towering cities to attempt to reach the stars, which they worship as gems of great spiritual and magical significance." + + wikilink = "https://wiki.vore-station.net/Vasilissans" + catalogue_data = list(/datum/category_item/catalogue/fauna/vasilissan) hazard_low_pressure = 20 //Prevents them from dying normally in space. Special code handled below. diff --git a/code/modules/mob/living/carbon/human/species/station/station_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_vr.dm index 92819aae65e..b1fae43ce2f 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_vr.dm @@ -27,6 +27,9 @@ racial tensions which has resulted in more than a number of wars and outright attempts at genocide. Sergals have an incredibly long \ lifespan, but due to their lust for violence, only a handful have ever survived beyond the age of 80, such as the infamous and \ legendary General Rain Silves who is claimed to have lived to 5000." + + wikilink="https://wiki.vore-station.net/Backstory#Sergal" + catalogue_data = list(/datum/category_item/catalogue/fauna/sergal) primitive_form = "Saru" @@ -88,6 +91,9 @@ allies over the next few hundred years. With the help of Skrellean technology, the Akula had their genome modified to be capable of \ surviving in open air for long periods of time. However, Akula even today still require a high humidity environment to avoid drying out \ after a few days, which would make life on an arid world like Virgo-Prime nearly impossible if it were not for Skrellean technology to aid them." + + wikilink="https://wiki.vore-station.net/Backstory#Akula" + catalogue_data = list(/datum/category_item/catalogue/fauna/akula) primitive_form = "Sobaka" @@ -129,6 +135,9 @@ intelligence and very skillful hands that are put use for constructing precision instruments, but tire-out fast when repeatedly working \ over and over again. Consequently, they struggle to make copies of same things. Both genders have a voice that echoes a lot. Their natural \ tone oscillates between tenor and soprano. They are excessively noisy when they quarrel in their native language." + + wikilink="https://wiki.vore-station.net/Backstory#Nevrean" + catalogue_data = list(/datum/category_item/catalogue/fauna/nevrean) primitive_form = "Sparra" @@ -168,6 +177,8 @@ mountainous areas, they have a differing societal structure than the Flatland Zorren having a more feudal social structure, like the Flatland Zorren, \ the Highland Zorren have also only recently been hired by the Trans-Stellar Corporations, but thanks to the different social structure they seem to \ have adjusted better to their new lives. Though similar fox-like beings have been seen they are different than the Zorren." + wikilink="https://wiki.vore-station.net/Zorren" + catalogue_data = list(/datum/category_item/catalogue/fauna/zorren, /datum/category_item/catalogue/fauna/highzorren) @@ -210,6 +221,8 @@ mountainous areas, they have a differing societal structure than the Flatland Zorren having a more feudal social structure, like the Flatland Zorren, \ the Highland Zorren have also only recently been hired by the Trans-Stellar Corporations, but thanks to the different social structure they \ seem to have adjusted better to their new lives. Though similar fox-like beings have been seen they are different than the Zorren." + wikilink="https://wiki.vore-station.net/Zorren" + catalogue_data = list(/datum/category_item/catalogue/fauna/zorren, /datum/category_item/catalogue/fauna/flatzorren) @@ -254,6 +267,9 @@ culture both feared and respected for their scientific breakthroughs. Discovery, loyalty, and utilitarianism dominates their lifestyles \ to the degree it can cause conflict with more rigorous and strict authorities. They speak a guttural language known as 'Canilunzt' \ which has a heavy emphasis on utilizing tail positioning and ear twitches to communicate intent." + + wikilink="https://wiki.vore-station.net/Backstory#Vulpkanin" + catalogue_data = list(/datum/category_item/catalogue/fauna/vulpkanin) primitive_form = "Wolpin" @@ -288,10 +304,11 @@ but there are multiple exceptions. All xenomorph hybrids have had their ability to lay eggs containing facehuggers \ removed if they had the ability to, although hybrids that previously contained this ability is extremely rare." catalogue_data = list(/datum/category_item/catalogue/fauna/xenohybrid) + // No wiki page for xenohybrids at present //primitive_form = "" //None for these guys - spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR blood_color = "#12ff12" @@ -315,6 +332,7 @@ gluttonous = 0 inherent_verbs = list(/mob/living/proc/shred_limb) descriptors = list() + wikilink="https://wiki.vore-station.net/Unathi" /datum/species/tajaran spawn_flags = SPECIES_CAN_JOIN @@ -326,6 +344,7 @@ gluttonous = 0 //Moving this here so I don't have to fix this conflict every time polaris glances at station.dm inherent_verbs = list(/mob/living/proc/shred_limb, /mob/living/carbon/human/proc/lick_wounds) heat_discomfort_level = 295 //Prevents heat discomfort spam at 20c + wikilink="https://wiki.vore-station.net/Tajaran" /datum/species/skrell spawn_flags = SPECIES_CAN_JOIN @@ -335,12 +354,14 @@ min_age = 18 reagent_tag = null assisted_langs = list(LANGUAGE_EAL, LANGUAGE_ROOTLOCAL, LANGUAGE_ROOTGLOBAL, LANGUAGE_VOX) + wikilink="https://wiki.vore-station.net/Skrell" /datum/species/zaddat spawn_flags = SPECIES_CAN_JOIN min_age = 18 gluttonous = 0 descriptors = list() + // no wiki link exists for Zaddat yet /datum/species/zaddat/equip_survival_gear(var/mob/living/carbon/human/H) .=..() @@ -351,20 +372,23 @@ H.equip_to_slot_or_del(L, slot_in_backpack) /datum/species/diona - spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE min_age = 18 + wikilink="https://wiki.vore-station.net/Diona" /datum/species/teshari mob_size = MOB_MEDIUM spawn_flags = SPECIES_CAN_JOIN icobase = 'icons/mob/human_races/r_seromi_vr.dmi' deform = 'icons/mob/human_races/r_seromi_vr.dmi' + icobase_tail = 1 color_mult = 1 min_age = 18 push_flags = ~HEAVY //Allows them to use micro step code. swap_flags = ~HEAVY gluttonous = 0 descriptors = list() + wikilink="https://wiki.vore-station.net/Teshari" inherent_verbs = list( /mob/living/carbon/human/proc/sonar_ping, @@ -375,6 +399,7 @@ /datum/species/shapeshifter/promethean spawn_flags = SPECIES_CAN_JOIN + wikilink="https://wiki.vore-station.net/Promethean" /datum/species/human color_mult = 1 @@ -383,10 +408,11 @@ appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR min_age = 18 base_color = "#EECEB3" + wikilink="https://wiki.vore-station.net/Human" /datum/species/vox gluttonous = 0 - spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED + spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED | SPECIES_WHITELIST_SELECTABLE min_age = 18 icobase = 'icons/mob/human_races/r_vox_old.dmi' deform = 'icons/mob/human_races/r_def_vox_old.dmi' @@ -394,6 +420,7 @@ descriptors = list( /datum/mob_descriptor/vox_markings = 0 ) + wikilink="https://wiki.vore-station.net/Vox" datum/species/harpy name = SPECIES_RAPALA @@ -418,6 +445,9 @@ datum/species/harpy Sol researchers have commented on them having a very close resemblance to the mythical race called 'Harpies',\ who are known for having massive winged arms and talons as feet. They've been clocked at speeds of over 35 miler per hour chasing the planet's many fish-like fauna.\ The Rapalan's home-world 'Verita' is a strangely habitable gas giant, while no physical earth exists, there are fertile floating islands orbiting around the planet from past asteroid activity." + + wikilink="https://wiki.vore-station.net/Backstory#Rapala" + catalogue_data = list(/datum/category_item/catalogue/fauna/rapala) spawn_flags = SPECIES_CAN_JOIN diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index f3526983ef7..43a5ae66f24 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -25,18 +25,18 @@ var/global/list/sparring_attack_cache = list() /datum/unarmed_attack/proc/is_usable(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone) if(user.restrained()) - return 0 + return FALSE // Check if they have a functioning hand. var/obj/item/organ/external/E = user.organs_by_name["l_hand"] if(E && !E.is_stump()) - return 1 + return TRUE E = user.organs_by_name["r_hand"] if(E && !E.is_stump()) - return 1 + return TRUE - return 0 + return FALSE /datum/unarmed_attack/proc/get_unarmed_damage() return damage @@ -105,6 +105,9 @@ var/global/list/sparring_attack_cache = list() return user.visible_message("[user] attempts to press [TU.his] [eye_attack_text] into [target]'s eyes, but [TT.he] [TT.does]n't have any!") +/datum/unarmed_attack/proc/unarmed_override(var/mob/living/carbon/human/user,var/mob/living/carbon/human/target,var/zone) + return FALSE //return true if the unarmed override prevents further attacks + /datum/unarmed_attack/bite attack_verb = list("bit") attack_sound = 'sound/weapons/bite.ogg' @@ -121,7 +124,7 @@ var/global/list/sparring_attack_cache = list() return 0 if (user == target && (zone == BP_HEAD || zone == O_EYES || zone == O_MOUTH)) return 0 - return 1 + return TRUE /datum/unarmed_attack/punch attack_verb = list("punched") @@ -187,20 +190,20 @@ var/global/list/sparring_attack_cache = list() /datum/unarmed_attack/kick/is_usable(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone) if (user.legcuffed) - return 0 + return FALSE if(!(zone in list("l_leg", "r_leg", "l_foot", "r_foot", BP_GROIN))) - return 0 + return FALSE var/obj/item/organ/external/E = user.organs_by_name["l_foot"] if(E && !E.is_stump()) - return 1 + return TRUE E = user.organs_by_name["r_foot"] if(E && !E.is_stump()) - return 1 + return TRUE - return 0 + return FALSE /datum/unarmed_attack/kick/get_unarmed_damage(var/mob/living/carbon/human/user) var/obj/item/clothing/shoes = user.shoes @@ -231,23 +234,23 @@ var/global/list/sparring_attack_cache = list() /datum/unarmed_attack/stomp/is_usable(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone) if (user.legcuffed) - return 0 + return FALSE if(!istype(target)) - return 0 + return FALSE if (!user.lying && (target.lying || (zone in list("l_foot", "r_foot")))) if(target.grabbed_by == user && target.lying) - return 0 + return FALSE var/obj/item/organ/external/E = user.organs_by_name["l_foot"] if(E && !E.is_stump()) - return 1 + return TRUE E = user.organs_by_name["r_foot"] if(E && !E.is_stump()) - return 1 + return TRUE - return 0 + return FALSE /datum/unarmed_attack/stomp/get_unarmed_damage(var/mob/living/carbon/human/user) var/obj/item/clothing/shoes = user.shoes diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 249bfb5a91d..169f091c0c8 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -246,7 +246,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() for(var/organ_tag in species.has_limbs) var/obj/item/organ/external/part = organs_by_name[organ_tag] - if(isnull(part) || part.is_stump()) + if(isnull(part) || part.is_stump() || part.is_hidden_by_tail()) //VOREStation Edit allowing tails to prevent bodyparts rendering, granting more spriter freedom for taur/digitigrade stuff. icon_key += "0" continue if(part) @@ -289,7 +289,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() base_icon = chest.get_icon() for(var/obj/item/organ/external/part in organs) - if(isnull(part) || part.is_stump()) + if(isnull(part) || part.is_stump() || part.is_hidden_by_tail()) //VOREStation Edit allowing tails to prevent bodyparts rendering, granting more spriter freedom for taur/digitigrade stuff. continue var/icon/temp = part.get_icon(skeleton) //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST @@ -576,7 +576,15 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() return //Wearing a suit that prevents uniform rendering //Build a uniform sprite - overlays_standing[UNIFORM_LAYER] = w_uniform.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_w_uniform_str, default_icon = INV_W_UNIFORM_DEF_ICON, default_layer = UNIFORM_LAYER) + //VOREStation Edit start. + var/icon/c_mask = null + if(tail_style && tail_style.clip_mask_icon && tail_style.clip_mask_state) + var/obj/item/clothing/suit/S = wear_suit + if(!(wear_suit && ((wear_suit.flags_inv & HIDETAIL) || (istype(S) && S.taurized)))) //Clip the lower half of the suit off using the tail's clip mask. + c_mask = new /icon(tail_style.clip_mask_icon, tail_style.clip_mask_state) + overlays_standing[UNIFORM_LAYER] = w_uniform.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_w_uniform_str, default_icon = INV_W_UNIFORM_DEF_ICON, default_layer = UNIFORM_LAYER, clip_mask = c_mask) + //VOREStation Edit end. + apply_layer(UNIFORM_LAYER) /mob/living/carbon/human/update_inv_wear_id() @@ -658,6 +666,12 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(!shoes || (wear_suit && wear_suit.flags_inv & HIDESHOES) || (w_uniform && w_uniform.flags_inv & HIDESHOES)) return //Either nothing to draw, or it'd be hidden. + //VOREStation Edit + for(var/f in list(BP_L_FOOT, BP_R_FOOT)) + var/obj/item/organ/external/foot/foot = get_organ(f) + if(istype(foot) && foot.is_hidden_by_tail()) //If either foot is hidden by the tail, don't render footwear. + return + //Allow for shoe layer toggle nonsense var/shoe_layer = SHOES_LAYER if(istype(shoes, /obj/item/clothing/shoes)) @@ -741,12 +755,18 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() // Part of splitting the suit sprites up var/iconFile = INV_SUIT_DEF_ICON + var/obj/item/clothing/suit/S //VOREStation edit - break this var out a level for use below. if(istype(wear_suit, /obj/item/clothing/suit)) - var/obj/item/clothing/suit/S = wear_suit + S = wear_suit if(S.update_icon_define) iconFile = S.update_icon_define - overlays_standing[SUIT_LAYER] = wear_suit.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_suit_str, default_icon = iconFile, default_layer = SUIT_LAYER) + //VOREStation Edit start. + var/icon/c_mask = null + if((tail_style && tail_style.clip_mask_icon && tail_style.clip_mask_state) && !(wear_suit.flags_inv & HIDETAIL) && !(S && S.taurized)) //Clip the lower half of the suit off using the tail's clip mask. + c_mask = new /icon(tail_style.clip_mask_icon, tail_style.clip_mask_state) + overlays_standing[SUIT_LAYER] = wear_suit.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_wear_suit_str, default_icon = iconFile, default_layer = SUIT_LAYER, clip_mask = c_mask) + //VOREStation Edit end. apply_layer(SUIT_LAYER) @@ -921,7 +941,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/t_state = "[species.get_tail(src)]_once" var/used_tail_layer = tail_alt ? TAIL_LAYER_ALT : TAIL_LAYER // VOREStation Edit - Alt Tail Layer - + var/image/tail_overlay = overlays_standing[used_tail_layer] // VOREStation Edit - Alt Tail Layer if(tail_overlay && tail_overlay.icon_state == t_state) return //let the existing animation finish @@ -931,7 +951,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() spawn(20) //check that the animation hasn't changed in the meantime if(overlays_standing[used_tail_layer] == tail_overlay && tail_overlay.icon_state == t_state) // VOREStation Edit - Alt Tail Layer - animate_tail_stop() + animate_tail_stop() /mob/living/carbon/human/proc/animate_tail_start() if(QDESTROYING(src)) @@ -972,7 +992,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(vr_wing_image) vr_wing_image.layer = BODY_LAYER+WING_LAYER overlays_standing[WING_LAYER] = vr_wing_image - + apply_layer(WING_LAYER) // VOREStation Edit end diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 37d9e43b379..55bddfe1bd4 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -26,6 +26,9 @@ if(COLD_RESISTANCE in mutations) damage = 0 adjustFireLoss(damage * blocked) + if(SEARING) + apply_damage(damage / 3, BURN, def_zone, blocked, soaked, used_weapon, sharp, edge) + apply_damage(damage / 3 * 2, BRUTE, def_zone, blocked, soaked, used_weapon, sharp, edge) if(TOX) adjustToxLoss(damage * blocked) if(OXY) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d5295289faf..e6fde9860fa 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1060,7 +1060,7 @@ default behaviour is: var/mob/living/carbon/human/H = src if(!H.isSynthetic()) var/obj/item/organ/internal/liver/L = H.internal_organs_by_name["liver"] - if(L.is_broken()) + if(!L || L.is_broken()) blood_vomit = 1 Stun(5) @@ -1362,4 +1362,4 @@ default behaviour is: CLONE:[getCloneLoss()] BRAIN:[getBrainLoss()] - "} + "} \ No newline at end of file diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index b3ee75349c9..6384e904662 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -216,6 +216,9 @@ /mob/living/proc/hit_with_weapon(obj/item/I, mob/living/user, var/effective_force, var/hit_zone) visible_message("[src] has been [I.attack_verb.len? pick(I.attack_verb) : "attacked"] with [I.name] by [user]!") + if(ai_holder) + ai_holder.react_to_attack(user) + var/soaked = get_armor_soak(hit_zone, "melee") var/blocked = run_armor_check(hit_zone, "melee") diff --git a/code/modules/mob/living/living_defines_vr.dm b/code/modules/mob/living/living_defines_vr.dm index 8b463df93b1..72c495ce143 100644 --- a/code/modules/mob/living/living_defines_vr.dm +++ b/code/modules/mob/living/living_defines_vr.dm @@ -1,3 +1,9 @@ /mob/living var/ooc_notes = null - var/obj/structure/mob_spawner/source_spawner = null \ No newline at end of file + var/obj/structure/mob_spawner/source_spawner = null + +//custom say verbs + var/custom_say = null + var/custom_ask = null + var/custom_exclaim = null + var/custom_whisper = null \ No newline at end of file diff --git a/code/modules/mob/living/living_vr.dm b/code/modules/mob/living/living_vr.dm new file mode 100644 index 00000000000..7616ac61d55 --- /dev/null +++ b/code/modules/mob/living/living_vr.dm @@ -0,0 +1,25 @@ +/mob/living/verb/customsay() + set category = "IC" + set name = "Customise Speech Verbs" + set desc = "Customise the text which appears when you type- e.g. 'says', 'asks', 'exclaims'." + + if(src.client) + var/customsaylist[] = list( + "Say", + "Whisper", + "Ask (?)", + "Exclaim/Shout/Yell (!)", + "Cancel" + ) + var/sayselect = input("Which say-verb do you wish to customise?") as null|anything in customsaylist //we can't use alert() for this because there's too many terms + + if(sayselect == "Say") + custom_say = sanitize(input(usr, "This word or phrase will appear instead of 'says': [src] says, \"Hi.\"", "Custom Say", null) as text) + else if(sayselect == "Whisper") + custom_whisper = sanitize(input(usr, "This word or phrase will appear instead of 'whispers': [src] whispers, \"Hi...\"", "Custom Whisper", null) as text) + else if(sayselect == "Ask (?)") + custom_ask = sanitize(input(usr, "This word or phrase will appear instead of 'asks': [src] asks, \"Hi?\"", "Custom Ask", null) as text) + else if(sayselect == "Exclaim/Shout/Yell (!)") + custom_exclaim = sanitize(input(usr, "This word or phrase will appear instead of 'exclaims', 'shouts' or 'yells': [src] exclaims, \"Hi!\"", "Custom Exclaim", null) as text) + else + return diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 02900ffe1a0..c53e24c8650 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -275,6 +275,20 @@ proc/get_radio_key_from_channel(var/channel) message_range = 1 sound_vol *= 0.5 + //VOREStation edit - allows for custom say verbs, overriding all other say-verb types- e.g. "says loudly" instead of "shouts" + //You'll still stammer if injured or slur if drunk, but it won't have those specific words + var/ending = copytext(message, length(message)) + + if(custom_whisper && whispering) + verb = "[custom_whisper]" + else if(custom_exclaim && ending=="!") + verb = "[custom_exclaim]" + else if(custom_ask && ending=="?") + verb = "[custom_ask]" + else if(custom_say) + verb = "[custom_say]" + //VOREStation edit ends + //Handle nonverbal and sign languages here if (speaking) if (speaking.flags & SIGNLANG) @@ -399,6 +413,10 @@ proc/get_radio_key_from_channel(var/channel) for(var/hearer in mobs) var/mob/M = hearer M.hear_signlang(message, verb, language, src) + var/list/objs = potentials["objs"] + for(var/hearer in objs) + var/obj/O = hearer + O.hear_signlang(message, verb, language, src) return 1 /obj/effect/speech_bubble diff --git a/code/modules/mob/living/silicon/ai/ai_remote_control.dm b/code/modules/mob/living/silicon/ai/ai_remote_control.dm index cef8cec7e8b..3e976784258 100644 --- a/code/modules/mob/living/silicon/ai/ai_remote_control.dm +++ b/code/modules/mob/living/silicon/ai/ai_remote_control.dm @@ -27,7 +27,7 @@ for(var/borgie in GLOB.available_ai_shells) var/mob/living/silicon/robot/R = borgie - if(R.shell && !R.deployed && (R.stat != DEAD) && (!R.connected_ai || (R.connected_ai == src) ) ) + if(R.shell && !R.deployed && (R.stat != DEAD) && (!R.connected_ai || (R.connected_ai == src) ) && !(using_map.ai_shell_restricted && !(R.z in using_map.ai_shell_allowed_levels)) ) //VOREStation Edit: shell restrictions possible += R if(!LAZYLEN(possible)) diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index ac2417a0772..b6d4052a5fd 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -35,7 +35,8 @@ "Fox" = "pai-fox", "Parrot" = "pai-parrot", "Rabbit" = "pai-rabbit", - "Bear" = "pai-bear" //VOREStation Edit + "Bear" = "pai-bear", //VOREStation Edit + "Fennec" = "pai-fen" // VOREStation Edit - Rykka ) var/global/list/possible_say_verbs = list( diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm index bfff010d03a..882a7d934b8 100644 --- a/code/modules/mob/living/silicon/robot/component.dm +++ b/code/modules/mob/living/silicon/robot/component.dm @@ -208,6 +208,18 @@ name = "broken component" icon = 'icons/obj/robot_component.dmi' icon_state = "broken" + matter = list(DEFAULT_WALL_MATERIAL = 1000) + +/obj/item/broken_device/random + var/list/possible_icons = list("binradio_broken", + "motor_broken", + "armor_broken", + "camera_broken", + "analyser_broken", + "radio_broken") + +/obj/item/broken_device/random/Initialize() + icon_state = pick(possible_icons) /obj/item/robot_parts/robot_component icon = 'icons/obj/robot_component.dmi' diff --git a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm index 68308efc664..312d7f06db6 100644 --- a/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm +++ b/code/modules/mob/living/silicon/robot/dogborg/dog_sleeper_vr.dm @@ -42,6 +42,10 @@ flags |= NOBLUDGEON //No more attack messages files = new /datum/research/techonly(src) +/obj/item/device/dogborg/sleeper/Destroy() + go_out() + ..() + /obj/item/device/dogborg/sleeper/Exit(atom/movable/O) return 0 diff --git a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm index 2f688a90080..2595d451c1e 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_abilities.dm @@ -26,10 +26,10 @@ if(!istype(H) || !Adjacent(H)) return ..() if(H.a_intent == "grab" && hat && !(H.l_hand && H.r_hand)) - hat.loc = get_turf(src) H.put_in_hands(hat) H.visible_message("\The [H] removes \the [src]'s [hat].") hat = null updateicon() + return else return ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 080196f0aaa..2959616130c 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -153,6 +153,7 @@ /mob/living/silicon/robot/handle_regular_hud_updates() var/fullbright = FALSE + var/seemeson = FALSE if (src.stat == 2 || (XRAY in mutations) || (src.sight_mode & BORGXRAY)) src.sight |= SEE_TURFS src.sight |= SEE_MOBS @@ -170,6 +171,7 @@ src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM fullbright = TRUE + seemeson = TRUE else if (src.sight_mode & BORGMATERIAL) src.sight |= SEE_OBJS src.see_in_dark = 8 @@ -194,6 +196,7 @@ src.see_invisible = SEE_INVISIBLE_LIVING // This is normal vision (25), setting it lower for normal vision means you don't "see" things like darkness since darkness // has a "invisible" value of 15 plane_holder.set_vis(VIS_FULLBRIGHT,fullbright) + plane_holder.set_vis(VIS_MESONS,seemeson) ..() if (src.healths) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index ea851806c39..a9097f89131 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -259,11 +259,16 @@ if(module) return var/list/modules = list() - modules.Add(robot_module_types) - if(crisis || security_level == SEC_LEVEL_RED || crisis_override) // VOREStation Edit - to_chat(src, "Crisis mode active. Combat module available.") - modules+="Combat" - modules+="ERT" //VOREStation Edit + //VOREStatation Edit Start: shell restrictions + if(shell) + modules.Add(shell_module_types) + else + modules.Add(robot_module_types) + if(crisis || security_level == SEC_LEVEL_RED || crisis_override) + to_chat(src, "Crisis mode active. Combat module available.") + modules+="Combat" + modules+="ERT" + //VOREStatation Edit End: shell restrictions modtype = input("Please, select a module!", "Robot module", null, null) as null|anything in modules if(module) diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index b820451adfd..4a3f4741ba2 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -48,6 +48,8 @@ var/global/list/robot_modules = list( apply_status_flags(R) if(R.radio) + if(R.shell) + channels = R.mainframe.aiRadio.channels R.radio.recalculateChannels() vr_add_sprites() //Vorestation Edit: For vorestation only sprites @@ -470,6 +472,10 @@ var/global/list/robot_modules = list( S.synths = list(metal) src.modules += S + var/obj/item/stack/tile/roofing/cyborg/CT = new /obj/item/stack/tile/roofing/cyborg(src) + CT.synths = list(metal) + src.modules += CT + var/obj/item/stack/material/cyborg/glass/reinforced/RG = new (src) RG.synths = list(metal, glass) src.modules += RG diff --git a/code/modules/mob/living/silicon/robot/robot_remote_control.dm b/code/modules/mob/living/silicon/robot/robot_remote_control.dm index 90d74b2638f..35ad010b97f 100644 --- a/code/modules/mob/living/silicon/robot/robot_remote_control.dm +++ b/code/modules/mob/living/silicon/robot/robot_remote_control.dm @@ -69,11 +69,14 @@ GLOBAL_LIST_EMPTY(available_ai_shells) // Languages and comms. languages = AI.languages.Copy() speech_synthesizer_langs = AI.speech_synthesizer_langs.Copy() - if(radio && AI.aiRadio) //AI keeps all channels, including Syndie if it is an Infiltrator. + //VOREStation Edit Start + if(radio && AI.aiRadio && module) //AI keeps all channels, including Syndie if it is an Infiltrator. // if(AI.radio.syndie) // radio.make_syndie() radio.subspace_transmission = TRUE - radio.channels = AI.aiRadio.channels + module.channels = AI.aiRadio.channels + radio.recalculateChannels() + //VOREStation Edit End // Called after the AI transfers over. /mob/living/silicon/robot/proc/post_deploy() @@ -94,7 +97,8 @@ GLOBAL_LIST_EMPTY(available_ai_shells) mainframe.deployed_shell = null SetName("[modtype] AI Shell [num2text(ident)]") // undeployment_action.Remove(src) - if(radio) //Return radio to normal + if(radio && module) //Return radio to normal //VOREStation Edit + module.channels = initial(module.channels) //VOREStation Edit radio.recalculateChannels() if(!QDELETED(camera)) camera.c_tag = real_name //update the camera name too diff --git a/code/modules/mob/living/silicon/robot/robot_vr.dm b/code/modules/mob/living/silicon/robot/robot_vr.dm index e66ad05ec93..e3264aee4e5 100644 --- a/code/modules/mob/living/silicon/robot/robot_vr.dm +++ b/code/modules/mob/living/silicon/robot/robot_vr.dm @@ -258,3 +258,10 @@ return if(buckle_mob(M)) visible_message("[M] starts riding [name]!") + +/mob/living/silicon/robot/onTransitZ(old_z, new_z) + if(shell) + if(deployed && using_map.ai_shell_restricted && !(new_z in using_map.ai_shell_allowed_levels)) + to_chat(src,"Your connection with the shell is suddenly interrupted!") + undeploy() + ..() diff --git a/code/modules/mob/living/simple_animal/aliens/hivebot.dm b/code/modules/mob/living/simple_animal/aliens/hivebot.dm index 12851c5af32..fbb0b8909b7 100644 --- a/code/modules/mob/living/simple_animal/aliens/hivebot.dm +++ b/code/modules/mob/living/simple_animal/aliens/hivebot.dm @@ -87,7 +87,7 @@ /mob/living/simple_mob/hostile/hivebot/range/ion name = "engineering hivebot" desc = "A robot. It has a tool which emits focused electromagnetic pulses, which are deadly to synthetic adverseries." - projectiletype = /obj/item/projectile/ion/small //VOREStation Edit + projectiletype = /obj/item/projectile/ion/pistol //VOREStation Edit projectilesound = 'sound/weapons/Laser.ogg' icon_living = "engi" ranged = TRUE diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm index 5f352705b81..62b2c43fe81 100644 --- a/code/modules/mob/living/simple_animal/corpse.dm +++ b/code/modules/mob/living/simple_animal/corpse.dm @@ -99,7 +99,19 @@ corpseidjob = "Operative" corpseidaccess = "Syndicate" - +/obj/effect/landmark/mobcorpse/solarpeacekeeper + name = "Mercenary" + corpseuniform = /obj/item/clothing/under/syndicate + corpsesuit = /obj/item/clothing/suit/armor/pcarrier/blue/sol + corpseshoes = /obj/item/clothing/shoes/boots/swat + corpsegloves = /obj/item/clothing/gloves/swat + corpseradio = /obj/item/device/radio/headset + corpsemask = /obj/item/clothing/mask/gas + corpsehelmet = /obj/item/clothing/head/helmet/swat + corpseback = /obj/item/weapon/storage/backpack + corpseid = 1 + corpseidjob = "Peacekeeper" + corpseidaccess = "Syndicate" /obj/effect/landmark/mobcorpse/syndicatecommando name = "Syndicate Commando" diff --git a/code/modules/mob/living/simple_animal/corpse_vr.dm b/code/modules/mob/living/simple_animal/corpse_vr.dm new file mode 100644 index 00000000000..82399a83282 --- /dev/null +++ b/code/modules/mob/living/simple_animal/corpse_vr.dm @@ -0,0 +1,2 @@ +/obj/effect/landmark/mobcorpse/syndicatecommando + name = "Mercenary Commando" \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/life.dm b/code/modules/mob/living/simple_mob/life.dm index 4c063e4bd93..d4ed684deb0 100644 --- a/code/modules/mob/living/simple_mob/life.dm +++ b/code/modules/mob/living/simple_mob/life.dm @@ -88,7 +88,7 @@ if(Environment) - if( abs(Environment.temperature - bodytemperature) > 40 ) + if( abs(Environment.temperature - bodytemperature) > temperature_range ) //VOREStation Edit: heating adjustments bodytemperature += ((Environment.temperature - bodytemperature) / 5) if(min_oxy) diff --git a/code/modules/mob/living/simple_mob/simple_mob_vr.dm b/code/modules/mob/living/simple_mob/simple_mob_vr.dm index d388d1ec885..24faf9cc2a7 100644 --- a/code/modules/mob/living/simple_mob/simple_mob_vr.dm +++ b/code/modules/mob/living/simple_mob/simple_mob_vr.dm @@ -4,6 +4,8 @@ #define SA_ICON_REST 0x03 /mob/living/simple_mob + var/temperature_range = 40 // How close will they get to environmental temperature before their body stops changing its heat + var/vore_active = 0 // If vore behavior is enabled for this mob var/vore_capacity = 1 // The capacity (in people) this person can hold diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm index 2ff8c55598c..4e86b1c68a4 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/giant_spider_vr.dm @@ -11,7 +11,7 @@ base_attack_cooldown = 10 projectilesound = 'sound/weapons/taser2.ogg' - projectiletype = /obj/item/projectile/ion/small + projectiletype = /obj/item/projectile/ion/pistol melee_damage_lower = 8 melee_damage_upper = 15 diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm index 6889d5ba6a1..84f3d533cf7 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/giant_spider/nurse.dm @@ -51,6 +51,9 @@ var/egg_type = /obj/effect/spider/eggcluster/small var/web_type = /obj/effect/spider/stickyweb/dark +/datum/ai_holder/simple_mob/melee/nurse_spider + mauling = TRUE // The nurse puts mobs into webs by attacking, so it needs to attack in crit + handle_corpse = TRUE // Lets the nurse wrap dead things /mob/living/simple_mob/animal/giant_spider/nurse/inject_poison(mob/living/L, target_zone) ..() // Inject the stoxin here. diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm index 70afdaf910a..e1cb92ada30 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse.dm @@ -112,4 +112,4 @@ /datum/say_list/mouse speak = list("Squeek!","SQUEEK!","Squeek?") emote_hear = list("squeeks","squeaks","squiks") - emote_see = list("runs in a circle", "shakes", "scritches at something") \ No newline at end of file + emote_see = list("runs in a circle", "shakes", "scritches at something") diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse_vr.dm new file mode 100644 index 00000000000..4b4cdcade4a --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/mouse_vr.dm @@ -0,0 +1,18 @@ +/mob/living/simple_mob/animal/passive/mouse + no_vore = 1 //Mice can't eat others due to the amount of bugs caused by it. + vore_taste = "cheese" + + can_pull_size = ITEMSIZE_TINY // Rykka - Uncommented these. Not sure why they were commented out in the original Polaris files, maybe a mob rework mistake? + can_pull_mobs = MOB_PULL_NONE // Rykka - Uncommented these. Not sure why they were commented out in the original Polaris files, maybe a mob rework mistake? + + desc = "A small rodent, often seen hiding in maintenance areas and making a nuisance of itself. And stealing cheese, or annoying the chef. SQUEAK! <3" + +/mob/living/simple_mob/animal/passive/mouse/attack_hand(mob/living/hander) + if(hander.a_intent == I_HELP) //if lime intent + get_scooped(hander) //get scooped + +/obj/item/weapon/holder/mouse/attack_self(var/mob/U) + for(var/mob/living/simple_mob/M in src.contents) + if((I_HELP) && U.canClick()) //a little snowflakey, but makes it use the same cooldown as interacting with non-inventory objects + U.setClickCooldown(U.get_attack_speed()) //if there's a cleaner way in baycode, I'll change this + U.visible_message("[U] [M.response_help] \the [M].") diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/fluffy_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/fluffy_vr.dm index c821cf4a567..8507480f01b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/fluffy_vr.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/fluffy_vr.dm @@ -18,6 +18,7 @@ see_in_dark = 5 mob_size = MOB_TINY makes_dirt = FALSE // No more dirt + mob_bump_flag = 0 response_help = "scritches" response_disarm = "bops" diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm index e455f221684..ae1abb363f8 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/glitterfly.dm @@ -7,7 +7,9 @@ An herbivorous insectoid beloved for its glittering wings. \
      \ The creature has four wings mirrored laterally, which reflect \ - the ambient light to provide a measure of camouflage." + the ambient light to provide a measure of camouflage. \ + Their wings appearance does not come free, causing them to \ + produce large amounts of reflective flake-like dandruff." value = CATALOGUER_REWARD_TRIVIAL /datum/category_item/catalogue/fauna/glitterfly_rare @@ -21,7 +23,8 @@ /mob/living/simple_mob/animal/sif/glitterfly name = "glitterfly" - desc = "A shiny butterfly!" + desc = "A large, shiny butterfly!" + description_info = "Glitterflies tend to have a wingspan equivalent to the length of an average human head." tt_desc = "S Lepidoptera adamas" catalogue_data = list(/datum/category_item/catalogue/fauna/glitterfly) @@ -60,9 +63,11 @@ default_pixel_y = rand(5,12) pixel_y = default_pixel_y + adjust_scale(round(rand(90, 105) / 100)) + /mob/living/simple_mob/animal/sif/glitterfly/rare name = "sparkling glitterfly" - desc = "An incredibly shiny butterfly!" + desc = "A large, incredibly shiny butterfly!" catalogue_data = list(/datum/category_item/catalogue/fauna/glitterfly, /datum/category_item/catalogue/fauna/glitterfly_rare) maxHealth = 30 health = 30 @@ -99,4 +104,5 @@ if(friendly_animal_corpse) hostile = TRUE return - hostile = initial(hostile) + else if(prob(1)) + hostile = initial(hostile) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm index 32eccb00af6..5f4a4dc7e0e 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/hooligan_crab.dm @@ -72,7 +72,7 @@ attack_edge = TRUE melee_attack_delay = 1 SECOND - meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/crab response_help = "pets" response_disarm = "gently pushes aside" @@ -117,4 +117,4 @@ for(var/mob/living/L in hearers(holder)) if(!istype(L, holder)) // Don't follow other hooligan crabs. holder.visible_message("\The [holder] starts to follow \the [L].") - set_follow(L, rand(20 SECONDS, 40 SECONDS)) \ No newline at end of file + set_follow(L, rand(20 SECONDS, 40 SECONDS)) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm b/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm index 4022198fdfe..9fbb2926bb3 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/space/worm.dm @@ -411,7 +411,7 @@ /obj/random/bomb_supply = 7, /obj/random/contraband = 3, /obj/random/unidentified_medicine/old_medicine = 7, - /obj/item/weapon/ore/strangerock = 3, + /obj/item/weapon/strangerock = 3, /obj/item/weapon/ore/phoron = 7, /obj/random/handgun = 1, /obj/random/toolbox = 4, diff --git a/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm b/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm index 514f45df120..bddfc140d4d 100644 --- a/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm +++ b/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs.dm @@ -162,6 +162,16 @@ base_attack_cooldown = 5 // Two attacks a second or so. reload_max = 20 +/mob/living/simple_mob/humanoid/merc/ranged/smg/sol + icon_state = "bluforranged_smg" + icon_living = "blueforranged_smg" + + corpse = /obj/effect/landmark/mobcorpse/solarpeacekeeper + loot_list = list(/obj/item/weapon/gun/projectile/automatic/c20r = 100) + + base_attack_cooldown = 5 // Two attacks a second or so. + reload_max = 20 + // Laser Rifle /mob/living/simple_mob/humanoid/merc/ranged/laser icon_state = "syndicateranged_laser" diff --git a/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs_vr.dm b/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs_vr.dm index 36253dce846..55a9172c07f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs_vr.dm +++ b/code/modules/mob/living/simple_mob/subtypes/humanoid/mercs/mercs_vr.dm @@ -5,5 +5,21 @@ /mob/living/simple_mob/humanoid/merc/melee/sword/space name = "mercenary commando" + maxbodytemp = 700 + /mob/living/simple_mob/humanoid/merc/ranged/space - name = "mercenary commando" \ No newline at end of file + name = "mercenary commando" + + maxbodytemp = 700 + +/mob/living/simple_mob/humanoid/merc/ranged/virgo + name = "suspicious individual" + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + minbodytemp = 0 \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm b/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm index 347e64c093c..4098d9ff9cb 100644 --- a/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm +++ b/code/modules/mob/living/simple_mob/subtypes/mechanical/viscerator.dm @@ -63,4 +63,24 @@ . = ..() if(!.) // Not friendly, see if they're a baddie first. if(L.mind && raiders.is_antagonist(L.mind)) - return TRUE \ No newline at end of file + return TRUE + +// Variant that is neutral, and thus on the station's side. It checks records. +/mob/living/simple_mob/mechanical/viscerator/station + icon_state = "viscerator_b_attack" + icon_living = "viscerator_b_attack" + + faction = "station" + maxHealth = 20 + health = 20 + + melee_damage_lower = 2 + melee_damage_upper = 5 + base_attack_cooldown = 8 + +/mob/living/simple_mob/mechanical/viscerator/station/IIsAlly(mob/living/L) + . = ..() + if(!.) + if(isrobot(L)) // They ignore synths. + return TRUE + return L.assess_perp(src, FALSE, FALSE, TRUE, FALSE) <= 3 diff --git a/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm b/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm index 519ad4ce888..aa49ce806b1 100644 --- a/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm +++ b/code/modules/mob/living/simple_mob/subtypes/mechanical/ward/monitor_ward.dm @@ -43,7 +43,20 @@ faction = "syndicate" /mob/living/simple_mob/mechanical/ward/monitor/crew - faction = "neutral" + icon_state = "ward-nt" + +/mob/living/simple_mob/mechanical/ward/monitor/crew/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/card/id) && !owner) + owner = user + return + ..() + +/mob/living/simple_mob/mechanical/ward/monitor/crew/IIsAlly(mob/living/L) + . = ..() + if(!.) + if(isrobot(L)) // They ignore synths. + return TRUE + return L.assess_perp(src, FALSE, FALSE, TRUE, FALSE) <= 3 /mob/living/simple_mob/mechanical/ward/monitor/death() if(owner) @@ -55,10 +68,10 @@ /mob/living/simple_mob/mechanical/ward/monitor/update_icon() if(seen_mobs.len) - icon_living = "ward_spotted" + icon_living = "[initial(icon_state)]_spotted" glow_color = "#FF0000" else - icon_living = "ward" + icon_living = "[initial(icon_state)]" glow_color = "#00FF00" handle_light() // Update the light immediately. ..() @@ -118,4 +131,4 @@ return FALSE /datum/ai_holder/simple_mob/monitor/ranged_attack(atom/A) - return FALSE \ No newline at end of file + return FALSE diff --git a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/consumption.dm b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/consumption.dm index 84af3fcc3cf..13764d20fdc 100644 --- a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/consumption.dm +++ b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/consumption.dm @@ -140,6 +140,13 @@ if(L.getCloneLoss() >= L.getMaxHealth() * 1.5) to_chat(src, "This subject does not have an edible life energy...") return FALSE + //VOREStation Addition start + if(istype(L, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = L + if(H.species.flags & NO_SCAN) + to_chat(src, "This subject's life energy is beyond my reach...") + return FALSE + //VOREStation Addition end if(L.has_buckled_mobs()) for(var/A in L.buckled_mobs) if(istype(A, /mob/living/simple_mob/slime/xenobio)) diff --git a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes_vr.dm b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes_vr.dm index e67717403d5..3188ae0aa1c 100644 --- a/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes_vr.dm +++ b/code/modules/mob/living/simple_mob/subtypes/slime/xenobio/subtypes_vr.dm @@ -1,2 +1,7 @@ -/mob/living/simple_mob/slime/xenobio/rainbow/kendrick - mob_bump_flag = 0 \ No newline at end of file +/mob/living/simple_mob/slime/xenobio + temperature_range = 5 + mob_bump_flag = 0 + +/mob/living/simple_mob/slime/xenobio/Initialize(mapload, var/mob/living/simple_mob/slime/xenobio/my_predecessor) + ..() + Weaken(10) \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/mimic.dm b/code/modules/mob/living/simple_mob/subtypes/vore/mimic.dm index 00a18feaadf..5093caad4c8 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/mimic.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/mimic.dm @@ -58,7 +58,7 @@ desc = "A rectangular steel crate." icon_state = "crate" icon_living = "crate" - icon = 'icons/obj/storage.dmi' + icon = 'icons/obj/storage_vr.dmi' faction = "mimic" diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm new file mode 100644 index 00000000000..0aa1b700a6e --- /dev/null +++ b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm @@ -0,0 +1,171 @@ +#define MORPH_COOLDOWN 50 + +/mob/living/simple_mob/vore/hostile/morph + name = "morph" + real_name = "morph" + desc = "A revolting, pulsating pile of flesh." + tt_desc = "morphus shapeshiftus" + icon = 'icons/mob/animal_vr.dmi' + icon_state = "morph" + icon_living = "morph" + icon_dead = "morph_dead" + movement_cooldown = 1 + status_flags = CANPUSH + pass_flags = PASSTABLE + mob_bump_flag = 0 + + min_oxy = 0 + max_oxy = 0 + min_tox = 0 + max_tox = 0 + min_co2 = 0 + max_co2 = 0 + min_n2 = 0 + max_n2 = 0 + + minbodytemp = 0 + maxHealth = 150 + health = 150 + melee_damage_lower = 20 + melee_damage_upper = 20 + see_in_dark = 8 + attacktext = "glomps" + attack_sound = 'sound/effects/blobattack.ogg' + + meat_amount = 2 + meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat + + showvoreprefs = 0 + vore_active = 1 + + var/morphed = FALSE + var/tooltip = TRUE + var/melee_damage_disguised = 0 + var/eat_while_disguised = FALSE + var/atom/movable/form = null + var/morph_time = 0 + var/our_size_multiplier = 1 + var/static/list/blacklist_typecache = typecacheof(list( + /obj/screen, + /obj/singularity, + /mob/living/simple_mob/vore/hostile/morph, + /obj/effect)) + +/mob/living/simple_mob/vore/hostile/morph/Initialize() + verbs += /mob/living/proc/ventcrawl + return ..() + +/mob/living/simple_mob/vore/hostile/morph/proc/allowed(atom/movable/A) + return !is_type_in_typecache(A, blacklist_typecache) && (isobj(A) || ismob(A)) + +/mob/living/simple_mob/vore/hostile/morph/examine(mob/user) + if(morphed) + form.examine(user) + if(get_dist(user,src)<=3) + to_chat(user, "It doesn't look quite right...") + else + ..() + return + +/mob/living/simple_mob/vore/hostile/morph/ShiftClickOn(atom/movable/A) + if(Adjacent(A)) + if(morph_time <= world.time && !stat) + if(A == src) + restore() + return + if(istype(A) && allowed(A)) + assume(A) + else + to_chat(src, "Your chameleon skin is still repairing itself!") + else + ..() + +/mob/living/simple_mob/vore/hostile/morph/proc/assume(atom/movable/target) + if(morphed) + to_chat(src, "You must restore to your original form first!") + return + morphed = TRUE + form = target + + visible_message("[src] suddenly twists and changes shape, becoming a copy of [target]!") + appearance = target.appearance + copy_overlays(target) + alpha = max(alpha, 150) //fucking chameleons + transform = initial(transform) + our_size_multiplier = size_multiplier + if(isobj(target)) + size_multiplier = 1 + icon_scale_x = target.icon_scale_x + icon_scale_y = target.icon_scale_y + update_transform() + else if(ismob(target)) + var/mob/living/M = target + resize(M.size_multiplier) + pixel_y = initial(pixel_y) + pixel_x = initial(pixel_x) + density = target.density + + //Morphed is weaker + melee_damage_lower = melee_damage_disguised + melee_damage_upper = melee_damage_disguised + movement_cooldown = 5 + + morph_time = world.time + MORPH_COOLDOWN + return + +/mob/living/simple_mob/vore/hostile/morph/proc/restore() + if(!morphed) + to_chat(src, "You're already in your normal form!") + return + morphed = FALSE + form = null + alpha = initial(alpha) + color = initial(color) + layer = initial(layer) + plane = initial(plane) + maptext = null + + visible_message("[src] suddenly collapses in on itself, dissolving into a pile of green flesh!") + name = initial(name) + desc = initial(desc) + icon = initial(icon) + icon_state = initial(icon_state) + size_multiplier = 0 + resize(our_size_multiplier) + overlays.Cut() + density = initial(density) + + //Baseline stats + melee_damage_lower = initial(melee_damage_lower) + melee_damage_upper = initial(melee_damage_upper) + movement_cooldown = initial(movement_cooldown) + + morph_time = world.time + MORPH_COOLDOWN + +/mob/living/simple_mob/vore/hostile/morph/death(gibbed) + if(morphed) + visible_message("[src] twists and dissolves into a pile of green flesh!") + restore() + ..() + +/mob/living/simple_mob/vore/hostile/morph/will_show_tooltip() + return (!morphed) + +/mob/living/simple_mob/vore/hostile/morph/resize(var/new_size, var/animate = TRUE) + if(morphed && !ismob(form)) + return + return ..() + +/mob/living/simple_mob/vore/hostile/morph/update_icons() + if(morphed) + return + return ..() + +/mob/living/simple_mob/vore/hostile/morph/update_transform() + if(morphed) + var/matrix/M = matrix() + M.Scale(icon_scale_x, icon_scale_y) + M.Turn(icon_rotation) + src.transform = M + else + ..() diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm index 3f04c0d28af..b06f5ed4f9b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/solargrub_larva.dm @@ -138,9 +138,10 @@ var/global/list/grub_machine_overlays = list() sparks.start() if(machine_effect) QDEL_NULL(machine_effect) - set_AI_busy(FALSE) ai_holder.target = null powermachine.draining = 1 + spawn(30) + set_AI_busy(FALSE) /mob/living/simple_mob/animal/solargrub_larva/proc/do_ventcrawl(var/obj/machinery/atmospherics/unary/vent_pump/vent) if(!vent) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm b/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm index 9520d9a3ac5..b5a3bc2c60e 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/zz_vore_overrides.dm @@ -121,7 +121,7 @@ health = 80 // Increase health to compensate maxHealth = 80 */ - +/* /mob/living/simple_mob/animal/space/mimic vore_active = 1 // NO VORE SPRITES @@ -130,7 +130,7 @@ // Overrides to non-vore version maxHealth = 60 health = 60 - +*/ /mob/living/simple_mob/animal/passive/cat vore_active = 1 // NO VORE SPRITES diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 8d07f3f2246..ec032d7b46b 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -730,7 +730,7 @@ listed_turf = null else if(statpanel("Turf")) - stat("\icon[listed_turf]", listed_turf.name) + stat(listed_turf) for(var/atom/A in listed_turf) if(!A.mouse_opacity) continue diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index b335faf1d37..7ad90dfc43f 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -174,6 +174,12 @@ assailant.visible_message("[assailant] covers [affecting]'s eyes!") if(affecting.eye_blind < 3) affecting.Blind(3) + //TFF 12/8/19 VoreStation Addition Start + if(BP_HEAD) + if(force_down) + if(announce) + assailant.visible_message("[assailant] sits on [target]'s head!") + //VoreStation Addition End /obj/item/weapon/grab/attack_self() return s_click(hud) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index af06226e151..a60586bbf2a 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -147,6 +147,8 @@ proc/getsensorlevel(A) var/miss_chance = 10 if (zone in base_miss_chance) miss_chance = base_miss_chance[zone] + if (zone == "eyes" || zone == "mouth") + miss_chance = base_miss_chance["head"] miss_chance = max(miss_chance + miss_chance_mod, 0) if(prob(miss_chance)) if(prob(70)) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index b03649183bc..e66cf6f4acb 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -84,7 +84,7 @@ /client/verb/drop_item() set hidden = 1 - if(!isrobot(mob) && mob.stat == CONSCIOUS && isturf(mob.loc)) + if(!isrobot(mob) && mob.stat == CONSCIOUS && (isturf(mob.loc) || isbelly(mob.loc))) // VOREStation Edit: dropping in bellies return mob.drop_item() return diff --git a/code/modules/mob/new_player/login_vr.dm b/code/modules/mob/new_player/login_vr.dm new file mode 100644 index 00000000000..5eeb269bc55 --- /dev/null +++ b/code/modules/mob/new_player/login_vr.dm @@ -0,0 +1,2 @@ +/obj/effect/lobby_image + name = "VORE Station" \ No newline at end of file diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 441ee77234f..749a88dba6a 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -114,7 +114,7 @@ if(href_list["observe"]) - if(alert(src,"Are you sure you wish to observe? You will have to wait 5 minute before being able to respawn!","Player Setup","Yes","No") == "Yes") //Vorestation edit + if(alert(src,"Are you sure you wish to observe? You will have to wait 60 seconds before being able to respawn!","Player Setup","Yes","No") == "Yes") //Vorestation edit - Rykka corrected to 60 seconds to match current spawn time if(!client) return 1 //Make a new mannequin quickly, and allow the observer to take the appearance diff --git a/code/modules/mob/new_player/new_player_vr.dm b/code/modules/mob/new_player/new_player_vr.dm index 0be1ba819b7..b18e66fd836 100644 --- a/code/modules/mob/new_player/new_player_vr.dm +++ b/code/modules/mob/new_player/new_player_vr.dm @@ -21,6 +21,11 @@ pass = FALSE to_chat(src,"You have not set your scale yet. Do this on the VORE tab in character setup.") + //Can they play? + if(!is_alien_whitelisted(src,all_species[client.prefs.species]) && !check_rights(R_ADMIN, 0)) + pass = FALSE + to_chat(src,"You are not allowed to spawn in as this species.") + //Custom species checks if (client && client.prefs && client.prefs.species == "Custom Species") diff --git a/code/modules/mob/new_player/preferences_setup_vr.dm b/code/modules/mob/new_player/preferences_setup_vr.dm index a690c271707..8b1760c65c7 100644 --- a/code/modules/mob/new_player/preferences_setup_vr.dm +++ b/code/modules/mob/new_player/preferences_setup_vr.dm @@ -22,4 +22,8 @@ stamp.Scale(stamp.Width()*size_multiplier,stamp.Height()*size_multiplier) preview_icon.Blend(stamp, ICON_OVERLAY, 112-stamp.Width()/2, 5) - preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser. \ No newline at end of file + preview_icon.Scale(preview_icon.Width() * 2, preview_icon.Height() * 2) // Scaling here to prevent blurring in the browser. + +//TFF 5/8/19 - add randomised sensor setting for random button clicking +/datum/preferences/randomize_appearance_and_body_for(var/mob/living/carbon/human/H) + sensorpref = rand(1,5) \ No newline at end of file diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index c1d0f9de647..6f05b298e60 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -91,7 +91,7 @@ add_language(LANGUAGE_SCHECHI, 1) add_language(LANGUAGE_SIGN, 1) add_language(LANGUAGE_TERMINUS, 1) - add_language(LANGUAGE_ZADDAT = 0) + add_language(LANGUAGE_ZADDAT, 0) // Lorefolks say it may be so. if(O.client && O.client.prefs) @@ -182,7 +182,7 @@ var/datum/preferences/B = O.client.prefs for(var/language in B.alternate_languages) O.add_language(language) - O.resize(B.size_multiplier, animate = FALSE) //VOREStation Addition: add size prefs to borgs + O.resize(B.size_multiplier, animate = TRUE) //VOREStation Addition: add size prefs to borgs O.fuzzy = B.fuzzy //VOREStation Addition: add size prefs to borgs callHook("borgify", list(O)) diff --git a/code/modules/modular_computers/computers/modular_computer/damage.dm b/code/modules/modular_computers/computers/modular_computer/damage.dm index d63bf39fdf4..9084bad735a 100644 --- a/code/modules/modular_computers/computers/modular_computer/damage.dm +++ b/code/modules/modular_computers/computers/modular_computer/damage.dm @@ -16,7 +16,7 @@ H.take_damage(rand(10,30)) qdel() -/obj/item/modular_computer/proc/take_damage(var/amount, var/component_probability, var/damage_casing = 1, var/randomize = 1) +/obj/item/modular_computer/take_damage(var/amount, var/component_probability, var/damage_casing = 1, var/randomize = 1) if(randomize) // 75%-125%, rand() works with integers, apparently. amount *= (rand(75, 125) / 100.0) diff --git a/code/modules/modular_computers/file_system/program_events.dm b/code/modules/modular_computers/file_system/program_events.dm index 73386ca198d..ef1eac09aa9 100644 --- a/code/modules/modular_computers/file_system/program_events.dm +++ b/code/modules/modular_computers/file_system/program_events.dm @@ -13,6 +13,6 @@ /datum/computer_file/program/proc/event_networkfailure(var/background) kill_program(1) if(background) - computer.visible_message("\The [computer]'s screen displays an error: \"Network connectivity lost - process [filename].[filetype] (PID [rand(100,999)]) terminated.\"", 1) + computer.visible_message("\The [computer]'s screen displays an error: \"Network connectivity lost - process [filename].[filetype] (PID [rand(100,999)]) terminated.\"") else - computer.visible_message("\The [computer]'s screen briefly freezes and then shows: \"FATAL NETWORK ERROR - NTNet connection lost. Please try again later. If problem persists, please contact your system administrator.\"", 1) + computer.visible_message("\The [computer]'s screen briefly freezes and then shows: \"FATAL NETWORK ERROR - NTNet connection lost. Please try again later. If problem persists, please contact your system administrator.\"") diff --git a/code/modules/modular_computers/file_system/programs/command/card.dm b/code/modules/modular_computers/file_system/programs/command/card.dm index 80a250ca6bc..5bcac7adf8e 100644 --- a/code/modules/modular_computers/file_system/programs/command/card.dm +++ b/code/modules/modular_computers/file_system/programs/command/card.dm @@ -167,8 +167,8 @@ computer.proc_eject_id(user) if("terminate") if(computer && can_run(user, 1)) - id_card.assignment = "Terminated" - remove_nt_access(id_card) + id_card.assignment = "Dismissed" //VOREStation Edit: setting adjustment + id_card.access = list() callHook("terminate_employee", list(id_card)) if("edit") if(computer && can_run(user, 1)) @@ -206,8 +206,7 @@ access = jobdatum.get_access() - remove_nt_access(id_card) - apply_access(id_card, access) + id_card.access = access id_card.assignment = t1 id_card.rank = t1 @@ -225,9 +224,3 @@ SSnanoui.update_uis(NM) return 1 - -/datum/computer_file/program/card_mod/proc/remove_nt_access(var/obj/item/weapon/card/id/id_card) - id_card.access -= get_access_ids(ACCESS_TYPE_STATION|ACCESS_TYPE_CENTCOM) - -/datum/computer_file/program/card_mod/proc/apply_access(var/obj/item/weapon/card/id/id_card, var/list/accesses) - id_card.access |= accesses diff --git a/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm index 482872b533a..20c4dde1ca1 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/alarm_monitor.dm @@ -1,12 +1,12 @@ /datum/computer_file/program/alarm_monitor - filename = "alarmmonitor" - filedesc = "Alarm Monitoring" + filename = "alarmmonitoreng" + filedesc = "Alarm Monitoring (Engineering)" nanomodule_path = /datum/nano_module/alarm_monitor/engineering ui_header = "alarm_green.gif" program_icon_state = "alert-green" program_key_state = "atmos_key" program_menu_icon = "alert" - extended_desc = "This program provides visual interface for the alarm system." + extended_desc = "This program provides visual interface for the engineering alarm system." required_access = access_engine requires_ntnet = 1 network_destination = "alarm monitoring network" @@ -46,7 +46,7 @@ /datum/nano_module/alarm_monitor/engineering/New() ..() - alarm_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, power_alarm) + alarm_handlers = list(atmosphere_alarm, fire_alarm, power_alarm) /datum/nano_module/alarm_monitor/security/New() ..() @@ -132,4 +132,4 @@ ui.auto_update_layout = 1 ui.set_initial_data(data) ui.open() - ui.set_auto_update(1) + ui.set_auto_update(1) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/programs/generic/camera.dm b/code/modules/modular_computers/file_system/programs/generic/camera.dm index 15c7868737f..a722dea6b6b 100644 --- a/code/modules/modular_computers/file_system/programs/generic/camera.dm +++ b/code/modules/modular_computers/file_system/programs/generic/camera.dm @@ -11,10 +11,15 @@ return 0 if(NETWORK_ENGINE,NETWORK_ALARM_ATMOS,NETWORK_ALARM_FIRE,NETWORK_ALARM_POWER) return access_engine + if(NETWORK_CIRCUITS) + return access_research if(NETWORK_ERT) return access_cent_specops - return access_security // Default for all other networks + if(network in using_map.station_networks) + return access_security // Default for all other station networks + else + return 999 //Inaccessible if not a station network and not mentioned above /datum/computer_file/program/camera_monitor filename = "cammon" @@ -41,10 +46,17 @@ var/list/all_networks[0] for(var/network in using_map.station_networks) - all_networks.Add(list(list( - "tag" = network, - "has_access" = can_access_network(user, get_camera_access(network)) - ))) + if(can_access_network(user, get_camera_access(network), 1)) + all_networks.Add(list(list( + "tag" = network, + "has_access" = 1 + ))) + for(var/network in using_map.secondary_networks) + if(can_access_network(user, get_camera_access(network), 0)) + all_networks.Add(list(list( + "tag" = network, + "has_access" = 1 + ))) all_networks = modify_networks_list(all_networks) @@ -67,12 +79,15 @@ /datum/nano_module/camera_monitor/proc/modify_networks_list(var/list/networks) return networks -/datum/nano_module/camera_monitor/proc/can_access_network(var/mob/user, var/network_access) +/datum/nano_module/camera_monitor/proc/can_access_network(var/mob/user, var/network_access, var/station_network = 0) // No access passed, or 0 which is considered no access requirement. Allow it. if(!network_access) return 1 - return check_access(user, access_security) || check_access(user, access_heads) || check_access(user, network_access) + if(station_network) + return check_access(user, network_access) || check_access(user, access_security) || check_access(user, access_heads) + else + return check_access(user, network_access) /datum/nano_module/camera_monitor/Topic(href, href_list) if(..()) @@ -90,7 +105,7 @@ else if(href_list["switch_network"]) // Either security access, or access to the specific camera network's department is required in order to access the network. - if(can_access_network(usr, get_camera_access(href_list["switch_network"]))) + if(can_access_network(usr, get_camera_access(href_list["switch_network"]), (href_list["switch_network"] in using_map.station_networks))) current_network = href_list["switch_network"] else to_chat(usr, "\The [nano_host()] shows an \"Network Access Denied\" error message.") diff --git a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm index 86ccaa73bc4..668d3f81e22 100644 --- a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm +++ b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm @@ -39,9 +39,15 @@ data["isAI"] = isAI(user) data["map_levels"] = using_map.get_map_levels(T.z, FALSE) data["crewmembers"] = list() - for(var/z in (data["map_levels"] | T.z)) // Always show crew from the current Z even if we can't show a map + for(var/z in data["map_levels"]) // VOREStation Edit data["crewmembers"] += crew_repository.health_data(z) + if(!data["map_levels"].len) + to_chat(user, "The crew monitor doesn't seem like it'll work here.") + if(ui) // VOREStation Addition + ui.close() // VOREStation Addition + return + ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) if(!ui) ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800, state = state) diff --git a/code/modules/modular_computers/file_system/programs/security/alarm_monitor.dm b/code/modules/modular_computers/file_system/programs/security/alarm_monitor.dm new file mode 100644 index 00000000000..2254cc1dae9 --- /dev/null +++ b/code/modules/modular_computers/file_system/programs/security/alarm_monitor.dm @@ -0,0 +1,6 @@ +/datum/computer_file/program/alarm_monitor/security //Subtype of engineering alarm monitor, look at /engineering/alarm_monitor for details + filename = "alarmmonitorsec" + filedesc = "Alarm Monitoring (Security)" + extended_desc = "This program provides visual interface for the security alarm system." + nanomodule_path = /datum/nano_module/alarm_monitor/security + required_access = access_security \ No newline at end of file diff --git a/code/modules/modular_computers/hardware/_hardware.dm b/code/modules/modular_computers/hardware/_hardware.dm index 90150bc5474..fb73609d84c 100644 --- a/code/modules/modular_computers/hardware/_hardware.dm +++ b/code/modules/modular_computers/hardware/_hardware.dm @@ -81,7 +81,7 @@ to_chat(user, "It seems to be slightly damaged.") // Damages the component. Contains necessary checks. Negative damage "heals" the component. -/obj/item/weapon/computer_hardware/proc/take_damage(var/amount) +/obj/item/weapon/computer_hardware/take_damage(var/amount) damage += round(amount) // We want nice rounded numbers here. damage = between(0, damage, max_damage) // Clamp the value. diff --git a/code/modules/multi-tile/multi-tile.dm b/code/modules/multi-tile/multi-tile.dm new file mode 100644 index 00000000000..b8dd9ef5124 --- /dev/null +++ b/code/modules/multi-tile/multi-tile.dm @@ -0,0 +1,28 @@ +/* + * This is the home of multi-tile movement checks, and thus here be dragons. You are warned. + */ + +/atom/movable/proc/check_multi_tile_move_density_dir(var/stepdir) + if(!locs || !locs.len) + return TRUE + + if(bound_height > 32 || bound_width > 32) + var/safe_move = TRUE + var/list/checked_turfs = list() + for(var/turf/T in locs) + var/turf/Tcheck = get_step(T, stepdir) + if(Tcheck in checked_turfs) + continue + if(Tcheck in locs) + checked_turfs |= Tcheck + continue + if(!(Tcheck in locs)) + if(!T.Exit(src, Tcheck)) + safe_move = FALSE + if(!Tcheck.Enter(src, T)) + safe_move = FALSE + checked_turfs |= Tcheck + if(!safe_move) + break + return safe_move + return TRUE diff --git a/code/modules/nifsoft/nifsoft.dm b/code/modules/nifsoft/nifsoft.dm index b4791003d0b..6f110de8566 100644 --- a/code/modules/nifsoft/nifsoft.dm +++ b/code/modules/nifsoft/nifsoft.dm @@ -165,15 +165,19 @@ return ..() ///////////////// -// A NIFSoft Disk +// A NIFSoft Uploader /obj/item/weapon/disk/nifsoft - name = "NIFSoft Disk" + name = "NIFSoft Uploader" desc = "It has a small label: \n\ - \"Portable NIFSoft Disk. \n\ - Insert directly into brain.\"" - icon = 'icons/obj/cloning.dmi' - icon_state = "datadisk2" - item_state = "card-id" + \"Portable NIFSoft Installation Media. \n\ + Align ocular port with eye socket and depress red plunger.\"" + icon = 'icons/obj/nanomods.dmi' + icon_state = "medical" + item_state = "nanomod" + item_icons = list( + slot_l_hand_str = 'icons/mob/items/lefthand_vr.dmi', + slot_r_hand_str = 'icons/mob/items/righthand_vr.dmi', + ) w_class = ITEMSIZE_SMALL var/datum/nifsoft/stored = null @@ -188,7 +192,7 @@ var/mob/living/carbon/human/Hu = user if(!Ht.nif || Ht.nif.stat != NIF_WORKING) - to_chat(user,"Either they don't have a NIF, or the disk can't connect.") + to_chat(user,"Either they don't have a NIF, or the uploader can't connect.") return var/extra = extra_params() @@ -197,9 +201,18 @@ else Ht.visible_message("[Hu] begins uploading [src] into [Ht]!","[Hu] is uploading [src] into you!") - if(A == user || do_after(Hu,10 SECONDS,Ht)) + icon_state = "[initial(icon_state)]-animate" //makes it play the item animation upon using on a valid target + update_icon() + + if(A == user && do_after(Hu,1 SECONDS,Ht)) new stored(Ht.nif,extra) qdel(src) + else if(A != user && do_after(Hu,10 SECONDS,Ht)) + new stored(Ht.nif,extra) + qdel(src) + else + icon_state = "[initial(icon_state)]" //If it fails to apply to a valid target and doesn't get deleted, reset its icon state + update_icon() //So disks can pass fancier stuff. /obj/item/weapon/disk/nifsoft/proc/extra_params() @@ -208,8 +221,14 @@ // Compliance Disk // /obj/item/weapon/disk/nifsoft/compliance - name = "NIFSoft Disk (Compliance)" + name = "NIFSoft Uploader (Compliance)" desc = "Wow, adding laws to people? That seems illegal. It probably is. Okay, it really is." + icon_state = "compliance" + item_state = "healthanalyzer" + item_icons = list( + slot_l_hand_str = 'icons/mob/items/lefthand.dmi', + slot_r_hand_str = 'icons/mob/items/righthand.dmi', + ) stored = /datum/nifsoft/compliance var/laws @@ -233,19 +252,20 @@ // Security Disk // /obj/item/weapon/disk/nifsoft/security - name = "NIFSoft Disk - Security" + name = "NIFSoft Uploader - Security" desc = "Contains free NIFSofts useful for security members.\n\ It has a small label: \n\ - \"Portable NIFSoft Disk. \n\ - Insert directly into brain.\"" + \"Portable NIFSoft Installation Media. \n\ + Align ocular port with eye socket and depress red plunger.\"" + icon_state = "security" stored = /datum/nifsoft/package/security /datum/nifsoft/package/security software = list(/datum/nifsoft/ar_sec,/datum/nifsoft/flashprot) /obj/item/weapon/storage/box/nifsofts_security - name = "security nifsoft disks" + name = "security nifsoft uploaders" desc = "A box of free nifsofts for security employees." icon_state = "disk_kit" @@ -256,19 +276,20 @@ // Engineering Disk // /obj/item/weapon/disk/nifsoft/engineering - name = "NIFSoft Disk - Engineering" + name = "NIFSoft Uploader - Engineering" desc = "Contains free NIFSofts useful for engineering members.\n\ It has a small label: \n\ - \"Portable NIFSoft Disk. \n\ - Insert directly into brain.\"" + \"Portable NIFSoft Installation Media. \n\ + Align ocular port with eye socket and depress red plunger.\"" + icon_state = "engineering" stored = /datum/nifsoft/package/engineering /datum/nifsoft/package/engineering software = list(/datum/nifsoft/ar_eng,/datum/nifsoft/alarmmonitor,/datum/nifsoft/uvblocker) /obj/item/weapon/storage/box/nifsofts_engineering - name = "engineering nifsoft disks" + name = "engineering nifsoft uploaders" desc = "A box of free nifsofts for engineering employees." icon_state = "disk_kit" @@ -279,11 +300,11 @@ // Medical Disk // /obj/item/weapon/disk/nifsoft/medical - name = "NIFSoft Disk - Medical" + name = "NIFSoft Uploader - Medical" desc = "Contains free NIFSofts useful for medical members.\n\ It has a small label: \n\ - \"Portable NIFSoft Disk. \n\ - Insert directly into brain.\"" + \"Portable NIFSoft Installation Media. \n\ + Align ocular port with eye socket and depress red plunger.\"" stored = /datum/nifsoft/package/medical @@ -291,7 +312,7 @@ software = list(/datum/nifsoft/ar_med,/datum/nifsoft/crewmonitor) /obj/item/weapon/storage/box/nifsofts_medical - name = "medical nifsoft disks" + name = "medical nifsoft uploaders" desc = "A box of free nifsofts for medical employees." icon_state = "disk_kit" @@ -302,19 +323,20 @@ // Mining Disk // /obj/item/weapon/disk/nifsoft/mining - name = "NIFSoft Disk - Mining" + name = "NIFSoft Uploader - Mining" desc = "Contains free NIFSofts useful for mining members.\n\ It has a small label: \n\ - \"Portable NIFSoft Disk. \n\ - Insert directly into brain.\"" + \"Portable NIFSoft Installation Media. \n\ + Align ocular port with eye socket and depress red plunger.\"" + icon_state = "mining" stored = /datum/nifsoft/package/mining /datum/nifsoft/package/mining software = list(/datum/nifsoft/material,/datum/nifsoft/spare_breath) /obj/item/weapon/storage/box/nifsofts_mining - name = "mining nifsoft disks" + name = "mining nifsoft uploaders" desc = "A box of free nifsofts for mining employees." icon_state = "disk_kit" diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm index b0aadff2a23..215ef65ced8 100644 --- a/code/modules/organs/organ.dm +++ b/code/modules/organs/organ.dm @@ -78,6 +78,7 @@ var/list/organ_cache = list() if(E.internal_organs == null) E.internal_organs = list() E.internal_organs |= src + H.internal_organs_by_name[organ_tag] = src if(dna) if(!blood_DNA) blood_DNA = list() @@ -292,7 +293,7 @@ var/list/organ_cache = list() W.time_inflicted = world.time //Note: external organs have their own version of this proc -/obj/item/organ/proc/take_damage(amount, var/silent=0) +/obj/item/organ/take_damage(amount, var/silent=0) if(src.robotic >= ORGAN_ROBOT) src.damage = between(0, src.damage + (amount * 0.8), max_damage) else diff --git a/code/modules/organs/organ_external_vr.dm b/code/modules/organs/organ_external_vr.dm index 0e3fb07d9ee..491cce94287 100644 --- a/code/modules/organs/organ_external_vr.dm +++ b/code/modules/organs/organ_external_vr.dm @@ -13,3 +13,7 @@ min_broken_damage = o_min_broken_damage else return ..() + +/obj/item/organ/external/proc/is_hidden_by_tail() + if(owner && owner.tail_style && owner.tail_style.hide_body_parts && (organ_tag in owner.tail_style.hide_body_parts)) + return 1 \ No newline at end of file diff --git a/code/modules/organs/robolimbs.dm b/code/modules/organs/robolimbs.dm index fd59a97d076..8f0ef8174c2 100644 --- a/code/modules/organs/robolimbs.dm +++ b/code/modules/organs/robolimbs.dm @@ -129,7 +129,9 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ icon = 'icons/mob/human_races/cyberlimbs/grayson/grayson_main.dmi' unavailable_to_build = 1 monitor_styles = "blank=grayson_off;\ + red=grayson_red;\ green=grayson_green;\ + blue=grayson_blue;\ rgb=grayson_rgb" /datum/robolimb/grayson_alt1 @@ -177,7 +179,8 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ desc = "This rather thick limb has a militaristic green plating." icon = 'icons/mob/human_races/cyberlimbs/hephaestus/hephaestus_alt2.dmi' unavailable_to_build = 1 - + monitor_styles = "red=athena_red;\ + blank=athena_off" /datum/robolimb/hephaestus_monitor company = "Hephaestus Monitor" @@ -266,7 +269,9 @@ var/const/standard_monitor_styles = "blank=ipc_blank;\ icon = 'icons/mob/human_races/cyberlimbs/xion/xion_alt2.dmi' unavailable_to_build = 1 monitor_styles = "blank=xion_off;\ + red=xion_red;\ green=xion_green;\ + blue=xion_blue;\ rgb=xion_rgb" /datum/robolimb/xion_alt3 diff --git a/code/modules/organs/subtypes/slime.dm b/code/modules/organs/subtypes/slime.dm index f22b90caea2..5fb54a21b45 100644 --- a/code/modules/organs/subtypes/slime.dm +++ b/code/modules/organs/subtypes/slime.dm @@ -56,3 +56,89 @@ max_damage = 30 encased = 0 spread_dam = 1 + +/* + * Internal Slime organs. + */ + +/obj/item/organ/internal/heart/grey/colormatch/slime + name = "pneumatic network" + desc = "A disgusting sac of goo." + icon_state = "sac_slime" + dead_icon = null + standard_pulse_level = PULSE_NONE + +/obj/item/organ/internal/heart/grey/colormatch/slime/process() + ..() + if(!(QDELETED(src)) && src.loc != owner) + visible_message("\The [src] splatters!") + var/turf/T = get_turf(src) + var/obj/effect/decal/cleanable/blood/B = new (T) + + B.basecolor = src.color + B.update_icon() + qdel(src) + +/obj/item/organ/internal/regennetwork + name = "pneumoregenesis network" + parent_organ = BP_TORSO + organ_tag = O_REGBRUTE + + icon_state = "sac_slime" + + var/strain = 0 // The amount of stress this organ is under. Capped at min_broken_damage, usually half its max damage. + + var/last_strain_increase = 0 // World time of the last increase in strain. + var/strain_regen_cooldown = 5 MINUTES + +/obj/item/organ/internal/regennetwork/Initialize() + ..() + var/mob/living/carbon/human/H = null + spawn(15) + if(ishuman(owner)) + H = owner + color = H.species.get_blood_colour(H) + +/obj/item/organ/internal/regennetwork/proc/get_strain_percent(var/cost) + adjust_strain(cost) + + if((status & ORGAN_CUT_AWAY) || (status & ORGAN_BROKEN) || (status & ORGAN_DEAD)) + return 1 + + return round((strain / min_broken_damage) * 10) / 10 + +/obj/item/organ/internal/regennetwork/proc/adjust_strain(var/amount) + if(amount < 0 && world.time < (last_strain_increase + strain_regen_cooldown)) + return + + else if(amount > 0) + last_strain_increase = world.time + + strain = CLAMP(strain + amount, 0, min_broken_damage) + +/obj/item/organ/internal/regennetwork/process() + ..() + + if(!(QDELETED(src)) && src.loc != owner) + visible_message("\The [src] splatters!") + var/turf/T = get_turf(src) + var/obj/effect/decal/cleanable/blood/B = new (T) + + B.basecolor = src.color + B.update_icon() + qdel(src) + + if(src && !is_bruised()) + adjust_strain(-0.25 * max(0, (min_broken_damage - damage) / min_broken_damage)) // Decrease the current strain with respect to the current strain level. + +/obj/item/organ/internal/regennetwork/burn + name = "thermoregenesis network" + organ_tag = O_REGBURN + +/obj/item/organ/internal/regennetwork/oxy + name = "respiroregenesis network" + organ_tag = O_REGOXY + +/obj/item/organ/internal/regennetwork/tox + name = "toxoregenesis network" + organ_tag = O_REGTOX diff --git a/code/modules/power/apc_vr.dm b/code/modules/power/apc_vr.dm new file mode 100644 index 00000000000..c08c9b8db04 --- /dev/null +++ b/code/modules/power/apc_vr.dm @@ -0,0 +1,9 @@ +/obj/machinery/power/apc/proc/update_area() + var/area/NA = get_area(src) + if(!(NA == area)) + if(area.apc == src) + area.apc = null + NA.apc = src + area = NA + name = "[area.name] APC" + update() \ No newline at end of file diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index d271943dcc6..ba60c84d32d 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -9,7 +9,7 @@ #define LIGHT_BROKEN 2 #define LIGHT_BURNED 3 #define LIGHT_BULB_TEMPERATURE 400 //K - used value for a 60W bulb -#define LIGHTING_POWER_FACTOR 5 //5W per luminosity * range +#define LIGHTING_POWER_FACTOR 2 //5W per luminosity * range //VOREStation Edit: why the fuck are lights eating so much power, 2W per thing var/global/list/light_type_cache = list() /proc/get_light_type_instance(var/light_type) @@ -30,13 +30,15 @@ var/global/list/light_type_cache = list() var/fixture_type = /obj/machinery/light var/sheets_refunded = 2 -/obj/machinery/light_construct/New(atom/newloc, obj/machinery/light/fixture = null) +/obj/machinery/light_construct/New(var/atom/newloc, var/newdir, var/building = 0, var/datum/frame/frame_types/frame_type, var/obj/machinery/light/fixture = null) ..(newloc) if(fixture) fixture_type = fixture.type fixture.transfer_fingerprints_to(src) set_dir(fixture.dir) stage = 2 + else if(newdir) + set_dir(newdir) update_icon() /obj/machinery/light_construct/update_icon() @@ -168,7 +170,7 @@ var/global/list/light_type_cache = list() layer = ABOVE_MOB_LAYER use_power = 2 idle_power_usage = 2 - active_power_usage = 20 // VOREStation Edit - Keep lights at 20 power + active_power_usage = 10 power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list var/on = 0 // 1 if on, 0 if off var/brightness_range @@ -218,6 +220,13 @@ var/global/list/light_type_cache = list() shows_alerts = FALSE //VOREStation Edit var/lamp_shade = 1 +/obj/machinery/light/flamp/New(atom/newloc, obj/machinery/light_construct/construct = null) + ..(newloc, construct) + + if(construct) + lamp_shade = 0 + update_icon() + /obj/machinery/light/flamp/flicker auto_flicker = TRUE @@ -380,6 +389,16 @@ var/global/list/light_type_cache = list() broken() return 1 +/obj/machinery/light/take_damage(var/damage) + if(!damage) + return + if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) + return + if(!(status == LIGHT_OK||status == LIGHT_BURNED)) + return + broken() + return 1 + /obj/machinery/light/blob_act() broken() @@ -488,7 +507,7 @@ var/global/list/light_type_cache = list() playsound(src, W.usesound, 75, 1) user.visible_message("[user.name] opens [src]'s casing.", \ "You open [src]'s casing.", "You hear a noise.") - new construct_type(src.loc, src) + new construct_type(src.loc, fixture = src) qdel(src) return diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index bbc13e381e8..7d46fcd73f7 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -180,15 +180,15 @@ if(dna_lock && attached_lock.stored_dna) if(!authorized_user(user)) if(attached_lock.safety_level == 0) - to_chat(M, "\The [src] buzzes in dissapoint and displays an invalid DNA symbol.") + to_chat(M, "\The [src] buzzes in dissapointment and displays an invalid DNA symbol.") return 0 if(!attached_lock.exploding) if(attached_lock.safety_level == 1) to_chat(M, "\The [src] hisses in dissapointment.") visible_message("\The [src] announces, \"Self-destruct occurring in ten seconds.\"", "\The [src] announces, \"Self-destruct occurring in ten seconds.\"") + attached_lock.exploding = 1 spawn(100) explosion(src, 0, 0, 3, 4) - attached_lock.exploding = 1 sleep(1) qdel(src) return 0 @@ -693,7 +693,7 @@ if (istype(in_chamber)) user.visible_message("[user] pulls the trigger.") play_fire_sound() - if(istype(in_chamber, /obj/item/projectile/beam/lastertag)) + if(istype(in_chamber, /obj/item/projectile/beam/lasertag)) user.show_message("You feel rather silly, trying to commit suicide with a toy.") mouthshoot = 0 return diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index 6d7bdfef7ad..eeb8d779d28 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -1,247 +1,261 @@ -/obj/item/weapon/gun/energy/laser - name = "laser rifle" - desc = "A Hephaestus Industries G40E rifle, designed to kill with concentrated energy blasts. This variant has the ability to \ - switch between standard fire and a more efficent but weaker 'suppressive' fire." - icon_state = "laser" - item_state = "laser" - wielded_item_state = "laser-wielded" - fire_delay = 8 - slot_flags = SLOT_BELT|SLOT_BACK - w_class = ITEMSIZE_LARGE - force = 10 - origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2) - matter = list(DEFAULT_WALL_MATERIAL = 2000) - projectile_type = /obj/item/projectile/beam/midlaser -// one_handed_penalty = 30 - - firemodes = list( - list(mode_name="normal", fire_delay=8, projectile_type=/obj/item/projectile/beam/midlaser, charge_cost = 240), - list(mode_name="suppressive", fire_delay=5, projectile_type=/obj/item/projectile/beam/weaklaser, charge_cost = 60), - ) - -/obj/item/weapon/gun/energy/laser/mounted - self_recharge = 1 - use_external_power = 1 - one_handed_penalty = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. - -/obj/item/weapon/gun/energy/laser/practice - name = "practice laser carbine" - desc = "A modified version of the HI G40E, this one fires less concentrated energy bolts designed for target practice." - projectile_type = /obj/item/projectile/beam/practice - charge_cost = 48 - - cell_type = /obj/item/weapon/cell/device - - firemodes = list( - list(mode_name="normal", projectile_type=/obj/item/projectile/beam/practice, charge_cost = 48), - list(mode_name="suppressive", projectile_type=/obj/item/projectile/beam/practice, charge_cost = 12), - ) - -/obj/item/weapon/gun/energy/retro - name = "retro laser" - icon_state = "retro" - item_state = "retro" - desc = "An older model of the basic lasergun. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws." - slot_flags = SLOT_BELT - w_class = ITEMSIZE_NORMAL - projectile_type = /obj/item/projectile/beam - fire_delay = 10 //old technology - -/obj/item/weapon/gun/energy/retro/mounted - self_recharge = 1 - use_external_power = 1 - -/obj/item/weapon/gun/energy/retro/empty - icon_state = "retro" - cell_type = null - - -/datum/category_item/catalogue/anomalous/precursor_a/alien_pistol - name = "Precursor Alpha Weapon - Appendageheld Laser" - desc = "This object strongly resembles a weapon, and if one were to pull the \ - trigger located on the handle of the object, it would fire a deadly \ - laser at whatever it was pointed at. The beam fired appears to cause too \ - much damage to whatever it would hit to have served as a long ranged repair tool, \ - therefore this object was most likely designed to be a deadly weapon. If so, this \ - has several implications towards its creators;\ -

      \ - Firstly, it implies that these precursors, at some point during their development, \ - had needed to defend themselves, or otherwise had a need to utilize violence, and \ - as such created better tools to do so. It is unclear if violence was employed against \ - themselves as a form of in-fighting, or if violence was exclusive to outside species.\ -

      \ - Secondly, the shape and design of the weapon implies that the creators of this \ - weapon were able to grasp objects, and be able to manipulate the trigger independently \ - from merely holding onto the weapon, making certain types of appendages like tentacles be \ - unlikely.\ -

      \ - An interesting note about this weapon, when compared to contemporary energy weapons, is \ - that this gun appears to be inferior to modern laser weapons. The beam fired has less \ - of an ability to harm, and the power consumption appears to be higher than average for \ - a human-made energy side-arm. One possible explaination is that the creators of this \ - weapon, in their later years, had less of a need to optimize their capability for war, \ - and instead focused on other endeavors. Another explaination is that vast age of the weapon \ - may have caused it to degrade, yet still remain functional at a reduced capability." - value = CATALOGUER_REWARD_MEDIUM - -/obj/item/weapon/gun/energy/alien - name = "alien pistol" - desc = "A weapon that works very similarly to a traditional energy weapon. How this came to be will likely be a mystery for the ages." - catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/alien_pistol) - icon_state = "alienpistol" - item_state = "alienpistol" - fire_sound = 'sound/weapons/eLuger.ogg' - fire_delay = 10 // Handguns should be inferior to two-handed weapons. Even alien ones I suppose. - charge_cost = 480 // Five shots. - - projectile_type = /obj/item/projectile/beam/cyan - cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien // Self charges. - origin_tech = list(TECH_COMBAT = 8, TECH_MAGNET = 7) - modifystate = "alienpistol" - - -/obj/item/weapon/gun/energy/captain - name = "antique laser gun" - icon_state = "caplaser" - item_state = "caplaser" - desc = "A rare weapon, handcrafted by a now defunct specialty manufacturer on Luna for a small fortune. It's certainly aged well." - force = 5 - slot_flags = SLOT_BELT - w_class = ITEMSIZE_NORMAL - projectile_type = /obj/item/projectile/beam - origin_tech = null - fire_delay = 10 //Old pistol - charge_cost = 480 //to compensate a bit for self-recharging - cell_type = /obj/item/weapon/cell/device/weapon/recharge/captain - battery_lock = 1 - -/obj/item/weapon/gun/energy/lasercannon - name = "laser cannon" - desc = "With the laser cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron \ - flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!" - icon_state = "lasercannon" - item_state = null - origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3) - slot_flags = SLOT_BELT|SLOT_BACK - projectile_type = /obj/item/projectile/beam/heavylaser/cannon - battery_lock = 1 - fire_delay = 20 - w_class = ITEMSIZE_LARGE -// one_handed_penalty = 90 // The thing's heavy and huge. - accuracy = 45 - charge_cost = 600 - -/obj/item/weapon/gun/energy/lasercannon/mounted - name = "mounted laser cannon" - self_recharge = 1 - use_external_power = 1 - recharge_time = 10 - accuracy = 0 // Mounted cannons are just fine the way they are. - one_handed_penalty = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. - projectile_type = /obj/item/projectile/beam/heavylaser - charge_cost = 400 - fire_delay = 20 - -/obj/item/weapon/gun/energy/xray - name = "xray laser gun" - desc = "A high-power laser gun capable of expelling concentrated xray blasts, which are able to penetrate matter easier than \ - standard photonic beams, resulting in an effective 'anti-armor' energy weapon." - icon_state = "xray" - item_state = "xray" - origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 3, TECH_MAGNET = 2) - projectile_type = /obj/item/projectile/beam/xray - charge_cost = 200 - -/obj/item/weapon/gun/energy/sniperrifle - name = "marksman energy rifle" - desc = "The HI DMR 9E is an older design of Hephaestus Industries. A designated marksman rifle capable of shooting powerful \ - ionized beams, this is a weapon to kill from a distance." - icon_state = "sniper" - item_state = "sniper" - item_state_slots = list(slot_r_hand_str = "z8carbine", slot_l_hand_str = "z8carbine") //placeholder - origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 5, TECH_POWER = 4) - projectile_type = /obj/item/projectile/beam/sniper - slot_flags = SLOT_BACK - battery_lock = 1 - charge_cost = 600 - fire_delay = 35 - force = 10 - w_class = ITEMSIZE_HUGE // So it can't fit in a backpack. - accuracy = -45 //shooting at the hip - scoped_accuracy = 0 -// requires_two_hands = 1 -// one_handed_penalty = 60 // The weapon itself is heavy, and the long barrel makes it hard to hold steady with just one hand. - -/obj/item/weapon/gun/energy/sniperrifle/verb/scope() - set category = "Object" - set name = "Use Scope" - set popup_menu = 1 - - toggle_scope(2.0) - -/obj/item/weapon/gun/energy/monorifle - name = "antique mono-rifle" - desc = "An old laser rifle. This one can only fire once before requiring recharging." - description_fluff = "Modeled after ancient hunting rifles, this rifle was dubbed the 'Rainy Day Special' by some, due to its use as some barmens' fight-stopper of choice. One shot is all it takes, or so they say." - icon_state = "eshotgun" - item_state = "shotgun" - origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_POWER = 3) - projectile_type = /obj/item/projectile/beam/sniper - slot_flags = SLOT_BACK - charge_cost = 1300 - fire_delay = 20 - force = 8 - w_class = ITEMSIZE_LARGE - accuracy = 10 - scoped_accuracy = 15 - var/scope_multiplier = 1.5 - -/obj/item/weapon/gun/energy/monorifle/verb/sights() - set category = "Object" - set name = "Aim Down Sights" - set popup_menu = 1 - - toggle_scope(scope_multiplier) - -/obj/item/weapon/gun/energy/monorifle/combat - name = "combat mono-rifle" - desc = "A modernized version of the mono-rifle. This one can fire twice before requiring recharging." - description_fluff = "A modern design produced by a company once working from Saint Columbia, based on the antique mono-rifle 'Rainy Day Special' design." - icon_state = "ecshotgun" - item_state = "cshotgun" - charge_cost = 1000 - force = 12 - accuracy = 0 - scoped_accuracy = 20 - -////////Laser Tag//////////////////// - -/obj/item/weapon/gun/energy/lasertag - name = "laser tag gun" - item_state = "laser" - desc = "Standard issue weapon of the Imperial Guard" - origin_tech = list(TECH_COMBAT = 1, TECH_MAGNET = 2) - matter = list(DEFAULT_WALL_MATERIAL = 2000) - projectile_type = /obj/item/projectile/beam/lastertag/blue - cell_type = /obj/item/weapon/cell/device/weapon/recharge - battery_lock = 1 - var/required_vest - -/obj/item/weapon/gun/energy/lasertag/special_check(var/mob/living/carbon/human/M) - if(ishuman(M)) - if(!istype(M.wear_suit, required_vest)) - M << "You need to be wearing your laser tag vest!" - return 0 - return ..() - -/obj/item/weapon/gun/energy/lasertag/blue - icon_state = "bluetag" - item_state = "bluetag" - projectile_type = /obj/item/projectile/beam/lastertag/blue - required_vest = /obj/item/clothing/suit/bluetag - -/obj/item/weapon/gun/energy/lasertag/red - icon_state = "redtag" - item_state = "redtag" - projectile_type = /obj/item/projectile/beam/lastertag/red - required_vest = /obj/item/clothing/suit/redtag +/obj/item/weapon/gun/energy/laser + name = "laser rifle" + desc = "A Hephaestus Industries G40E rifle, designed to kill with concentrated energy blasts. This variant has the ability to \ + switch between standard fire and a more efficent but weaker 'suppressive' fire." + icon_state = "laser" + item_state = "laser" + wielded_item_state = "laser-wielded" + fire_delay = 8 + slot_flags = SLOT_BELT|SLOT_BACK + w_class = ITEMSIZE_LARGE + force = 10 + origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2) + matter = list(DEFAULT_WALL_MATERIAL = 2000) + projectile_type = /obj/item/projectile/beam/midlaser +// one_handed_penalty = 30 + + firemodes = list( + list(mode_name="normal", fire_delay=8, projectile_type=/obj/item/projectile/beam/midlaser, charge_cost = 240), + list(mode_name="suppressive", fire_delay=5, projectile_type=/obj/item/projectile/beam/weaklaser, charge_cost = 60), + ) + +/obj/item/weapon/gun/energy/laser/mounted + self_recharge = 1 + use_external_power = 1 + one_handed_penalty = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. + +/obj/item/weapon/gun/energy/laser/practice + name = "practice laser carbine" + desc = "A modified version of the HI G40E, this one fires less concentrated energy bolts designed for target practice." + projectile_type = /obj/item/projectile/beam/practice + charge_cost = 48 + + cell_type = /obj/item/weapon/cell/device + + firemodes = list( + list(mode_name="normal", projectile_type=/obj/item/projectile/beam/practice, charge_cost = 48), + list(mode_name="suppressive", projectile_type=/obj/item/projectile/beam/practice, charge_cost = 12), + ) + +/obj/item/weapon/gun/energy/retro + name = "retro laser" + icon_state = "retro" + item_state = "retro" + desc = "An older model of the basic lasergun. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws." + slot_flags = SLOT_BELT + w_class = ITEMSIZE_NORMAL + projectile_type = /obj/item/projectile/beam + fire_delay = 10 //old technology + +/obj/item/weapon/gun/energy/retro/mounted + self_recharge = 1 + use_external_power = 1 + +/obj/item/weapon/gun/energy/retro/empty + icon_state = "retro" + cell_type = null + + +/datum/category_item/catalogue/anomalous/precursor_a/alien_pistol + name = "Precursor Alpha Weapon - Appendageheld Laser" + desc = "This object strongly resembles a weapon, and if one were to pull the \ + trigger located on the handle of the object, it would fire a deadly \ + laser at whatever it was pointed at. The beam fired appears to cause too \ + much damage to whatever it would hit to have served as a long ranged repair tool, \ + therefore this object was most likely designed to be a deadly weapon. If so, this \ + has several implications towards its creators;\ +

      \ + Firstly, it implies that these precursors, at some point during their development, \ + had needed to defend themselves, or otherwise had a need to utilize violence, and \ + as such created better tools to do so. It is unclear if violence was employed against \ + themselves as a form of in-fighting, or if violence was exclusive to outside species.\ +

      \ + Secondly, the shape and design of the weapon implies that the creators of this \ + weapon were able to grasp objects, and be able to manipulate the trigger independently \ + from merely holding onto the weapon, making certain types of appendages like tentacles be \ + unlikely.\ +

      \ + An interesting note about this weapon, when compared to contemporary energy weapons, is \ + that this gun appears to be inferior to modern laser weapons. The beam fired has less \ + of an ability to harm, and the power consumption appears to be higher than average for \ + a human-made energy side-arm. One possible explaination is that the creators of this \ + weapon, in their later years, had less of a need to optimize their capability for war, \ + and instead focused on other endeavors. Another explaination is that vast age of the weapon \ + may have caused it to degrade, yet still remain functional at a reduced capability." + value = CATALOGUER_REWARD_MEDIUM + +/obj/item/weapon/gun/energy/alien + name = "alien pistol" + desc = "A weapon that works very similarly to a traditional energy weapon. How this came to be will likely be a mystery for the ages." + catalogue_data = list(/datum/category_item/catalogue/anomalous/precursor_a/alien_pistol) + icon_state = "alienpistol" + item_state = "alienpistol" + fire_delay = 10 // Handguns should be inferior to two-handed weapons. Even alien ones I suppose. + charge_cost = 480 // Five shots. + + projectile_type = /obj/item/projectile/beam/cyan + cell_type = /obj/item/weapon/cell/device/weapon/recharge/alien // Self charges. + origin_tech = list(TECH_COMBAT = 8, TECH_MAGNET = 7) + modifystate = "alienpistol" + + +/obj/item/weapon/gun/energy/captain + name = "antique laser gun" + icon_state = "caplaser" + item_state = "caplaser" + desc = "A rare weapon, handcrafted by a now defunct specialty manufacturer on Luna for a small fortune. It's certainly aged well." + force = 5 + slot_flags = SLOT_BELT + w_class = ITEMSIZE_NORMAL + projectile_type = /obj/item/projectile/beam + origin_tech = null + fire_delay = 10 //Old pistol + charge_cost = 480 //to compensate a bit for self-recharging + cell_type = /obj/item/weapon/cell/device/weapon/recharge/captain + battery_lock = 1 + +/obj/item/weapon/gun/energy/lasercannon + name = "laser cannon" + desc = "With the laser cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron \ + flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!" + icon_state = "lasercannon" + item_state = null + origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3) + slot_flags = SLOT_BELT|SLOT_BACK + projectile_type = /obj/item/projectile/beam/heavylaser/cannon + battery_lock = 1 + fire_delay = 20 + w_class = ITEMSIZE_LARGE +// one_handed_penalty = 90 // The thing's heavy and huge. + accuracy = 45 + charge_cost = 600 + +/obj/item/weapon/gun/energy/lasercannon/mounted + name = "mounted laser cannon" + self_recharge = 1 + use_external_power = 1 + recharge_time = 10 + accuracy = 0 // Mounted cannons are just fine the way they are. + one_handed_penalty = 0 // Not sure if two-handing gets checked for mounted weapons, but better safe than sorry. + projectile_type = /obj/item/projectile/beam/heavylaser + charge_cost = 400 + fire_delay = 20 + +/obj/item/weapon/gun/energy/xray + name = "xray laser gun" + desc = "A high-power laser gun capable of expelling concentrated xray blasts, which are able to penetrate matter easier than \ + standard photonic beams, resulting in an effective 'anti-armor' energy weapon." + icon_state = "xray" + item_state = "xray" + origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 3, TECH_MAGNET = 2) + projectile_type = /obj/item/projectile/beam/xray + charge_cost = 200 + +/obj/item/weapon/gun/energy/sniperrifle + name = "marksman energy rifle" + desc = "The HI DMR 9E is an older design of Hephaestus Industries. A designated marksman rifle capable of shooting powerful \ + ionized beams, this is a weapon to kill from a distance." + icon_state = "sniper" + item_state = "sniper" + item_state_slots = list(slot_r_hand_str = "z8carbine", slot_l_hand_str = "z8carbine") //placeholder + origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 5, TECH_POWER = 4) + projectile_type = /obj/item/projectile/beam/sniper + slot_flags = SLOT_BACK + battery_lock = 1 + charge_cost = 600 + fire_delay = 35 + force = 10 + w_class = ITEMSIZE_HUGE // So it can't fit in a backpack. + accuracy = -45 //shooting at the hip + scoped_accuracy = 0 +// requires_two_hands = 1 +// one_handed_penalty = 60 // The weapon itself is heavy, and the long barrel makes it hard to hold steady with just one hand. + +/obj/item/weapon/gun/energy/sniperrifle/verb/scope() + set category = "Object" + set name = "Use Scope" + set popup_menu = 1 + + toggle_scope(2.0) + +/obj/item/weapon/gun/energy/monorifle + name = "antique mono-rifle" + desc = "An old laser rifle. This one can only fire once before requiring recharging." + description_fluff = "Modeled after ancient hunting rifles, this rifle was dubbed the 'Rainy Day Special' by some, due to its use as some barmens' fight-stopper of choice. One shot is all it takes, or so they say." + icon_state = "eshotgun" + item_state = "shotgun" + origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 4, TECH_POWER = 3) + projectile_type = /obj/item/projectile/beam/sniper + slot_flags = SLOT_BACK + charge_cost = 1300 + fire_delay = 20 + force = 8 + w_class = ITEMSIZE_LARGE + accuracy = 10 + scoped_accuracy = 15 + var/scope_multiplier = 1.5 + +/obj/item/weapon/gun/energy/monorifle/verb/sights() + set category = "Object" + set name = "Aim Down Sights" + set popup_menu = 1 + + toggle_scope(scope_multiplier) + +/obj/item/weapon/gun/energy/monorifle/combat + name = "combat mono-rifle" + desc = "A modernized version of the mono-rifle. This one can fire twice before requiring recharging." + description_fluff = "A modern design produced by a company once working from Saint Columbia, based on the antique mono-rifle 'Rainy Day Special' design." + icon_state = "ecshotgun" + item_state = "cshotgun" + charge_cost = 1000 + force = 12 + accuracy = 0 + scoped_accuracy = 20 + +////////Laser Tag//////////////////// + +/obj/item/weapon/gun/energy/lasertag + name = "laser tag gun" + item_state = "laser" + desc = "Standard issue weapon of the Imperial Guard" + origin_tech = list(TECH_COMBAT = 1, TECH_MAGNET = 2) + matter = list(DEFAULT_WALL_MATERIAL = 2000) + projectile_type = /obj/item/projectile/beam/lasertag/blue + cell_type = /obj/item/weapon/cell/device/weapon/recharge + battery_lock = 1 + var/required_vest + +/obj/item/weapon/gun/energy/lasertag/special_check(var/mob/living/carbon/human/M) + if(ishuman(M)) + if(!istype(M.wear_suit, required_vest)) + M << "You need to be wearing your laser tag vest!" + return 0 + return ..() + +/obj/item/weapon/gun/energy/lasertag/blue + icon_state = "bluetag" + item_state = "bluetag" + projectile_type = /obj/item/projectile/beam/lasertag/blue + required_vest = /obj/item/clothing/suit/bluetag + +/obj/item/weapon/gun/energy/lasertag/red + icon_state = "redtag" + item_state = "redtag" + projectile_type = /obj/item/projectile/beam/lasertag/red + required_vest = /obj/item/clothing/suit/redtag + +/obj/item/weapon/gun/energy/lasertag/omni + projectile_type = /obj/item/projectile/beam/lasertag/omni + +// Laser scattergun, proof of concept. + +/obj/item/weapon/gun/energy/lasershotgun + name = "laser scattergun" + icon = 'icons/obj/energygun.dmi' + item_state = "laser" + icon_state = "scatter" + desc = "A strange Almachi weapon, utilizing a refracting prism to turn a single laser blast into a diverging cluster." + origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 1, TECH_MATERIAL = 4) + + projectile_type = /obj/item/projectile/scatter/laser \ No newline at end of file diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 85d8d5ecdf5..ee04e27653c 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -109,6 +109,8 @@ obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() options["H&K PT"] = "detective_panther" options["Vintage LeMat"] = "lemat_old" options["Webley MKVI "] = "webley" + options["Lombardi Buzzard"] = "detective_buzzard" + options["Constable Deluxe 2502"] = "detective_constable" var/choice = input(M,"Choose your sprite!","Resprite Gun") in options if(src && choice && !M.stat && in_range(M,src)) icon_state = options[choice] @@ -275,4 +277,4 @@ obj/item/weapon/gun/projectile/revolver/detective45/verb/rename_gun() desc = "A shiny Mosley Autococker automatic revolver, with black accents. Marketed as the 'Revolver for the Modern Era'. Uses .44 magnum rounds." fire_delay = 5.7 //Autorevolver. Also synced with the animation fire_anim = "mosley_fire" - origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) \ No newline at end of file + origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 2) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index e180ac271c8..0eaf2d2f425 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -84,8 +84,17 @@ var/accuracy = 0 var/dispersion = 0.0 + // Sub-munitions. Basically, multi-projectile shotgun, rather than pellets. + var/use_submunitions = FALSE + var/only_submunitions = FALSE // Will the projectile delete itself after firing the submunitions? + var/list/submunitions = list() // Assoc list of the paths of any submunitions, and how many they are. [projectilepath] = [projectilecount]. + var/submunition_spread_max = 30 // Divided by 10 to get the percentile dispersion. + var/submunition_spread_min = 5 // Above. + var/force_max_submunition_spread = FALSE // Do we just force the maximum? + var/spread_submunition_damage = FALSE // Do we assign damage to our sub projectiles based on our main projectile damage? + var/damage = 10 - var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS are the only things that should be in here + var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS, ELECTROCUTE, BIOACID are the only things that should be in here var/SA_bonus_damage = 0 // Some bullets inflict extra damage on simple animals. var/SA_vulnerability = null // What kind of simple animal the above bonus damage should be applied to. Set to null to apply to all SAs. var/nodamage = 0 //Determines if the projectile will skip any damage inflictions @@ -346,10 +355,18 @@ /obj/item/projectile/proc/preparePixelProjectile(atom/target, atom/source, params, spread = 0) var/turf/curloc = get_turf(source) var/turf/targloc = get_turf(target) + + if(istype(source, /atom/movable)) + var/atom/movable/MT = source + if(MT.locs && MT.locs.len) // Multi tile! + for(var/turf/T in MT.locs) + if(get_dist(T, target) < get_turf(curloc)) + curloc = get_turf(T) + trajectory_ignore_forcemove = TRUE forceMove(get_turf(source)) trajectory_ignore_forcemove = FALSE - starting = get_turf(source) + starting = curloc original = target if(targloc || !params) yo = targloc.y - curloc.y @@ -641,6 +658,37 @@ if(get_turf(target) == get_turf(src)) direct_target = target + if(use_submunitions && submunitions.len) + var/temp_min_spread = 0 + if(force_max_submunition_spread) + temp_min_spread = submunition_spread_max + else + temp_min_spread = submunition_spread_min + + var/damage_override = null + + if(spread_submunition_damage) + damage_override = damage + if(nodamage) + damage_override = 0 + + var/projectile_count = 0 + + for(var/proj in submunitions) + projectile_count += submunitions[proj] + + damage_override = round(damage_override / max(1, projectile_count)) + + for(var/path in submunitions) + for(var/count = 1 to submunitions[path]) + var/obj/item/projectile/SM = new path(get_turf(loc)) + SM.shot_from = shot_from + SM.silenced = silenced + SM.dispersion = rand(temp_min_spread, submunition_spread_max) / 10 + if(!isnull(damage_override)) + SM.damage = damage_override + SM.launch_projectile(target, target_zone, user, params, angle_override) + preparePixelProjectile(target, user? user : get_turf(src), params, forced_spread) return fire(angle_override, direct_target) @@ -651,3 +699,45 @@ silenced = launcher.silenced return launch_projectile(target, target_zone, user, params, angle_override, forced_spread) + +/obj/item/projectile/proc/launch_projectile_from_turf(atom/target, target_zone, mob/user, params, angle_override, forced_spread = 0) + original = target + def_zone = check_zone(target_zone) + firer = user + var/direct_target + if(get_turf(target) == get_turf(src)) + direct_target = target + + if(use_submunitions && submunitions.len) + var/temp_min_spread = 0 + if(force_max_submunition_spread) + temp_min_spread = submunition_spread_max + else + temp_min_spread = submunition_spread_min + + var/damage_override = null + + if(spread_submunition_damage) + damage_override = damage + if(nodamage) + damage_override = 0 + + var/projectile_count = 0 + + for(var/proj in submunitions) + projectile_count += submunitions[proj] + + damage_override = round(damage_override / max(1, projectile_count)) + + for(var/path in submunitions) + for(var/count = 1 to submunitions[path]) + var/obj/item/projectile/SM = new path(get_turf(loc)) + SM.shot_from = shot_from + SM.silenced = silenced + SM.dispersion = rand(temp_min_spread, submunition_spread_max) / 10 + if(!isnull(damage_override)) + SM.damage = damage_override + SM.launch_projectile_from_turf(target, target_zone, user, params, angle_override) + + preparePixelProjectile(target, get_turf(src), params, forced_spread) + return fire(angle_override, direct_target) diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 9073ead8317..ec2670c61d2 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -63,7 +63,7 @@ icon_state = "emitter" fire_sound = 'sound/weapons/emitter.ogg' light_color = "#00CC33" - excavation_amount = 70 // 3 shots to mine a turf + excavation_amount = 140 // 2 shots to dig a standard rock turf. Superior due to being a mounted tool beam, to make it actually viable. muzzle_type = /obj/effect/projectile/muzzle/emitter tracer_type = /obj/effect/projectile/tracer/emitter @@ -89,6 +89,7 @@ /obj/item/projectile/beam/cyan name = "cyan beam" icon_state = "cyan" + fire_sound = 'sound/weapons/eluger.ogg' damage = 40 light_color = "#00C6FF" @@ -125,62 +126,52 @@ tracer_type = /obj/effect/projectile/tracer/emitter impact_type = /obj/effect/projectile/impact/emitter -/obj/item/projectile/beam/lastertag/blue +/obj/item/projectile/beam/lasertag name = "lasertag beam" - icon_state = "bluelaser" damage = 0 + eyeblur = 0 no_attack_log = 1 damage_type = BURN check_armour = "laser" - light_color = "#0066FF" combustion = FALSE +/obj/item/projectile/beam/lasertag/blue + icon_state = "bluelaser" + light_color = "#0066FF" + muzzle_type = /obj/effect/projectile/muzzle/laser_blue tracer_type = /obj/effect/projectile/tracer/laser_blue impact_type = /obj/effect/projectile/impact/laser_blue -/obj/item/projectile/beam/lastertag/blue/on_hit(var/atom/target, var/blocked = 0) - if(istype(target, /mob/living/carbon/human)) +/obj/item/projectile/beam/lasertag/blue/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) var/mob/living/carbon/human/M = target if(istype(M.wear_suit, /obj/item/clothing/suit/redtag)) M.Weaken(5) return 1 -/obj/item/projectile/beam/lastertag/red - name = "lasertag beam" +/obj/item/projectile/beam/lasertag/red icon_state = "laser" - damage = 0 - no_attack_log = 1 - damage_type = BURN - check_armour = "laser" light_color = "#FF0D00" - combustion = FALSE - -/obj/item/projectile/beam/lastertag/red/on_hit(var/atom/target, var/blocked = 0) - if(istype(target, /mob/living/carbon/human)) +/obj/item/projectile/beam/lasertag/red/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) var/mob/living/carbon/human/M = target if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag)) M.Weaken(5) return 1 -/obj/item/projectile/beam/lastertag/omni//A laser tag bolt that stuns EVERYONE - name = "lasertag beam" +/obj/item/projectile/beam/lasertag/omni//A laser tag bolt that stuns EVERYONE icon_state = "omnilaser" - damage = 0 - damage_type = BURN - check_armour = "laser" light_color = "#00C6FF" - combustion = FALSE - muzzle_type = /obj/effect/projectile/muzzle/laser_omni tracer_type = /obj/effect/projectile/tracer/laser_omni impact_type = /obj/effect/projectile/impact/laser_omni -/obj/item/projectile/beam/lastertag/omni/on_hit(var/atom/target, var/blocked = 0) - if(istype(target, /mob/living/carbon/human)) +/obj/item/projectile/beam/lasertag/omni/on_hit(var/atom/target, var/blocked = 0) + if(ishuman(target)) var/mob/living/carbon/human/M = target if((istype(M.wear_suit, /obj/item/clothing/suit/bluetag))||(istype(M.wear_suit, /obj/item/clothing/suit/redtag))) M.Weaken(5) @@ -222,4 +213,17 @@ /obj/item/projectile/beam/stun/med name = "stun beam" icon_state = "stun" - agony = 30 \ No newline at end of file + agony = 30 + +/obj/item/projectile/beam/shock + name = "shock beam" + icon_state = "lightning" + damage_type = ELECTROCUTE + + muzzle_type = /obj/effect/projectile/muzzle/lightning + tracer_type = /obj/effect/projectile/tracer/lightning + impact_type = /obj/effect/projectile/impact/lightning + + damage = 30 + agony = 15 + eyeblur = 2 diff --git a/code/modules/projectiles/projectile/scatter.dm b/code/modules/projectiles/projectile/scatter.dm new file mode 100644 index 00000000000..0aa6ad57198 --- /dev/null +++ b/code/modules/projectiles/projectile/scatter.dm @@ -0,0 +1,62 @@ + +/* + * Home of the purely submunition projectiles. + */ + +/obj/item/projectile/scatter + name = "scatter projectile" + icon = 'icons/obj/projectiles.dmi' + icon_state = "bullet" + density = FALSE + anchored = TRUE + unacidable = TRUE + pass_flags = PASSTABLE + mouse_opacity = 0 + + use_submunitions = TRUE + + damage = 8 + spread_submunition_damage = TRUE + only_submunitions = TRUE + range = 0 // Immediately deletes itself after firing, as its only job is to fire other projectiles. + + submunition_spread_max = 30 + submunition_spread_min = 2 + + submunitions = list( + /obj/item/projectile/bullet/pellet/shotgun/flak = 3 + ) + +/obj/item/projectile/scatter/laser + damage = 40 + + submunition_spread_max = 40 + submunition_spread_min = 10 + + submunitions = list( + /obj/item/projectile/beam/prismatic = 4 + ) + +/obj/item/projectile/beam/prismatic + name = "prismatic beam" + icon_state = "omnilaser" + damage = 10 + damage_type = BURN + check_armour = "laser" + light_color = "#00C6FF" + + stutter = 2 + + muzzle_type = /obj/effect/projectile/muzzle/laser_omni + tracer_type = /obj/effect/projectile/tracer/laser_omni + impact_type = /obj/effect/projectile/impact/laser_omni + +/obj/item/projectile/scatter/ion + damage = 20 + + submunition_spread_max = 40 + submunition_spread_min = 10 + + submunitions = list( + /obj/item/projectile/bullet/shotgun/ion = 3 + ) diff --git a/code/modules/projectiles/targeting/targeting_gun.dm b/code/modules/projectiles/targeting/targeting_gun.dm index e2ef466255e..3b806582262 100644 --- a/code/modules/projectiles/targeting/targeting_gun.dm +++ b/code/modules/projectiles/targeting/targeting_gun.dm @@ -17,5 +17,7 @@ user.face_atom(A) if(ismob(A) && user.aiming) user.aiming.aim_at(A, src) + if(!isliving(A)) + return 0 return 1 return 0 \ No newline at end of file diff --git a/code/modules/reagents/Chemistry-Machinery.dm b/code/modules/reagents/Chemistry-Machinery.dm index dee4cabfa69..a481cfaf337 100644 --- a/code/modules/reagents/Chemistry-Machinery.dm +++ b/code/modules/reagents/Chemistry-Machinery.dm @@ -281,6 +281,28 @@ var/obj/item/weapon/reagent_containers/food/condiment/P = new/obj/item/weapon/reagent_containers/food/condiment(src.loc) reagents.trans_to_obj(P,50) + else if (href_list["createpatch"]) + if(reagents.total_volume < 1) //Sanity checking. + return + + var/name = sanitizeSafe(input(usr,"Name:","Name your patch!","[reagents.get_master_reagent_name()] ([round(reagents.total_volume)]u)") as null|text, MAX_NAME_LEN) + + if(!name) //Blank name (sanitized to nothing, or left empty) or cancel + return + + if(reagents.total_volume < 1) //Sanity checking. + return + var/obj/item/weapon/reagent_containers/pill/patch/P = new/obj/item/weapon/reagent_containers/pill/patch(src.loc) + if(!name) name = reagents.get_master_reagent_name() + P.name = "[name] patch" + P.pixel_x = rand(-7, 7) //random position + P.pixel_y = rand(-7, 7) + + reagents.trans_to_obj(P, 60) + if(src.loaded_pill_bottle) + if(loaded_pill_bottle.contents.len < loaded_pill_bottle.max_storage_space) + P.loc = loaded_pill_bottle + else if(href_list["pill_sprite"]) pillsprite = href_list["pill_sprite"] else if(href_list["bottle_sprite"]) diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm index 13edff9fc73..48afe19b7e7 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Food-Drinks.dm @@ -127,6 +127,14 @@ M.sleeping = max(M.sleeping, 20) M.drowsyness = max(M.drowsyness, 60) +/datum/reagent/nutriment/mayo + name = "mayonnaise" + id = "mayo" + description = "A thick, bitter sauce." + taste_description = "unmistakably mayonnaise" + nutriment_factor = 10 + color = "#FFFFFF" + /datum/reagent/nutriment/flour name = "Flour" id = "flour" @@ -140,6 +148,24 @@ if(!istype(T, /turf/space)) new /obj/effect/decal/cleanable/flour(T) +/datum/reagent/nutriment/coffee + name = "Coffee Powder" + id = "coffeepowder" + description = "A bitter powder made by grinding coffee beans." + taste_description = "bitterness" + taste_mult = 1.3 + nutriment_factor = 1 + color = "#482000" + +/datum/reagent/nutriment/tea + name = "Tea Powder" + id = "teapowder" + description = "A dark, tart powder made from black tea leaves." + taste_description = "tartness" + taste_mult = 1.3 + nutriment_factor = 1 + color = "#101000" + /datum/reagent/nutriment/coco name = "Coco Powder" id = "coco" @@ -150,6 +176,41 @@ nutriment_factor = 5 color = "#302000" +/datum/reagent/nutriment/instantjuice + name = "Juice Powder" + id = "instantjuice" + description = "Dehydrated, powdered juice of some kind." + taste_mult = 1.3 + nutriment_factor = 1 + +/datum/reagent/nutriment/instantjuice/grape + name = "Grape Juice Powder" + id = "instantgrape" + description = "Dehydrated, powdered grape juice." + taste_description = "dry grapes" + color = "#863333" + +/datum/reagent/nutriment/instantjuice/orange + name = "Orange Juice Powder" + id = "instantorange" + description = "Dehydrated, powdered orange juice." + taste_description = "dry oranges" + color = "#e78108" + +/datum/reagent/nutriment/instantjuice/watermelon + name = "Watermelon Juice Powder" + id = "instantwatermelon" + description = "Dehydrated, powdered watermelon juice." + taste_description = "dry sweet watermelon" + color = "#b83333" + +/datum/reagent/nutriment/instantjuice/apple + name = "Apple Juice Powder" + id = "instantapple" + description = "Dehydrated, powdered apple juice." + taste_description = "dry sweet apples" + color = "#c07c40" + /datum/reagent/nutriment/soysauce name = "Soysauce" id = "soysauce" @@ -214,6 +275,76 @@ if(volume >= 3) T.wet_floor() +/datum/reagent/nutriment/peanutoil + name = "Peanut Oil" + id = "peanutoil" + description = "An oil derived from various types of nuts." + taste_description = "nuts" + taste_mult = 0.3 + reagent_state = LIQUID + nutriment_factor = 15 + color = "#4F3500" + +/datum/reagent/nutriment/peanutoil/touch_turf(var/turf/simulated/T) + if(!istype(T)) + return + + var/hotspot = (locate(/obj/fire) in T) + if(hotspot && !istype(T, /turf/space)) + var/datum/gas_mixture/lowertemp = T.remove_air(T:air:total_moles) + lowertemp.temperature = max(min(lowertemp.temperature-2000, lowertemp.temperature / 2), 0) + lowertemp.react() + T.assume_air(lowertemp) + qdel(hotspot) + + if(volume >= 5) + T.wet_floor() + +/datum/reagent/nutriment/peanutbutter + name = "Peanut Butter" + id = "peanutbutter" + description = "A butter derived from various types of nuts." + taste_description = "peanuts" + taste_mult = 0.5 + reagent_state = LIQUID + nutriment_factor = 30 + color = "#4F3500" + +/datum/reagent/nutriment/vanilla + name = "Vanilla Extract" + id = "vanilla" + description = "Vanilla extract. Tastes suspiciously like boring ice-cream." + taste_description = "vanilla" + taste_mult = 5 + reagent_state = LIQUID + nutriment_factor = 2 + color = "#0F0A00" + +/datum/reagent/nutriment/durian + name = "Durian Paste" + id = "durianpaste" + description = "A strangely sweet and savory paste." + taste_description = "sweet and savory" + color = "#757631" + + glass_name = "durian paste" + glass_desc = "Durian paste. It smells horrific." + +/datum/reagent/nutriment/durian/touch_mob(var/mob/M, var/amount) + if(iscarbon(M) && !M.isSynthetic()) + var/message = pick("Oh god, it smells disgusting here.", "What is that stench?", "That's an awful odor.") + to_chat(M,"[message]") + if(prob(CLAMP(amount, 5, 90))) + var/mob/living/L = M + L.vomit() + return ..() + +/datum/reagent/nutriment/durian/touch_turf(var/turf/T, var/amount) + if(istype(T)) + var/obj/effect/decal/cleanable/chemcoating/C = new /obj/effect/decal/cleanable/chemcoating(T) + C.reagents.add_reagent(id, amount) + return ..() + /datum/reagent/nutriment/virus_food name = "Virus Food" id = "virusfood" @@ -559,6 +690,16 @@ glass_name = "berry juice" glass_desc = "Berry juice. Or maybe it's jam. Who cares?" +/datum/reagent/drink/juice/pineapple + name = "Pineapple Juice" + id = "pineapplejuice" + description = "A sour but refreshing juice from a pineapple." + taste_description = "pineapple" + color = "#C3AF00" + + glass_name = "pineapple juice" + glass_desc = "Pineapple juice. Or maybe it's spineapple. Who cares?" + /datum/reagent/drink/juice/carrot name = "Carrot juice" id = "carrotjuice" @@ -1080,6 +1221,42 @@ glass_desc = "Oh the nostalgia..." glass_special = list(DRINK_FIZZ) +/datum/reagent/drink/soda/melonade + name = "Melonade" + id = "melonade" + description = "Oh the.. nostalgia?" + taste_description = "watermelon" + color = "#FFB3BB" + adj_temp = -5 + + glass_name = "melonade" + glass_desc = "Oh the.. nostalgia?" + glass_special = list(DRINK_FIZZ) + +/datum/reagent/drink/soda/appleade + name = "Appleade" + id = "appleade" + description = "Applejuice, improved." + taste_description = "apples" + color = "#FFD1B3" + adj_temp = -5 + + glass_name = "appleade" + glass_desc = "Applejuice, improved." + glass_special = list(DRINK_FIZZ) + +/datum/reagent/drink/soda/pineappleade + name = "Pineappleade" + id = "pineappleade" + description = "Spineapple, juiced up." + taste_description = "sweet`n`sour pineapples" + color = "#FFFF00" + adj_temp = -5 + + glass_name = "pineappleade" + glass_desc = "Spineapple, juiced up." + glass_special = list(DRINK_FIZZ) + /datum/reagent/drink/soda/kiraspecial name = "Kira Special" id = "kiraspecial" @@ -1175,6 +1352,16 @@ /datum/reagent/drink/milkshake/coffeeshake/overdose(var/mob/living/carbon/M, var/alien) M.make_jittery(5) +/datum/reagent/drink/milkshake/peanutshake + name = "Peanut Milkshake" + id = "peanutmilkshake" + description = "Savory cream in an ice-cold stature." + taste_description = "cold peanuts and cream" + color = "#8e6f44" + + glass_name = "Peanut Milkshake" + glass_desc = "Savory cream in an ice-cold stature." + /datum/reagent/drink/rewriter name = "Rewriter" id = "rewriter" @@ -1217,6 +1404,7 @@ description = "Made in the modern day with proper pomegranate substitute. Who uses real fruit, anyways?" taste_description = "100% pure pomegranate" color = "#FF004F" + water_based = FALSE glass_name = "grenadine syrup" glass_desc = "Sweet and tangy, a bar syrup used to add color or flavor to drinks." @@ -1285,7 +1473,6 @@ glass_desc = "A tangy substance made of 0.5% natural citrus!" glass_special = list(DRINK_FIZZ) - /datum/reagent/drink/soda/gingerale name = "Ginger Ale" id = "gingerale" @@ -1509,6 +1696,18 @@ glass_desc = "A concoction that should probably be in an engine, rather than your stomach." glass_icon = DRINK_ICON_NOISY +/datum/reagent/drink/slimeslammer + name = "Slick Slimes Slammer" + id = "slimeslammer" + description = "A viscous, but savory, ooze." + taste_description = "peanuts`n`slime" + color = "#93604D" + water_based = FALSE + + glass_name = "Slick Slime Slammer" + glass_desc = "A concoction that should probably be in an engine, rather than your stomach. Still." + glass_icon = DRINK_ICON_NOISY + /datum/reagent/drink/eggnog name = "Eggnog" id = "eggnog" @@ -1575,6 +1774,73 @@ if(D.water_based) M.adjustToxLoss(removed * -2) +/datum/reagent/drink/mojito + name = "Mojito" + id = "virginmojito" + description = "Mint, bubbly water, and citrus, made for sailing." + taste_description = "mint and lime" + color = "#FFF7B3" + + glass_name = "mojito" + glass_desc = "Mint, bubbly water, and citrus, made for sailing." + glass_special = list(DRINK_FIZZ) + +/datum/reagent/drink/sexonthebeach + name = "Virgin Sex On The Beach" + id = "virginsexonthebeach" + description = "A secret combination of orange juice and pomegranate." + taste_description = "60% orange juice, 40% pomegranate" + color = "#7051E3" + + glass_name = "sex on the beach" + glass_desc = "A secret combination of orange juice and pomegranate." + +/datum/reagent/drink/driverspunch + name = "Driver's Punch" + id = "driverspunch" + description = "A fruity punch!" + taste_description = "sharp, sour apples" + color = "#D2BA6E" + + glass_name = "driver`s punch" + glass_desc = "A fruity punch!" + glass_special = list(DRINK_FIZZ) + +/datum/reagent/drink/berrycordial + name = "Berry Cordial" + id = "berrycordial" + description = "How berry cordial of you." + taste_description = "sweet chivalry" + color = "#D26EB8" + + glass_name = "berry cordial" + glass_desc = "How berry cordial of you." + glass_icon = DRINK_ICON_NOISY + +/datum/reagent/drink/tropicalfizz + name = "Tropical Fizz" + id = "tropicalfizz" + description = "One sip and you're in the bahamas." + taste_description = "tropical" + color = "#69375C" + + glass_name = "tropical fizz" + glass_desc = "One sip and you're in the bahamas." + glass_icon = DRINK_ICON_NOISY + glass_special = list(DRINK_FIZZ) + +/datum/reagent/drink/fauxfizz + name = "Faux Fizz" + id = "fauxfizz" + description = "One sip and you're in the bahamas... maybe." + taste_description = "slightly tropical" + color = "#69375C" + + glass_name = "tropical fizz" + glass_desc = "One sip and you're in the bahamas... maybe." + glass_icon = DRINK_ICON_NOISY + glass_special = list(DRINK_FIZZ) + /* Alcohol */ // Basic @@ -1662,6 +1928,17 @@ return M.dizziness +=5 +/datum/reagent/ethanol/firepunch + name = "Fire Punch" + id = "firepunch" + description = "Yo ho ho and a jar of honey." + taste_description = "sharp butterscotch" + color = "#ECB633" + strength = 7 + + glass_name = "fire punch" + glass_desc = "Yo ho ho and a jar of honey." + /datum/reagent/ethanol/gin name = "Gin" id = "gin" @@ -1729,6 +2006,18 @@ glass_name = "melon liquor" glass_desc = "A relatively sweet and fruity 46 proof liquor." +/datum/reagent/ethanol/melonspritzer + name = "Melon Spritzer" + id = "melonspritzer" + description = "Melons: Citrus style." + taste_description = "sour melon" + color = "#934D5D" + strength = 10 + + glass_name = "melon spritzer" + glass_desc = "Melons: Citrus style." + glass_special = list(DRINK_FIZZ) + /datum/reagent/ethanol/rum name = "Rum" id = "rum" @@ -1752,6 +2041,17 @@ glass_name = "sake" glass_desc = "A glass of sake." +/datum/reagent/ethanol/sexonthebeach + name = "Sex On The Beach" + id = "sexonthebeach" + description = "A concoction of vodka and a secret combination of orange juice and pomegranate." + taste_description = "60% orange juice, 40% pomegranate, 100% alcohol" + color = "#7051E3" + strength = 15 + + glass_name = "sex on the beach" + glass_desc = "A concoction of vodka and a secret combination of orange juice and pomegranate." + /datum/reagent/ethanol/tequila name = "Tequila" id = "tequilla" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm index e2724f06475..d1213eb7836 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Medicine.dm @@ -16,6 +16,28 @@ M.add_chemical_effect(CE_STABLE, 15) M.add_chemical_effect(CE_PAINKILLER, 10) +/datum/reagent/inaprovaline/topical + name = "Inaprovalaze" + id = "inaprovalaze" + description = "Inaprovalaze is a topical variant of Inaprovaline." + taste_description = "bitterness" + reagent_state = LIQUID + color = "#00BFFF" + overdose = REAGENTS_OVERDOSE * 2 + metabolism = REM * 0.5 + scannable = 1 + touch_met = REM * 0.75 + +/datum/reagent/inaprovaline/topical/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien != IS_DIONA) + ..() + M.adjustToxLoss(2 * removed) + +/datum/reagent/inaprovaline/topical/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) + if(alien != IS_DIONA) + M.add_chemical_effect(CE_STABLE, 20) + M.add_chemical_effect(CE_PAINKILLER, 12) + /datum/reagent/bicaridine name = "Bicaridine" id = "bicaridine" @@ -51,6 +73,33 @@ if(W.damage <= 0) O.wounds -= W +/datum/reagent/bicaridine/topical + name = "Bicaridaze" + id = "bicaridaze" + description = "Bicaridaze is a topical variant of the chemical Bicaridine." + taste_description = "bitterness" + taste_mult = 3 + reagent_state = LIQUID + color = "#BF0000" + overdose = REAGENTS_OVERDOSE * 0.75 + scannable = 1 + touch_met = REM * 0.75 + +/datum/reagent/bicaridine/topical/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + var/chem_effective = 1 + if(alien == IS_SLIME) + chem_effective = 0.75 + if(alien != IS_DIONA) + ..(M, alien, removed * chem_effective) + M.adjustToxLoss(2 * removed) + +/datum/reagent/bicaridine/topical/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) + var/chem_effective = 1 + if(alien == IS_SLIME) + chem_effective = 0.75 + if(alien != IS_DIONA) + M.heal_organ_damage(6 * removed * chem_effective, 0) + /datum/reagent/kelotane name = "Kelotane" id = "kelotane" @@ -87,6 +136,33 @@ if(alien != IS_DIONA) M.heal_organ_damage(0, 8 * removed * chem_effective) //VOREStation edit +/datum/reagent/dermaline/topical + name = "Dermalaze" + id = "dermalaze" + description = "Dermalaze is a topical variant of the chemical Dermaline." + taste_description = "bitterness" + taste_mult = 1.5 + reagent_state = LIQUID + color = "#FF8000" + overdose = REAGENTS_OVERDOSE * 0.4 + scannable = 1 + touch_met = REM * 0.75 + +/datum/reagent/dermaline/topical/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + var/chem_effective = 1 + if(alien == IS_SLIME) + chem_effective = 0.75 + if(alien != IS_DIONA) + ..(M, alien, removed * chem_effective) + M.adjustToxLoss(2 * removed) + +/datum/reagent/dermaline/topical/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) + var/chem_effective = 1 + if(alien == IS_SLIME) + chem_effective = 0.75 + if(alien != IS_DIONA) + M.heal_organ_damage(0, 12 * removed * chem_effective) + /datum/reagent/dylovene name = "Dylovene" id = "anti_toxin" @@ -203,6 +279,10 @@ M.heal_organ_damage(1.5 * removed, 1.5 * removed * chem_effective) M.adjustToxLoss(-1.5 * removed * chem_effective) +/datum/reagent/tricordrazine/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) + if(alien != IS_DIONA) + affect_blood(M, alien, removed * 0.4) + /datum/reagent/cryoxadone name = "Cryoxadone" id = "cryoxadone" @@ -865,6 +945,9 @@ to_chat(M, "Your senses feel unfocused, and divided.") M.add_chemical_effect(CE_ANTIBIOTIC, dose >= overdose ? ANTIBIO_OD : ANTIBIO_NORM) +/datum/reagent/spaceacillin/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) + affect_blood(M, alien, removed * 0.8) // Not 100% as effective as injections, though still useful. + /datum/reagent/corophizine name = "Corophizine" id = "corophizine" diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Modifiers.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Modifiers.dm new file mode 100644 index 00000000000..d9a7483ec1e --- /dev/null +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Modifiers.dm @@ -0,0 +1,58 @@ +/* + * Modifier-applying chemicals. + */ + +/datum/reagent/modapplying + name = "brute juice" + id = "berserkmed" + description = "A liquid that is capable of causing a prolonged state of heightened aggression and durability." + taste_description = "metal" + reagent_state = LIQUID + color = "#ff5555" + metabolism = REM + + var/modifier_to_add = /datum/modifier/berserk + var/modifier_duration = 2 SECONDS // How long, per unit dose, will this last? + +/datum/reagent/modapplying/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_DIONA) + return + M.add_modifier(modifier_to_add, dose * modifier_duration) + +/datum/reagent/modapplying/cryofluid + name = "cryogenic slurry" + id = "cryoslurry" + description = "An incredibly strange liquid that rapidly absorbs thermal energy from materials it contacts." + taste_description = "siberian hellscape" + color = "#4CDBDB" + metabolism = REM * 0.5 + + modifier_to_add = /datum/modifier/cryogelled + modifier_duration = 3 SECONDS + +/datum/reagent/modapplying/cryofluid/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + ..(M, alien, removed) + M.bodytemperature -= removed * 20 + +/datum/reagent/modapplying/cryofluid/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) + affect_blood(M, alien, removed * 2.5) + +/datum/reagent/modapplying/cryofluid/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) + affect_blood(M, alien, removed * 0.6) + +/datum/reagent/modapplying/cryofluid/touch_mob(var/mob/M, var/amount) + if(isliving(M)) + var/mob/living/L = M + for(var/I = 1 to rand(1, round(amount + 1))) + L.add_modifier(modifier_to_add, amount * rand(modifier_duration / 2, modifier_duration * 2)) + return + +/datum/reagent/modapplying/cryofluid/touch_turf(var/turf/T, var/amount) + if(istype(T, /turf/simulated/floor/water) && prob(amount)) + T.visible_message("\The [T] crackles loudly as the cryogenic fluid causes it to boil away, leaving behind a hard layer of ice.") + T.ChangeTurf(/turf/simulated/floor/outdoors/ice, 1, 1, TRUE) + else + if(istype(T, /turf/simulated)) + var/turf/simulated/S = T + S.freeze_floor() + return diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm index 79304733dd8..38a65a78d86 100644 --- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm +++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm @@ -11,6 +11,7 @@ metabolism = REM * 0.25 // 0.05 by default. Hopefully enough to get some help, or die horribly, whatever floats your boat filtered_organs = list(O_LIVER, O_KIDNEYS) var/strength = 4 // How much damage it deals per unit + var/skin_danger = 0.2 // The multiplier for how effective the toxin is when making skin contact. /datum/reagent/toxin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) if(strength && alien != IS_DIONA) @@ -23,6 +24,9 @@ M.heal_organ_damage((10/strength) * removed, (10/strength) * removed) //Doses of toxins below 10 units, and 10 strength, are capable of providing useful compounds for repair. M.adjustToxLoss(strength * removed) +/datum/reagent/toxin/affect_touch(var/mob/living/carbon/M, var/alien, var/removed) + affect_blood(M, alien, removed * 0.2) + /datum/reagent/toxin/plasticide name = "Plasticide" id = "plasticide" @@ -58,6 +62,7 @@ reagent_state = LIQUID color = "#005555" strength = 8 + skin_danger = 0.4 /datum/reagent/toxin/neurotoxic_protein/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) ..() @@ -121,6 +126,7 @@ color = "#9D14DB" strength = 30 touch_met = 5 + skin_danger = 1 /datum/reagent/toxin/phoron/touch_mob(var/mob/living/L, var/amount) if(istype(L)) @@ -346,6 +352,36 @@ if(alien == IS_DIONA) M.adjustToxLoss(50 * removed) +/datum/reagent/toxin/sifslurry + name = "Sivian Sap" + id = "sifsap" + description = "A natural slurry comprised of fluorescent bacteria native to Sif, in the Vir system." + taste_description = "sour" + reagent_state = LIQUID + color = "#C6E2FF" + strength = 2 + overdose = 20 + +/datum/reagent/toxin/sifslurry/affect_blood(var/mob/living/carbon/M, var/alien, var/removed) + if(alien == IS_DIONA) // Symbiotic bacteria. + M.nutrition += strength * removed + return + else + M.add_modifier(/datum/modifier/slow_pulse, 30 SECONDS) + ..() + +/datum/reagent/toxin/sifslurry/overdose(var/mob/living/carbon/M, var/alien, var/removed) // Overdose effect. + if(alien == IS_DIONA) + return + if(ishuman(M)) + var/mob/living/carbon/human/H = M + overdose_mod *= H.species.chemOD_mod + M.apply_effect(2 * removed,IRRADIATE, 0, 0) + M.apply_effect(5 * removed,DROWSY, 0, 0) + +/datum/reagent/toxin/sifslurry/affect_ingest(var/mob/living/carbon/M, var/alien, var/removed) + affect_blood(M, alien, removed * 0.7) + /datum/reagent/acid/polyacid name = "Polytrinic acid" id = "pacid" diff --git a/code/modules/reagents/Chemistry-Recipes.dm b/code/modules/reagents/Chemistry-Recipes.dm index 7d2a588d526..01de315c2d4 100644 --- a/code/modules/reagents/Chemistry-Recipes.dm +++ b/code/modules/reagents/Chemistry-Recipes.dm @@ -34,6 +34,7 @@ var/reaction_sound = 'sound/effects/bubbles.ogg' var/log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file. + /datum/chemical_reaction/proc/can_happen(var/datum/reagents/holder) //check that all the required reagents are present if(!holder.has_all_reagents(required_reagents)) @@ -500,6 +501,15 @@ required_reagents = list("carpotoxin" = 5, "stoxin" = 5, "copper" = 5) result_amount = 2 +/datum/chemical_reaction/carpotoxin + name = "Carpotoxin" + id = "carpotoxin" + result = "carpotoxin" + required_reagents = list("spidertoxin" = 2, "biomass" = 1, "sifsap" = 2) + catalysts = list("sifsap" = 10) + inhibitors = list("radium" = 1) + result_amount = 2 + /datum/chemical_reaction/mindbreaker name = "Mindbreaker Toxin" id = "mindbreaker" @@ -737,9 +747,12 @@ var/mob/living/L = holder.my_atom if(L.stat != DEAD) e.amount *= 0.5 + //VOREStation Add Start else holder.clear_reagents() //No more powergaming by creating a tiny amount of this + //VORESTation Add End e.start() + //holder.clear_reagents() //VOREStation Removal return /datum/chemical_reaction/flash_powder @@ -784,8 +797,10 @@ // 100 created volume = 4 heavy range & 7 light range. A few tiles smaller than traitor EMP grandes. // 200 created volume = 8 heavy range & 14 light range. 4 tiles larger than traitor EMP grenades. empulse(location, round(created_volume / 24), round(created_volume / 20), round(created_volume / 18), round(created_volume / 14), 1) + //VOREStation Edit Start if(!isliving(holder.my_atom)) //No more powergaming by creating a tiny amount of this holder.clear_reagents() + //VOREStation Edit End return /datum/chemical_reaction/nitroglycerin @@ -804,10 +819,13 @@ var/mob/living/L = holder.my_atom if(L.stat!=DEAD) e.amount *= 0.5 + //VOREStation Add Start else holder.clear_reagents() //No more powergaming by creating a tiny amount of this + //VOREStation Add End e.start() + //holder.clear_reagents() //VOREStation Removal return /datum/chemical_reaction/napalm @@ -840,8 +858,10 @@ playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3) spawn(0) S.start() + //VOREStation Edit Start if(!isliving(holder.my_atom)) //No more powergaming by creating a tiny amount of this holder.clear_reagents() + //VOREStation Edit End return /datum/chemical_reaction/foam @@ -861,8 +881,10 @@ var/datum/effect/effect/system/foam_spread/s = new() s.set_up(created_volume, location, holder, 0) s.start() + //VOREStation Edit Start if(!isliving(holder.my_atom)) //No more powergaming by creating a tiny amount of this holder.clear_reagents() + //VOREStation Edit End return /datum/chemical_reaction/metalfoam @@ -1178,6 +1200,20 @@ new /obj/item/weapon/reagent_containers/food/snacks/chocolatebar(location) return +/datum/chemical_reaction/drinks/coffee + name = "Coffee" + id = "coffee" + result = "coffee" + required_reagents = list("water" = 5, "coffeepowder" = 1) + result_amount = 5 + +/datum/chemical_reaction/drinks/tea + name = "Black tea" + id = "tea" + result = "tea" + required_reagents = list("water" = 5, "teapowder" = 1) + result_amount = 5 + /datum/chemical_reaction/drinks/hot_coco name = "Hot Coco" id = "hot_coco" @@ -1192,6 +1228,34 @@ required_reagents = list("soymilk" = 4, "sacid" = 1) result_amount = 5 +/datum/chemical_reaction/drinks/grapejuice + name = "Grape Juice" + id = "grapejuice" + result = "grapejuice" + required_reagents = list("water" = 3, "instantgrape" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/orangejuice + name = "Orange Juice" + id = "orangejuice" + result = "orangejuice" + required_reagents = list("water" = 3, "instantorange" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/watermelonjuice + name = "Watermelon Juice" + id = "watermelonjuice" + result = "watermelonjuice" + required_reagents = list("water" = 3, "instantwatermelon" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/applejuice + name = "Apple Juice" + id = "applejuice" + result = "applejuice" + required_reagents = list("water" = 3, "instantapple" = 1) + result_amount = 3 + /datum/chemical_reaction/food/ketchup name = "Ketchup" id = "ketchup" @@ -1199,6 +1263,21 @@ required_reagents = list("tomatojuice" = 2, "water" = 1, "sugar" = 1) result_amount = 4 +/datum/chemical_reaction/food/peanutbutter + name = "Peanut Butter" + id = "peanutbutter" + result = "peanutbutter" + required_reagents = list("peanutoil" = 2, "sugar" = 1, "sodiumchloride" = 1) + catalysts = list("enzyme" = 5) + result_amount = 3 + +/datum/chemical_reaction/food/mayonnaise + name = "mayonnaise" + id = "mayo" + result = "mayo" + required_reagents = list("egg" = 9, "cornoil" = 5, "lemonjuice" = 5, "sodiumchloride" = 1) + result_amount = 15 + /datum/chemical_reaction/food/cheesewheel name = "Cheesewheel" id = "cheesewheel" @@ -1827,6 +1906,79 @@ required_reagents = list("lemonjuice" = 1, "sugar" = 1, "water" = 1) result_amount = 3 +/datum/chemical_reaction/drinks/melonade + name = "Melonade" + id = "melonade" + result = "melonade" + required_reagents = list("watermelonjuice" = 1, "sugar" = 1, "sodawater" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/appleade + name = "Appleade" + id = "appleade" + result = "appleade" + required_reagents = list("applejuice" = 1, "sugar" = 1, "sodawater" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/pineappleade + name = "Pineappleade" + id = "pineappleade" + result = "pineappleade" + required_reagents = list("pineapplejuice" = 2, "limejuice" = 1, "sodawater" = 2, "honey" = 1) + result_amount = 5 + +/datum/chemical_reaction/drinks/driverspunch + name = "Driver`s Punch" + id = "driverspunch" + result = "driverspunch" + required_reagents = list("appleade" = 2, "orangejuice" = 1, "mint" = 1, "sodawater" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/mintapplesparkle + name = "Mint Apple Sparkle" + id = "mintapplesparkle" + result = "mintapplesparkle" + required_reagents = list("appleade" = 2, "mint" = 1) + inhibitors = list("sodawater" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/berrycordial + name = "Berry Cordial" + id = "berrycordial" + result = "berrycordial" + required_reagents = list("berryjuice" = 4, "sugar" = 1, "lemonjuice" = 1) + result_amount = 5 + +/datum/chemical_reaction/drinks/tropicalfizz + name = "Tropical Fizz" + id = "tropicalfizz" + result = "tropicalfizz" + required_reagents = list("sodawater" = 6, "berryjuice" = 1, "mint" = 1, "limejuice" = 1, "lemonjuice" = 1, "pineapplejuice" = 1) + inhibitors = list("sugar" = 1) + result_amount = 8 + +/datum/chemical_reaction/drinks/melonspritzer + name = "Melon Spritzer" + id = "melonspritzer" + result = "melonspritzer" + required_reagents = list("watermelonjuice" = 2, "wine" = 2, "applejuice" = 1, "limejuice" = 1) + result_amount = 6 + +/datum/chemical_reaction/drinks/fauxfizz + name = "Faux Fizz" + id = "fauxfizz" + result = "fauxfizz" + required_reagents = list("sodawater" = 2, "berryjuice" = 1, "applejuice" = 1, "limejuice" = 1, "honey" = 1) + inhibitors = list("sugar" = 1) + result_amount = 6 + +/datum/chemical_reaction/drinks/firepunch + name = "Fire Punch" + id = "firepunch" + result = "firepunch" + required_reagents = list("sugar" = 1, "rum" = 2) + result_amount = 3 + /datum/chemical_reaction/drinks/kiraspecial name = "Kira Special" id = "kiraspecial" @@ -1848,6 +2000,13 @@ required_reagents = list("cream" = 1, "ice" = 2, "milk" = 2) result_amount = 5 +/datum/chemical_reaction/drinks/peanutmilkshake + name = "Peanutbutter Milkshake" + id = "peanutmilkshake" + result = "peanutmilkshake" + required_reagents = list("cream" = 1, "ice" = 1, "peanutbutter" = 2, "milk" = 1) + result_amount = 5 + /datum/chemical_reaction/drinks/rewriter name = "Rewriter" id = "rewriter" @@ -2221,6 +2380,13 @@ required_reagents = list("rum" = 3, "limejuice" = 1, "mint" = 1) result_amount = 5 +/datum/chemical_reaction/drinks/virginmojito + name = "Mojito" + id = "virginmojito" + result = "virginmojito" + required_reagents = list("sodawater" = 3, "limejuice" = 1, "mint" = 1, "sugar" = 1) + result_amount = 5 + /datum/chemical_reaction/drinks/piscosour name = "Pisco Sour" id = "piscosour" @@ -2293,6 +2459,27 @@ required_reagents = list("cornoil" = 2, "honey" = 1) result_amount = 3 +/datum/chemical_reaction/drinks/slimeslam + name = "Slick Slime Slammer" + id = "slimeslammer" + result = "slimeslammer" + required_reagents = list("cornoil" = 2, "peanutbutter" = 1) + result_amount = 3 + +/datum/chemical_reaction/drinks/virginsexonthebeach + name = "Virgin Sex On The Beach" + id = "virginsexonthebeach" + result = "virginsexonthebeach" + required_reagents = list("orangejuice" = 3, "grenadine" = 2) + result_amount = 4 + +/datum/chemical_reaction/drinks/sexonthebeach + name = "Sex On The Beach" + id = "sexonthebeach" + result = "sexonthebeach" + required_reagents = list("orangejuice" = 3, "grenadine" = 2, "vodka" = 1) + result_amount = 6 + /datum/chemical_reaction/drinks/eggnog name = "Eggnog" id = "eggnog" @@ -2378,7 +2565,7 @@ id = "biomass" result = "biomass" required_reagents = list("protein" = 1, "sugar" = 1, "phoron" = 1) - result_amount = 6 // Roughly 120u per phoron sheet //VOREStation Edit + result_amount = 1 // Roughly 20u per phoron sheet // Neutralization. @@ -2388,3 +2575,19 @@ result = "protein" required_reagents = list("anti_toxin" = 1, "neurotoxic_protein" = 2) result_amount = 2 + +/datum/chemical_reaction/neutralize_carpotoxin + name = "Neutralize Carpotoxin" + id = "carpotoxin_neutral" + result = "protein" + required_reagents = list("radium" = 1, "carpotoxin" = 1, "sifsap" = 1) + catalysts = list("sifsap" = 10) + result_amount = 2 + +/datum/chemical_reaction/neutralize_spidertoxin + name = "Neutralize Spidertoxin" + id = "spidertoxin_neutral" + result = "protein" + required_reagents = list("radium" = 1, "spidertoxin" = 1, "sifsap" = 1) + catalysts = list("sifsap" = 10) + result_amount = 2 diff --git a/code/modules/reagents/Chemistry-Recipes_vr.dm b/code/modules/reagents/Chemistry-Recipes_vr.dm index 098cae99f06..ac8fa9a7f20 100644 --- a/code/modules/reagents/Chemistry-Recipes_vr.dm +++ b/code/modules/reagents/Chemistry-Recipes_vr.dm @@ -101,7 +101,7 @@ name = "Vermicetol" id = "vermicetol" result = "vermicetol" - required_reagents = list("kelotane" = 1, "dermaline" = 1, "shockchem" = 1, "phoron" = 0.1) + required_reagents = list("bicaridine" = 2, "shockchem" = 1, "phoron" = 0.1) catalysts = list("phoron" = 5) result_amount = 3 @@ -340,4 +340,10 @@ if(prob(50)) for(var/j = 1, j <= rand(1, 3), j++) step(C, pick(NORTH,SOUTH,EAST,WEST)) -*/ \ No newline at end of file +*/ + +/datum/chemical_reaction/food/syntiflesh + required_reagents = list("blood" = 5, "clonexadone" = 1) + +/datum/chemical_reaction/biomass + result_amount = 6 // Roughly 120u per phoron sheet diff --git a/code/modules/reagents/dispenser/cartridge.dm b/code/modules/reagents/dispenser/cartridge.dm index 70142fabd8a..ddcd173cb7c 100644 --- a/code/modules/reagents/dispenser/cartridge.dm +++ b/code/modules/reagents/dispenser/cartridge.dm @@ -8,7 +8,7 @@ volume = CARTRIDGE_VOLUME_LARGE amount_per_transfer_from_this = 50 // Large, but inaccurate. Use a chem dispenser or beaker for accuracy. - possible_transfer_amounts = list(50, 100) + possible_transfer_amounts = list(50, 100, 250, 500) unacidable = 1 var/spawn_reagent = null diff --git a/code/modules/reagents/distilling/Distilling-Recipes.dm b/code/modules/reagents/distilling/Distilling-Recipes.dm new file mode 100644 index 00000000000..f7fae181784 --- /dev/null +++ b/code/modules/reagents/distilling/Distilling-Recipes.dm @@ -0,0 +1,170 @@ +/datum/chemical_reaction/distilling +// name = null +// id = null +// result = null +// required_reagents = list() +// catalysts = list() +// inhibitors = list() +// result_amount = 0 + + //how far the reaction proceeds each time it is processed. Used with either REACTION_RATE or HALF_LIFE macros. + reaction_rate = HALF_LIFE(6) + + //if less than 1, the reaction will be inhibited if the ratio of products/reagents is too high. + //0.5 = 50% yield -> reaction will only proceed halfway until products are removed. +// yield = 1.0 + + //If limits on reaction rate would leave less than this amount of any reagent (adjusted by the reaction ratios), + //the reaction goes to completion. This is to prevent reactions from going on forever with tiny reagent amounts. +// min_reaction = 2 + + mix_message = "The solution churns." + reaction_sound = 'sound/effects/slosh.ogg' + +// log_is_important = 0 // If this reaction should be considered important for logging. Important recipes message admins when mixed, non-important ones just log to file. + + var/list/temp_range = list(T0C, T20C) + var/temp_shift = 0 // How much the temperature changes when the reaction occurs. + +/datum/chemical_reaction/distilling/can_happen(var/datum/reagents/holder) + //check that all the required reagents are present + if(!holder.has_all_reagents(required_reagents)) + return 0 + + //check that all the required catalysts are present in the required amount + if(!holder.has_all_reagents(catalysts)) + return 0 + + //check that none of the inhibitors are present in the required amount + if(holder.has_any_reagent(inhibitors)) + return 0 + + if(!istype(holder.my_atom, /obj/item/weapon/reagent_containers/glass/distilling)) + return 0 + + else // Super special temperature check. + var/obj/item/weapon/reagent_containers/glass/distilling/D = holder.my_atom + var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = D.Master + if(RD.current_temp < temp_range[1] || RD.current_temp > temp_range[2]) + return 0 + + return 1 + +/datum/chemical_reaction/distilling/on_reaction(var/datum/reagents/holder, var/created_volume) + if(istype(holder.my_atom, /obj/item/weapon/reagent_containers/glass/distilling)) + var/obj/item/weapon/reagent_containers/glass/distilling/D = holder.my_atom + var/obj/machinery/portable_atmospherics/powered/reagent_distillery/RD = D.Master + RD.current_temp += temp_shift + return + +// Subtypes // + +// Biomass +/datum/chemical_reaction/distilling/biomass + name = "Distilling Biomass" + id = "distill_biomass" + result = "biomass" + required_reagents = list("blood" = 1, "sugar" = 1, "phoron" = 0.5) + result_amount = 1 // 40 units per sheet, requires actually using the machine, and having blood to spare. + + temp_range = list(T20C + 80, T20C + 130) + temp_shift = -2 + +// Medicinal +/datum/chemical_reaction/distilling/inaprovalaze + name = "Distilling Inaprovalaze" + id = "distill_inaprovalaze" + result = "inaprovalaze" + required_reagents = list("inaprovaline" = 2, "foaming_agent" = 1) + result_amount = 2 + + reaction_rate = HALF_LIFE(10) + + temp_range = list(T0C + 100, T0C + 120) + +/datum/chemical_reaction/distilling/bicaridaze + name = "Distilling Bicaridaze" + id = "distill_bicaridaze" + result = "bicaridaze" + required_reagents = list("bicaridine" = 2, "foaming_agent" = 1) + result_amount = 2 + + reaction_rate = HALF_LIFE(10) + + temp_range = list(T0C + 110, T0C + 130) + +/datum/chemical_reaction/distilling/dermalaze + name = "Distilling Dermalaze" + id = "distill_dermalaze" + result = "dermalaze" + required_reagents = list("dermaline" = 2, "foaming_agent" = 1) + result_amount = 2 + + reaction_rate = HALF_LIFE(10) + + temp_range = list(T0C + 115, T0C + 130) + +// Alcohol +/datum/chemical_reaction/distilling/beer + name = "Distilling Beer" + id = "distill_beer" + result = "beer" + required_reagents = list("nutriment" = 1, "water" = 1, "sugar" = 1) + result_amount = 2 + + reaction_rate = HALF_LIFE(30) + + temp_range = list(T20C, T20C + 2) + +/datum/chemical_reaction/distilling/ale + name = "Distilling Ale" + id = "distill_ale" + result = "ale" + required_reagents = list("nutriment" = 1, "beer" = 1) + inhibitors = list("water" = 1) + result_amount = 2 + + reaction_rate = HALF_LIFE(30) + + temp_shift = 0.5 + temp_range = list(T0C + 7, T0C + 13) + +// Unique +/datum/chemical_reaction/distilling/berserkjuice + name = "Distilling Brute Juice" + id = "distill_brutejuice" + result = "berserkmed" + required_reagents = list("biomass" = 1, "hyperzine" = 3, "synaptizine" = 2, "phoron" = 1) + result_amount = 3 + + temp_range = list(T0C + 600, T0C + 700) + temp_shift = 4 + +/datum/chemical_reaction/distilling/berserkjuice/on_reaction(var/datum/reagents/holder, var/created_volume) + ..() + + if(prob(1)) + var/turf/T = get_turf(holder.my_atom) + explosion(T, -1, rand(-1, 1), rand(1,2), rand(3,5)) + return + +/datum/chemical_reaction/distilling/cryogel + name = "Distilling Cryogellatin" + id = "distill_cryoslurry" + result = "cryoslurry" + required_reagents = list("frostoil" = 7, "enzyme" = 3, "plasticide" = 3, "foaming_agent" = 2) + inhibitors = list("water" = 5) + result_amount = 1 + + temp_range = list(0, 15) + temp_shift = 20 + +/datum/chemical_reaction/distilling/cryogel/on_reaction(var/datum/reagents/holder, var/created_volume) + ..() + + if(prob(1)) + var/turf/T = get_turf(holder.my_atom) + var/datum/effect/effect/system/smoke_spread/frost/F = new (holder.my_atom) + F.set_up(6, 0, T) + F.start() + return diff --git a/code/modules/reagents/distilling/distilling.dm b/code/modules/reagents/distilling/distilling.dm new file mode 100644 index 00000000000..b86bcc74352 --- /dev/null +++ b/code/modules/reagents/distilling/distilling.dm @@ -0,0 +1,317 @@ + +/* + * Distillery, used for over-time temperature-based mixes. + */ + +/obj/machinery/portable_atmospherics/powered/reagent_distillery + name = "chemical distillery" + desc = "A complex machine utilizing state-of-the-art components to mix chemicals at different temperatures." + use_power = 1 + + icon = 'icons/obj/machines/reagent.dmi' + icon_state = "distiller" + var/base_state // The string var used in update icon for overlays, either set manually or initialized. + + power_rating = 3000 + power_losses = 240 + + var/on = FALSE + + var/target_temp = T20C + + var/max_temp = T20C + 300 + var/min_temp = T0C - 10 + + var/current_temp = T20C + + var/use_atmos = FALSE // If true, this machine will be connectable to ports, and use gas mixtures as the source of heat, rather than its internal controls. + + var/static/radial_examine = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_examine") + var/static/radial_use = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_use") + + var/static/radial_pump = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_pump") + + var/static/radial_eject_input = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject_input") + var/static/radial_eject_output = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject_output") + + var/static/radial_adjust_temp = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_temp") + + var/static/radial_install_input = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_add") + var/static/radial_install_output = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_add") + + var/static/radial_inspectgauges = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_lookat") + + var/static/radial_mix = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_mix") + +// Overlay holders so we don't have to constantly remake them. + var/image/overlay_output_beaker + var/image/overlay_input_beaker + var/image/overlay_off + var/image/overlay_ready + var/image/overlay_cooling + var/image/overlay_heating + var/image/overlay_dumping + var/image/overlay_connected + +// Our unique beaker, used in its unique recipes to ensure things can only react inside this machine and minimize oddities from trying to transfer to a machine and back. + var/obj/item/weapon/reagent_containers/glass/distilling/Reservoir + + var/obj/item/weapon/reagent_containers/glass/InputBeaker + var/obj/item/weapon/reagent_containers/glass/OutputBeaker + +// A multiplier for the production amount. This should really only ever be lower than one, otherwise you end up with duping. + var/efficiency = 1 + +/obj/item/weapon/reagent_containers/glass/distilling + name = "distilling chamber" + desc = "You should not be seeing this." + volume = 600 + + var/obj/machinery/portable_atmospherics/powered/reagent_distillery/Master + +/obj/item/weapon/reagent_containers/glass/distilling/Destroy() + Master = null + ..() + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/Initialize() + ..() + + Reservoir = new (src) + Reservoir.Master = src + + if(!base_state) + base_state = icon_state + + setup_overlay_vars() + + update_icon() + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/proc/setup_overlay_vars() + overlay_output_beaker = image(icon = src.icon, icon_state = "[base_state]-output") + overlay_input_beaker = image(icon = src.icon, icon_state = "[base_state]-input") + overlay_off = image(icon = src.icon, icon_state = "[base_state]-bad") + overlay_ready = image(icon = src.icon, icon_state = "[base_state]-good") + overlay_cooling = image(icon = src.icon, icon_state = "[base_state]-cool") + overlay_heating = image(icon = src.icon, icon_state = "[base_state]-heat") + overlay_dumping = image(icon = src.icon, icon_state = "[base_state]-dump") + overlay_connected = image(icon = src.icon, icon_state = "[base_state]-connector") + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/Destroy() + qdel(Reservoir) + Reservoir = null + if(InputBeaker) + qdel(InputBeaker) + InputBeaker = null + if(OutputBeaker) + qdel(OutputBeaker) + OutputBeaker = null + + ..() + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/attack_hand(mob/user) + var/list/options = list() + options["examine"] = radial_examine + options["use"] = radial_use + options["inspect gauges"] = radial_inspectgauges + options["pulse agitator"] = radial_mix + + if(InputBeaker) + options["eject input"] = radial_eject_input + if(OutputBeaker) + options["eject output"] = radial_eject_output + + if(!use_atmos) + options["adjust temp"] = radial_adjust_temp + + if(length(options) < 1) + return + + var/list/choice = list() + if(length(options) == 1) + for(var/key in options) + choice = key + else + choice = show_radial_menu(user, src, options, require_near = !issilicon(user)) + + switch(choice) + if("examine") + examine(user) + + if("use") + if(powered()) + on = !on + to_chat(user, "You turn \the [src] [on ? "on" : "off"].") + + if("inspect gauges") + to_chat(user, "\The [src]'s gauges read:") + if(!use_atmos) + to_chat(user, "- Target Temperature: [target_temp]") + to_chat(user, "- Temperature: [current_temp]") + + if("pulse agitator") + to_chat(user, "You press \the [src]'s chamber agitator button.") + if(on) + visible_message("\The [src] rattles to life.") + Reservoir.reagents.handle_reactions() + else + spawn(1 SECOND) + to_chat(user, "Nothing happens..") + + if("eject input") + if(InputBeaker) + InputBeaker.forceMove(get_turf(src)) + InputBeaker = null + + if("eject output") + if(OutputBeaker) + OutputBeaker.forceMove(get_turf(src)) + OutputBeaker = null + + if("adjust temp") + target_temp = input("Choose a target temperature.", "Temperature.", T20C) as num + target_temp = CLAMP(target_temp, min_temp, max_temp) + + update_icon() + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/attackby(obj/item/weapon/W as obj, mob/user as mob) + var/list/options = list() + if(istype(W, /obj/item/weapon/reagent_containers/glass)) + if(!InputBeaker) + options["install input"] = radial_install_input + if(!OutputBeaker) + options["install output"] = radial_install_output + + if(!options || !options.len) + update_icon() + return ..() + + var/list/choice = list() + if(length(options) == 1) + for(var/key in options) + choice = key + else + choice = show_radial_menu(user, src, options, require_near = TRUE) // No telekinetics. + + switch(choice) + if("install input") + if(!InputBeaker) + user.drop_from_inventory(W) + W.add_fingerprint(user) + W.forceMove(src) + InputBeaker = W + + if("install output") + if(!OutputBeaker) + user.drop_from_inventory(W) + W.add_fingerprint(user) + W.forceMove(src) + OutputBeaker = W + + update_icon() + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/use_power(var/amount, var/chan = -1) + last_power_draw = amount + if(use_cell && cell && cell.charge) + var/cellcharge = cell.charge + cell.use(amount) + + var/celldifference = max(0, cellcharge - cell.charge) + + amount = celldifference + + var/area/A = get_area(src) + if(!A || !isarea(A)) + return + if(chan == -1) + chan = power_channel + A.use_power(amount, chan) + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/process() + ..() + + var/run_pump = FALSE + + if(InputBeaker || OutputBeaker) + run_pump = TRUE + + var/avg_temp = 0 + var/avg_pressure = 0 + + if(connected_port && connected_port.network.line_members.len) + var/list/members = list() + var/datum/pipe_network/Net = connected_port.network + members = Net.line_members.Copy() + + for(var/datum/pipeline/Line in members) + avg_pressure += Line.air.return_pressure() + avg_temp += Line.air.temperature + + avg_temp /= members.len + avg_pressure /= members.len + + if(!powered()) + on = FALSE + + if(!on || (use_atmos && (!connected_port || avg_pressure < 1000))) + current_temp = round((current_temp + T20C) / 2) + + else if(on) + if(!use_atmos) + if(current_temp != round(target_temp)) + var/shift_mod = 0 + if(current_temp < target_temp) + shift_mod = 1 + else if(current_temp > target_temp) + shift_mod = -1 + current_temp = CLAMP(round((current_temp + 1 * shift_mod) + (rand(-5, 5) / 10)), min_temp, max_temp) + use_power(power_rating * CELLRATE) + else if(connected_port && avg_pressure > 1000) + current_temp = round((current_temp + avg_temp) / 2) + else if(!run_pump) + visible_message("\The [src]'s motors wind down.") + on = FALSE + + if(InputBeaker && Reservoir.reagents.total_volume < Reservoir.reagents.maximum_volume) + InputBeaker.reagents.trans_to_holder(Reservoir.reagents, amount = rand(10,20)) + + if(OutputBeaker && OutputBeaker.reagents.total_volume < OutputBeaker.reagents.maximum_volume) + use_power(power_rating * CELLRATE * 0.5) + Reservoir.reagents.trans_to_holder(OutputBeaker.reagents, amount = rand(1, 5)) + + update_icon() + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/update_icon() + ..() + cut_overlays() + + if(InputBeaker) + add_overlay(overlay_input_beaker) + + if(OutputBeaker) + add_overlay(overlay_output_beaker) + + if(on) + if(OutputBeaker && OutputBeaker.reagents.total_volume < OutputBeaker.reagents.maximum_volume) + add_overlay(overlay_dumping) + else if(current_temp == round(target_temp)) + add_overlay(overlay_ready) + else if(current_temp < target_temp) + add_overlay(overlay_heating) + else + add_overlay(overlay_cooling) + + else + add_overlay(overlay_off) + + if(connected_port) + add_overlay(overlay_connected) + +/* + * Subtypes + */ + +/obj/machinery/portable_atmospherics/powered/reagent_distillery/industrial + name = "industrial chemical distillery" + desc = "A gas-operated variant of a chemical distillery. Able to reach much higher, and lower, temperatures through the use of treated gas." + + use_atmos = TRUE diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index 4cc781fdea3..3c9fdcba6f7 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -14,7 +14,7 @@ possible_transfer_amounts = list(5,10,15,25,30,60) volume = 60 w_class = ITEMSIZE_SMALL - flags = OPENCONTAINER + flags = OPENCONTAINER | NOCONDUCT unacidable = 1 //glass doesn't dissolve in acid var/label_text = "" @@ -44,7 +44,8 @@ /obj/machinery/smartfridge/, /obj/machinery/biogenerator, /obj/structure/frame, - /obj/machinery/radiocarbon_spectrometer + /obj/machinery/radiocarbon_spectrometer, + /obj/machinery/portable_atmospherics/powered/reagent_distillery ) /obj/item/weapon/reagent_containers/glass/Initialize() @@ -135,8 +136,8 @@ /obj/item/weapon/reagent_containers/glass/proc/update_name_label() if(label_text == "") name = base_name - else if(length(label_text) > 10) - var/short_label_text = copytext(label_text, 1, 11) + else if(length(label_text) > 20) + var/short_label_text = copytext(label_text, 1, 21) name = "[base_name] ([short_label_text]...)" else name = "[base_name] ([label_text])" diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 4b5949595b7..6b7910fab3e 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -44,7 +44,14 @@ to_chat(user, "You cannot inject a robotic limb.") return - if(!H.stat) + //VOREStation Add Start - Adds Prototype Hypo functionality + if(H != user && prototype) + to_chat(user, "You begin injecting [H] with \the [src].") + to_chat(H, " [user] is trying to inject you with \the [src]!") + if(!do_after(user, 30, H)) + return + //VOREstation Add End + else if(!H.stat && !prototype) //VOREStation Edit if(H != user) if(H.a_intent != I_HELP) to_chat(user, "[H] is resisting your attempt to inject them with \the [src].") diff --git a/code/modules/reagents/reagent_containers/hypospray_vr.dm b/code/modules/reagents/reagent_containers/hypospray_vr.dm index 9f52d9f699f..d0777e32161 100644 --- a/code/modules/reagents/reagent_containers/hypospray_vr.dm +++ b/code/modules/reagents/reagent_containers/hypospray_vr.dm @@ -22,3 +22,11 @@ ..() for (var/i = 1 to 7) new /obj/item/weapon/reagent_containers/hypospray/autoinjector/miner(src) + +/obj/item/weapon/reagent_containers/hypospray + var/prototype = 0 + +/obj/item/weapon/reagent_containers/hypospray/science + name = "prototype hypospray" + desc = "This reproduction hypospray is nearly a perfect replica of the early model DeForest hyposprays, sharing many of the same features. However, there are additional safety measures installed to prevent unwanted injections." + prototype = 1 diff --git a/code/modules/reagents/reagent_containers/patch.dm b/code/modules/reagents/reagent_containers/patch.dm new file mode 100644 index 00000000000..007669286e0 --- /dev/null +++ b/code/modules/reagents/reagent_containers/patch.dm @@ -0,0 +1,82 @@ + +/* + * Patches. A subtype of pills, in order to inherit the possible future produceability within chem-masters, and dissolving. + */ + +/obj/item/weapon/reagent_containers/pill/patch + name = "patch" + desc = "A patch." + icon = 'icons/obj/chemical.dmi' + icon_state = null + item_state = "pill" + + base_state = "patch" + + possible_transfer_amounts = null + w_class = ITEMSIZE_TINY + slot_flags = SLOT_EARS + volume = 60 + + var/pierce_material = FALSE // If true, the patch can be used through thick material. + +/obj/item/weapon/reagent_containers/pill/patch/attack(mob/M as mob, mob/user as mob) + var/mob/living/L = user + + if(M == L) + if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/affecting = H.get_organ(check_zone(L.zone_sel.selecting)) + if(!affecting) + to_chat(user, "The limb is missing!") + return + if(affecting.status >= ORGAN_ROBOT) + to_chat(user, "\The [src] won't work on a robotic limb!") + return + + if(!H.can_inject(user, FALSE, L.zone_sel.selecting, pierce_material)) + to_chat(user, "\The [src] can't be applied through such a thick material!") + return + + to_chat(H, "\The [src] is placed on your [affecting].") + M.drop_from_inventory(src) //icon update + if(reagents.total_volume) + reagents.trans_to_mob(M, reagents.total_volume, CHEM_TOUCH) + qdel(src) + return 1 + + else if(istype(M, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = M + var/obj/item/organ/external/affecting = H.get_organ(check_zone(L.zone_sel.selecting)) + if(!affecting) + to_chat(user, "The limb is missing!") + return + if(affecting.status >= ORGAN_ROBOT) + to_chat(user, "\The [src] won't work on a robotic limb!") + return + + if(!H.can_inject(user, FALSE, L.zone_sel.selecting, pierce_material)) + to_chat(user, "\The [src] can't be applied through such a thick material!") + return + + user.visible_message("[user] attempts to place \the [src] onto [H]`s [affecting].") + + user.setClickCooldown(user.get_attack_speed(src)) + if(!do_mob(user, M)) + return + + user.drop_from_inventory(src) //icon update + user.visible_message("[user] applies \the [src] to [H].") + + var/contained = reagentlist() + add_attack_logs(user,M,"Applied a patch containing [contained]") + + to_chat(H, "\The [src] is placed on your [affecting].") + M.drop_from_inventory(src) //icon update + + if(reagents.total_volume) + reagents.trans_to_mob(M, reagents.total_volume, CHEM_TOUCH) + qdel(src) + + return 1 + + return 0 \ No newline at end of file diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index c0b647e53b7..5ca47a6d3be 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -7,6 +7,9 @@ icon = 'icons/obj/chemical.dmi' icon_state = null item_state = "pill" + + var/base_state = "pill" + possible_transfer_amounts = null w_class = ITEMSIZE_TINY slot_flags = SLOT_EARS @@ -15,7 +18,7 @@ /obj/item/weapon/reagent_containers/pill/Initialize() . = ..() if(!icon_state) - icon_state = "pill[rand(1, 4)]" //preset pills only use colour changing or unique icons + icon_state = "[base_state][rand(1, 4)]" //preset pills only use colour changing or unique icons /obj/item/weapon/reagent_containers/pill/attack(mob/M as mob, mob/user as mob) if(M == user) diff --git a/code/modules/reagents/reagent_containers/pill_vr.dm b/code/modules/reagents/reagent_containers/pill_vr.dm index ad9663d0201..30d084570fc 100644 --- a/code/modules/reagents/reagent_containers/pill_vr.dm +++ b/code/modules/reagents/reagent_containers/pill_vr.dm @@ -1,7 +1,7 @@ /obj/item/weapon/reagent_containers/pill/nutriment name = "Nutriment pill" desc = "Used to feed people on the field. Contains 30 units of Nutriment." - icon_state = "pill6" + icon_state = "pill10" /obj/item/weapon/reagent_containers/pill/nutriment/Initialize() ..() @@ -10,7 +10,7 @@ /obj/item/weapon/reagent_containers/pill/protein name = "Meat pill" desc = "Used to feed carnivores on the field. Contains 30 units of Protein." - icon_state = "pill20" + icon_state = "pill24" /obj/item/weapon/reagent_containers/pill/protein/Initialize() ..() @@ -19,11 +19,12 @@ /obj/item/weapon/reagent_containers/pill/rezadone name = "Rezadone pill" desc = "A powder with almost magical properties, this substance can effectively treat genetic damage in humanoids, though excessive consumption has side effects." - icon_state = "pill13" + icon_state = "pill2" /obj/item/weapon/reagent_containers/pill/rezadone/Initialize() ..() reagents.add_reagent("rezadone", 5) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/peridaxon name = "Peridaxon pill" @@ -37,38 +38,42 @@ /obj/item/weapon/reagent_containers/pill/carthatoline name = "Carthatoline pill" desc = "Carthatoline is strong evacuant used to treat severe poisoning." - icon_state = "pill17" + icon_state = "pill4" /obj/item/weapon/reagent_containers/pill/carthatoline/Initialize() ..() reagents.add_reagent("carthatoline", 10) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/alkysine name = "Alkysine pill" desc = "Alkysine is a drug used to lessen the damage to neurological tissue after a catastrophic injury. Can heal brain tissue." - icon_state = "pill7" + icon_state = "pill3" /obj/item/weapon/reagent_containers/pill/alkysine/Initialize() ..() reagents.add_reagent("alkysine", 10) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/imidazoline name = "Imidazoline pill" desc = "Heals eye damage." - icon_state = "pill9" + icon_state = "pill3" /obj/item/weapon/reagent_containers/pill/imidazoline/Initialize() ..() reagents.add_reagent("imidazoline", 15) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/osteodaxon name = "Osteodaxon pill" desc = "An experimental drug used to heal bone fractures." - icon_state = "pill19" + icon_state = "pill2" /obj/item/weapon/reagent_containers/pill/osteodaxon/Initialize() ..() reagents.add_reagent("osteodaxon", 10) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/myelamine name = "Myelamine pill" @@ -78,15 +83,17 @@ /obj/item/weapon/reagent_containers/pill/myelamine/Initialize() ..() reagents.add_reagent("myelamine", 10) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/hyronalin name = "Hyronalin pill" desc = "Hyronalin is a medicinal drug used to counter the effect of radiation poisoning." - icon_state = "pill17" + icon_state = "pill4" /obj/item/weapon/reagent_containers/pill/hyronalin/Initialize() ..() reagents.add_reagent("hyronalin", 15) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/arithrazine name = "Arithrazine pill" @@ -96,21 +103,24 @@ /obj/item/weapon/reagent_containers/pill/arithrazine/Initialize() ..() reagents.add_reagent("arithrazine", 5) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/corophizine name = "Corophizine pill" desc = "A wide-spectrum antibiotic drug. Powerful and uncomfortable in equal doses." - icon_state = "pill9" + icon_state = "pill2" /obj/item/weapon/reagent_containers/pill/corophizine/Initialize() ..() reagents.add_reagent("corophizine", 5) + color = reagents.get_color() /obj/item/weapon/reagent_containers/pill/healing_nanites name = "Healing nanites capsule" desc = "Miniature medical robots that swiftly restore bodily damage." - icon_state = "pill5" + icon_state = "pill1" /obj/item/weapon/reagent_containers/pill/healing_nanites/Initialize() ..() reagents.add_reagent("healing_nanites", 30) + color = reagents.get_color() diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index d2b4dc149d8..4ccd444d0ea 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -158,7 +158,7 @@ message_admins("[key_name_admin(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]) (JMP).") log_game("[key_name(Proj.firer)] shot fueltank at [loc.loc.name] ([loc.x],[loc.y],[loc.z]).") - if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) + if(!istype(Proj ,/obj/item/projectile/beam/lasertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) explode() /obj/structure/reagent_dispensers/fueltank/ex_act() diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 98d3500c6eb..8a2e9796cda 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -136,7 +136,7 @@ if(isrobot(user)) return - if(!I) + if(!I || I.anchored || !I.canremove) return user.drop_item() diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index b60b71cc4e4..69b9937158b 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -1,7 +1,7 @@ /obj/structure/bigDelivery desc = "A big wrapped package." name = "large parcel" - icon = 'icons/obj/storage.dmi' + icon = 'icons/obj/storage_vr.dmi' //VOREStation Edit icon_state = "deliverycloset" var/obj/wrapped = null density = 1 @@ -109,7 +109,7 @@ /obj/item/smallDelivery desc = "A small wrapped package." name = "small parcel" - icon = 'icons/obj/storage.dmi' + icon = 'icons/obj/storage_vr.dmi' //VOREStation Edit icon_state = "deliverycrate3" var/obj/item/wrapped = null var/sortTag = null diff --git a/code/modules/research/designs/circuits.dm b/code/modules/research/designs/circuits.dm index e2824361bfc..f47ff46947f 100644 --- a/code/modules/research/designs/circuits.dm +++ b/code/modules/research/designs/circuits.dm @@ -287,6 +287,13 @@ CIRCUITS BELOW build_path = /obj/item/weapon/circuitboard/solar_control sort_string = "JAAAF" +/datum/design/circuit/shutoff_monitor + name = "Automatic shutoff valve monitor" + id = "shutoff_monitor" + req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3) + build_path = /obj/item/weapon/circuitboard/shutoff_monitor + sort_string = "JAAAG" + /datum/design/circuit/pacman name = "PACMAN-type generator" id = "pacman" @@ -467,14 +474,14 @@ CIRCUITS BELOW req_tech = list(TECH_DATA = 4, TECH_COMBAT = 2) build_path = /obj/item/weapon/circuitboard/mecha/gygax/targeting sort_string = "NAACC" -/* //Uncomment me to allow Serenity construction + /datum/design/circuit/mecha/gygax_medical name = "'Serenity' medical control" id = "gygax_medical" req_tech = list(TECH_DATA = 4, TECH_BIO = 2) build_path = /obj/item/weapon/circuitboard/mecha/gygax/medical sort_string = "NAACD" -*/ + /datum/design/circuit/mecha/durand_main name = "'Durand' central control" id = "durand_main" @@ -608,4 +615,4 @@ CIRCUITS BELOW /datum/design/circuit/shield req_tech = list(TECH_BLUESPACE = 4, TECH_PHORON = 3) materials = list("$glass" = 2000, "sacid" = 20, "$phoron" = 10000, "$diamond" = 5000, "$gold" = 10000) -*/ \ No newline at end of file +*/ diff --git a/code/modules/research/designs/illegal.dm b/code/modules/research/designs/illegal.dm index 4e99fc8665a..f0a50fa5dd0 100644 --- a/code/modules/research/designs/illegal.dm +++ b/code/modules/research/designs/illegal.dm @@ -25,3 +25,11 @@ materials = list(MAT_PLASTEEL = 3500, "glass" = 1000, MAT_LEAD = 2250, MAT_METALHYDROGEN = 500) build_path = /obj/item/weapon/melee/energy/sword/charge sort_string = "VASCA" + +/datum/design/item/weapon/eaxe + name = "Energy Axe" + id = "chargeaxe" + req_tech = list(TECH_COMBAT = 6, TECH_MAGNET = 5, TECH_ENGINEERING = 4, TECH_ILLEGAL = 4) + materials = list(MAT_PLASTEEL = 3500, MAT_OSMIUM = 2000, MAT_LEAD = 2000, MAT_METALHYDROGEN = 500) + build_path = /obj/item/weapon/melee/energy/axe/charge + sort_string = "VASCB" diff --git a/code/modules/research/designs/mining_toys.dm b/code/modules/research/designs/mining_toys.dm index f9b76032cbd..c170cb827b9 100644 --- a/code/modules/research/designs/mining_toys.dm +++ b/code/modules/research/designs/mining_toys.dm @@ -45,4 +45,12 @@ req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2, TECH_BLUESPACE = 2) materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 1000) build_path = /obj/item/device/depth_scanner - sort_string = "KAAAF" \ No newline at end of file + sort_string = "KAAAF" + +/datum/design/item/device/graviton_visor + desc = "Used to see via the complex interation of meson particles and graviton particles." + id = "graviton_goggles" + req_tech = list(TECH_MAGNET = 5, TECH_ENGINEERING = 3, TECH_BLUESPACE = 3, TECH_PHORON = 3) + materials = list(MAT_PLASTEEL = 2000, "glass" = 3000, MAT_PHORON = 1500) + build_path = /obj/item/clothing/glasses/graviton + sort_string = "KAAAG" diff --git a/code/modules/research/designs/misc.dm b/code/modules/research/designs/misc.dm index 29231a7cd9a..f14b73d2e68 100644 --- a/code/modules/research/designs/misc.dm +++ b/code/modules/research/designs/misc.dm @@ -19,23 +19,28 @@ id = "health_hud" req_tech = list(TECH_BIO = 2, TECH_MAGNET = 3) build_path = /obj/item/clothing/glasses/hud/health - sort_string = "GAAAA" + sort_string = "GBAAA" /datum/design/item/hud/security name = "security records" id = "security_hud" req_tech = list(TECH_MAGNET = 3, TECH_COMBAT = 2) build_path = /obj/item/clothing/glasses/hud/security - sort_string = "GAAAB" + sort_string = "GBAAB" /datum/design/item/hud/mesons - name = "Optical meson scanners design" - desc = "Using the meson-scanning technology those glasses allow you to see through walls, floor or anything else." + name = "optical meson scanner" id = "mesons" req_tech = list(TECH_MAGNET = 2, TECH_ENGINEERING = 2) - materials = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50) build_path = /obj/item/clothing/glasses/meson - sort_string = "GAAAC" + sort_string = "GBAAC" + +/datum/design/item/hud/material + name = "optical material scanner" + id = "material" + req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 3) + build_path = /obj/item/clothing/glasses/material + sort_string = "GBAAD" /datum/design/item/device/ano_scanner name = "Alden-Saraspova counter" @@ -80,22 +85,65 @@ datum/design/item/laserpointer build_path = /obj/item/device/communicator sort_string = "VABAJ" +/datum/design/item/gps + req_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 500) + +/datum/design/item/gps/generic + name = "Triangulating device design (GEN)" + id = "gps_gen" + build_path = /obj/item/device/gps + sort_string = "VADAA" + +/datum/design/item/gps/comand + name = "Triangulating device design (COM)" + id = "gps_com" + build_path = /obj/item/device/gps/command + sort_string = "VADAB" + +/datum/design/item/gps/security + name = "Triangulating device design (SEC)" + id = "gps_sec" + build_path = /obj/item/device/gps/security + sort_string = "VADAC" + +/datum/design/item/gps/medical + name = "Triangulating device design (MED)" + id = "gps_med" + build_path = /obj/item/device/gps/medical + sort_string = "VADAD" + +/datum/design/item/gps/engineering + name = "Triangulating device design (ENG)" + id = "gps_eng" + build_path = /obj/item/device/gps/engineering + sort_string = "VADAE" + +/datum/design/item/gps/science + name = "Triangulating device design (SCI)" + id = "gps_sci" + build_path = /obj/item/device/gps/science + sort_string = "VADAF" + +/datum/design/item/gps/mining + name = "Triangulating device design (MINE)" + id = "gps_mine" + build_path = /obj/item/device/gps/mining + sort_string = "VADAG" + +/datum/design/item/gps/explorer + name = "Triangulating device design (EXP)" + id = "gps_exp" + build_path = /obj/item/device/gps/explorer + sort_string = "VADAH" + /datum/design/item/beacon name = "Bluespace tracking beacon design" id = "beacon" req_tech = list(TECH_BLUESPACE = 1) materials = list (DEFAULT_WALL_MATERIAL = 20, "glass" = 10) build_path = /obj/item/device/radio/beacon - sort_string = "VADAA" - -/datum/design/item/gps - name = "Triangulating device design" - desc = "Triangulates approximate co-ordinates using a nearby satellite network." - id = "gps" - req_tech = list(TECH_MATERIAL = 2, TECH_DATA = 2, TECH_BLUESPACE = 2) - materials = list(DEFAULT_WALL_MATERIAL = 500) - build_path = /obj/item/device/gps - sort_string = "VADAB" + sort_string = "VADBA" /datum/design/item/beacon_locator name = "Beacon tracking pinpointer" @@ -104,7 +152,7 @@ datum/design/item/laserpointer req_tech = list(TECH_MAGNET = 3, TECH_ENGINEERING = 2, TECH_BLUESPACE = 3) materials = list(DEFAULT_WALL_MATERIAL = 1000,"glass" = 500) build_path = /obj/item/device/beacon_locator - sort_string = "VADAC" + sort_string = "VADBB" /datum/design/item/bag_holding name = "'Bag of Holding', an infinite capacity bag prototype" diff --git a/code/modules/research/designs/precursor.dm b/code/modules/research/designs/precursor.dm index eaf7b3a923a..bcf80b66a01 100644 --- a/code/modules/research/designs/precursor.dm +++ b/code/modules/research/designs/precursor.dm @@ -77,3 +77,12 @@ var/obj/item/I = build_path desc = initial(I.desc) ..() + +/datum/design/item/anomaly/camotrap + name = "Chameleon Trap" + desc = "A self-miraging mechanical trap, capable of producing short bursts of electric current when triggered." + id = "hunt_trap" + materials = list(MAT_DURASTEEL = 3000, MAT_METALHYDROGEN = 1000, MAT_PHORON = 2000) + req_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_PHORON = 2, TECH_ARCANE = 2) + build_path = /obj/item/weapon/beartrap/hunting + sort_string = "ARCAT" diff --git a/code/modules/research/designs_vr.dm b/code/modules/research/designs_vr.dm index 518c77a504b..958d359ab16 100644 --- a/code/modules/research/designs_vr.dm +++ b/code/modules/research/designs_vr.dm @@ -117,6 +117,15 @@ build_path = /obj/item/device/nifrepairer sort_string = "HABBE" //Changed String from HABBD to HABBE +/datum/design/item/medical/protohypospray + name = "prototype hypospray" + desc = "This prototype hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients." + id = "protohypospray" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 3, TECH_POWER = 2, TECH_BIO = 4, TECH_ILLEGAL = 2) + materials = list(DEFAULT_WALL_MATERIAL = 500, "glass" = 1500, "silver" = 2000, "gold" = 1500, "uranium" = 1000) + build_path = /obj/item/weapon/reagent_containers/hypospray/science + sort_string = "MBBAH" + // Resleeving Circuitboards /datum/design/circuit/transhuman_clonepod diff --git a/code/modules/research/mechfab_designs.dm b/code/modules/research/mechfab_designs.dm index e67172fa942..199acd42fbd 100644 --- a/code/modules/research/mechfab_designs.dm +++ b/code/modules/research/mechfab_designs.dm @@ -107,13 +107,13 @@ /datum/design/item/mechfab/gygax category = "Gygax" -/* //uncomment me to make the Serenity produceable in Robotics + /datum/design/item/mechfab/gygax/chassis/serenity name = "Serenity Chassis" id = "serenity_chassis" build_path = /obj/item/mecha_parts/chassis/serenity materials = list(DEFAULT_WALL_MATERIAL = 18750, "phoron" = 4000) -*/ + /datum/design/item/mechfab/gygax/chassis name = "Gygax Chassis" id = "gygax_chassis" @@ -616,6 +616,46 @@ materials = list(DEFAULT_WALL_MATERIAL = 7500, "diamond" = 4875) build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/diamonddrill +/datum/design/item/mecha/ground_drill + name = "Surface Bore" + desc = "A heavy duty bore. Bigger, better, stronger than the core sampler, but not quite as good as a large drill." + id = "mech_ground_drill" + req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 2, TECH_PHORON = 1) + materials = list(DEFAULT_WALL_MATERIAL = 7000, "silver" = 3000, "phoron" = 2000) + build_path = /obj/item/mecha_parts/mecha_equipment/tool/drill/bore + +/datum/design/item/mecha/orescanner + name = "Ore Scanner" + desc = "A hefty device used to scan for subterranean veins of ore." + id = "mech_ore_scanner" + req_tech = list(TECH_MATERIAL = 2, TECH_MAGNET = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 4000, "glass" = 1000) + build_path = /obj/item/mecha_parts/mecha_equipment/tool/orescanner + +/datum/design/item/mecha/advorescanner + name = "Advanced Ore Scanner" + desc = "A hefty device used to scan for the exact volumes of subterranean veins of ore." + id = "mech_ore_scanner_adv" + req_tech = list(TECH_MATERIAL = 5, TECH_MAGNET = 4, TECH_POWER = 4, TECH_BLUESPACE = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "osmium" = 3000, "silver" = 1000) + build_path = /obj/item/mecha_parts/mecha_equipment/tool/orescanner/advanced + +/datum/design/item/mecha/powerwrench + name = "hydraulic wrench" + desc = "A large, hydraulic wrench." + id = "mech_wrench" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 5000, "plastic" = 2000, "glass" = 1250) + build_path = /obj/item/mecha_parts/mecha_equipment/tool/powertool + +/datum/design/item/mecha/powercrowbar + name = "hydraulic prybar" + desc = "A large, hydraulic prybar." + id = "mech_crowbar" + req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2, TECH_POWER = 2) + materials = list(DEFAULT_WALL_MATERIAL = 4000, "osmium" = 3000, "glass" = 1000) + build_path = /obj/item/mecha_parts/mecha_equipment/tool/powertool/prybar + /datum/design/item/mecha/generator_nuclear name = "Nuclear Reactor" desc = "Exosuit-held nuclear reactor. Converts uranium and everyone's health to energy." @@ -624,6 +664,14 @@ materials = list(DEFAULT_WALL_MATERIAL = 7500, "silver" = 375, "glass" = 750) build_path = /obj/item/mecha_parts/mecha_equipment/generator/nuclear +/datum/design/item/mecha/speedboost_ripley + name = "Ripley Leg Actuator Overdrive" + desc = "System enhancements and overdrives to make a mech's legs move faster." + id = "mech_speedboost_ripley" + req_tech = list( TECH_POWER = 5, TECH_MATERIAL = 4, TECH_ENGINEERING = 4) + materials = list(DEFAULT_WALL_MATERIAL = 10000, "silver" = 1000, "gold" = 1000) + build_path = /obj/item/mecha_parts/mecha_equipment/speedboost + /datum/design/item/synthetic_flash name = "Synthetic Flash" id = "sflash" diff --git a/code/modules/shieldgen/energy_field.dm b/code/modules/shieldgen/energy_field.dm index 65eb6dc363e..5b7d7f2118b 100644 --- a/code/modules/shieldgen/energy_field.dm +++ b/code/modules/shieldgen/energy_field.dm @@ -60,6 +60,9 @@ user.do_attack_animation(src) user.setClickCooldown(user.get_attack_speed()) +/obj/effect/energy_field/take_damage(var/damage) + adjust_strength(-damage / 20) + /obj/effect/energy_field/attack_hand(var/mob/living/user) impact_effect(3) // Harmless, but still produces the 'impact' effect. ..() diff --git a/code/modules/surgery/external_repair.dm b/code/modules/surgery/external_repair.dm index b26d803b343..4ed2d96c1a5 100644 --- a/code/modules/surgery/external_repair.dm +++ b/code/modules/surgery/external_repair.dm @@ -9,8 +9,10 @@ req_open = 1 /datum/surgery_step/repairflesh/can_use(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool) - if (target.stat == DEAD) // Sorry defibs, your subjects need to have pumping fluids for these to work. - return 0 +/* VOREStation Removal for Mlem Reasons(TM) + if (target.stat == DEAD) // Sorry defibs, your subjects need to have pumping fluids for these to work. + return 0 +*/ if (isslime(target)) return 0 if (target_zone == O_EYES || target_zone == O_MOUTH) @@ -34,7 +36,6 @@ /datum/surgery_step/repairflesh/scan_injury allowed_tools = list( /obj/item/weapon/autopsy_scanner = 100, - /obj/item/device/healthanalyzer = 80, /obj/item/device/analyzer = 10 ) @@ -85,8 +86,6 @@ /datum/surgery_step/repairflesh/repair_burns allowed_tools = list( /obj/item/stack/medical/advanced/ointment = 100, - /obj/item/weapon/surgical/FixOVein = 100, - /obj/item/weapon/surgical/hemostat = 60, /obj/item/stack/medical/ointment = 50, /obj/item/weapon/tape_roll = 30, /obj/item/taperoll = 10 @@ -153,8 +152,6 @@ /datum/surgery_step/repairflesh/repair_brute allowed_tools = list( /obj/item/stack/medical/advanced/bruise_pack = 100, - /obj/item/weapon/surgical/cautery = 100, - /obj/item/weapon/surgical/bonesetter = 60, /obj/item/stack/medical/bruise_pack = 50, /obj/item/weapon/tape_roll = 40, /obj/item/taperoll = 10 diff --git a/code/modules/surgery/neck.dm b/code/modules/surgery/neck.dm index 5b1522d60c2..ec9803309f0 100644 --- a/code/modules/surgery/neck.dm +++ b/code/modules/surgery/neck.dm @@ -24,7 +24,6 @@ priority = 1 allowed_tools = list( /obj/item/weapon/surgical/FixOVein = 100, - /obj/item/stack/nanopaste = 50, /obj/item/stack/cable_coil = 40, /obj/item/device/assembly/mousetrap = 5) diff --git a/code/modules/tables/presets.dm b/code/modules/tables/presets.dm index 06fca651383..085489b26a4 100644 --- a/code/modules/tables/presets.dm +++ b/code/modules/tables/presets.dm @@ -58,6 +58,23 @@ material = get_material_by_name("wood") ..() +/obj/structure/table/sifwoodentable + icon_state = "plain_preview" + color = "#824B28" + +/obj/structure/table/sifwoodentable/New() + material = get_material_by_name("alien wood") + ..() + +/obj/structure/table/sifwooden_reinforced + icon_state = "reinf_preview" + color = "#824B28" + +/obj/structure/table/sifwooden_reinforced/New() + material = get_material_by_name("alien wood") + reinforced = get_material_by_name(DEFAULT_WALL_MATERIAL) + ..() + /obj/structure/table/gamblingtable icon_state = "gamble_preview" @@ -75,6 +92,15 @@ material = get_material_by_name("glass") ..() +/obj/structure/table/borosilicate + icon_state = "plain_preview" + color = "#4D3EAC" + alpha = 77 + +/obj/structure/table/borosilicate/New() + material = get_material_by_name("borosilicate glass") + ..() + /obj/structure/table/holotable icon_state = "holo_preview" color = "#EEEEEE" @@ -168,6 +194,18 @@ material = get_material_by_name("wood") ..() +/obj/structure/table/bench/sifwooden + icon_state = "plain_preview" + color = "#824B28" + +/obj/structure/table/bench/sifwooden/New() + material = get_material_by_name("alien wood") + ..() + +/obj/structure/table/bench/sifwooden/padded + icon_state = "padded_preview" + carpeted = 1 + /obj/structure/table/bench/padded icon_state = "padded_preview" diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm index 17d2a8e1146..c5b7bde70e7 100644 --- a/code/modules/tables/tables.dm +++ b/code/modules/tables/tables.dm @@ -26,6 +26,7 @@ var/list/table_icon_cache = list() // Gambling tables. I'd prefer reinforced with carpet/felt/cloth/whatever, but AFAIK it's either harder or impossible to get /obj/item/stack/material of those. // Convert if/when you can easily get stacks of these. var/carpeted = 0 + var/carpeted_type = /obj/item/stack/tile/carpet var/list/connections = list("nw0", "ne0", "sw0", "se0") @@ -43,7 +44,7 @@ var/list/table_icon_cache = list() health += maxhealth - old_maxhealth -/obj/structure/table/proc/take_damage(amount) +/obj/structure/table/take_damage(amount) // If the table is made of a brittle material, and is *not* reinforced with a non-brittle material, damage is multiplied by TABLE_BRITTLE_MATERIAL_MULTIPLIER if(material && material.is_brittle()) if(reinforced) @@ -110,7 +111,7 @@ var/list/table_icon_cache = list() if(carpeted && W.is_crowbar()) user.visible_message("\The [user] removes the carpet from \the [src].", "You remove the carpet from \the [src].") - new /obj/item/stack/tile/carpet(loc) + new carpeted_type(loc) carpeted = 0 update_icon() return 1 @@ -121,6 +122,7 @@ var/list/table_icon_cache = list() user.visible_message("\The [user] adds \the [C] to \the [src].", "You add \the [C] to \the [src].") carpeted = 1 + carpeted_type = W.type update_icon() return 1 else @@ -315,7 +317,7 @@ var/list/table_icon_cache = list() S = material.place_shard(loc) if(S) shards += S if(carpeted && (full_return || prob(50))) // Higher chance to get the carpet back intact, since there's no non-intact option - new /obj/item/stack/tile/carpet(src.loc) + new carpeted_type(src.loc) if(full_return || prob(20)) new /obj/item/stack/material/steel(src.loc) else diff --git a/code/modules/tension/tension.dm b/code/modules/tension/tension.dm index 82151a7e78f..841d6910377 100644 --- a/code/modules/tension/tension.dm +++ b/code/modules/tension/tension.dm @@ -69,7 +69,7 @@ var/friendly = threatened.faction == faction - var/threat = guess_threat_level() + var/threat = guess_threat_level(threatened) // Hurt entities contribute less tension. threat *= health @@ -99,7 +99,120 @@ return threat +// Carbon / mostly Human threat check. +/mob/living/carbon/get_threat(var/mob/living/threatened) + . = ..() + if(has_AI()) + if(!ai_holder.hostile) + return 0 + + if(incapacitated(INCAPACITATION_DISABLED)) + return 0 + + var/friendly = (IIsAlly(threatened) && a_intent == I_HELP) + + var/threat = guess_threat_level(threatened) + + threat *= health + threat /= getMaxHealth() + + // Allies reduce tension instead of adding. + if(friendly) + threat = -threat + + else + if(threatened.invisibility > see_invisible) + threat /= 2 // Target cannot be seen by src. + if(invisibility > threatened.see_invisible) + threat *= 2 // Target cannot see src. + + // Handle statuses. + if(confused) + threat /= 2 + + if(has_modifier_of_type(/datum/modifier/berserk)) + threat *= 2 + + return threat + +/mob/living/carbon/guess_threat_level(var/mob/living/threatened) + var/threat_guess = 0 + + // First lets consider their attack ability. + var/will_point_blank = FALSE + if(has_AI()) + will_point_blank = ai_holder.pointblank + + . = ..() + + var/obj/item/I = get_active_hand() + if(!I || !istype(I)) + var/damage_guess = 0 + if(ishuman(src) && ishuman(threatened)) + var/mob/living/carbon/human/H = src + var/datum/unarmed_attack/attack = H.get_unarmed_attack(threatened, BP_TORSO) + if(!attack) + damage_guess += 5 + + var/punch_damage = attack.get_unarmed_damage(H) + if(H.gloves) + if(istype(H.gloves, /obj/item/clothing/gloves)) + var/obj/item/clothing/gloves/G = H.gloves + punch_damage += G.punch_force + + damage_guess += punch_damage + + else + damage_guess += 5 + + for(var/datum/modifier/M in modifiers) + if(!isnull(M.outgoing_melee_damage_percent)) + damage_guess *= M.outgoing_melee_damage_percent + + threat_guess += damage_guess + + else + var/weapon_attack_speed = get_attack_speed(I) / (1 SECOND) + var/weapon_damage = I.force + + for(var/datum/modifier/M in modifiers) + if(!isnull(M.outgoing_melee_damage_percent)) + weapon_damage *= M.outgoing_melee_damage_percent + + if(istype(I, /obj/item/weapon/gun)) + will_point_blank = TRUE + var/obj/item/weapon/gun/G = I + var/obj/item/projectile/P + + P = new G.projectile_type() + + if(P) // Does the gun even have a projectile type? + weapon_damage = P.damage + if(will_point_blank && a_intent == I_HURT) + weapon_damage *= 1.5 + weapon_attack_speed = G.fire_delay / (1 SECOND) + qdel(P) + + var/average_damage = weapon_damage / weapon_attack_speed + + threat_guess += average_damage + + // Consider intent. + switch(a_intent) + if(I_HELP) // Not likely to fight us. + threat_guess *= 0.4 + if(I_DISARM) // Might engage us, but unlikely to be with the intent to kill. + threat_guess *= 0.8 + if(I_GRAB) // May try to restrain us. This is here for reference, or later tweaking if needed. + threat_guess *= 1 + if(I_HURT) // May try to hurt us. + threat_guess *= 1.25 + + // Then consider their defense. + threat_guess += getMaxHealth() / 5 // 100 health translates to 20 threat. + + return threat_guess // Gives a rough idea of how much danger someone is in. Meant to be used for PvE things since PvP has too many unknown variables. /mob/living/proc/get_tension() diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm index d761dbd6e8c..8c626a6b465 100644 --- a/code/modules/vehicles/bike.dm +++ b/code/modules/vehicles/bike.dm @@ -59,6 +59,9 @@ set category = "Vehicle" set src in view(0) + if(!isliving(usr) || ismouse(usr)) + return + if(usr.incapacitated()) return if(!on && cell && cell.charge > charge_use) @@ -73,6 +76,9 @@ set category = "Vehicle" set src in view(0) + if(!isliving(usr) || ismouse(usr)) + return + if(usr.incapacitated()) return if(kickstand) diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index 45cbcd7a13b..46e838d37a2 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -1,7 +1,7 @@ /obj/vehicle/train/engine name = "cargo train tug" desc = "A ridable electric car designed for pulling cargo trolleys." - icon = 'icons/obj/vehicles.dmi' + icon = 'icons/obj/vehicles_vr.dmi' //VOREStation Edit icon_state = "cargo_engine" on = 0 powered = 1 @@ -26,7 +26,7 @@ /obj/vehicle/train/trolley name = "cargo train trolley" - icon = 'icons/obj/vehicles.dmi' + icon = 'icons/obj/vehicles_vr.dmi' //VOREStation Edit icon_state = "cargo_trailer" anchored = 0 passenger_allowed = 0 @@ -34,7 +34,7 @@ load_item_visible = 1 load_offset_x = 0 - load_offset_y = 4 + load_offset_y = 7 //VOREStation Edit mob_offset_y = 8 //------------------------------------------- @@ -44,7 +44,7 @@ ..() cell = new /obj/item/weapon/cell/high(src) key = new key_type(src) - var/image/I = new(icon = 'icons/obj/vehicles.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs + var/image/I = new(icon = 'icons/obj/vehicles_vr.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs //VOREStation edit overlays += I turn_off() //so engine verbs are correctly set @@ -374,3 +374,17 @@ anchored = 0 else anchored = 1 + +// VOREStation Edit Start - Overlay stuff for the chair-like effect +/obj/vehicle/train/engine/update_icon() + ..() + overlays = null + var/image/O = image(icon = 'icons/obj/vehicles_vr.dmi', icon_state = "cargo_engine_overlay", dir = src.dir) + O.layer = FLY_LAYER + O.plane = MOB_PLANE + overlays += O + +/obj/vehicle/train/engine/set_dir() + ..() + update_icon() +// VOREStation Edit End - Overlay stuff for the chair-like effect diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index 1bef7d41eac..87a1b72466a 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -81,7 +81,6 @@ if(riding_datum) riding_datum.handle_ride(user, direction) - /obj/vehicle/Moved() . = ..() if(riding_datum) @@ -425,3 +424,12 @@ new /obj/effect/decal/cleanable/blood/oil(src.loc) spawn(1) healthcheck() return 1 + +/obj/vehicle/take_damage(var/damage) + if(!damage) + return + src.health -= damage + if(mechanical && prob(10)) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + spawn(1) healthcheck() + return 1 diff --git a/code/modules/ventcrawl/ventcrawl.dm b/code/modules/ventcrawl/ventcrawl.dm index a306caea192..4728ed6ecf6 100644 --- a/code/modules/ventcrawl/ventcrawl.dm +++ b/code/modules/ventcrawl/ventcrawl.dm @@ -18,6 +18,7 @@ var/list/ventcrawl_machinery = list( /mob/living/var/list/icon/pipes_shown = list() /mob/living/var/last_played_vent /mob/living/var/is_ventcrawling = 0 +/mob/living/var/prepping_to_ventcrawl = 0 /mob/var/next_play_vent = 0 /mob/living/proc/can_ventcrawl() @@ -106,7 +107,7 @@ var/list/ventcrawl_machinery = list( /mob/living/var/ventcrawl_layer = 3 /mob/living/proc/handle_ventcrawl(var/atom/clicked_on) - if(!can_ventcrawl()) + if(!can_ventcrawl() || prepping_to_ventcrawl) return var/obj/machinery/atmospherics/unary/vent_found @@ -153,6 +154,9 @@ var/list/ventcrawl_machinery = list( to_chat(src, "You feel a roaring wind pushing you away from the vent!") fade_towards(vent_found,45) + prepping_to_ventcrawl = 1 + spawn(50) + prepping_to_ventcrawl = 0 if(!do_after(src, 45, vent_found, 1, 1)) return if(!can_ventcrawl()) diff --git a/code/modules/vore/appearance/sprite_accessories_taur_vr.dm b/code/modules/vore/appearance/sprite_accessories_taur_vr.dm index 301d0841be6..04e0baeaf83 100644 --- a/code/modules/vore/appearance/sprite_accessories_taur_vr.dm +++ b/code/modules/vore/appearance/sprite_accessories_taur_vr.dm @@ -153,6 +153,9 @@ //Messages for smalls moving under larges var/msg_owner_stepunder = "%owner runs between your legs." //Weird becuase in the case this is used, %owner is the 'bumper' (src) var/msg_prey_stepunder = "You run between %prey's legs." //Same, inverse + hide_body_parts = list(BP_L_LEG, BP_L_FOOT, BP_R_LEG, BP_R_FOOT) //Exclude pelvis just in case. + clip_mask_icon = 'icons/mob/vore/taurs_vr.dmi' + clip_mask_state = "taur_clip_mask_def" //Used to clip off the lower part of suits & uniforms. /datum/sprite_accessory/tail/taur/roiz_long_lizard // Not ACTUALLY a taur, but it uses 32x64 so it wouldn't fit in tails.dmi, and having it as a tail bugs up the sprite. name = "Long Lizard Tail (Roiz Lizden)" @@ -438,6 +441,7 @@ ckeys_allowed = list("natje") do_colouration = 0 can_ride = 0 + clip_mask_state = "taur_clip_mask_alraune" msg_prey_stepunder = "You run between %prey's vines." @@ -468,4 +472,26 @@ ckeys_allowed = null do_colouration = 1 extra_overlay = "alraunecolor_markings" - extra_overlay_w = "alraunecolor_closed_markings" \ No newline at end of file + extra_overlay_w = "alraunecolor_closed_markings" + clip_mask_state = "taur_clip_mask_alraune" + +/datum/sprite_accessory/tail/taur/wasp + name = "Wasp (dual color)" + icon_state = "wasp_s" + extra_overlay = "wasp_markings" + clip_mask_state = "taur_clip_mask_wasp" + + msg_owner_disarm_run = "You quickly push %prey to the ground with your leg!" + msg_prey_disarm_run = "%owner pushes you down to the ground with their leg!" + + msg_owner_disarm_walk = "You firmly push your leg down on %prey, painfully but harmlessly pinning them to the ground!" + msg_prey_disarm_walk = "%owner firmly pushes their leg down on you, quite painfully but harmlessly pinning you to the ground!" + + msg_owner_harm_walk = "You methodically place your leg down upon %prey's body, slowly applying pressure, crushing them against the floor!" + msg_prey_harm_walk = "%owner methodically places their leg upon your body, slowly applying pressure, crushing you against the floor!" + + msg_owner_grab_success = "You pin %prey down on the ground with your front leg before using your other leg to pick them up, trapping them between two of your front legs!" + msg_prey_grab_success = "%owner pins you down on the ground with their front leg before using their other leg to pick you up, trapping you between two of their front legs!" + + msg_owner_grab_fail = "You step down onto %prey, squishing them and forcing them down to the ground!" + msg_prey_grab_fail = "%owner steps down and squishes you with their leg, forcing you down to the ground!" diff --git a/code/modules/vore/appearance/sprite_accessories_vr.dm b/code/modules/vore/appearance/sprite_accessories_vr.dm index 50b8d763a2f..89f5e9c7464 100644 --- a/code/modules/vore/appearance/sprite_accessories_vr.dm +++ b/code/modules/vore/appearance/sprite_accessories_vr.dm @@ -653,6 +653,9 @@ var/desc = "You should not see this..." var/ani_state // State when wagging/animated var/extra_overlay_w // Wagging state for extra overlay + var/list/hide_body_parts = list() //Uses organ tag defines. Bodyparts in this list do not have their icons rendered, allowing for more spriter freedom when doing taur/digitigrade stuff. + var/icon/clip_mask_icon = null //Icon file used for clip mask. + var/clip_mask_state = null //Icon state to generate clip mask. Clip mask is used to 'clip' off the lower part of clothing such as jumpsuits & full suits. /datum/sprite_accessory/tail/invisible name = "hide species-sprite tail" @@ -950,6 +953,9 @@ icon_state = "satyr" color_blend_mode = ICON_MULTIPLY do_colouration = 1 + hide_body_parts = list(BP_L_LEG, BP_L_FOOT, BP_R_LEG, BP_R_FOOT) //Exclude pelvis just in case. + clip_mask_icon = 'icons/mob/vore/taurs_vr.dmi' + clip_mask_state = "taur_mask_def" //Used to clip off the lower part of suits & uniforms. /datum/sprite_accessory/tail/tailmaw name = "tailmaw, colorable" diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 94308a0f22d..8c5f15f7418 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -600,6 +600,8 @@ I.forceMove(vore_selected) updateVRPanel() + log_admin("VORE: [src] used Eat Trash to swallow [I].") + if(istype(I,/obj/item/device/flashlight/flare) || istype(I,/obj/item/weapon/flame/match) || istype(I,/obj/item/weapon/storage/box/matches)) to_chat(src, "You can taste the flavor of spicy cardboard.") else if(istype(I,/obj/item/device/flashlight/glowstick)) @@ -641,6 +643,10 @@ to_chat(src, "You can taste the flavor of garbage and leftovers. Delicious?") else to_chat(src, "You can taste the flavor of gluttonous waste of food.") + //TFF 10/7/19 - Add custom flavour for collars for trash can trait. + else if (istype(I,/obj/item/clothing/accessory/collar)) + visible_message("[src] demonstrates their voracious capabilities by swallowing [I] whole!") + to_chat(src, "You can taste the submissiveness in the wearer of [I]!") else to_chat(src, "You can taste the flavor of garbage. Delicious.") return diff --git a/code/modules/vore/fluffstuff/custom_clothes_vr.dm b/code/modules/vore/fluffstuff/custom_clothes_vr.dm index fc1fe9d0ff8..fa24a83424f 100644 --- a/code/modules/vore/fluffstuff/custom_clothes_vr.dm +++ b/code/modules/vore/fluffstuff/custom_clothes_vr.dm @@ -693,9 +693,6 @@ icon_override = 'icons/vore/custom_clothes_vr.dmi' item_state = "rig-hos_mob" - //Slightly improved security voidsuit, which when made, was: - //armor = list(melee = 50, bullet = 25, laser = 25, energy = 5, bomb = 45, bio = 100, rad = 10) - armor = list("melee" = 60, "bullet" = 35, "laser" = 35, "energy" = 15, "bomb" = 50, "bio" = 100, "rad" = 10) species_restricted = null //HOS Hardsuit Helmet @@ -709,7 +706,6 @@ icon_override = 'icons/vore/custom_clothes_vr.dmi' item_state = "rig0-hos_mob" - armor = list("melee" = 60, "bullet" = 35, "laser" = 35, "energy" = 15, "bomb" = 50, "bio" = 100, "rad" = 10) species_restricted = null //adk09:Lethe @@ -1848,4 +1844,21 @@ Departamental Swimsuits, for general use icon_state = "goldenstring" item_state = "goldenstring" w_class = ITEMSIZE_TINY - slot_flags = SLOT_TIE \ No newline at end of file + slot_flags = SLOT_TIE + +//Chaoko99: Aika Hisakawa +/obj/item/clothing/suit/fluff/blue_trimmed_coat + name = "blue-trimmed greatcoat" + desc = "A heavy, form-obscuring coat with gilded buttons and azure trim." + icon = 'icons/vore/custom_clothes_vr.dmi' + icon_state = "aika_coat" + + icon_override = 'icons/vore/custom_clothes_vr.dmi' + item_state = "aika_coat_mob" + flags_inv = HIDEJUMPSUIT | HIDETIE + + item_icons = list( + slot_l_hand_str = 'icons/vore/custom_clothes_vr.dmi', + slot_r_hand_str = 'icons/vore/custom_clothes_vr.dmi', + ) + item_state_slots = list(slot_r_hand_str = "aika_coat_mob_r", slot_l_hand_str = "aika_coat_mob_l") \ No newline at end of file diff --git a/code/modules/vore/fluffstuff/custom_items_vr.dm b/code/modules/vore/fluffstuff/custom_items_vr.dm index ff2c752e339..3cc4395141b 100644 --- a/code/modules/vore/fluffstuff/custom_items_vr.dm +++ b/code/modules/vore/fluffstuff/custom_items_vr.dm @@ -1244,7 +1244,8 @@ w_class = ITEMSIZE_SMALL origin_tech = list(TECH_MAGNET = 5, TECH_BLUESPACE = 5, TECH_ILLEGAL = 7) - var/obj/item/weapon/cell/device/weapon/power_source + var/cell_type = /obj/item/weapon/cell/device/weapon + var/obj/item/weapon/cell/power_source var/charge_cost = 800 // cell/device/weapon has 2400 var/list/beacons = list() @@ -1259,7 +1260,10 @@ /obj/item/device/perfect_tele/New() ..() flags |= NOBLUDGEON - power_source = new (src) + if(cell_type) + power_source = new cell_type(src) + else + power_source = new /obj/item/weapon/cell/device(src) spk = new(src) spk.set_up(5, 0, src) spk.attach(src) @@ -1276,7 +1280,7 @@ /obj/item/device/perfect_tele/update_icon() if(!power_source) icon_state = "[initial(icon_state)]_o" - else if(ready && power_source.check_charge(charge_cost)) + else if(ready && (power_source.check_charge(charge_cost) || power_source.fully_charged())) icon_state = "[initial(icon_state)]" else icon_state = "[initial(icon_state)]_w" @@ -1338,7 +1342,7 @@ return /obj/item/device/perfect_tele/attackby(obj/W, mob/user) - if(istype(W,/obj/item/weapon/cell/device/weapon) && !power_source) + if(istype(W,cell_type) && !power_source) power_source = W power_source.update_icon() //Why doesn't a cell do this already? :| user.unEquip(power_source) @@ -1367,7 +1371,7 @@ return FALSE //Check for charge - if(!power_source.check_charge(charge_cost)) + if((!power_source.check_charge(charge_cost)) && (!power_source.fully_charged())) to_chat(user,"\The [src] does not have enough power left!") return FALSE @@ -1398,10 +1402,13 @@ //No, you can't port to or from away missions. Stupidly complicated check. var/turf/uT = get_turf(user) var/turf/dT = get_turf(destination) + var/list/dat = list() + dat["z_level_detection"] = using_map.get_map_levels(uT.z) + if(!uT || !dT) return FALSE - if( (uT.z != dT.z) && ( (uT.z > max_default_z_level() ) || (dT.z > max_default_z_level()) ) ) + if( (uT.z != dT.z) && (!(dT.z in dat["z_level_detection"])) ) to_chat(user,"\The [src] can't teleport you that far!") return FALSE @@ -1562,14 +1569,17 @@ desc = "A more limited translocator with a single beacon, useful for some things, like setting the mining department on fire accidentally. Legal for use in the pursuit of NanoTrasen interests, namely mining and exploration." icon_state = "minitrans" beacons_left = 1 //Just one - charge_cost = 2400 //One per + cell_type = /obj/item/weapon/cell/device + origin_tech = list(TECH_MAGNET = 5, TECH_BLUESPACE = 5) +/* /obj/item/device/perfect_tele/one_beacon/teleport_checks(mob/living/target,mob/living/user) var/turf/T = get_turf(destination) if(T && user.z != T.z) to_chat(user,"\The [src] is too far away from the beacon. Try getting closer first!") return FALSE return ..() +*/ //InterroLouis: Ruda Lizden /obj/item/clothing/accessory/badge/holo/detective/ruda @@ -2007,4 +2017,23 @@ /obj/item/weapon/reagent_containers/food/drinks/flask/vacuumflask/fluff/viktor/Initialize() ..() - reagents.add_reagent("pwine", 60) \ No newline at end of file + reagents.add_reagent("pwine", 60) + +//RadiantAurora: Tiemli Kroto +/obj/item/clothing/glasses/welding/tiemgogs + name = "custom-fitted welding goggles" + desc = "A pair of thick, custom-fitted goggles with LEDs above the lenses. Ruggedly engraved below the lenses is the name 'Tiemli Kroto'." + + icon = 'icons/vore/custom_items_vr.dmi' + icon_state = "tiemgogs" + + icon_override = 'icons/vore/custom_clothes_vr.dmi' + icon_state = "tiemgogs" + +/obj/item/clothing/glasses/welding/tiemgogs/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0) + if(..()) + if(H.ckey != "radiantaurora") + to_chat(H, "These don't look like they were made to fit you...") + return 0 + else + return 1 diff --git a/code/modules/xenoarcheaology/finds/find_spawning.dm b/code/modules/xenoarcheaology/finds/find_spawning.dm index 2c04d491d05..be86279b087 100644 --- a/code/modules/xenoarcheaology/finds/find_spawning.dm +++ b/code/modules/xenoarcheaology/finds/find_spawning.dm @@ -511,6 +511,16 @@ desc = new_item.desc item_type = new_item.name + if(39) + // Telecube. + if(prob(25)) + apply_prefix = FALSE + if(prob(75)) + apply_image_decorations = TRUE + if(prob(25)) + apply_material_decorations = FALSE + new_item = new /obj/item/weapon/telecube/randomized(src.loc) + if(istype(new_item, /obj/item/weapon/material)) var/new_item_mat = pickweight( DEFAULT_WALL_MATERIAL = 80, diff --git a/code/modules/xenoarcheaology/finds/finds.dm b/code/modules/xenoarcheaology/finds/finds.dm index ab5d00e7861..8e89dcd9478 100644 --- a/code/modules/xenoarcheaology/finds/finds.dm +++ b/code/modules/xenoarcheaology/finds/finds.dm @@ -14,20 +14,22 @@ clearance_range = rand(4, 12) dissonance_spread = rand(1500, 2500) / 100 -/obj/item/weapon/ore/strangerock +/obj/item/weapon/strangerock name = "Strange rock" desc = "Seems to have some unusal strata evident throughout it." icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "strange" + var/datum/geosample/geologic_data origin_tech = list(TECH_MATERIAL = 5) -/obj/item/weapon/ore/strangerock/New(loc, var/inside_item_type = 0) - ..(loc) +/obj/item/weapon/strangerock/New(loc, var/inside_item_type = 0) + pixel_x = rand(0,16)-8 + pixel_y = rand(0,8)-8 if(inside_item_type) new /obj/item/weapon/archaeological_find(src, new_item_type = inside_item_type) -/obj/item/weapon/ore/strangerock/attackby(var/obj/item/I, var/mob/user) +/obj/item/weapon/strangerock/attackby(var/obj/item/I, var/mob/user) if(istype(I, /obj/item/weapon/pickaxe/brush)) var/obj/item/inside = locate() in src if(inside) diff --git a/code/modules/xenoarcheaology/tools/coolant_tank.dm b/code/modules/xenoarcheaology/tools/coolant_tank.dm index df6c901517b..9f5172b3dee 100644 --- a/code/modules/xenoarcheaology/tools/coolant_tank.dm +++ b/code/modules/xenoarcheaology/tools/coolant_tank.dm @@ -11,7 +11,7 @@ /obj/structure/reagent_dispensers/coolanttank/bullet_act(var/obj/item/projectile/Proj) if(Proj.get_structure_damage()) - if(!istype(Proj ,/obj/item/projectile/beam/lastertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) // TODO: make this not terrible + if(!istype(Proj ,/obj/item/projectile/beam/lasertag) && !istype(Proj ,/obj/item/projectile/beam/practice) ) // TODO: make this not terrible explode() /obj/structure/reagent_dispensers/coolanttank/ex_act() diff --git a/code/modules/xenoarcheaology/tools/equipment.dm b/code/modules/xenoarcheaology/tools/equipment.dm index a2f21199a40..b241f714be3 100644 --- a/code/modules/xenoarcheaology/tools/equipment.dm +++ b/code/modules/xenoarcheaology/tools/equipment.dm @@ -24,7 +24,7 @@ icon_state = "cespace_suit" item_state = "cespace_suit" armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100) - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/pickaxe) slowdown = 1 // Pressure protection inherited from space suits diff --git a/code/modules/xenoarcheaology/tools/tools_pickaxe.dm b/code/modules/xenoarcheaology/tools/tools_pickaxe.dm index d911843cca2..778a2043877 100644 --- a/code/modules/xenoarcheaology/tools/tools_pickaxe.dm +++ b/code/modules/xenoarcheaology/tools/tools_pickaxe.dm @@ -5,6 +5,8 @@ item_state = "syringe_0" slot_flags = SLOT_EARS digspeed = 20 + force = 0 + throwforce = 0 desc = "Thick metallic wires for clearing away dust and loose scree (1 centimetre excavation depth)." excavation_amount = 1 drill_sound = 'sound/weapons/thudswoosh.ogg' @@ -16,6 +18,7 @@ icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "pick1" item_state = "syringe_0" + force = 2 digspeed = 20 desc = "A miniature excavation tool for precise digging (2 centimetre excavation depth)." excavation_amount = 2 @@ -28,6 +31,7 @@ icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "pick2" item_state = "syringe_0" + force = 2 digspeed = 20 desc = "A miniature excavation tool for precise digging (4 centimetre excavation depth)." excavation_amount = 4 @@ -40,6 +44,7 @@ icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "pick3" item_state = "syringe_0" + force = 3 digspeed = 20 desc = "A miniature excavation tool for precise digging (6 centimetre excavation depth)." excavation_amount = 6 @@ -52,6 +57,7 @@ icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "pick4" item_state = "syringe_0" + force = 3 digspeed = 20 desc = "A miniature excavation tool for precise digging (8 centimetre excavation depth)." excavation_amount = 8 @@ -64,6 +70,7 @@ icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "pick5" item_state = "syringe_0" + force = 5 digspeed = 20 desc = "A miniature excavation tool for precise digging (10 centimetre excavation depth)." excavation_amount = 10 @@ -76,6 +83,7 @@ icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "pick6" item_state = "syringe_0" + force = 5 digspeed = 20 desc = "A miniature excavation tool for precise digging (12 centimetre excavation depth)." excavation_amount = 12 @@ -88,6 +96,7 @@ icon = 'icons/obj/xenoarchaeology.dmi' icon_state = "pick_hand" item_state = "syringe_0" + force = 10 digspeed = 30 desc = "A smaller, more precise version of the pickaxe (30 centimetre excavation depth)." excavation_amount = 30 diff --git a/code/modules/xenobio/items/weapons.dm b/code/modules/xenobio/items/weapons.dm index 4abb89ffeae..b44c73a0327 100644 --- a/code/modules/xenobio/items/weapons.dm +++ b/code/modules/xenobio/items/weapons.dm @@ -37,17 +37,7 @@ // Research borg's version /obj/item/weapon/melee/baton/slime/robot hitcost = 200 - -/obj/item/weapon/melee/baton/slime/robot/attack_self(mob/user) - //try to find our power cell - var/mob/living/silicon/robot/R = loc - if (istype(R)) - bcell = R.cell - return ..() - -/obj/item/weapon/melee/baton/slime/robot/attackby(obj/item/weapon/W, mob/user) - return - + use_external_power = TRUE // Xeno stun gun + projectile /obj/item/weapon/gun/energy/taser/xeno diff --git a/config/alienwhitelist.txt b/config/alienwhitelist.txt index d81e3c383ca..833eee4b946 100644 --- a/config/alienwhitelist.txt +++ b/config/alienwhitelist.txt @@ -3,6 +3,7 @@ some~user - Species 911earlyarther - Xenomorph Hybrid admiraldragon - Vox aether_elemental - Daemon +A Random Alien - Xenochimera arokha - Protean aruis - Diona aruis - Xenochimera @@ -12,6 +13,7 @@ bothnevarbackwards - Diona cameron653 - Xenomorph Hybrid funnyman2003 - Xenochimera hawkerthegreat - Vox +hollifex - Diona inuzari - Diona jademanique - Xenochimera jemli - Gutter @@ -28,6 +30,7 @@ rikaru19xjenkins - Xenomorph Hybrid rikaru19xjenkins - Xenochimera rixunie - Diona rixunie - Gutter +rykkastormheart - Xenochimera seiga - Vox sepulchre - Vox sepulchre - Xenomorph Hybrid @@ -38,6 +41,7 @@ singo - Gutter tastypred - Xenochimera varonis - Xenochimera verkister - Xenochimera +westfire - Xenomorph Hybrid wickedtemp - Shadekin Empathy wtfismyname - Xenomorph Hybrid xioen - Diona diff --git a/config/custom_items.txt b/config/custom_items.txt index 9438ff8d228..e6dbdd7e6d1 100644 --- a/config/custom_items.txt +++ b/config/custom_items.txt @@ -629,6 +629,13 @@ item_path: /obj/item/weapon/fluff/dragor_dot # ######## R CKEYS +{ +ckey: radiantaurora +character_name: Tiemli Kroto +item_path: /obj/item/clothing/glasses/welding/tiemgogs +req_titles: Roboticist +} + # ######## S CKEYS { ckey: samanthafyre @@ -974,3 +981,10 @@ ckey: zodiacshadow character_name: Nehi Maximus item_path: /obj/item/device/radio/headset/fluff/zodiacshadow } + +{ +ckey: chaoko99 +character_name: Aika Hisakawa +item_path: /obj/item/clothing/suit/fluff/blue_trimmed_coat +} + diff --git a/config/jobwhitelist.txt b/config/jobwhitelist.txt index e615f5eafd7..859e8e2007d 100644 --- a/config/jobwhitelist.txt +++ b/config/jobwhitelist.txt @@ -8,3 +8,4 @@ tinybear16 - clown chargae - mime verkister - clown H0lySquirr3l - clown +sgtryder - mime \ No newline at end of file diff --git a/html/changelog.html b/html/changelog.html index d2898f86e35..a1b7e3bd02d 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -53,6 +53,208 @@ -->
      +

      21 August 2019

      +

      Atermonera updated:

      +
        +
      • Atmospherics is now bigger, with more room for fun and sanity-destroying spaghetti!
      • +
      +

      Mechoid updated:

      +
        +
      • Exosuits are now targetted by turrets again.
      • +
      • Mining charge strength lowered, price increased. Can be upgraded through R&D laser components.
      • +
      • Searing damage type added. Energy axe now uses searing damage.
      • +
      • Survey points added. Vendor added for explorer use. Costs are universally 'lower' compared to the mining vendor due to the rarity of points.
      • +
      • Swiping an ID card on a cataloguer will transfer the points to the card.
      • +
      • Any melee energy weapon can now be made to use a cell and charge.
      • +
      • Energy Axe prototype added to R&D.
      • +
      • Anomalous 'hunting trap' added to R&D. Useful for an initial stun on mobs for explorer scanning.
      • +
      • Beartraps now stun for a quarter of a second, so they are actually useful again, due to resistability.
      • +
      • Emergency welding pack added. Incredibly slow, but requires no protection.
      • +
      • Random turf modifier added for mapping use. Random humanoid remains spawner added for mapping use.
      • +
      • Plants under obj/structure/flora now can be made to be harvestable / forage-able.
      • +
      • Sif trees now occasionally have fruit containing useful microbes. Microbes slow blood flow resulting in slower chemical absorption and blood loss.
      • +
      • Flora by default are now under mobs, on the same layer as turf decals. Flora can now also randomize their size, previously only codified in Sivian trees.
      • +
      • Moss tendrils added to Sif, making eye-plants more rare.
      • +
      • Multiple PoIs added. 'Blue shuttle down' variant, 'UFO Frigate', multiple geysers, cliffs, and two variants of SFR which take drastically different approaches to the SFR standard. A vault was added, too.
      • +
      • Vault PoIs are now in a template group.
      • +
      • Generic AI-controlled humanoids added. Subtype made for use on Sif, clad in weak armor and temperature resistance, used as 'mindless clones'.
      • +
      • More artifice added.
      • +
      • Fultons made to be [somewhat] sane. Now only useable planetside.
      • +
      • Graviton Visor moved to R&D from the mining equipment vendor. Silver and Diamond pickaxes removed.
      • +
      • Added multiple new organs for Prometheans. Removing them will cause them to take large amounts of Toxloss untill they are Regenerated using the active regeneration verb.
      • +
      • Organ: pneumatic network, a series of skeletal tubes with high pressure used to move nutrients and waste.
      • +
      • Organs: -regenesis systems, different 'networks' of clumped cellular matter that allow Prometheans to recover rapidly from small injuries. Large or numerous injuries cause un-needed stress, and pain.
      • +
      • Internal organs now properly add themselves to the internal organ-by-name list, the one referenced 99.9% of the time.
      • +
      • Active regeneration will now replace internal organs if they are nonexistant, as it does for limbs.
      • +
      +

      Nalarac updated:

      +
        +
      • Mech cable layer works again.
      • +
      • Added setting for turrets to fire upon downed/laying targets.
      • +
      +

      TheFurryFeline updated:

      +
        +
      • New orange jumpsuit for loadout that doesn't get locked to tracking.
      • +
      • Prison jumpsuit filepath changed accordingly and closets with obj updated.
      • +
      +

      Woodrat updated:

      +
        +
      • Made the solgov uniforms use accessories for denoting department instead of having several different sprites in the uniform dmi folder.
      • +
      • Removed redundant solgov uniforms from uniform.dmi and moved the sprites for the solgov uniforms to their own dmi.
      • +
      • Fixed storage vests and drop pouches disappearing when one rolls down a uniform.
      • +
      + +

      08 August 2019

      +

      Mechoid updated:

      +
        +
      • Adds two new integrated circuit components: an advanced Text to Speech, and a Sign-Language reading camera.
      • +
      +

      Nalarac updated:

      +
        +
      • Lowered Chance of bots being emagged during ion storm.
      • +
      • Changes space helmet cameras to be a verb instead of on toggling lights.
      • +
      • Toggling helmet camera resets user upon activation (so you can have a new user).
      • +
      • Medibots will no longer attempt to heal FBPs.
      • +
      • Heavy-duty cell chargers can be built and upgraded.
      • +
      • Cyborgs can upgrade rechargers now.
      • +
      • Security bots will smack attackers once more.
      • +
      • Security bots will cable cuff people with hardsuit gauntlets instead of stun-locking.
      • +
      • Cut real time for security bots demanding surrender in half (6 seconds).
      • +
      • Updates the Supermatter Engine Operating Manual.
      • +
      +

      mistyLuminescence updated:

      +
        +
      • Serenity mech can now be built by robotics.
      • +
      + +

      30 July 2019

      +

      Atermonera updated:

      +
        +
      • Added a shutoff monitoring console, which displays the status and location of all automatic shutoff valves. Currently mapped into the atmos monitoring room and the auxiliary engineering room on deck 1.
      • +
      + +

      27 July 2019

      +

      Mechoid updated:

      +
        +
      • Pipes will now leak if their ends are unsealed.
      • +
      • Added stasis clamps, which act as valves that can be placed on existing straight pipe segments.
      • +
      • Added automatic shutoff valves, which can automatically close if a leak appears anywhere on their pipe network.
      • +
      • Added a Xenobio-compatible ED-209.
      • +
      +

      Nalarac updated:

      +
        +
      • Repairing bots (like Beepsky) works now.
      • +
      • Emagged bots can be repaired with proximity sensors.
      • +
      • Combat mechs can punch more things. Mech punch sounds like juggernaut now
      • +
      • Simple mobs can attack more things.
      • +
      • Cult pylons take damage from bullets.
      • +
      • Click delay added on attacking simple doors and security barricades.
      • +
      • Material doors and barricades have different attacked sounds depending if its metal, wood, or resin.
      • +
      • Fixes ability of cyborg meson to see holes in ceiling.
      • +
      • Gives cyborgs a roofing synthesizer.
      • +
      • Husking bodies requires more burn.
      • +
      • Ripley speed boost module that can be built in robotics.
      • +
      • Added transmission and capacitance SMES coils to supply console.
      • +
      • Adds laser tag turrets orderable from cargo.
      • +
      • Turrets will shoot people laying down if emagged or set to lethal.
      • +
      • Turrets can not be lethal if built with non-lethal weapon.
      • +
      • Alien pistol fire noise moved to projectile. Now the turret will use the proper noise.
      • +
      • Turrets will have new colors based on projectile used.
      • +
      • Projectile lastertag is no more. It is now properly lasertag.
      • +
      • Integrated circuit printers no longer take fractions of a sheet.
      • +
      +

      Schnayy updated:

      +
        +
      • Replaces Cindi Kate's and Boot Knives bar sign sprites with new ones.
      • +
      • Added new clothes to the loadout: cardigans, pleated skirt, lilac dress, ugly Christmas sweater, flowery sweater, and red turtleneck.
      • +
      + +

      19 July 2019

      +

      Nalarac updated:

      +
        +
      • Add xenobio/xenobot to farmbots.
      • +
      +

      Woodrat updated:

      +
        +
      • Added a clotting kit to the Raider Shuttle.
      • +
      • Swapped out the ai turrets for industrial turrets in the teleporter rooms.
      • +
      • Adjusted access to the turret controls to heads of staff access, moved them outside of the rooms.
      • +
      + +

      07 July 2019

      +

      Heroman3003 updated:

      +
        +
      • Broken components now have matter worth of 1000 steel units (half a sheet).
      • +
      • Components dropped from loot piles will now use random proper sprite instead of default placeholder.
      • +
      +

      mistyLuminescence updated:

      +
        +
      • Now available in Cargo: xenoarch technology (100 points) and tactical light armor (75 points)!
      • +
      • Tactical light armor is like regular tactical armor, but lighter (a full set is 0.5 slowdown), warmer (protects against moderate snow) and a little less protective.
      • +
      • Leg guards can now store bootknives.
      • +
      • Xenoarch brushes and pickaxes now have a reasonable force rating instead of hitting like a truck.
      • +
      • Adds the 'POI - ' prefix to the POI location names to make it easier for ghosts to teleport to them- e.g. 'POI - Rocky2' rather than just 'Rocky2'.
      • +
      • Fixes a runtime caused by attempting to use a crew monitor console while on an invalid Z-level.
      • +
      • Fixes GPSes not detecting other GPSes while on an invalid Z-level. Transit Z is unaffected by this- no spying on other shuttles!
      • +
      + +

      23 June 2019

      +

      Mechoid updated:

      +
        +
      • E-swords and Changeling arm-weapons can now block projectiles (again).
      • +
      +

      Novacat updated:

      +
        +
      • Adds greyscale pills, which are colored by their reagent
      • +
      • Adds colored pill bottles, most pre-spawned pill bottles are colored
      • +
      • Prespawn pills and pill bottles have had their names simplified
      • +
      • Attempts to make lighting less uniform
      • +
      • Cleans up lighting code
      • +
      +

      TheFurryFeline updated:

      +
        +
      • Fixes infinite frame production for some machinery objects such as grounding rods or exonet nodes. If there's no available circuit board to get, then don't return anything when attempting deconstruction. Ported from Cit RP. Eliminates 'Cannot read null.board_type' runtimes where they apply.
      • +
      • Allows hydroponic machines to be unwrenched.
      • +
      +

      Woodrat updated:

      +
        +
      • Turrets and respective controls added to each teleporter room.
      • +
      • Air tank on shuttles switched out with an air canister.
      • +
      • Roundstart Tcomms SMES starts fully charged.
      • +
      • Air tanks on station have the same amount in them as air canisters.
      • +
      • Expanded atmospheric tanks to be 2 by 3 instead of 2 by 2.
      • +
      • Wilderness Shuttle landing point shelter updated.
      • +
      • Teleporter room hand tele can now spawn in one of 4 places.
      • +
      • Halved the warm up time when the autopilot on the shuttles start at round start from ten minutes to five and nine respectively. Should mean the first shuttle will be taking from the outpost when the second shuttle leaves the station.
      • +
      • Reduced transit time from 75 seconds with pilot, 150 seconds without to 60 and 120 respectively.
      • +
      • Amount of phoron in the outposts reduced.
      • +
      • Ground Xenobio and Xenoflora torn down partially.
      • +
      • Reduction of the amount of steel and glass in engineering by half.
      • +
      • Reduction of the amount of steel and glass in EVA by half.
      • +
      • Fix for Dock 2 Transfer Shuttle airlock buttons not working.
      • +
      • Intercoms added to arrivals shuttle.
      • +
      • Modular computers scattered around the main station.
      • +
      • Elevator can be accessed at centcomm.
      • +
      • Fix Bridge Secretary Quarters tint.
      • +
      • Landmarks for Bluespacerift added.
      • +
      • Wilderness Shuttle landing sides should no longer shiskabob shuttles.
      • +
      • Modular Computers replacing wrong computers.
      • +
      • Chapel Mass Driver.
      • +
      • Merc Turrets function properly.
      • +
      • Map issues on the main outpost.
      • +
      +

      mistyLuminescence updated:

      +
        +
      • Splints now work on all areas of the body.
      • +
      • When the supermatter explodes, it now leaves behind a shattered plinth that continues to emit radiation. You should probably get rid of it.
      • +
      • If you destroy the supermatter early (e.g. through admin deletion shenanigans), it no longer irradiates everyone forever.
      • +
      • Welding lockers now actually updates their sprites properly.
      • +
      • Every floor tile now has a minor (2%) chance to spawn with some dirt on it. The Janitor now has a job again.
      • +
      • Similarly, every Sif grass tile now has a minor (5%) chance to spawn with some fancy eyebulb grass on it. It can be removed by clicking on it with harm intent.
      • +
      • Adds cats-in-boxes, which can be activated (once) to spawn cats. There's an orange tabby (Cargo cats) and a tuxedo (Runtime) version.
      • +
      • Fixes a material duplication exploit.
      • +
      +

      04 June 2019

      Chaoko99 updated:

        diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index bae7843a5b3..fe2730f0679 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -4536,3 +4536,210 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. the user's hair style and color, and eye color. - bugfix: Random event timers now wait until the round starts to begin counting down. +2019-06-23: + Mechoid: + - tweak: E-swords and Changeling arm-weapons can now block projectiles (again). + Novacat: + - rscadd: Adds greyscale pills, which are colored by their reagent + - rscadd: Adds colored pill bottles, most pre-spawned pill bottles are colored + - tweak: Prespawn pills and pill bottles have had their names simplified + - tweak: Attempts to make lighting less uniform + - tweak: Cleans up lighting code + TheFurryFeline: + - bugfix: Fixes infinite frame production for some machinery objects such as grounding + rods or exonet nodes. If there's no available circuit board to get, then don't + return anything when attempting deconstruction. Ported from Cit RP. Eliminates + 'Cannot read null.board_type' runtimes where they apply. + - tweak: Allows hydroponic machines to be unwrenched. + Woodrat: + - rscadd: Turrets and respective controls added to each teleporter room. + - tweak: Air tank on shuttles switched out with an air canister. + - tweak: Roundstart Tcomms SMES starts fully charged. + - tweak: Air tanks on station have the same amount in them as air canisters. + - tweak: Expanded atmospheric tanks to be 2 by 3 instead of 2 by 2. + - tweak: Wilderness Shuttle landing point shelter updated. + - tweak: Teleporter room hand tele can now spawn in one of 4 places. + - tweak: Halved the warm up time when the autopilot on the shuttles start at round + start from ten minutes to five and nine respectively. Should mean the first + shuttle will be taking from the outpost when the second shuttle leaves the station. + - tweak: Reduced transit time from 75 seconds with pilot, 150 seconds without to + 60 and 120 respectively. + - tweak: Amount of phoron in the outposts reduced. + - tweak: Ground Xenobio and Xenoflora torn down partially. + - rscdel: Reduction of the amount of steel and glass in engineering by half. + - rscdel: Reduction of the amount of steel and glass in EVA by half. + - bugfix: Fix for Dock 2 Transfer Shuttle airlock buttons not working. + - rscadd: Intercoms added to arrivals shuttle. + - rscadd: Modular computers scattered around the main station. + - rscadd: Elevator can be accessed at centcomm. + - bugfix: Fix Bridge Secretary Quarters tint. + - bugfix: Landmarks for Bluespacerift added. + - bugfix: Wilderness Shuttle landing sides should no longer shiskabob shuttles. + - bugfix: Modular Computers replacing wrong computers. + - bugfix: Chapel Mass Driver. + - bugfix: Merc Turrets function properly. + - bugfix: Map issues on the main outpost. + mistyLuminescence: + - tweak: Splints now work on all areas of the body. + - tweak: When the supermatter explodes, it now leaves behind a shattered plinth + that continues to emit radiation. You should probably get rid of it. + - bugfix: If you destroy the supermatter early (e.g. through admin deletion shenanigans), + it no longer irradiates everyone forever. + - bugfix: Welding lockers now actually updates their sprites properly. + - tweak: Every floor tile now has a minor (2%) chance to spawn with some dirt on + it. The Janitor now has a job again. + - tweak: Similarly, every Sif grass tile now has a minor (5%) chance to spawn with + some fancy eyebulb grass on it. It can be removed by clicking on it with harm + intent. + - rscadd: Adds cats-in-boxes, which can be activated (once) to spawn cats. There's + an orange tabby (Cargo cats) and a tuxedo (Runtime) version. + - bugfix: Fixes a material duplication exploit. +2019-07-07: + Heroman3003: + - rscadd: Broken components now have matter worth of 1000 steel units (half a sheet). + - tweak: Components dropped from loot piles will now use random proper sprite instead + of default placeholder. + mistyLuminescence: + - rscadd: 'Now available in Cargo: xenoarch technology (100 points) and tactical + light armor (75 points)!' + - rscadd: Tactical light armor is like regular tactical armor, but lighter (a full + set is 0.5 slowdown), warmer (protects against moderate snow) and a little less + protective. + - tweak: Leg guards can now store bootknives. + - tweak: Xenoarch brushes and pickaxes now have a reasonable force rating instead + of hitting like a truck. + - tweak: Adds the 'POI - ' prefix to the POI location names to make it easier for + ghosts to teleport to them- e.g. 'POI - Rocky2' rather than just 'Rocky2'. + - bugfix: Fixes a runtime caused by attempting to use a crew monitor console while + on an invalid Z-level. + - bugfix: Fixes GPSes not detecting other GPSes while on an invalid Z-level. Transit + Z is unaffected by this- no spying on other shuttles! +2019-07-19: + Nalarac: + - tweak: Add xenobio/xenobot to farmbots. + Woodrat: + - rscadd: Added a clotting kit to the Raider Shuttle. + - tweak: Swapped out the ai turrets for industrial turrets in the teleporter rooms. + - tweak: Adjusted access to the turret controls to heads of staff access, moved + them outside of the rooms. +2019-07-27: + Mechoid: + - rscadd: Pipes will now leak if their ends are unsealed. + - rscadd: Added stasis clamps, which act as valves that can be placed on existing + straight pipe segments. + - rscadd: Added automatic shutoff valves, which can automatically close if a leak + appears anywhere on their pipe network. + - rscadd: Added a Xenobio-compatible ED-209. + Nalarac: + - bugfix: Repairing bots (like Beepsky) works now. + - rscadd: Emagged bots can be repaired with proximity sensors. + - tweak: Combat mechs can punch more things. Mech punch sounds like juggernaut now + - tweak: Simple mobs can attack more things. + - bugfix: Cult pylons take damage from bullets. + - bugfix: Click delay added on attacking simple doors and security barricades. + - tweak: Material doors and barricades have different attacked sounds depending + if its metal, wood, or resin. + - tweak: Fixes ability of cyborg meson to see holes in ceiling. + - rscadd: Gives cyborgs a roofing synthesizer. + - tweak: Husking bodies requires more burn. + - rscadd: Ripley speed boost module that can be built in robotics. + - rscadd: Added transmission and capacitance SMES coils to supply console. + - rscadd: Adds laser tag turrets orderable from cargo. + - bugfix: Turrets will shoot people laying down if emagged or set to lethal. + - bugfix: Turrets can not be lethal if built with non-lethal weapon. + - bugfix: Alien pistol fire noise moved to projectile. Now the turret will use the + proper noise. + - tweak: Turrets will have new colors based on projectile used. + - tweak: Projectile lastertag is no more. It is now properly lasertag. + - bugfix: Integrated circuit printers no longer take fractions of a sheet. + Schnayy: + - tweak: Replaces Cindi Kate's and Boot Knives bar sign sprites with new ones. + - rscadd: 'Added new clothes to the loadout: cardigans, pleated skirt, lilac dress, + ugly Christmas sweater, flowery sweater, and red turtleneck.' +2019-07-30: + Atermonera: + - rscadd: Added a shutoff monitoring console, which displays the status and location + of all automatic shutoff valves. Currently mapped into the atmos monitoring + room and the auxiliary engineering room on deck 1. +2019-08-08: + Mechoid: + - rscadd: 'Adds two new integrated circuit components: an advanced Text to Speech, + and a Sign-Language reading camera.' + Nalarac: + - tweak: Lowered Chance of bots being emagged during ion storm. + - tweak: Changes space helmet cameras to be a verb instead of on toggling lights. + - rscadd: Toggling helmet camera resets user upon activation (so you can have a + new user). + - bugfix: Medibots will no longer attempt to heal FBPs. + - tweak: Heavy-duty cell chargers can be built and upgraded. + - bugfix: Cyborgs can upgrade rechargers now. + - bugfix: Security bots will smack attackers once more. + - tweak: Security bots will cable cuff people with hardsuit gauntlets instead of + stun-locking. + - tweak: Cut real time for security bots demanding surrender in half (6 seconds). + - tweak: Updates the Supermatter Engine Operating Manual. + mistyLuminescence: + - tweak: Serenity mech can now be built by robotics. +2019-08-21: + Atermonera: + - tweak: Atmospherics is now bigger, with more room for fun and sanity-destroying + spaghetti! + Mechoid: + - bugfix: Exosuits are now targetted by turrets again. + - tweak: Mining charge strength lowered, price increased. Can be upgraded through + R&D laser components. + - rscadd: Searing damage type added. Energy axe now uses searing damage. + - rscadd: Survey points added. Vendor added for explorer use. Costs are universally + 'lower' compared to the mining vendor due to the rarity of points. + - rscadd: Swiping an ID card on a cataloguer will transfer the points to the card. + - tweak: Any melee energy weapon can now be made to use a cell and charge. + - rscadd: Energy Axe prototype added to R&D. + - rscadd: Anomalous 'hunting trap' added to R&D. Useful for an initial stun on mobs + for explorer scanning. + - tweak: Beartraps now stun for a quarter of a second, so they are actually useful + again, due to resistability. + - rscadd: Emergency welding pack added. Incredibly slow, but requires no protection. + - rscadd: Random turf modifier added for mapping use. Random humanoid remains spawner + added for mapping use. + - rscadd: Plants under obj/structure/flora now can be made to be harvestable / forage-able. + - rscadd: Sif trees now occasionally have fruit containing useful microbes. Microbes + slow blood flow resulting in slower chemical absorption and blood loss. + - tweak: Flora by default are now under mobs, on the same layer as turf decals. + Flora can now also randomize their size, previously only codified in Sivian + trees. + - rscadd: Moss tendrils added to Sif, making eye-plants more rare. + - rscadd: Multiple PoIs added. 'Blue shuttle down' variant, 'UFO Frigate', multiple + geysers, cliffs, and two variants of SFR which take drastically different approaches + to the SFR standard. A vault was added, too. + - tweak: Vault PoIs are now in a template group. + - rscadd: Generic AI-controlled humanoids added. Subtype made for use on Sif, clad + in weak armor and temperature resistance, used as 'mindless clones'. + - rscadd: More artifice added. + - tweak: Fultons made to be [somewhat] sane. Now only useable planetside. + - tweak: Graviton Visor moved to R&D from the mining equipment vendor. Silver and + Diamond pickaxes removed. + - rscadd: Added multiple new organs for Prometheans. Removing them will cause them + to take large amounts of Toxloss untill they are Regenerated using the active + regeneration verb. + - rscadd: 'Organ: pneumatic network, a series of skeletal tubes with high pressure + used to move nutrients and waste.' + - rscadd: 'Organs: -regenesis systems, different ''networks'' of clumped cellular + matter that allow Prometheans to recover rapidly from small injuries. Large + or numerous injuries cause un-needed stress, and pain.' + - bugfix: Internal organs now properly add themselves to the internal organ-by-name + list, the one referenced 99.9% of the time. + - tweak: Active regeneration will now replace internal organs if they are nonexistant, + as it does for limbs. + Nalarac: + - bugfix: Mech cable layer works again. + - rscadd: Added setting for turrets to fire upon downed/laying targets. + TheFurryFeline: + - rscadd: New orange jumpsuit for loadout that doesn't get locked to tracking. + - tweak: Prison jumpsuit filepath changed accordingly and closets with obj updated. + Woodrat: + - tweak: Made the solgov uniforms use accessories for denoting department instead + of having several different sprites in the uniform dmi folder. + - tweak: Removed redundant solgov uniforms from uniform.dmi and moved the sprites + for the solgov uniforms to their own dmi. + - bugfix: Fixed storage vests and drop pouches disappearing when one rolls down + a uniform. diff --git a/html/changelogs/Heroman3003 - bellfixes.yml b/html/changelogs/Heroman3003 - bellfixes.yml new file mode 100644 index 00000000000..dd3a5a712e0 --- /dev/null +++ b/html/changelogs/Heroman3003 - bellfixes.yml @@ -0,0 +1,38 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Heroman3003 + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - tweak: "Desk bells can now be picked up like normal items." + - tweak: "Desk bells can now be deconstructed with a wrench while on the ground." + - tweak: "Desk bells can now only be made out of steel." diff --git a/html/changelogs/Mechoid - Melee2RevengeoftheDeflect.yml b/html/changelogs/Mechoid - Leaky Pipes.yml similarity index 93% rename from html/changelogs/Mechoid - Melee2RevengeoftheDeflect.yml rename to html/changelogs/Mechoid - Leaky Pipes.yml index 6841c34912e..62c477edb79 100644 --- a/html/changelogs/Mechoid - Melee2RevengeoftheDeflect.yml +++ b/html/changelogs/Mechoid - Leaky Pipes.yml @@ -33,4 +33,5 @@ delete-after: True # Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. # Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. changes: - - tweak: "Changeling arm-weapons and E-swords can now block projectiles (again)." + - rscadd: "Pipes will now leak if their ends are unsealed." + - rscadd: "Pipe clamps now exist." diff --git a/html/changelogs/Novacat - Lighting.yml b/html/changelogs/MisterLayne - conductivity_fix.yml similarity index 92% rename from html/changelogs/Novacat - Lighting.yml rename to html/changelogs/MisterLayne - conductivity_fix.yml index eba91c1d213..5d8d4a06b7c 100644 --- a/html/changelogs/Novacat - Lighting.yml +++ b/html/changelogs/MisterLayne - conductivity_fix.yml @@ -22,7 +22,7 @@ ################################# # Your name. -author: Novacat +author: MisterLayne # Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. delete-after: True @@ -33,5 +33,4 @@ delete-after: True # Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. # Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. changes: - - tweak: "Attempts to make lighting less uniform" - - tweak: "Cleans up lighting code" + - tweak: "Material weapons that should not conduct, do not conduct." diff --git a/html/changelogs/Woodrat - Map Tweaksv2.yml b/html/changelogs/MisterLayne - glass_shard_self_harm.yml similarity index 86% rename from html/changelogs/Woodrat - Map Tweaksv2.yml rename to html/changelogs/MisterLayne - glass_shard_self_harm.yml index 07b5d0d3de9..dd0c47bf857 100644 --- a/html/changelogs/Woodrat - Map Tweaksv2.yml +++ b/html/changelogs/MisterLayne - glass_shard_self_harm.yml @@ -22,7 +22,7 @@ ################################# # Your name. -author: Woodrat +author: MisterLayne # Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. delete-after: True @@ -33,8 +33,4 @@ delete-after: True # Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. # Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. changes: - - bugfix: "Modular Computers replacing wrong computers." - - bugfix: "Chapel Mass Driver." - - bugfix: "Merc Turrets function properly." - - bugfix: "Map issues on the main outpost." - + - tweak: "Glass shards now do damage when you attack with them, based on the type of gloves you are wearing." diff --git a/html/changelogs/Novacat - Colorablepill.yml b/html/changelogs/Nalarac - Combat Mech Punch.yml similarity index 76% rename from html/changelogs/Novacat - Colorablepill.yml rename to html/changelogs/Nalarac - Combat Mech Punch.yml index 41b0195f412..6df8be6917d 100644 --- a/html/changelogs/Novacat - Colorablepill.yml +++ b/html/changelogs/Nalarac - Combat Mech Punch.yml @@ -22,7 +22,7 @@ ################################# # Your name. -author: Novacat +author: Nalarac # Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. delete-after: True @@ -33,6 +33,8 @@ delete-after: True # Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. # Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. changes: - - rscadd: "Adds greyscale pills, which are colored by their reagent" - - rscadd: "Adds colored pill bottles, most pre-spawned pill bottles are colored" - - tweak: "Prespawn pills and pill bottles have had their names simplified" + - tweak: "Combat mechs can punch more things. Mech punch sounds like juggernaut now" + - tweak: "Simple mobs can attack more things." + - bugfix: "Cult pylons take damage from bullets." + - bugfix: "Click delay added on attacking simple doors and security barricades." + - tweak: "Material doors and barricades have different attacked sounds depending if its metal, wood, or resin." \ No newline at end of file diff --git a/html/changelogs/TheFurryFeline - Infinite Frame Fixy.yml b/html/changelogs/TheFurryFeline - Infinite Frame Fixy.yml deleted file mode 100644 index c6ef9a2316e..00000000000 --- a/html/changelogs/TheFurryFeline - Infinite Frame Fixy.yml +++ /dev/null @@ -1,37 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: TheFurryFeline - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - bugfix: "Fixes infinite frame production for some machinery objects such as grounding rods or exonet nodes. If there's no available circuit board to get, then don't return anything when attempting deconstruction. Ported from Cit RP. Eliminates 'Cannot read null.board_type' runtimes where they apply." - - tweak: "Allows hydroponic machines to be unwrenched." diff --git a/html/changelogs/Woodrat - Map Tweaks.yml b/html/changelogs/Woodrat - Map Tweaks.yml deleted file mode 100644 index 49a4c2d4ee1..00000000000 --- a/html/changelogs/Woodrat - Map Tweaks.yml +++ /dev/null @@ -1,56 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: Woodrat - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - rscadd: "Turrets and respective controls added to each teleporter room." - - tweak: "Air tank on shuttles switched out with an air canister." - - tweak: "Roundstart Tcomms SMES starts fully charged." - - tweak: "Air tanks on station have the same amount in them as air canisters." - - tweak: "Expanded atmospheric tanks to be 2 by 3 instead of 2 by 2." - - tweak: "Wilderness Shuttle landing point shelter updated." - - tweak: "Teleporter room hand tele can now spawn in one of 4 places." - - tweak: "Halved the warm up time when the autopilot on the shuttles start at round start from ten minutes to five and nine respectively. Should mean the first shuttle will be taking from the outpost when the second shuttle leaves the station." - - tweak: "Current transit time 75 seconds with pilot, 150 seconds without. Reduced to 60 and 120 respectively." - - tweak: "Amount of phoron in the outposts reduced." - - tweak: "Ground Xenobio and Xenoflora torn down partially." - - rscdel: "Reduction of the amount of steel and glass in engineering by half." - - rscdel: "Reduction of the amount of steel and glass in EVA by half." - - bugfix: "Fix for Dock 2 Transfer Shuttle airlock buttons not working." - - rscadd: "Intercoms added to arrivals shuttle." - - rscadd: "Modular computers scattered around the main station." - - rscadd: "Elevator can be accessed at centcomm." - - bugfix: "Fix Bridge Secretary Quarters tint." - - bugfix: "Landmarks for Bluespacerift added." - - bugfix: "Wilderness Shuttle landing sides should no longer shiskabob shuttles." - diff --git a/html/changelogs/chaoko99 - stomach_pump.yml b/html/changelogs/chaoko99 - stomach_pump.yml new file mode 100644 index 00000000000..ff753858ebb --- /dev/null +++ b/html/changelogs/chaoko99 - stomach_pump.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# hey can we PLEASE get a changelog bot already + +# Your name. +author: chaoko99 + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "Ported Bay's stomach pump." \ No newline at end of file diff --git a/html/changelogs/mistyLuminescence - Sayverbs.yml b/html/changelogs/mistyLuminescence - Sayverbs.yml new file mode 100644 index 00000000000..dc54f0712d2 --- /dev/null +++ b/html/changelogs/mistyLuminescence - Sayverbs.yml @@ -0,0 +1,36 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Novacat + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "You can now select customised say-verbs in the IC tab. You know how when you use a question mark, you always 'ask' something? You don't have to "ask" any more, you can "query" instead, for example." \ No newline at end of file diff --git a/html/changelogs/mistyLuminescence - Splinting.yml b/html/changelogs/mistyLuminescence - Serenity Unlocked.yml similarity index 95% rename from html/changelogs/mistyLuminescence - Splinting.yml rename to html/changelogs/mistyLuminescence - Serenity Unlocked.yml index 440ae26488f..1bdc1068ce1 100644 --- a/html/changelogs/mistyLuminescence - Splinting.yml +++ b/html/changelogs/mistyLuminescence - Serenity Unlocked.yml @@ -33,4 +33,4 @@ delete-after: True # Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. # Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. changes: - - tweak: "Splints now work on all areas of the body." \ No newline at end of file + - tweak: "Allows construction of serenity in robotics." \ No newline at end of file diff --git a/html/changelogs/mistyLuminescence - Serenity.yml b/html/changelogs/mistyLuminescence - Serenity.yml deleted file mode 100644 index e9504903d64..00000000000 --- a/html/changelogs/mistyLuminescence - Serenity.yml +++ /dev/null @@ -1,37 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: mistyLuminescence - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - rscadd: The Serenity medical mech is now available as an adminspawn-only mech (for now!). A lightly-armored variation of the Gygax, the Serenity is swift, effective, and a little too fragile to be practical. A PR adding the Serenity to Robotics will open in two weeks. - - rscadd: The Serenity, like the Firefighter, requires its own chassis, but uses the parts of its parent mech (the Gygax). Instead of armor plating, use plasteel, and instead of a targeting board, use the new Serenity medical control board. \ No newline at end of file diff --git a/html/changelogs/mistyLuminescence - tetherz.yml b/html/changelogs/mistyLuminescence - tetherz.yml new file mode 100644 index 00000000000..ced0cb0a54e --- /dev/null +++ b/html/changelogs/mistyLuminescence - tetherz.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: mistyLuminescence + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Fixes runtimes caused when attempting to use the crew monitor console outside of the main six Z-levels. (As a result, the AR-M can now detect people in the Underdark, if the person wearing it is also in the Underdark.)" + - bugfix: "Fixes GPS signals not showing up outside of the main six Z-levels." \ No newline at end of file diff --git a/html/changelogs/mistyLuminescence - tinytweaks.yml b/html/changelogs/mistyLuminescence - tinytweaks.yml deleted file mode 100644 index ce00ccecd23..00000000000 --- a/html/changelogs/mistyLuminescence - tinytweaks.yml +++ /dev/null @@ -1,42 +0,0 @@ -################################ -# Example Changelog File -# -# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. -# -# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) -# When it is, any changes listed below will disappear. -# -# Valid Prefixes: -# bugfix -# wip (For works in progress) -# tweak -# soundadd -# sounddel -# rscadd (general adding of nice things) -# rscdel (general deleting of nice things) -# imageadd -# imagedel -# maptweak -# spellcheck (typo fixes) -# experiment -################################# - -# Your name. -author: mistyLuminescence - -# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. -delete-after: True - -# Any changes you've made. See valid prefix list above. -# INDENT WITH TWO SPACES. NOT TABS. SPACES. -# SCREW THIS UP AND IT WON'T WORK. -# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. -# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. -changes: - - tweak: "When the supermatter explodes, it now leaves behind a shattered plinth that continues to emit radiation. You should probably get rid of it." - - bugfix: "If you destroy the supermatter early (e.g. through admin deletion shenanigans), it no longer irradiates everyone forever." - - bugfix: "Welding lockers now actually updates their sprite properly." - - tweak: "Every floor tile now has a minor (2%) chance to spawn with some dirt on it. The Janitor now has a job again." - - tweak: "Similarly, every Sif grass tile now has a minor (5%) chance to spawn with some fancy eyebulb grass on it. It can be removed by clicking on it with harm intent." - - rscadd: "Adds cats-in-boxes, which can be activated (once) to spawn cats. There's an orange tabby (Cargo cats) and a tuxedo (Runtime) version." - - bugfix: "Fixes a material duplication exploit." \ No newline at end of file diff --git a/html/create_object.html b/html/create_object.html index f4e0aa8644c..7ed93d98180 100644 --- a/html/create_object.html +++ b/html/create_object.html @@ -26,6 +26,7 @@
        + Type
        Offset: @@ -35,7 +36,7 @@ Number: Dir: - Name:
        + Name:
        Where:

        -
        + Number of matches:
        +

        + +
        + +
        + +