Merge branch 'master' of https://github.com/tgstation/-tg-station into VisionUpdateRefactor

Conflicts:
	code/_onclick/hud/alien.dm
	code/_onclick/hud/alien_larva.dm
	code/_onclick/hud/hud.dm
	code/_onclick/hud/human.dm
	code/_onclick/hud/monkey.dm
	code/_onclick/hud/other_mobs.dm
	code/_onclick/hud/robot.dm
	code/game/machinery/Sleeper.dm
	code/modules/mob/living/carbon/alien/larva/death.dm
	code/modules/mob/living/carbon/brain/death.dm
	code/modules/mob/living/carbon/human/death.dm
	code/modules/mob/living/carbon/human/life.dm
	code/modules/mob/living/carbon/human/species.dm
	code/modules/mob/living/carbon/life.dm
	code/modules/mob/living/carbon/monkey/death.dm
	code/modules/mob/living/death.dm
	code/modules/mob/living/life.dm
	code/modules/mob/living/silicon/ai/death.dm
	code/modules/mob/living/silicon/ai/life.dm
	code/modules/mob/living/silicon/ai/login.dm
	code/modules/mob/living/silicon/pai/death.dm
	code/modules/mob/living/silicon/robot/death.dm
	code/modules/mob/living/silicon/robot/robot.dm
	code/modules/mob/mob_defines.dm
This commit is contained in:
phil235
2016-02-06 15:42:13 +01:00
committed by phil235
232 changed files with 3352 additions and 3653 deletions
+1 -1
View File
@@ -177,7 +177,7 @@ var/list/admin_ranks = list() //list of all admin_rank datums
continue
//Split the line at every "="
var/list/List = text2list(line, "=")
var/list/List = splittext(line, "=")
if(!List.len)
continue
+1 -1
View File
@@ -596,7 +596,7 @@ var/list/admin_verbs_hideable = list(
//load text from file
var/list/Lines = file2list("config/admins.txt")
for(var/line in Lines)
var/list/splitline = text2list(line, " = ")
var/list/splitline = splittext(line, " = ")
if(ckey(splitline[1]) == ckey)
if(splitline.len >= 2)
rank = ckeyEx(splitline[2])
+1 -1
View File
@@ -2,7 +2,7 @@
/datum/admins/proc/create_mob(mob/user)
if (!create_mob_html)
var/mobjs = null
mobjs = list2text(typesof(/mob), ";")
mobjs = jointext(typesof(/mob), ";")
create_mob_html = file2text('html/create_object.html')
create_mob_html = replacetext(create_mob_html, "null /* object types */", "\"[mobjs]\"")
+2 -2
View File
@@ -7,7 +7,7 @@ var/list/create_object_forms = list(
/datum/admins/proc/create_object(mob/user)
if (!create_object_html)
var/objectjs = null
objectjs = list2text(typesof(/obj), ";")
objectjs = jointext(typesof(/obj), ";")
create_object_html = file2text('html/create_object.html')
create_object_html = replacetext(create_object_html, "null /* object types */", "\"[objectjs]\"")
@@ -19,7 +19,7 @@ var/list/create_object_forms = list(
var/html_form = create_object_forms[path]
if (!html_form)
var/objectjs = list2text(typesof(path), ";")
var/objectjs = jointext(typesof(path), ";")
html_form = file2text('html/create_object.html')
html_form = replacetext(html_form, "null /* object types */", "\"[objectjs]\"")
create_object_forms[path] = html_form
+1 -1
View File
@@ -2,7 +2,7 @@
/datum/admins/proc/create_turf(mob/user)
if (!create_turf_html)
var/turfjs = null
turfjs = list2text(typesof(/turf), ";")
turfjs = jointext(typesof(/turf), ";")
create_turf_html = file2text('html/create_object.html')
create_turf_html = replacetext(create_turf_html, "null /* object types */", "\"[turfjs]\"")
+7 -10
View File
@@ -169,9 +169,6 @@
output += ruler
usr << browse(output, "window=show_notes;size=900x500")
/proc/regex_note_sql_extract(str, exp)
return new /datum/regex(str, exp, call(LIBREGEX_LIBRARY, "regEx_find")(str, exp))
#define NOTESFILE "data/player_notes.sav"
//if the AUTOCONVERT_NOTES is turned on, anytime a player connects this will be run to try and add all their notes to the databas
/proc/convert_notes_sql(ckey)
@@ -184,13 +181,13 @@
var/notetext
notesfile >> notetext
var/server
if (config && config.server_name)
if(config && config.server_name)
server = config.server_name
var/regex = "^(\\d{2}-\\w{3}-\\d{4}) \\| (.+) ~(\\w+)$"
var/datum/regex/results = regex_note_sql_extract(notetext, regex)
var/timestamp = results.str(2)
notetext = results.str(3)
var/adminckey = results.str(4)
var/regex/note = new("^(\\d{2}-\\w{3}-\\d{4}) \\| (.+) ~(\\w+)$", "i")
note.Find(notetext)
var/timestamp = note.group[2]
notetext = note.group[3]
var/adminckey = note.group[4]
var/DBQuery/query_convert_time = dbcon.NewQuery("SELECT ADDTIME(STR_TO_DATE('[timestamp]','%d-%b-%Y'), '0')")
if(!query_convert_time.Execute())
var/err = query_convert_time.ErrorMsg()
@@ -217,4 +214,4 @@ this proc can take several minutes to execute fully if converting and cause DD t
world << "Deleting NOTESFILE"
fdel(NOTESFILE)
world << "Finished mass note conversion, remember to turn off AUTOCONVERT_NOTES"*/
#undef NOTESFILE
#undef NOTESFILE
+8 -8
View File
@@ -175,10 +175,10 @@
if (!ban)
return null
. = params2list(ban)
.["keys"] = text2list(.["keys"], ",")
.["type"] = text2list(.["type"], ",")
.["IP"] = text2list(.["IP"], ",")
.["computer_id"] = text2list(.["computer_id"], ",")
.["keys"] = splittext(.["keys"], ",")
.["type"] = splittext(.["type"], ",")
.["IP"] = splittext(.["IP"], ",")
.["computer_id"] = splittext(.["computer_id"], ",")
/proc/list2stickyban(var/list/ban)
@@ -186,13 +186,13 @@
return null
. = ban.Copy()
if (.["keys"])
.["keys"] = list2text(.["keys"], ",")
.["keys"] = jointext(.["keys"], ",")
if (.["type"])
.["type"] = list2text(.["type"], ",")
.["type"] = jointext(.["type"], ",")
if (.["IP"])
.["IP"] = list2text(.["IP"], ",")
.["IP"] = jointext(.["IP"], ",")
if (.["computer_id"])
.["computer_id"] = list2text(.["computer_id"], ",")
.["computer_id"] = jointext(.["computer_id"], ",")
. = list2params(.)
+1 -1
View File
@@ -1882,7 +1882,7 @@
alert("Select fewer object types, (max 5)")
return
var/list/offset = text2list(href_list["offset"],",")
var/list/offset = splittext(href_list["offset"],",")
var/number = Clamp(text2num(href_list["object_count"]), 1, 100)
var/X = offset.len > 0 ? text2num(offset[1]) : 0
var/Y = offset.len > 1 ? text2num(offset[2]) : 0
+2 -2
View File
@@ -4,7 +4,7 @@
var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","alien","as", "i")
//explode the input msg into a list
var/list/msglist = text2list(msg, " ")
var/list/msglist = splittext(msg, " ")
//generate keywords lookup
var/list/surnames = list()
@@ -16,7 +16,7 @@
indexing += M.mind.name
for(var/string in indexing)
var/list/L = text2list(string, " ")
var/list/L = splittext(string, " ")
var/surname_found = 0
//surnames
for(var/i=L.len, i>=1, i--)
+7 -7
View File
@@ -688,19 +688,19 @@ var/global/list/g_fancy_list_of_types = null
switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs","Clients","Joined Clients"))
if("Players")
usr << list2text(player_list,",")
usr << jointext(player_list,",")
if("Admins")
usr << list2text(admins,",")
usr << jointext(admins,",")
if("Mobs")
usr << list2text(mob_list,",")
usr << jointext(mob_list,",")
if("Living Mobs")
usr << list2text(living_mob_list,",")
usr << jointext(living_mob_list,",")
if("Dead Mobs")
usr << list2text(dead_mob_list,",")
usr << jointext(dead_mob_list,",")
if("Clients")
usr << list2text(clients,",")
usr << jointext(clients,",")
if("Joined Clients")
usr << list2text(joined_player_list,",")
usr << jointext(joined_player_list,",")
/client/proc/cmd_display_del_log()
set category = "Debug"
@@ -8,91 +8,92 @@ What are the archived variables for?
once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
var/list/meta_gas_info = meta_gas_list() //see ATMOSPHERICS/gas_types.dm
var/list/cached_gases_list = null
/proc/gaslist(gasid)
if(!cached_gases_list)
cached_gases_list = new /list(meta_gas_info.len)
var/list/gaslist_cache = null
/proc/gaslist(id)
var/list/cached_gas
if(!cached_gases_list[gasid])
if(!meta_gas_info[gasid])
CRASH("Error: no such gas type! Type : [gasid]")
if(!gaslist_cache)
gaslist_cache = new(meta_gas_info.len)
var/list/new_gas_list = new(3)
new_gas_list[MOLES] = 0
new_gas_list[ARCHIVE] = 0
new_gas_list[GAS_META] = meta_gas_info[gasid]
cached_gases_list[gasid] = new_gas_list
if(!gaslist_cache[id])
if(!meta_gas_info[id])
CRASH("Gas [id] does not exist!")
cached_gas = new(3)
gaslist_cache[id] = cached_gas
var/list/gas = cached_gases_list[gasid]
. = gas.Copy()
cached_gas[MOLES] = 0
cached_gas[ARCHIVE] = 0
cached_gas[GAS_META] = meta_gas_info[id]
else
cached_gas = gaslist_cache[id]
return cached_gas.Copy()
/datum/gas_mixture
var/list/gases
var/temperature //in Kelvin
var/temperature // degrees Kelvin
var/tmp/temperature_archived
var/volume
var/last_share
var/tmp/fuel_burnt
/datum/gas_mixture/New(Volume = CELL_VOLUME)
. = ..()
/datum/gas_mixture/New(volume = CELL_VOLUME)
..()
gases = new
temperature = 0
temperature_archived = 0
volume = Volume
src.volume = volume
last_share = 0
fuel_burnt = 0
//listmos procs
//listmos procs
//assert_gas(gas_id) - used to guarantee that the gas list for this id exists.
//Must be used before adding to a gas. May be used before reading from a gas.
//assert_gas(gas_id) - used to guarantee that the gas list for this id exists.
//Must be used before adding to a gas. May be used before reading from a gas.
/datum/gas_mixture/proc/assert_gas(gas_id)
var/cached_gases = gases
if(cached_gases[gas_id])
return
cached_gases[gas_id] = gaslist(gas_id) //see ATMOSPHERICS/gas_types.dm
//assert_gases(args) - shorthand for calling assert_gas() once for each gas type.
//assert_gases(args) - shorthand for calling assert_gas() once for each gas type.
/datum/gas_mixture/proc/assert_gases()
for(var/id in args)
assert_gas(id)
//add_gas(gas_id) - similar to assert_gas(), but does not check for an existing
//gas list for this id.
//Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
//add_gas(gas_id) - similar to assert_gas(), but does not check for an existing
//gas list for this id. This can clobber existing gases.
//Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
/datum/gas_mixture/proc/add_gas(gas_id)
gases[gas_id] = gaslist(gas_id)
//add_gases(args) - shorthand for calling add_gas() once for each gas_type.
//add_gases(args) - shorthand for calling add_gas() once for each gas_type.
/datum/gas_mixture/proc/add_gases()
for(var/id in args)
add_gas(id)
//garbage_collect() - removes any gas list which is empty.
//Must be used after subtracting from a gas. Must be used after assert_gas()
//if assert_gas() was called only to read from the gas.
//By removing empty gases, processing speed is increased.
//garbage_collect() - removes any gas list which is empty.
//Must be used after subtracting from a gas. Must be used after assert_gas()
//if assert_gas() was called only to read from the gas.
//By removing empty gases, processing speed is increased.
/datum/gas_mixture/proc/garbage_collect()
var/list/cached_gases = gases
for(var/id in cached_gases)
var/gas = cached_gases[id]
if(QUANTIZE(gas[MOLES]) <= 0 && QUANTIZE(gas[ARCHIVE]) <= 0)
if(cached_gases[id][MOLES] <= 0 && cached_gases[id][ARCHIVE] <= 0)
cached_gases -= id
//PV=nRT - related procedures
//PV = nRT
/datum/gas_mixture/proc/heat_capacity()
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
. += cached_gases[id][MOLES]*cached_gases[id][GAS_META][META_GAS_SPECIFIC_HEAT]
. += cached_gases[id][MOLES] * cached_gases[id][GAS_META][META_GAS_SPECIFIC_HEAT]
/datum/gas_mixture/proc/heat_capacity_archived()
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
. += cached_gases[id][ARCHIVE]*cached_gases[id][GAS_META][META_GAS_SPECIFIC_HEAT]
. += cached_gases[id][ARCHIVE] * cached_gases[id][GAS_META][META_GAS_SPECIFIC_HEAT]
/datum/gas_mixture/proc/total_moles()
var/list/cached_gases = gases
@@ -101,40 +102,38 @@ var/list/cached_gases_list = null
. += cached_gases[id][MOLES]
/datum/gas_mixture/proc/return_pressure()
if(volume>0)
return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume
if(volume > 0) // to prevent division by zero
return total_moles() * R_IDEAL_GAS_EQUATION * temperature / volume
return 0
/datum/gas_mixture/proc/return_temperature()
return temperature
/datum/gas_mixture/proc/return_volume()
return max(0, volume)
/datum/gas_mixture/proc/thermal_energy()
return temperature*heat_capacity()
return temperature * heat_capacity()
//Procedures used for very specific events
/datum/gas_mixture/proc/react(atom/dump_location)
var/list/procgases = gases //this speeds things up because >byond
var/list/cached_gases = gases //this speeds things up because >byond
var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network)
if(temperature < TCMB)
temperature = TCMB
if(procgases["agent_b"] && temperature > 900 && procgases["plasma"] && procgases["co2"])
if(procgases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY && procgases["co2"][MOLES] > MINIMUM_HEAT_CAPACITY)
var/reaction_rate = min(procgases["co2"][MOLES]*0.75, procgases["plasma"][MOLES]*0.25, procgases["agent_b"][MOLES]*0.05)
procgases["co2"][MOLES] -= reaction_rate
if(cached_gases["agent_b"] && temperature > 900 && cached_gases["plasma"] && cached_gases["co2"])
if(cached_gases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY && cached_gases["co2"][MOLES] > MINIMUM_HEAT_CAPACITY)
var/reaction_rate = min(cached_gases["co2"][MOLES]*0.75, cached_gases["plasma"][MOLES]*0.25, cached_gases["agent_b"][MOLES]*0.05)
cached_gases["co2"][MOLES] -= reaction_rate
assert_gas("o2") //only need to assert oxygen, as this reaction doesn't occur without the other gases existing
procgases["o2"][MOLES] += reaction_rate
cached_gases["o2"][MOLES] += reaction_rate
procgases["agent_b"][MOLES] -= reaction_rate*0.05
cached_gases["agent_b"][MOLES] -= reaction_rate*0.05
temperature -= (reaction_rate*20000)/heat_capacity()
@@ -143,26 +142,26 @@ var/list/cached_gases_list = null
reacting = 1
/*
if(thermal_energy() > (PLASMA_BINDING_ENERGY*10))
if(procgases["plasma"] && procgases["co2"] && procgases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY && procgases["co2"][MOLES] > MINIMUM_HEAT_CAPACITY && (procgases["plasma"][MOLES]+procgases["co2"][MOLES])/total_moles() >= FUSION_PURITY_THRESHOLD)//Fusion wont occur if the level of impurities is too high.
//world << "pre [temperature, [procgases["plasma"][MOLES]], [procgases["co2"][MOLES]]
if(cached_gases["plasma"] && cached_gases["co2"] && cached_gases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY && cached_gases["co2"][MOLES] > MINIMUM_HEAT_CAPACITY && (cached_gases["plasma"][MOLES]+cached_gases["co2"][MOLES])/total_moles() >= FUSION_PURITY_THRESHOLD)//Fusion wont occur if the level of impurities is too high.
//world << "pre [temperature, [cached_gases["plasma"][MOLES]], [cached_gases["co2"][MOLES]]
var/old_heat_capacity = heat_capacity()
var/carbon_efficency = min(procgases["plasma"][MOLES]/procgases["co2"][MOLES],MAX_CARBON_EFFICENCY)
var/carbon_efficency = min(cached_gases["plasma"][MOLES]/cached_gases["co2"][MOLES],MAX_CARBON_EFFICENCY)
var/reaction_energy = thermal_energy()
var/moles_impurities = total_moles()-(procgases["plasma"][MOLES]+procgases["co2"][MOLES])
var/moles_impurities = total_moles()-(cached_gases["plasma"][MOLES]+cached_gases["co2"][MOLES])
var/plasma_fused = (PLASMA_FUSED_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY)
var/carbon_catalyzed = (CARBON_CATALYST_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY)
var/oxygen_added = carbon_catalyzed
var/nitrogen_added = (plasma_fused-oxygen_added)-(thermal_energy()/PLASMA_BINDING_ENERGY)
reaction_energy = max(reaction_energy+((carbon_efficency*procgases["plasma"][MOLES])/((moles_impurities/carbon_efficency)+2)*10)+((plasma_fused/(moles_impurities/carbon_efficency))*PLASMA_BINDING_ENERGY),0)
reaction_energy = max(reaction_energy+((carbon_efficency*cached_gases["plasma"][MOLES])/((moles_impurities/carbon_efficency)+2)*10)+((plasma_fused/(moles_impurities/carbon_efficency))*PLASMA_BINDING_ENERGY),0)
assert_gases("o2", "n2")
procgases["plasma"][MOLES] -= plasma_fused
procgases["co2"][MOLES] -= carbon_catalyzed
procgases["o2"][MOLES] += oxygen_added
procgases["n2"][MOLES] += nitrogen_added
cached_gases["plasma"][MOLES] -= plasma_fused
cached_gases["co2"][MOLES] -= carbon_catalyzed
cached_gases["o2"][MOLES] += oxygen_added
cached_gases["n2"][MOLES] += nitrogen_added
garbage_collect()
@@ -172,45 +171,46 @@ var/list/cached_gases_list = null
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = max(((temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB)
//Prevents whatever mechanism is causing it to hit negative temperatures.
//world << "post [temperature], [procgases["plasma"][MOLES]], [procgases["co2"][MOLES]]
//world << "post [temperature], [cached_gases["plasma"][MOLES]], [cached_gases["co2"][MOLES]]
*/
fuel_burnt = 0
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
//world << "pre [temperature], [procgases["o2"][MOLES]], [procgases["plasma"][MOLES]]"
//world << "pre [temperature], [cached_gases["o2"][MOLES]], [cached_gases["plasma"][MOLES]]"
if(fire())
reacting = 1
//world << "post [temperature], [procgases["o2"][MOLES]], [procgases["plasma"][MOLES]]"
//world << "post [temperature], [cached_gases["o2"][MOLES]], [cached_gases["plasma"][MOLES]]"
return reacting
/datum/gas_mixture/proc/fire()
var/energy_released = 0
var/old_heat_capacity = heat_capacity()
var/list/procgases = gases //this speeds things up because accessing datum vars is slow
var/list/cached_gases = gases //this speeds things up because accessing datum vars is slow
if(procgases["v_fuel"] && procgases["v_fuel"][MOLES]) //General volatile gas burn
//General volatile gas burn
if(cached_gases["v_fuel"] && cached_gases["v_fuel"][MOLES])
var/burned_fuel
if(!procgases["o2"])
if(!cached_gases["o2"])
burned_fuel = 0
else if(procgases["o2"][MOLES] < procgases["v_fuel"][MOLES])
burned_fuel = procgases["o2"][MOLES]
procgases["v_fuel"][MOLES] -= burned_fuel
procgases["o2"][MOLES] = 0
else if(cached_gases["o2"][MOLES] < cached_gases["v_fuel"][MOLES])
burned_fuel = cached_gases["o2"][MOLES]
cached_gases["v_fuel"][MOLES] -= burned_fuel
cached_gases["o2"][MOLES] = 0
else
burned_fuel = procgases["v_fuel"][MOLES]
procgases["o2"][MOLES] -= procgases["v_fuel"][MOLES]
burned_fuel = cached_gases["v_fuel"][MOLES]
cached_gases["o2"][MOLES] -= cached_gases["v_fuel"][MOLES]
if(burned_fuel)
energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel
assert_gas("co2")
procgases["co2"][MOLES] += burned_fuel
cached_gases["co2"][MOLES] += burned_fuel
fuel_burnt += burned_fuel
//Handle plasma burning
if(procgases["plasma"] && procgases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY)
if(cached_gases["plasma"] && cached_gases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY)
var/plasma_burn_rate = 0
var/oxygen_burn_rate = 0
//more plasma released at higher temperatures
@@ -221,16 +221,16 @@ var/list/cached_gases_list = null
temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
if(temperature_scale > 0)
assert_gas("o2")
assert_gas("co2")
oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale
if(procgases["o2"][MOLES] > procgases["plasma"][MOLES]*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (procgases["plasma"][MOLES]*temperature_scale)/PLASMA_BURN_RATE_DELTA
if(cached_gases["o2"][MOLES] > cached_gases["plasma"][MOLES]*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (cached_gases["plasma"][MOLES]*temperature_scale)/PLASMA_BURN_RATE_DELTA
else
plasma_burn_rate = (temperature_scale*(procgases["o2"][MOLES]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
plasma_burn_rate = (temperature_scale*(cached_gases["o2"][MOLES]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
procgases["plasma"][MOLES] -= plasma_burn_rate
procgases["o2"][MOLES] -= plasma_burn_rate*oxygen_burn_rate
procgases["co2"][MOLES] += plasma_burn_rate
assert_gas("co2")
cached_gases["plasma"][MOLES] = QUANTIZE(cached_gases["plasma"][MOLES] - plasma_burn_rate)
cached_gases["o2"][MOLES] = QUANTIZE(cached_gases["o2"][MOLES] - (plasma_burn_rate * oxygen_burn_rate))
cached_gases["co2"][MOLES] += plasma_burn_rate
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
@@ -260,12 +260,20 @@ var/list/cached_gases_list = null
//Proportionally removes amount of gas from the gas_mixture
//Returns: gas_mixture with the gases removed
/datum/gas_mixture/proc/copy()
//Creates new, identical gas mixture
//Returns: duplicate gas mixture
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
//Copies variables from sample
/datum/gas_mixture/proc/copy_from_turf(turf/model)
//Copies all gas info from the turf into the gas list along with temperature
/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Return: amount of gas exchanged (+ if sharer received)
/datum/gas_mixture/proc/mimic(turf/model)
//Similar to share(...), except the model is not modified
//Return: amount of gas exchanged
@@ -283,138 +291,148 @@ var/list/cached_gases_list = null
//Compares sample to self to see if within acceptable ranges that group processing may be enabled
//returns: a string indicating what check failed, or "" if check passes
/datum/gas_mixture/proc/copy_from_turf(turf/model)
//Copies all gas info from the turf into the gas list along with copying temperature, then archives
/datum/gas_mixture/archive()
var/list/cached_gases = gases
temperature_archived = temperature
for(var/id in cached_gases)
cached_gases[id][ARCHIVE] = cached_gases[id][MOLES]
temperature_archived = temperature
. = 1
return 1
/datum/gas_mixture/merge(datum/gas_mixture/giver)
if(!giver)
return 0
if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
if(abs(temperature - giver.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = giver.heat_capacity()
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity)
temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
temperature = (giver.temperature * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/giver_gases = giver.gases
for(var/giver_id in giver_gases)
assert_gas(giver_id)
cached_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
. = 1
return 1
/datum/gas_mixture/remove(amount)
var/sum = total_moles()
amount = min(amount,sum) //Can not take more air than tile has!
amount = min(amount, sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/list/cached_gases = gases
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
for(var/id in cached_gases)
removed.assert_gas(id)
removed_gases[id][MOLES] = QUANTIZE((cached_gases[id][MOLES]/sum)*amount)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
removed.temperature = temperature
for(var/id in cached_gases)
removed.add_gas(id)
removed_gases[id][MOLES] = QUANTIZE((cached_gases[id][MOLES] / sum) * amount)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
. = removed
return removed
/datum/gas_mixture/remove_ratio(ratio)
if(ratio <= 0)
return null
ratio = min(ratio, 1)
var/list/cached_gases = gases
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
for(var/id in cached_gases)
removed.assert_gas(id)
removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES]*ratio)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
removed.temperature = temperature
for(var/id in cached_gases)
removed.add_gas(id)
removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES] * ratio)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
garbage_collect()
. = removed
return removed
/datum/gas_mixture/copy()
var/list/cached_gases = gases
var/datum/gas_mixture/copy = new
var/list/copy_gases = copy.gases
copy.temperature = temperature
for(var/id in cached_gases)
add_gas(id)
copy_gases[id][MOLES] = cached_gases[id][MOLES]
return copy
/datum/gas_mixture/copy_from(datum/gas_mixture/sample)
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/sample_gases = sample.gases
var/list/copied_gases = list()
for(var/sample_id in sample_gases)
assert_gas(sample_id)
cached_gases[sample_id][MOLES] = sample_gases[sample_id][MOLES]
copied_gases += sample_id
for(var/id in cached_gases-copied_gases)
assert_gas(id)
cached_gases[id][MOLES] = 0
garbage_collect()
temperature = sample.temperature
for(var/id in sample_gases)
assert_gas(id)
cached_gases[id][MOLES] = sample_gases[id][MOLES]
cached_gases &= sample_gases
return 1
/datum/gas_mixture/copy_from_turf(turf/model)
var/list/cached_gases = gases
temperature = model.temperature
assert_gases(arglist(hardcoded_gases))
cached_gases["o2"][MOLES] = model.oxygen
cached_gases["n2"][MOLES] = model.nitrogen
cached_gases["plasma"][MOLES] = model.toxins
cached_gases["co2"][MOLES] = model.carbon_dioxide
cached_gases &= hardcoded_gases
return 1
/datum/gas_mixture/check_turf(turf/model, atmos_adjacent_turfs = 4)
var/datum/gas_mixture/copied = new
copied.copy_from_turf(model)
. = compare(copied, datatype = ARCHIVE, adjacents = atmos_adjacent_turfs)
return compare(copied, datatype = ARCHIVE, adjacents = atmos_adjacent_turfs)
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
. = 0
if(!sharer)
return
return 0
var/moved_moles = 0
var/abs_moved_moles = 0
//make this local to the proc for sanic speed
var/list/sharercache = sharer.gases
var/list/selfcache = gases
var/list/cached_gases = gases
var/list/sharer_gases = sharer.gases
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/temperature_delta = temperature_archived - sharer.temperature_archived
var/abs_temperature_delta = abs(temperature_delta)
var/old_self_heat_capacity = 0
var/old_sharer_heat_capacity = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
old_self_heat_capacity = heat_capacity()
old_sharer_heat_capacity = sharer.heat_capacity()
var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer
var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us
for(var/sharer_id in sharercache-selfcache)
add_gas(sharer_id) //we can use add_gas() because we're looping only through the IDs not in our cache
var/moved_moles = 0
var/abs_moved_moles = 0
//GAS TRANSFER
for(var/id in selfcache)
if(!sharercache[id]) //checking here prevents an uneeded proc call if the check fails.
for(var/id in sharer_gases - cached_gases) // create gases not in our cache
add_gas(id)
for(var/id in cached_gases) // transfer gases
if(!sharer_gases[id]) //checking here prevents an uneeded proc call if the check fails.
sharer.add_gas(id)
var/gas = selfcache[id]
var/sharergas = sharercache[id]
var/gas = cached_gases[id]
var/sharergas = sharer_gases[id]
var/delta = QUANTIZE(gas[ARCHIVE] - sharergas[ARCHIVE])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
if(delta && abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
if(delta && abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/gas_heat_capacity = delta * gas[GAS_META][META_GAS_SPECIFIC_HEAT]
if(delta > 0)
heat_capacity_self_to_sharer += gas_heat_capacity
@@ -429,7 +447,7 @@ var/list/cached_gases_list = null
last_share = abs_moved_moles
//THERMAL ENERGY TRANSFER
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
if(abs_temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
@@ -445,9 +463,9 @@ var/list/cached_gases_list = null
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
temperature_share(sharer, OPEN_HEAT_TRANSFER_COEFFICIENT)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
if(temperature_delta > MINIMUM_TEMPERATURE_TO_MOVE || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles)
. = delta_pressure*R_IDEAL_GAS_EQUATION/volume
. = delta_pressure * R_IDEAL_GAS_EQUATION / volume
garbage_collect()
sharer.garbage_collect()
@@ -455,17 +473,17 @@ var/list/cached_gases_list = null
/datum/gas_mixture/mimic(turf/model, atmos_adjacent_turfs = 4)
var/datum/gas_mixture/copied = new
copied.copy_from_turf(model)
. = share(copied, atmos_adjacent_turfs)
return share(copied, atmos_adjacent_turfs)
/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
//transfer of thermal energy (via conduction) between self and sharer
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/temperature_delta = temperature_archived - sharer.temperature_archived
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
var/sharer_heat_capacity = sharer.heat_capacity_archived()
if((sharer_heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
var/heat = conduction_coefficient*temperature_delta* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
temperature = max(temperature - heat/self_heat_capacity, TCMB)
@@ -473,39 +491,38 @@ var/list/cached_gases_list = null
//thermal energy of the system (self and sharer) is unchanged
/datum/gas_mixture/temperature_mimic(turf/model, conduction_coefficient)
var/delta_temperature = (temperature - model.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/temperature_delta = temperature - model.temperature
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
if((model.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
var/heat = conduction_coefficient*temperature_delta* \
(self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
temperature = max(temperature - heat/self_heat_capacity, TCMB)
/datum/gas_mixture/temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/temperature_delta = temperature_archived - sharer.temperature
if(abs(temperature_delta) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity()
if((sharer.heat_capacity > MINIMUM_HEAT_CAPACITY) && (self_heat_capacity > MINIMUM_HEAT_CAPACITY))
var/heat = conduction_coefficient*delta_temperature* \
var/heat = conduction_coefficient*temperature_delta* \
(self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
temperature = max(temperature - heat/self_heat_capacity, TCMB)
sharer.temperature = max(sharer.temperature + heat/sharer.heat_capacity, TCMB)
/datum/gas_mixture/compare(datum/gas_mixture/sample, datatype = MOLES, adjacents = 0)
. = ""
var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
for(var/id in cached_gases|sample_gases)
for(var/id in cached_gases | sample_gases) // compare gases from either mixture
var/gas_moles = cached_gases[id] ? cached_gases[id][datatype] : 0
var/sample_moles = sample_gases[id] ? sample_gases[id][datatype] : 0
var/delta = abs(gas_moles - sample_moles)/(adjacents+1)
if(delta > MINIMUM_AIR_TO_SUSPEND && \
delta > gas_moles*MINIMUM_AIR_RATIO_TO_SUSPEND)
delta > gas_moles * MINIMUM_AIR_RATIO_TO_SUSPEND)
return id
if(total_moles() > MINIMUM_AIR_TO_SUSPEND)
@@ -520,50 +537,30 @@ var/list/cached_gases_list = null
temp = temperature_archived
sample_temp = sample.temperature_archived
var/delta_temperature = abs(temp-sample_temp)
if((delta_temperature > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
delta_temperature > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND*temp)
var/temperature_delta = abs(temp - sample_temp)
if((temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
temperature_delta > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND * temp)
return "temp"
/datum/gas_mixture/copy_from_turf(turf/model)
assert_gases(arglist(hardcoded_gases))
var/list/cached_gases = gases
return ""
cached_gases["o2"][MOLES] = model.oxygen
cached_gases["n2"][MOLES] = model.nitrogen
cached_gases["plasma"][MOLES] = model.toxins
cached_gases["co2"][MOLES] = model.carbon_dioxide
for(var/id in cached_gases-hardcoded_gases)
cached_gases[id][MOLES] = 0 //turfs don't account for anything other than the four old hardcoded gases
temperature = model.temperature
garbage_collect()
//Takes the amount of the gas you want to PP as an argument
//So I don't have to do some hacky switches/defines/magic strings
//eg:
//Tox_PP = get_partial_pressure(gas_mixture.toxins)
//O2_PP = get_partial_pressure(gas_mixture.oxygen)
//Does handle trace gases!
/datum/gas_mixture/proc/get_breath_partial_pressure(gas_pressure)
return (gas_pressure*R_IDEAL_GAS_EQUATION*temperature)/BREATH_VOLUME
//Reverse of the above
/datum/gas_mixture/proc/get_true_breath_pressure(breath_pp)
return (breath_pp*BREATH_VOLUME)/(R_IDEAL_GAS_EQUATION*temperature)
return (gas_pressure * R_IDEAL_GAS_EQUATION * temperature) / BREATH_VOLUME
//inverse
/datum/gas_mixture/proc/get_true_breath_pressure(partial_pressure)
return (partial_pressure * BREATH_VOLUME) / (R_IDEAL_GAS_EQUATION * temperature)
//Mathematical proofs:
/*
get_breath_partial_pressure(gas_pp) --> gas_pp/total_moles()*breath_pp = pp
get_true_breath_pressure(pp) --> gas_pp = pp/breath_pp*total_moles()
10/20*5 = 2.5
10 = 2.5/5*20
*/
@@ -1,19 +1,17 @@
var/list/hardcoded_gases = list("o2","n2","co2","plasma") //the main four gases, which were at one time hardcoded
/proc/meta_gas_list()
var/meta_list = new /list
. = new /list
for(var/gas_path in subtypesof(/datum/gas))
var/list/gas_info = new(4)
var/datum/gas/g = gas_path
var/datum/gas/gas = gas_path
gas_info[META_GAS_SPECIFIC_HEAT] = initial(g.specific_heat)
gas_info[META_GAS_NAME] = initial(g.name)
gas_info[META_GAS_MOLES_VISIBLE] = initial(g.moles_visible)
if(gas_info[META_GAS_MOLES_VISIBLE] != null)
gas_info[META_GAS_OVERLAY] = new /obj/effect/overlay/gas(initial(g.gas_overlay))
meta_list[initial(g.id)] = gas_info
. = meta_list
gas_info[META_GAS_SPECIFIC_HEAT] = initial(gas.specific_heat)
gas_info[META_GAS_NAME] = initial(gas.name)
gas_info[META_GAS_MOLES_VISIBLE] = initial(gas.moles_visible)
if(initial(gas.moles_visible) != null)
gas_info[META_GAS_OVERLAY] = new /obj/effect/overlay/gas(initial(gas.gas_overlay))
.[initial(gas.id)] = gas_info
/*||||||||||||||/----------\||||||||||||||*\
||||||||||||||||[GAS DATUMS]||||||||||||||||
+114 -154
View File
@@ -42,12 +42,6 @@
#define AALARM_MODE_CONTAMINATED 8 //Turns on all filtering and widenet scrubbing.
#define AALARM_MODE_REFILL 9 //just like normal, but with triple the air output
#define AALARM_SCREEN_MAIN 1
#define AALARM_SCREEN_VENT 2
#define AALARM_SCREEN_SCRUB 3
#define AALARM_SCREEN_MODE 4
#define AALARM_SCREEN_SENSORS 5
#define AALARM_REPORT_TIMEOUT 100
/obj/machinery/airalarm
@@ -74,7 +68,6 @@
var/mode = AALARM_MODE_SCRUBBING
var/screen = AALARM_SCREEN_MAIN
var/area_uid
var/area/alarm_area
var/danger_level = 0
@@ -179,148 +172,126 @@
ui = new(user, src, ui_key, "airalarm", name, 440, 650, master_ui, state)
ui.open()
/obj/machinery/airalarm/get_ui_data(mob/user)
/obj/machinery/airalarm/ui_data(mob/user)
var/data = list(
"locked" = locked,
"siliconUser" = user.has_unlimited_silicon_privilege,
"screen" = screen,
"emagged" = emagged
"emagged" = emagged,
"atmos_alarm" = alarm_area.atmosalm,
"fire_alarm" = alarm_area.fire,
"danger_level" = danger_level,
)
populate_status(data)
var/turf/T = get_turf(src)
var/datum/gas_mixture/environment = T.return_air()
var/datum/tlv/cur_tlv
data["environment_data"] = list()
var/pressure = environment.return_pressure()
cur_tlv = TLV["pressure"]
data["environment_data"] += list(list(
"name" = "Pressure",
"value" = pressure,
"unit" = "kPa",
"danger_level" = cur_tlv.get_danger_level(pressure)
))
var/temperature = environment.temperature
cur_tlv = TLV["temperature"]
data["environment_data"] += list(list(
"name" = "Temperature",
"value" = temperature,
"unit" = "K ([round(temperature - T0C, 0.1)]C)",
"danger_level" = cur_tlv.get_danger_level(temperature)
))
var/total_moles = environment.total_moles()
var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
for(var/gas_id in environment.gases)
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
continue
cur_tlv = TLV[gas_id]
data["environment_data"] += list(list(
"name" = environment.gases[gas_id][GAS_META][META_GAS_NAME],
"value" = environment.gases[gas_id][MOLES] / total_moles * 100,
"unit" = "%",
"danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id][MOLES] * partial_pressure)
))
if(!locked || user.has_unlimited_silicon_privilege)
populate_controls(data)
return data
data["vents"] = list()
for(var/id_tag in alarm_area.air_vent_names)
var/long_name = alarm_area.air_vent_names[id_tag]
var/list/info = alarm_area.air_vent_info[id_tag]
if(!info || info["frequency"] != frequency)
continue
data["vents"] += list(list(
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"checks" = info["checks"],
"excheck" = info["checks"]&1,
"incheck" = info["checks"]&2,
"direction" = info["direction"],
"external" = info["external"],
"extdefault"= (info["external"] == ONE_ATMOSPHERE)
))
data["scrubbers"] = list()
for(var/id_tag in alarm_area.air_scrub_names)
var/long_name = alarm_area.air_scrub_names[id_tag]
var/list/info = alarm_area.air_scrub_info[id_tag]
if(!info || info["frequency"] != frequency)
continue
data["scrubbers"] += list(list(
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"scrubbing" = info["scrubbing"],
"widenet" = info["widenet"],
"filter_co2" = info["filter_co2"],
"filter_toxins" = info["filter_toxins"],
"filter_n2o" = info["filter_n2o"]
))
data["mode"] = mode
data["modes"] = list()
data["modes"] += list(list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0))
data["modes"] += list(list("name" = "Contaminated - Scrubs out ALL contaminants quickly","mode" = AALARM_MODE_CONTAMINATED, "selected" = mode == AALARM_MODE_CONTAMINATED, "danger" = 0))
data["modes"] += list(list("name" = "Draught - Siphons out air while replacing", "mode" = AALARM_MODE_VENTING, "selected" = mode == AALARM_MODE_VENTING, "danger" = 0))
data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 0))
data["modes"] += list(list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 1))
data["modes"] += list(list("name" = "Siphon - Siphons air out of the room", "mode" = AALARM_MODE_SIPHON, "selected" = mode == AALARM_MODE_SIPHON, "danger" = 1))
data["modes"] += list(list("name" = "Panic Siphon - Siphons air out of the room quickly","mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1))
data["modes"] += list(list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0))
if(emagged)
data["modes"] += list(list("name" = "Flood - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FLOOD, "selected" = mode == AALARM_MODE_FLOOD, "danger" = 1))
/obj/machinery/airalarm/proc/populate_status(list/data)
var/turf/location = get_turf(src)
if(!location)
return
var/datum/gas_mixture/environment = location.return_air()
var/list/env_gases = environment.gases
var/total = environment.total_moles()
var/datum/tlv/selected
var/list/thresholds = list()
var/list/environment_data = list()
data["atmos_alarm"] = alarm_area.atmosalm
data["fire_alarm"] = (alarm_area.fire != null && alarm_area.fire)
data["danger_level"] = danger_level
if(total)
var/datum/tlv/cur_tlv
selected = TLV["pressure"]
thresholds += list(list("name" = "Pressure", "settings" = list()))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2))
var/partial_pressure = R_IDEAL_GAS_EQUATION * environment.temperature / environment.volume
selected = TLV["temperature"]
thresholds += list(list("name" = "Temperature", "settings" = list()))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2))
var/pressure = environment.return_pressure()
cur_tlv = TLV["pressure"]
environment_data += list(list(
"name" = "Pressure",
"value" = pressure,
"unit" = "kPa",
"danger_level" = cur_tlv.get_danger_level(pressure)
))
var/temperature = environment.temperature
cur_tlv = TLV["temperature"]
environment_data += list(list(
"name" = "Temperature",
"value" = temperature,
"unit" = "K ([round(temperature - T0C, 0.1)]C)",
"danger_level" = cur_tlv.get_danger_level(temperature)
))
for(var/gas_id in env_gases)
for(var/gas_id in meta_gas_info)
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
continue
cur_tlv = TLV[gas_id]
environment_data += list(list(
"name" = env_gases[gas_id][GAS_META][META_GAS_NAME],
"value" = env_gases[gas_id][MOLES] / total * 100,
"unit" = "%",
"danger_level" = cur_tlv.get_danger_level(env_gases[gas_id][MOLES] * partial_pressure)
))
selected = TLV[gas_id]
thresholds += list(list("name" = meta_gas_info[gas_id][META_GAS_NAME], "settings" = list()))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max2", "selected" = selected.max2))
data["environment_data"] = environment_data
/obj/machinery/airalarm/proc/populate_controls(list/data)
switch(screen)
if(AALARM_SCREEN_MAIN)
data["mode"] = mode
if(AALARM_SCREEN_VENT)
data["vents"] = list()
for(var/id_tag in alarm_area.air_vent_names)
var/long_name = alarm_area.air_vent_names[id_tag]
var/list/info = alarm_area.air_vent_info[id_tag]
if(!info || info["frequency"] != frequency)
continue
data["vents"] += list(list(
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"checks" = info["checks"],
"excheck" = info["checks"]&1,
"incheck" = info["checks"]&2,
"direction" = info["direction"],
"external" = info["external"],
"extdefault"= (info["external"] == ONE_ATMOSPHERE)
))
if(AALARM_SCREEN_SCRUB)
data["scrubbers"] = list()
for(var/id_tag in alarm_area.air_scrub_names)
var/long_name = alarm_area.air_scrub_names[id_tag]
var/list/info = alarm_area.air_scrub_info[id_tag]
if(!info || info["frequency"] != frequency)
continue
data["scrubbers"] += list(list(
"id_tag" = id_tag,
"long_name" = sanitize(long_name),
"power" = info["power"],
"scrubbing" = info["scrubbing"],
"widenet" = info["widenet"],
"filter_co2" = info["filter_co2"],
"filter_toxins" = info["filter_toxins"],
"filter_n2o" = info["filter_n2o"]
))
if(AALARM_SCREEN_MODE)
data["mode"] = mode
data["modes"] = list()
data["modes"] += list(list("name" = "Filtering - Scrubs out contaminants", "mode" = AALARM_MODE_SCRUBBING, "selected" = mode == AALARM_MODE_SCRUBBING, "danger" = 0))
data["modes"] += list(list("name" = "Contaminated - Scrubs out ALL contaminants quickly","mode" = AALARM_MODE_CONTAMINATED, "selected" = mode == AALARM_MODE_CONTAMINATED, "danger" = 0))
data["modes"] += list(list("name" = "Draught - Siphons out air while replacing", "mode" = AALARM_MODE_VENTING, "selected" = mode == AALARM_MODE_VENTING, "danger" = 0))
data["modes"] += list(list("name" = "Refill - Triple vent output", "mode" = AALARM_MODE_REFILL, "selected" = mode == AALARM_MODE_REFILL, "danger" = 0))
data["modes"] += list(list("name" = "Cycle - Siphons air before replacing", "mode" = AALARM_MODE_REPLACEMENT, "selected" = mode == AALARM_MODE_REPLACEMENT, "danger" = 1))
data["modes"] += list(list("name" = "Siphon - Siphons air out of the room", "mode" = AALARM_MODE_SIPHON, "selected" = mode == AALARM_MODE_SIPHON, "danger" = 1))
data["modes"] += list(list("name" = "Panic Siphon - Siphons air out of the room quickly","mode" = AALARM_MODE_PANIC, "selected" = mode == AALARM_MODE_PANIC, "danger" = 1))
data["modes"] += list(list("name" = "Off - Shuts off vents and scrubbers", "mode" = AALARM_MODE_OFF, "selected" = mode == AALARM_MODE_OFF, "danger" = 0))
if (src.emagged)
data["modes"] += list(list("name" = "Flood - Shuts off scrubbers and opens vents", "mode" = AALARM_MODE_FLOOD, "selected" = mode == AALARM_MODE_FLOOD, "danger" = 1))
if(AALARM_SCREEN_SENSORS)
var/datum/tlv/selected
var/list/thresholds = list()
selected = TLV["pressure"]
thresholds += list(list("name" = "Pressure", "settings" = list()))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min2", "selected" = selected.min2))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "min1", "selected" = selected.min1))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max1", "selected" = selected.max1))
thresholds[thresholds.len]["settings"] += list(list("env" = "pressure", "val" = "max2", "selected" = selected.max2))
selected = TLV["temperature"]
thresholds += list(list("name" = "Temperature", "settings" = list()))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min2", "selected" = selected.min2))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "min1", "selected" = selected.min1))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max1", "selected" = selected.max1))
thresholds[thresholds.len]["settings"] += list(list("env" = "temperature", "val" = "max2", "selected" = selected.max2))
for (var/gas_id in meta_gas_info)
if(!(gas_id in TLV)) // We're not interested in this gas, it seems.
continue
selected = TLV[gas_id]
thresholds += list(list("name" = meta_gas_info[gas_id][META_GAS_NAME], "settings" = list()))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min2", "selected" = selected.min2))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "min1", "selected" = selected.min1))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max1", "selected" = selected.max1))
thresholds[thresholds.len]["settings"] += list(list("env" = gas_id, "val" = "max2", "selected" = selected.max2))
data["thresholds"] = thresholds
data["thresholds"] = thresholds
return data
/obj/machinery/airalarm/ui_act(action, params)
if(..() || buildstage != 2)
@@ -363,9 +334,6 @@
else
tlv.vars[name] = round(value, 0.01)
. = TRUE
if("screen")
screen = text2num(params["screen"])
. = TRUE
if("mode")
mode = text2num(params["mode"])
apply_mode()
@@ -667,7 +635,6 @@
if(src.allowed(usr) && !wires.is_cut(WIRE_IDSCAN))
locked = !locked
user << "<span class='notice'>You [ locked ? "lock" : "unlock"] the air alarm interface.</span>"
src.updateUsrDialog()
else
user << "<span class='danger'>Access denied.</span>"
return
@@ -727,19 +694,12 @@
return ..()
/obj/machinery/airalarm/power_change()
if(powered(power_channel))
stat &= ~NOPOWER
else
stat |= NOPOWER
spawn(rand(0,15))
if(loc)
update_icon()
..()
update_icon()
/obj/machinery/airalarm/emag_act(mob/user)
if(!emagged)
src.emagged = 1
if(user)
user.visible_message("<span class='warning'>Sparks fly out of the [src]!</span>", "<span class='notice'>You emag the [src], disabling its safeties.</span>")
playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
if(emagged)
return
emagged = TRUE
visible_message("<span class='warning'>Sparks fly out of the [src]!</span>", "<span class='notice'>You emag the [src], disabling its safeties.</span>")
playsound(src.loc, 'sound/effects/sparks4.ogg', 50, 1)
@@ -27,10 +27,11 @@ Pipelines + Other Objects -> Pipe network
var/device_type = 0
var/list/obj/machinery/atmospherics/nodes = list()
/obj/machinery/atmospherics/New()
/obj/machinery/atmospherics/New(process = TRUE)
nodes.len = device_type
..()
SSair.atmos_machinery += src
if(process)
SSair.atmos_machinery += src
SetInitDirections()
if(can_unwrench)
stored = new(src, make_from=src)
@@ -99,7 +99,7 @@ Passive gate is similar to the regular pump except:
ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/passive_gate/get_ui_data()
/obj/machinery/atmospherics/components/binary/passive_gate/ui_data()
var/data = list()
data["on"] = on
data["pressure"] = round(target_pressure)
@@ -26,14 +26,15 @@ Thus, the two variables affect pump operation are set in New():
var/id = null
var/datum/radio_frequency/radio_connection
/obj/machinery/atmospherics/components/binary/pump/on
on = 1
/obj/machinery/atmospherics/components/binary/pump/Destroy()
if(SSradio)
SSradio.remove_object(src,frequency)
if(radio_connection)
radio_connection = null
return ..()
/obj/machinery/atmospherics/components/binary/pump/on
on = 1
/obj/machinery/atmospherics/components/binary/pump/update_icon_nopipes()
if(stat & NOPOWER)
@@ -105,7 +106,7 @@ Thus, the two variables affect pump operation are set in New():
ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/pump/get_ui_data()
/obj/machinery/atmospherics/components/binary/pump/ui_data()
var/data = list()
data["on"] = on
data["pressure"] = round(target_pressure)
@@ -101,7 +101,7 @@ Thus, the two variables affect pump operation are set in New():
ui = new(user, src, ui_key, "atmos_pump", name, 310, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/volume_pump/get_ui_data()
/obj/machinery/atmospherics/components/binary/volume_pump/ui_data()
var/data = list()
data["on"] = on
data["rate"] = round(transfer_rate)
@@ -112,7 +112,7 @@
ui = new(user, src, ui_key, "atmos_filter", name, 470, 140, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/filter/get_ui_data()
/obj/machinery/atmospherics/components/trinary/filter/ui_data()
var/data = list()
data["on"] = on
data["pressure"] = round(target_pressure)
@@ -146,10 +146,10 @@
if("filter")
filter_type = ""
var/filter_name = "nothing"
var/mode = params["mode"]
if(mode in meta_gas_info)
filter_type = mode
filter_name = meta_gas_info[mode][META_GAS_NAME]
var/gas = params["mode"]
if(gas in meta_gas_info)
filter_type = gas
filter_name = meta_gas_info[gas][META_GAS_NAME]
investigate_log("was set to filter [filter_name] by [key_name(usr)]", "atmos")
. = TRUE
update_icon()
@@ -123,7 +123,7 @@
ui = new(user, src, ui_key, "atmos_mixer", name, 370, 165, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/mixer/get_ui_data()
/obj/machinery/atmospherics/components/trinary/mixer/ui_data()
var/data = list()
data["on"] = on
data["set_pressure"] = round(target_pressure)
@@ -162,7 +162,7 @@
user << "[src] seems empty."
/obj/machinery/atmospherics/components/unary/cryo_cell/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(target))
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target))
return
close_machine(target)
@@ -198,7 +198,7 @@
ui = new(user, src, ui_key, "cryo", name, 400, 550, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/cryo_cell/get_ui_data()
/obj/machinery/atmospherics/components/unary/cryo_cell/ui_data()
var/list/data = list()
data["isOperating"] = on
data["hasOccupant"] = occupant ? 1 : 0
@@ -116,7 +116,7 @@
ui = new(user, src, ui_key, "thermomachine", name, 400, 240, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/thermomachine/get_ui_data(mob/user)
/obj/machinery/atmospherics/components/unary/thermomachine/ui_data(mob/user)
var/list/data = list()
data["on"] = on
@@ -1,176 +0,0 @@
/obj/machinery/computer/area_atmos
name = "area air control computer"
desc = "A computer used to control the stationary scrubbers and pumps in the area."
icon_screen = "area_atmos"
icon_keyboard = "atmos_key"
circuit = "/obj/item/weapon/circuitboard/area_atmos"
var/list/connectedscrubbers = new()
var/status = ""
var/range = 25
//Simple variable to prevent me from doing attack_hand in both this and the child computer
var/zone = "This computer is working on a wireless range, the range is currently limited to 25 meters."
/obj/machinery/computer/area_atmos/New()
..()
//So the scrubbers have time to spawn
spawn(10)
scanscrubbers()
/obj/machinery/computer/area_atmos/attack_hand(mob/user)
if(..())
return
src.add_fingerprint(usr)
var/dat = {"
<html>
<head>
<style type="text/css">
a.green:link
{
color:#00CC00;
}
a.green:visited
{
color:#00CC00;
}
a.green:hover
{
color:#00CC00;
}
a.green:active
{
color:#00CC00;
}
a.red:link
{
color:#FF0000;
}
a.red:visited
{
color:#FF0000;
}
a.red:hover
{
color:#FF0000;
}
a.red:active
{
color:#FF0000;
}
</style>
</head>
<body>
<center><h1>Area Air Control</h1></center>
<font color="red">[status]</font><br>
<a href="?src=\ref[src];scan=1">Scan</a>
<table border="1" width="90%">"}
for(var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber in connectedscrubbers)
dat += {"
<tr>
<td>[scrubber.name]</td>
<td width="150"><a class="green" href="?src=\ref[src];scrub=\ref[scrubber];toggle=1">Turn On</a> <a class="red" href="?src=\ref[src];scrub=\ref[scrubber];toggle=0">Turn Off</a></td>
</tr>"}
dat += {"
</table><br>
<i>[zone]</i>
</body>
</html>"}
user << browse("[dat]", "window=miningshuttle;size=400x400")
status = ""
/obj/machinery/computer/area_atmos/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["scan"])
scanscrubbers()
else if(href_list["toggle"])
var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber = locate(href_list["scrub"])
if(!validscrubber(scrubber))
spawn(20)
status = "ERROR: Couldn't connect to scrubber! (timeout)"
connectedscrubbers -= scrubber
src.updateUsrDialog()
return
scrubber.on = text2num(href_list["toggle"])
scrubber.update_icon()
/obj/machinery/computer/area_atmos/proc/validscrubber( obj/machinery/portable_atmospherics/scrubber/huge/scrubber )
if(!isobj(scrubber) || get_dist(scrubber.loc, src.loc) > src.range || scrubber.loc.z != src.loc.z)
return 0
return 1
/obj/machinery/computer/area_atmos/proc/scanscrubbers()
connectedscrubbers = new()
var/found = 0
for(var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber in ultra_range(range, src.loc))
if(istype(scrubber))
found = 1
connectedscrubbers += scrubber
if(!found)
status = "ERROR: No scrubber found!"
src.updateUsrDialog()
/obj/machinery/computer/area_atmos/area
zone = "This computer is working in a wired network limited to this area."
validscrubber( obj/machinery/portable_atmospherics/scrubber/huge/scrubber )
if(!isobj(scrubber))
return 0
/*
wow this is stupid, someone help me
*/
var/turf/T_src = get_turf(src)
if(!T_src.loc) return 0
var/area/A_src = T_src.loc
if (A_src.master)
A_src = A_src.master
var/turf/T_scrub = get_turf(scrubber)
if(!T_scrub.loc) return 0
var/area/A_scrub = T_scrub.loc
if (A_scrub.master)
A_scrub = A_scrub.master
if(A_scrub != A_src)
return 0
return 1
/obj/machinery/computer/area_atmos/area/scanscrubbers()
connectedscrubbers = new()
var/found = 0
var/turf/T = get_turf(src)
if(!T.loc) return
var/area/A = T.loc
if (A.master)
A = A.master
for(var/obj/machinery/portable_atmospherics/scrubber/huge/scrubber in machines )
var/turf/T2 = get_turf(scrubber)
if(T2 && T2.loc)
var/area/A2 = T2.loc
if(istype(A2) && A2.master && A2.master == A )
connectedscrubbers += scrubber
found = 1
if(!found)
status = "ERROR: No scrubber found!"
src.updateUsrDialog()
@@ -1,25 +1,27 @@
#define CAN_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*10)
#define CAN_MIN_RELEASE_PRESSURE (ONE_ATMOSPHERE/10)
#define CAN_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE * 10)
#define CAN_MIN_RELEASE_PRESSURE (ONE_ATMOSPHERE / 10)
#define CAN_DEFAULT_RELEASE_PRESSURE (ONE_ATMOSPHERE)
/obj/machinery/portable_atmospherics/canister
name = "canister"
desc = "A canister for the storage of gas."
icon = 'icons/obj/atmos.dmi'
icon_state = "yellow"
density = 1
var/health = 100
var/valve_open = 0
var/release_pressure = ONE_ATMOSPHERE
var/canister_color = "yellow"
var/filled = 0.5
pressure_resistance = 7*ONE_ATMOSPHERE
var/temperature_resistance = 1000 + T0C
volume = 1000
use_power = 0
var/valve_open = FALSE
var/obj/machinery/atmospherics/components/binary/pump/pump
var/release_log = ""
var/update_flag = 0
volume = 1000
var/filled = 0.5
var/gas_type = ""
var/release_pressure = ONE_ATMOSPHERE
var/health = 100
pressure_resistance = 7 * ONE_ATMOSPHERE
var/temperature_resistance = 1000 + T0C
var/update = 0
var/static/list/label2types = list(
"n2" = /obj/machinery/portable_atmospherics/canister/nitrogen,
"o2" = /obj/machinery/portable_atmospherics/canister/oxygen,
@@ -34,25 +36,21 @@
name = "n2 canister"
desc = "Nitrogen gas. Reportedly useful for something."
icon_state = "red"
canister_color = "red"
gas_type = "n2"
/obj/machinery/portable_atmospherics/canister/oxygen
name = "o2 canister"
desc = "Oxygen. Necessary for human life."
icon_state = "blue"
canister_color = "blue"
gas_type = "o2"
/obj/machinery/portable_atmospherics/canister/carbon_dioxide
name = "co2 canister"
desc = "Carbon dioxide. What the fuck is carbon dioxide?"
icon_state = "black"
canister_color = "black"
gas_type = "co2"
/obj/machinery/portable_atmospherics/canister/toxins
name = "plasma canister"
desc = "Plasma gas. The reason YOU are here. Highly toxic."
icon_state = "orange"
canister_color = "orange"
gas_type = "plasma"
/obj/machinery/portable_atmospherics/canister/agent_b
name = "agent b canister"
@@ -62,75 +60,87 @@
name = "n2o canister"
desc = "Nitrous oxide gas. Known to cause drowsiness."
icon_state = "redws"
canister_color = "redws"
gas_type = "n2o"
/obj/machinery/portable_atmospherics/canister/air
name = "air canister"
desc = "Pre-mixed air."
icon_state = "grey"
canister_color = "grey"
/obj/machinery/portable_atmospherics/canister/proc/check_change()
var/old_flag = update_flag
update_flag = 0
if(holding)
update_flag |= 1
if(connected_port)
update_flag |= 2
/obj/machinery/portable_atmospherics/canister/New(loc)
..()
create_gas()
pump = new(src, FALSE)
pump.on = TRUE
pump.stat = 0
pump.build_network()
update_icon()
var/tank_pressure = air_contents.return_pressure()
if(tank_pressure < 10)
update_flag |= 4
else if(tank_pressure < ONE_ATMOSPHERE)
update_flag |= 8
else if(tank_pressure < 15*ONE_ATMOSPHERE)
update_flag |= 16
else
update_flag |= 32
/obj/machinery/portable_atmospherics/canister/Destroy()
qdel(pump)
pump = null
return ..()
if(update_flag == old_flag)
return 1
else
return 0
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
if(gas_type)
air_contents.assert_gas(gas_type)
air_contents.gases[gas_type][MOLES] = (maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
/obj/machinery/portable_atmospherics/canister/air/create_gas()
air_contents.assert_gases("o2","n2")
air_contents.gases["o2"][MOLES] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.gases["n2"][MOLES] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
#define HOLDING 1
#define CONNECTED 2
#define EMPTY 4
#define LOW 8
#define FULL 16
#define DANGER 32
/obj/machinery/portable_atmospherics/canister/update_icon()
/*
update_flag
1 = holding
2 = connected_port
4 = tank_pressure < 10
8 = tank_pressure < ONE_ATMOS
16 = tank_pressure < 15*ONE_ATMOS
32 = tank_pressure go boom.
*/
if (destroyed)
overlays = 0
icon_state = text("[]-1", canister_color)
if(destroyed)
overlays.Cut()
icon_state = "[initial(icon_state)]-1"
return
if(icon_state != "[canister_color]")
icon_state = "[canister_color]"
var/last_update = update
update = 0
if(check_change()) //Returns 1 if no change needed to icons.
if(holding)
update |= HOLDING
if(connected_port)
update |= CONNECTED
var/pressure = air_contents.return_pressure()
if(pressure < 10)
update |= EMPTY
else if(pressure < ONE_ATMOSPHERE)
update |= LOW
else if(pressure < 15 * ONE_ATMOSPHERE)
update |= FULL
else
update |= DANGER
if(update == last_update)
return
src.overlays = 0
if(update_flag & 1)
overlays.Cut()
if(update & HOLDING)
overlays += "can-open"
if(update_flag & 2)
if(update & CONNECTED)
overlays += "can-connector"
if(update_flag & 4)
if(update & EMPTY)
overlays += "can-o0"
if(update_flag & 8)
else if(update & LOW)
overlays += "can-o1"
else if(update_flag & 16)
else if(update & FULL)
overlays += "can-o2"
else if(update_flag & 32)
else if(update & DANGER)
overlays += "can-o3"
return
#undef HOLDING
#undef CONNECTED
#undef EMPTY
#undef LOW
#undef FULL
#undef DANGER
/obj/machinery/portable_atmospherics/canister/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > temperature_resistance)
@@ -139,86 +149,47 @@ update_flag
/obj/machinery/portable_atmospherics/canister/proc/healthcheck()
if(destroyed)
return 1
return
if (src.health <= 10)
var/atom/location = src.loc
location.assume_air(air_contents)
if(health <= 10)
var/turf/T = get_turf(src)
T.assume_air(air_contents)
air_update_turf()
src.destroyed = 1
destroyed = TRUE
density = 0
playsound(src.loc, 'sound/effects/spray.ogg', 10, 1, -3)
src.density = 0
update_icon()
investigate_log("was destroyed by heat/gunfire.", "atmos")
investigate_log("was destroyed.", "atmos")
if (src.holding)
src.holding.loc = src.loc
src.holding = null
return 1
else
return 1
if(holding)
holding.loc = T
holding = null
/obj/machinery/portable_atmospherics/canister/process_atmos()
if (destroyed)
if(destroyed)
return PROCESS_KILL
if(!valve_open)
return
..()
var/turf/T = get_turf(src)
pump.AIR1 = air_contents
pump.AIR2 = holding ? holding.air_contents : T.return_air()
pump.target_pressure = release_pressure
if(valve_open)
var/datum/gas_mixture/environment
if(holding)
environment = holding.air_contents
else
environment = loc.return_air()
var/env_pressure = environment.return_pressure()
var/pressure_delta = min(release_pressure - env_pressure, (air_contents.return_pressure() - env_pressure)/2)
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if((air_contents.temperature > 0) && (pressure_delta > 0))
transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
if(holding)
environment.merge(removed)
else
loc.assume_air(removed)
air_update_turf()
update_icon()
/obj/machinery/portable_atmospherics/canister/process()
src.updateDialog()
return ..()
/obj/machinery/portable_atmospherics/canister/return_air()
return air_contents
/obj/machinery/portable_atmospherics/canister/proc/return_temperature()
var/datum/gas_mixture/GM = src.return_air()
if(GM && GM.volume>0)
return GM.temperature
return 0
/obj/machinery/portable_atmospherics/canister/proc/return_pressure()
var/datum/gas_mixture/GM = src.return_air()
if(GM && GM.volume>0)
return GM.return_pressure()
return 0
pump.process_atmos() // Pump gas.
if(!holding)
air_update_turf() // Update the environment if needed.
update_icon()
/obj/machinery/portable_atmospherics/canister/blob_act()
src.health -= 200
health = 0
healthcheck()
return
/obj/machinery/portable_atmospherics/canister/bullet_act(obj/item/projectile/Proj)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
if(Proj.damage)
src.health -= round(Proj.damage / 2)
/obj/machinery/portable_atmospherics/canister/bullet_act(obj/item/projectile/P)
if((P.damage_type == BRUTE || P.damage_type == BURN))
if(P.damage)
health -= round(P.damage / 2)
healthcheck()
..()
@@ -227,55 +198,37 @@ update_flag
if(1)
if(destroyed || prob(30))
qdel(src)
return
else
src.health = 0
healthcheck()
return
health = 0
if(2)
if(destroyed)
qdel(src)
return
else
src.health -= rand(40, 100)
healthcheck()
return
health -= rand(40, 100)
if(3)
src.health -= rand(15,40)
healthcheck()
return
return
health -= rand(15, 40)
healthcheck()
/obj/machinery/portable_atmospherics/canister/attackby(obj/item/weapon/W, mob/user, params)
if(!istype(W, /obj/item/weapon/wrench) && !istype(W, /obj/item/weapon/tank) && !istype(W, /obj/item/device/analyzer) && !istype(W, /obj/item/device/pda))
investigate_log("was smacked with \a [W] by [key_name(user)]", "atmos")
investigate_log("was smacked with \a [W] by [key_name(user)].", "atmos")
health -= W.force
add_fingerprint(user)
healthcheck()
if(istype(user, /mob/living/silicon/robot) && istype(W, /obj/item/weapon/tank/jetpack))
var/datum/gas_mixture/thejetpack = W:air_contents
var/env_pressure = thejetpack.return_pressure()
var/pressure_delta = min(10*ONE_ATMOSPHERE - env_pressure, (air_contents.return_pressure() - env_pressure)/2)
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if((air_contents.temperature > 0) && (pressure_delta > 0))
transfer_moles = pressure_delta*thejetpack.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)//Actually transfer the gas
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
thejetpack.merge(removed)
user << "<span class='notice'>You pulse-pressurize your jetpack from the tank.</span>"
return
..()
else
..()
/obj/machinery/portable_atmospherics/canister/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "canister", name, 415, 405, master_ui, state)
ui = new(user, src, ui_key, "canister", name, 420, 405, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/canister/get_ui_data()
/obj/machinery/portable_atmospherics/canister/ui_data()
var/data = list()
data["name"] = name
data["portConnected"] = connected_port ? 1 : 0
data["tankPressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
data["releasePressure"] = round(release_pressure ? release_pressure : 0)
@@ -302,7 +255,6 @@ update_flag
if(newtype)
var/obj/machinery/portable_atmospherics/canister/replacement = new newtype(loc)
replacement.air_contents.copy_from(air_contents)
replacement.update_icon()
replacement.interact(usr)
qdel(src)
if("pressure")
@@ -325,7 +277,7 @@ update_flag
. = TRUE
if(.)
release_pressure = Clamp(round(pressure), CAN_MIN_RELEASE_PRESSURE, CAN_MAX_RELEASE_PRESSURE)
investigate_log("was set to [release_pressure] kPa by [key_name(usr)]", "atmos")
investigate_log("was set to [release_pressure] kPa by [key_name(usr)].", "atmos")
if("valve")
var/logmsg
valve_open = !valve_open
@@ -346,25 +298,7 @@ update_flag
if(holding)
if(valve_open)
investigate_log("[key_name(usr)] removed the [holding], leaving the valve open and transfering into the <span class='boldannounce'>air</span><br>", "atmos")
holding.loc = loc
holding.loc = get_turf(src)
holding = null
. = TRUE
update_icon()
/obj/machinery/portable_atmospherics/canister/New(loc)
..()
create_gas()
update_icon()
return 1
/obj/machinery/portable_atmospherics/canister/proc/create_gas()
if(gas_type)
air_contents.assert_gas(gas_type)
air_contents.gases[gas_type][MOLES] = (src.maximum_pressure*filled)*air_contents.volume/(R_IDEAL_GAS_EQUATION*air_contents.temperature)
/obj/machinery/portable_atmospherics/canister/air/create_gas()
air_contents.assert_gases("o2","n2")
// PV = nRT
air_contents.gases["o2"][MOLES] = (O2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
air_contents.gases["n2"][MOLES] = (N2STANDARD * maximum_pressure * filled) * air_contents.volume / (R_IDEAL_GAS_EQUATION * air_contents.temperature)
@@ -1,16 +1,16 @@
/obj/machinery/portable_atmospherics
name = "atmoalter"
name = "portable_atmospherics"
icon = 'icons/obj/atmos.dmi'
use_power = 0
var/datum/gas_mixture/air_contents = new
var/datum/gas_mixture/air_contents = new
var/obj/machinery/atmospherics/components/unary/portables_connector/connected_port
var/obj/item/weapon/tank/holding
var/volume = 0
var/destroyed = 0
var/maximum_pressure = 90*ONE_ATMOSPHERE
var/lastupdate = 0
var/maximum_pressure = 90 * ONE_ATMOSPHERE
/obj/machinery/portable_atmospherics/New()
..()
@@ -20,20 +20,19 @@
return 1
/obj/machinery/portable_atmospherics/process_atmos()
if(!connected_port) //only react when pipe_network will not it do it for you
//Allow for reactions
if(!connected_port) // Pipe network handles reactions if connected.
air_contents.react()
else
update_icon()
/obj/machinery/portable_atmospherics/process()
return
/obj/machinery/portable_atmospherics/Destroy()
qdel(air_contents)
air_contents = null
SSair.atmos_machinery -= src
return ..()
/obj/machinery/portable_atmospherics/update_icon()
return null
/obj/machinery/portable_atmospherics/return_air()
return air_contents
/obj/machinery/portable_atmospherics/proc/connect(obj/machinery/atmospherics/components/unary/portables_connector/new_port)
//Make sure not already connected to something else
@@ -65,19 +64,14 @@
return air_contents
/obj/machinery/portable_atmospherics/attackby(obj/item/weapon/W, mob/user, params)
if ((istype(W, /obj/item/weapon/tank) && !( src.destroyed )))
if (src.holding)
return
if(!user.drop_item())
return
if((istype(W, /obj/item/weapon/tank) && !destroyed))
var/obj/item/weapon/tank/T = W
if(holding || !user.drop_item())
return
T.loc = src
src.holding = T
holding = T
update_icon()
return
else if (istype(W, /obj/item/weapon/wrench))
else if(istype(W, /obj/item/weapon/wrench))
if(connected_port)
disconnect()
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
@@ -89,24 +83,19 @@
return
else
var/obj/machinery/atmospherics/components/unary/portables_connector/possible_port = locate(/obj/machinery/atmospherics/components/unary/portables_connector) in loc
if(possible_port)
if(connect(possible_port))
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user.visible_message( \
"[user] connects [src].", \
"<span class='notice'>You fasten [src] to the port.</span>", \
"<span class='italics'>You hear a ratchet.</span>")
update_icon()
return
else
user << "<span class='notice'>[name] failed to connect to the port.</span>"
return
else
if(!possible_port)
user << "<span class='notice'>Nothing happens.</span>"
return
else if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1)
if(!connect(possible_port))
user << "<span class='notice'>[name] failed to connect to the port.</span>"
return
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user.visible_message( \
"[user] connects [src].", \
"<span class='notice'>You fasten [src] to the port.</span>", \
"<span class='italics'>You hear a ratchet.</span>")
update_icon()
else if((istype(W, /obj/item/device/analyzer)) && Adjacent(user))
atmosanalyzer_scan(air_contents, user)
else
..()
@@ -1,157 +1,139 @@
#define PUMP_OUT "out"
#define PUMP_IN "in"
#define PUMP_MAX_PRESSURE (ONE_ATMOSPHERE * 10)
#define PUMP_MIN_PRESSURE (ONE_ATMOSPHERE / 10)
#define PUMP_DEFAULT_PRESSURE (ONE_ATMOSPHERE)
/obj/machinery/portable_atmospherics/pump
name = "portable air pump"
icon = 'icons/obj/atmos.dmi'
icon_state = "psiphon:0"
density = 1
var/on = 0
var/direction_out = 0 //0 = siphoning, 1 = releasing
var/target_pressure = 100
var/on = FALSE
var/direction = PUMP_OUT
var/obj/machinery/atmospherics/components/binary/pump/pump
volume = 1000
/obj/machinery/portable_atmospherics/pump/New()
..()
pump = new(src, FALSE)
pump.on = TRUE
pump.stat = 0
pump.build_network()
/obj/machinery/portable_atmospherics/pump/Destroy()
var/turf/T = get_turf(src)
T.assume_air(air_contents)
air_update_turf()
qdel(pump)
pump = null
return ..()
/obj/machinery/portable_atmospherics/pump/update_icon()
src.overlays = 0
if(on)
icon_state = "psiphon:1"
else
icon_state = "psiphon:0"
icon_state = "psiphon:[on]"
overlays.Cut()
if(holding)
overlays += "siphon-open"
if(connected_port)
overlays += "siphon-connector"
return
/obj/machinery/portable_atmospherics/pump/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
..(severity)
return
if(prob(50/severity))
on = !on
if(prob(100/severity))
direction_out = !direction_out
target_pressure = rand(0,1300)
update_icon()
..(severity)
/obj/machinery/portable_atmospherics/pump/process_atmos()
..()
if(on)
var/datum/gas_mixture/environment
if(holding)
environment = holding.air_contents
else
environment = loc.return_air()
if(direction_out)
var/pressure_delta = target_pressure - environment.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
if(!on)
return
var/transfer_moles = 0
if(air_contents.temperature > 0)
transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
var/turf/T = get_turf(src)
if(direction == PUMP_OUT) // Hook up the internal pump.
pump.AIR1 = holding ? holding.air_contents : air_contents
pump.AIR2 = holding ? air_contents : T.return_air()
else
pump.AIR1 = holding ? air_contents : T.return_air()
pump.AIR2 = holding ? holding.air_contents : air_contents
//Actually transfer the gas
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
pump.process_atmos() // Pump gas.
if(!holding)
air_update_turf() // Update the environment if needed.
if(holding)
environment.merge(removed)
else
loc.assume_air(removed)
air_update_turf()
else
var/pressure_delta = target_pressure - air_contents.return_pressure()
//Can not have a pressure delta that would cause environment pressure > tank pressure
var/transfer_moles = 0
if(environment.temperature > 0)
transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
//Actually transfer the gas
var/datum/gas_mixture/removed
if(holding)
removed = environment.remove(transfer_moles)
else
removed = loc.remove_air(transfer_moles)
air_update_turf()
air_contents.merge(removed)
//src.update_icon()
/obj/machinery/portable_atmospherics/pump/process()
/obj/machinery/portable_atmospherics/pump/emp_act(severity)
if(is_operational())
if(prob(50 / severity))
on = !on
if(prob(100 / severity))
direction = PUMP_OUT
pump.target_pressure = rand(0, 100 * ONE_ATMOSPHERE)
update_icon()
..()
src.updateDialog()
return
/obj/machinery/portable_atmospherics/pump/return_air()
return air_contents
/obj/machinery/portable_atmospherics/pump/attack_ai(mob/user)
return src.attack_hand(user)
/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_pump", name, 420, 415, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/pump/attack_paw(mob/user)
return src.attack_hand(user)
/obj/machinery/portable_atmospherics/pump/attack_hand(mob/user)
user.set_machine(src)
var/holding_text
/obj/machinery/portable_atmospherics/pump/ui_data()
var/data = list()
data["on"] = on
data["direction"] = direction
data["connected"] = connected_port ? 1 : 0
data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
data["target_pressure"] = round(pump.target_pressure ? pump.target_pressure : 0)
data["default_pressure"] = round(PUMP_DEFAULT_PRESSURE)
data["min_pressure"] = round(PUMP_MIN_PRESSURE)
data["max_pressure"] = round(PUMP_MAX_PRESSURE)
if(holding)
holding_text = {"<BR><B>Tank Pressure</B>: [holding.air_contents.return_pressure()] KPa<BR>
<A href='?src=\ref[src];remove_tank=1'>Remove Tank</A><BR>
"}
var/output_text = {"<TT><B>[name]</B><BR>
Pressure: [air_contents.return_pressure()] KPa<BR>
Port Status: [(connected_port)?("Connected"):("Disconnected")]
[holding_text]
<BR>
Power Switch: <A href='?src=\ref[src];power=1'>[on?("On"):("Off")]</A><BR>
Pump Direction: <A href='?src=\ref[src];direction=1'>[direction_out?("Out"):("In")]</A><BR>
Target Pressure: <A href='?src=\ref[src];pressure_adj=-1000'>-</A> <A href='?src=\ref[src];pressure_adj=-100'>-</A> <A href='?src=\ref[src];pressure_adj=-10'>-</A> <A href='?src=\ref[src];pressure_adj=-1'>-</A> [target_pressure] <A href='?src=\ref[src];pressure_adj=1'>+</A> <A href='?src=\ref[src];pressure_adj=10'>+</A> <A href='?src=\ref[src];pressure_adj=100'>+</A> <A href='?src=\ref[src];pressure_adj=1000'>+</A><BR>
<HR>
<A href='?src=\ref[user];mach_close=pump'>Close</A><BR>
"}
data["holding"] = list()
data["holding"]["name"] = holding.name
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
return data
user << browse(output_text, "window=pump;size=600x300")
onclose(user, "pump")
return
/obj/machinery/portable_atmospherics/pump/Topic(href, href_list)
..()
if (usr.stat || usr.restrained())
/obj/machinery/portable_atmospherics/pump/ui_act(action, params)
if(..())
return
if (((get_dist(src, usr) <= 1) && istype(src.loc, /turf)))
usr.set_machine(src)
if(href_list["power"])
switch(action)
if("power")
on = !on
if(href_list["direction"])
direction_out = !direction_out
if (href_list["remove_tank"])
if(on && !holding)
var/plasma = air_contents.gases["plasma"]
var/n2o = air_contents.gases["n2o"]
if(n2o || plasma)
message_admins("[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""]! (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
log_admin("[key_name(usr)] turned on a pump that contains [n2o ? "N2O" : ""][n2o && plasma ? " & " : ""][plasma ? "Plasma" : ""] at [x], [y], [z]")
. = TRUE
if("direction")
if(direction == PUMP_OUT)
direction = PUMP_IN
else
direction = PUMP_OUT
. = TRUE
if("pressure")
var/pressure = params["pressure"]
if(pressure == "reset")
pressure = PUMP_DEFAULT_PRESSURE
. = TRUE
else if(pressure == "min")
pressure = PUMP_MIN_PRESSURE
. = TRUE
else if(pressure == "max")
pressure = PUMP_MAX_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New release pressure ([PUMP_MIN_PRESSURE]-[PUMP_MAX_PRESSURE] kPa):", name, pump.target_pressure) as num|null
if(!isnull(pressure) && !..())
. = TRUE
else if(text2num(pressure) != null)
pressure = text2num(pressure)
. = TRUE
if(.)
pump.target_pressure = Clamp(round(pressure), PUMP_MIN_PRESSURE, PUMP_MAX_PRESSURE)
investigate_log("was set to [pump.target_pressure] kPa by [key_name(usr)].", "atmos")
if("eject")
if(holding)
holding.loc = loc
holding.loc = get_turf(src)
holding = null
if (href_list["pressure_adj"])
var/diff = text2num(href_list["pressure_adj"])
target_pressure = min(10*ONE_ATMOSPHERE, max(0, target_pressure+diff))
src.updateUsrDialog()
src.add_fingerprint(usr)
update_icon()
else
usr << browse(null, "window=pump")
return
return
. = TRUE
update_icon()
@@ -1,214 +1,134 @@
/obj/machinery/portable_atmospherics/scrubber
name = "portable air scrubber"
icon = 'icons/obj/atmos.dmi'
icon_state = "pscrubber:0"
density = 1
var/on = 0
var/volume_rate = 800
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
var/on = FALSE
var/volume_rate = 1000
volume = 1000
volume = 750
var/list/gases_to_scrub = list("plasma", "co2", "agent_b", "n2o") //datum var so we can VV it and maybe even change it in the future
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
if(stat & (BROKEN|NOPOWER))
..(severity)
return
if(prob(50/severity))
on = !on
update_icon()
..(severity)
var/list/scrubbing = list("plasma", "co2", "n2o", "agent_b")
/obj/machinery/portable_atmospherics/scrubber/Destroy()
var/turf/T = get_turf(src)
T.assume_air(air_contents)
air_update_turf()
return ..()
/obj/machinery/portable_atmospherics/scrubber/update_icon()
src.overlays = 0
if(on)
icon_state = "pscrubber:1"
else
icon_state = "pscrubber:0"
icon_state = "pscrubber:[on]"
overlays.Cut()
if(holding)
overlays += "scrubber-open"
if(connected_port)
overlays += "scrubber-connector"
return
/obj/machinery/portable_atmospherics/scrubber/process_atmos()
..()
if(!on)
return
scrub(loc)
if (widenet)
var/turf/T = loc
if (istype(T))
for (var/turf/simulated/tile in T.GetAtmosAdjacentTurfs(alldir=1))
scrub(tile)
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/turf/simulated/tile)
var/datum/gas_mixture/environment
if(holding)
environment = holding.air_contents
scrub(holding.air_contents)
else
environment = tile.return_air()
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
var/turf/T = get_turf(src)
scrub(T.return_air())
//Take a gas sample
var/datum/gas_mixture/removed
if(holding)
removed = environment.remove(transfer_moles)
else
removed = tile.remove_air(transfer_moles)
/obj/machinery/portable_atmospherics/scrubber/proc/scrub(var/datum/gas_mixture/mixture)
var/transfer_moles = min(1, volume_rate / mixture.volume) * mixture.total_moles()
//Filter it
if (removed)
var/datum/gas_mixture/filtered_out = new
var/list/filtered_gases = filtered_out.gases
var/list/removed_gases = removed.gases
for(var/id in removed_gases & gases_to_scrub)
filtered_out.assert_gas(id)
filtered_gases[id][MOLES] = removed_gases[id][MOLES]
removed_gases[id][MOLES] = 0
filtered_out.temperature = removed.temperature
removed.garbage_collect()
//Remix the resulting gases
air_contents.merge(filtered_out)
if(holding)
environment.merge(removed)
else
tile.assume_air(removed)
tile.air_update_turf()
/obj/machinery/portable_atmospherics/scrubber/process()
..()
src.updateDialog()
return
/obj/machinery/portable_atmospherics/scrubber/return_air()
return air_contents
/obj/machinery/portable_atmospherics/scrubber/attack_ai(mob/user)
return src.attack_hand(user)
/obj/machinery/portable_atmospherics/scrubber/attack_paw(mob/user)
return src.attack_hand(user)
/obj/machinery/portable_atmospherics/scrubber/attack_hand(mob/user)
user.set_machine(src)
var/holding_text
if(holding)
holding_text = {"<BR><B>Tank Pressure</B>: [holding.air_contents.return_pressure()] KPa<BR>
<A href='?src=\ref[src];remove_tank=1'>Remove Tank</A><BR>
"}
var/output_text = {"<TT><B>[name]</B><BR>
Pressure: [air_contents.return_pressure()] KPa<BR>
Port Status: [(connected_port)?("Connected"):("Disconnected")]
[holding_text]
<BR>
Power Switch: <A href='?src=\ref[src];power=1'>[on?("On"):("Off")]</A><BR>
Power regulator: <A href='?src=\ref[src];volume_adj=-1000'>-</A> <A href='?src=\ref[src];volume_adj=-100'>-</A> <A href='?src=\ref[src];volume_adj=-10'>-</A> <A href='?src=\ref[src];volume_adj=-1'>-</A> [volume_rate] <A href='?src=\ref[src];volume_adj=1'>+</A> <A href='?src=\ref[src];volume_adj=10'>+</A> <A href='?src=\ref[src];volume_adj=100'>+</A> <A href='?src=\ref[src];volume_adj=1000'>+</A><BR>
<HR>
<A href='?src=\ref[user];mach_close=scrubber'>Close</A><BR>
"}
user << browse(output_text, "window=scrubber;size=600x300")
onclose(user, "scrubber")
return
/obj/machinery/portable_atmospherics/scrubber/Topic(href, href_list)
..()
if (usr.stat || usr.restrained())
var/datum/gas_mixture/filtering = mixture.remove(transfer_moles) // Remove part of the mixture to filter.
var/datum/gas_mixture/filtered = new
if(!filtering)
return
if (((get_dist(src, usr) <= 1) && istype(src.loc, /turf)))
usr.set_machine(src)
filtered.temperature = filtering.temperature
for(var/gas in filtering.gases & scrubbing)
filtered.assert_gas(gas)
filtered.gases[gas][MOLES] = filtering.gases[gas][MOLES] // Shuffle the "bad" gasses to the filtered mixture.
filtering.gases[gas][MOLES] = 0
filtering.garbage_collect() // Now that the gasses are set to 0, clean up the mixture.
if(href_list["power"])
air_contents.merge(filtered) // Store filtered out gasses.
mixture.merge(filtering) // Returned the cleaned gas.
if(!holding)
air_update_turf()
/obj/machinery/portable_atmospherics/scrubber/emp_act(severity)
if(is_operational())
if(prob(50 / severity))
on = !on
if (href_list["remove_tank"])
if(holding)
holding.loc = loc
holding = null
if (href_list["volume_adj"])
var/diff = text2num(href_list["volume_adj"])
volume_rate = min(10*ONE_ATMOSPHERE, max(0, volume_rate+diff))
src.updateUsrDialog()
src.add_fingerprint(usr)
update_icon()
else
usr << browse(null, "window=scrubber")
..()
/obj/machinery/portable_atmospherics/scrubber/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "portable_scrubber", name, 420, 335, master_ui, state)
ui.open()
/obj/machinery/portable_atmospherics/scrubber/ui_data()
var/data = list()
data["on"] = on
data["connected"] = connected_port ? 1 : 0
data["pressure"] = round(air_contents.return_pressure() ? air_contents.return_pressure() : 0)
if(holding)
data["holding"] = list()
data["holding"]["name"] = holding.name
data["holding"]["pressure"] = round(holding.air_contents.return_pressure())
return data
/obj/machinery/portable_atmospherics/scrubber/ui_act(action, params)
if(..())
return
return
switch(action)
if("power")
on = !on
. = TRUE
if("eject")
if(holding)
holding.loc = get_turf(src)
holding = null
. = TRUE
update_icon()
/obj/machinery/portable_atmospherics/scrubber/huge
name = "huge air scrubber"
icon_state = "scrubber:0"
anchored = 1
anchored = TRUE
active_power_usage = 500
idle_power_usage = 10
volume_rate = 1500
volume = 50000
widenet = 1
var/static/gid = 1
var/id = 0
var/stationary = 0
var/movable = FALSE
/obj/machinery/portable_atmospherics/scrubber/huge/New()
..()
id = gid
gid++
name = "[name] (ID [id])"
/obj/machinery/portable_atmospherics/scrubber/huge/attack_hand(var/mob/user as mob)
usr << "<span class='warning'>You can't directly interact with this machine! Use the area atmos computer.</span>"
/obj/machinery/portable_atmospherics/scrubber/huge/movable
movable = TRUE
/obj/machinery/portable_atmospherics/scrubber/huge/update_icon()
src.overlays = 0
icon_state = "scrubber:[on]"
if(on)
icon_state = "scrubber:1"
else
icon_state = "scrubber:0"
/obj/machinery/portable_atmospherics/scrubber/huge/process_atmos()
if((!anchored && !movable) || !is_operational())
on = FALSE
update_icon()
use_power = 1 + on
if(!on)
return
..()
if(!holding)
var/turf/T = get_turf(src)
for(var/turf/simulated/AT in T.GetAtmosAdjacentTurfs(alldir = TRUE))
scrub(AT.return_air())
/obj/machinery/portable_atmospherics/scrubber/huge/attackby(obj/item/weapon/W, mob/user)
if(istype(W, /obj/item/weapon/wrench))
if(stationary)
user << "<span class='warning'>The bolts are too tight for you to unscrew!</span>"
return
if(on)
user << "<span class='warning'>Turn it off first!</span>"
return
anchored = !anchored
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "<span class='notice'>You [anchored ? "wrench" : "unwrench"] \the [src].</span>"
else if ((istype(W, /obj/item/device/analyzer)) && get_dist(user, src) <= 1)
atmosanalyzer_scan(air_contents, user)
/obj/machinery/portable_atmospherics/scrubber/huge/stationary
name = "stationary air scrubber"
stationary = 0
if(default_unfasten_wrench(user, W))
if(!movable)
on = FALSE
else
..()
@@ -151,7 +151,7 @@ var/global/dmm_suite/preloader/_preloader = null
var/variables_start = findtext(full_def,"{")
if(variables_start)//if there's any variable
full_def = copytext(full_def,variables_start+1,length(full_def))//removing the last '}'
fields = text2list(full_def,";")
fields = readlist(full_def, ";")
//then fill the members_attributes list with the corresponding variables
members_attributes.len++
@@ -258,7 +258,7 @@ var/global/dmm_suite/preloader/_preloader = null
//build a list from variables in text form (e.g {var1="derp"; var2; var3=7} => list(var1="derp", var2, var3=7))
//return the filled list
/dmm_suite/proc/text2list(text as text,delimiter=",")
/dmm_suite/proc/readlist(text as text, delimiter=",")
var/list/to_return = list()
@@ -292,7 +292,7 @@ var/global/dmm_suite/preloader/_preloader = null
//Check for list
else if(copytext(trim_right,1,5) == "list")
trim_right = text2list(copytext(trim_right,6,length(trim_right)))
trim_right = readlist(copytext(trim_right,6,length(trim_right)))
//Check for file
else if(copytext(trim_right,1,2) == "'")
+181
View File
@@ -0,0 +1,181 @@
/obj/machinery/computer/cargo
name = "supply console"
desc = "Used to order supplies, approve requests, and control the shuttle."
icon_screen = "supply"
circuit = /obj/item/weapon/circuitboard/cargo
var/requestonly = FALSE
var/contraband = FALSE
/obj/machinery/computer/cargo/request
name = "supply request console"
desc = "Used to request supplies from cargo."
icon_screen = "request"
circuit = /obj/item/weapon/circuitboard/cargo/request
requestonly = TRUE
/obj/machinery/computer/cargo/New()
..()
var/obj/item/weapon/circuitboard/cargo/board = circuit
contraband = board.contraband
/obj/machinery/computer/cargo/emag_act(mob/user)
if(!emagged)
user << "<span class='notice'>Special supplies unlocked.</span>"
emagged = TRUE
/obj/machinery/computer/cargo/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cargo", name, 1000, 800, master_ui, state)
ui.open()
/obj/machinery/computer/cargo/ui_data()
var/list/data = list()
data["requestonly"] = requestonly
data["location"] = SSshuttle.supply.getStatusText()
data["points"] = SSshuttle.points
data["away"] = SSshuttle.supply.getDockedId() == "supply_away"
data["docked"] = SSshuttle.supply.mode == SHUTTLE_IDLE
data["loan"] = !!SSshuttle.shuttle_loan
data["loan_dispatched"] = SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched
data["message"] = SSshuttle.centcom_message || "Remember to stamp and send back the supply manifests."
var/list/supplies = list()
supplies.len = all_supply_groups.len
for(var/group in all_supply_groups)
supplies[group] = list(
"name" = get_supply_group_name(group),
"packs" = list()
)
for(var/pack in SSshuttle.supply_packs)
var/datum/supply_packs/P = SSshuttle.supply_packs[pack]
if((P.hidden && !emagged) || (P.contraband && !contraband))
continue
supplies[P.group]["packs"] += list(list(
"name" = P.name,
"cost" = P.cost,
"id" = pack
))
data["supplies"] = supplies
data["cart"] = list()
for(var/datum/supply_order/SO in SSshuttle.shoppinglist)
data["cart"] += list(list(
"object" = SO.object.name,
"cost" = SO.object.cost,
"id" = SO.ordernum
))
data["requests"] = list()
for(var/datum/supply_order/SO in SSshuttle.requestlist)
data["requests"] += list(list(
"object" = SO.object.name,
"cost" = SO.object.cost,
"orderedby" = SO.orderedby,
"comment" = SO.comment,
"id" = SO.ordernum
))
return data
/obj/machinery/computer/cargo/ui_act(action, params, datum/tgui/ui)
if(..())
return
if(action != "add" && requestonly)
return
switch(action)
if("send")
if(SSshuttle.supply.canMove())
say("For safety reasons the automated supply shuttle cannot transport live organisms, classified nuclear weaponry or homing beacons.")
return
if(SSshuttle.supply.getDockedId() == "supply_home")
SSshuttle.moveShuttle("supply", "supply_away", TRUE)
say("The supply shuttle has departed.")
investigate_log("[key_name(usr)] has sent the supply shuttle away. Points: [SSshuttle.points]. Contents: [SSshuttle.sold_atoms].", "cargo")
else
investigate_log("[key_name(usr)] has called the supply shuttle. Points: [SSshuttle.points].", "cargo") // TODO: more robust logging here
say("The supply shuttle has been called and will arrive in [SSshuttle.supply.timeLeft(600)] minutes.")
SSshuttle.moveShuttle("supply", "supply_home", TRUE)
. = TRUE
if("loan")
if(!SSshuttle.shuttle_loan)
return
else if(SSshuttle.supply.mode == SHUTTLE_IDLE)
SSshuttle.shuttle_loan.loan_shuttle()
say("The supply shuttle has been loaned to Centcom.")
. = TRUE
if("add")
var/id = params["id"]
if(!SSshuttle.supply_packs[id])
return
var/name = "*None Provided*"
var/rank = "*None Provided*"
if(ishuman(usr))
var/mob/living/carbon/human/H = usr
name = H.get_authentification_name()
rank = H.get_assignment()
else if(issilicon(usr))
name = usr.real_name
rank = "Silicon"
var/reason = ""
if(requestonly)
reason = input("Reason:", name, "") as text|null
if(isnull(reason) || ..())
return
var/turf/T = get_turf(src)
var/datum/supply_order/SO = SSshuttle.generateSupplyOrder(id, name, rank, reason)
SO.generateRequisition(T)
if(requestonly)
SSshuttle.requestlist += SO
else
SSshuttle.shoppinglist += SO
. = TRUE
if("remove")
var/id = text2num(params["id"])
for(var/datum/supply_order/SO in SSshuttle.shoppinglist)
if(SO.ordernum == id)
SSshuttle.shoppinglist -= SO
. = TRUE
break
if("clear")
SSshuttle.shoppinglist.Cut()
. = TRUE
if("approve")
var/id = text2num(params["id"])
for(var/datum/supply_order/SO in SSshuttle.requestlist)
if(SO.ordernum == id)
SSshuttle.requestlist -= SO
SSshuttle.shoppinglist += SO
. = TRUE
break
if("deny")
var/id = text2num(params["id"])
for(var/datum/supply_order/SO in SSshuttle.requestlist)
if(SO.ordernum == id)
SSshuttle.requestlist -= SO
. = TRUE
break
if("denyall")
SSshuttle.requestlist.Cut()
. = TRUE
if(.)
post_signal("supply")
/obj/machinery/computer/cargo/proc/post_signal(command)
var/datum/radio_frequency/frequency = SSradio.return_frequency(1435)
if(!frequency)
return
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.data["command"] = command
frequency.post_signal(src, status_signal)
+121
View File
@@ -0,0 +1,121 @@
/datum/supply_order
var/ordernum
var/datum/supply_packs/object = null
var/orderedby = null
var/orderedbyRank
var/comment = null
/datum/supply_order/proc/generateRequisition(atom/_loc)
if(!object)
return
var/obj/item/weapon/paper/reqform = new /obj/item/weapon/paper(_loc)
reqform.name = "requisition form - [object.name]"
reqform.info += "<h3>[station_name] Supply Requisition Form</h3><hr>"
reqform.info += "INDEX: #[ordernum]<br>"
reqform.info += "REQUESTED BY: [orderedby]<br>"
reqform.info += "RANK: [orderedbyRank]<br>"
reqform.info += "REASON: [comment]<br>"
reqform.info += "SUPPLY CRATE TYPE: [object.name]<br>"
reqform.info += "ACCESS RESTRICTION: [get_access_desc(object.access)]<br>"
reqform.info += "CONTENTS:<br>"
reqform.info += object.manifest
reqform.info += "<hr>"
reqform.info += "STAMP BELOW TO APPROVE THIS REQUISITION:<br>"
reqform.update_icon() //Fix for appearing blank when printed.
return reqform
/datum/supply_order/proc/createObject(atom/_loc, errors=0)
if(!object)
return
//create the crate
var/atom/Crate = new object.containertype(_loc)
Crate.name = "[object.containername] [comment ? "([comment])":"" ]"
if(object.access)
Crate:req_access = list(text2num(object.access))
//create the manifest slip
var/obj/item/weapon/paper/manifest/slip = new /obj/item/weapon/paper/manifest()
slip.erroneous = errors
slip.points = object.cost
slip.ordernumber = ordernum
var/stationName = (errors & MANIFEST_ERROR_NAME) ? new_station_name() : station_name()
var/packagesAmt = SSshuttle.shoppinglist.len + ((errors & MANIFEST_ERROR_COUNT) ? rand(1,2) : 0)
slip.info = "<h3>[command_name()] Shipping Manifest</h3><hr><br>"
slip.info +="Order #[ordernum]<br>"
slip.info +="Destination: [stationName]<br>"
slip.info +="[packagesAmt] PACKAGES IN THIS SHIPMENT<br>"
slip.info +="CONTENTS:<br><ul>"
//we now create the actual contents
var/list/contains
if(istype(object, /datum/supply_packs/misc/randomised))
var/datum/supply_packs/misc/randomised/SO = object
contains = list()
if(object.contains.len)
for(var/j=1, j<=SO.num_contained, j++)
contains += pick(object.contains)
else
contains = object.contains
for(var/typepath in contains)
if(!typepath)
continue
var/atom/A = new typepath(Crate)
if(object.amount && A.vars.Find("amount") && A:amount)
A:amount = object.amount
slip.info += "<li>[A.name]</li>" //add the item to the manifest (even if it was misplaced)
if(istype(Crate, /obj/structure/closet/critter)) // critter crates do not actually spawn mobs yet and have no contains var, but the manifest still needs to list them
var/obj/structure/closet/critter/CritCrate = Crate
if(CritCrate.content_mob)
var/mob/crittername = CritCrate.content_mob
slip.info += "<li>[initial(crittername.name)]</li>"
if((errors & MANIFEST_ERROR_ITEM))
//secure and large crates cannot lose items
if(findtext("[object.containertype]", "/secure/") || findtext("[object.containertype]","/largecrate/"))
errors &= ~MANIFEST_ERROR_ITEM
else
var/lostAmt = max(round(Crate.contents.len/10), 1)
//lose some of the items
while(--lostAmt >= 0)
qdel(pick(Crate.contents))
//manifest finalisation
slip.info += "</ul><br>"
slip.info += "CHECK CONTENTS AND STAMP BELOW THE LINE TO CONFIRM RECEIPT OF GOODS<hr>" // And now this is actually meaningful.
slip.loc = Crate
if(istype(Crate, /obj/structure/closet/crate))
var/obj/structure/closet/crate/CR = Crate
CR.manifest = slip
CR.update_icon()
if(istype(Crate, /obj/structure/largecrate))
var/obj/structure/largecrate/LC = Crate
LC.manifest = slip
LC.update_icon()
return Crate
/datum/subsystem/shuttle/proc/generateSupplyOrder(packId, _orderedby, _orderedbyRank, _comment)
if(!packId)
return
var/datum/supply_packs/P = supply_packs[packId]
if(!P)
return
var/datum/supply_order/O = new()
O.ordernum = ordernum++
O.object = P
O.orderedby = _orderedby
O.orderedbyRank = _orderedbyRank
O.comment = _comment
return O
+3 -3
View File
@@ -201,12 +201,12 @@ var/next_external_rsc = 0
else
winset(src, "infowindow.changelog", "font-style=bold")
if (ckey in clientmessages)
for (var/message in clientmessages[ckey])
if(ckey in clientmessages)
for(var/message in clientmessages[ckey])
src << message
clientmessages.Remove(ckey)
if (config && config.autoconvert_notes)
if(config && config.autoconvert_notes)
convert_notes_sql(ckey)
if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them.
+5
View File
@@ -27,6 +27,7 @@ var/list/preferences_datums = list()
var/UI_style = "Midnight"
var/hotkeys = FALSE
var/tgui_fancy = TRUE
var/tgui_lock = TRUE
var/toggles = TOGGLES_DEFAULT
@@ -328,6 +329,7 @@ var/list/preferences_datums = list()
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
dat += "<b>UI Style:</b> <a href='?_src_=prefs;preference=ui'>[UI_style]</a><br>"
dat += "<b>Keybindings:</b> <a href='?_src_=prefs;preference=hotkeys'>[(hotkeys) ? "Hotkeys" : "Default"]</a><br>"
dat += "<b>tgui Style:</b> <a href='?_src_=prefs;preference=tgui_fancy'>[(tgui_fancy) ? "Fancy" : "No Frills"]</a><br>"
dat += "<b>tgui Monitors:</b> <a href='?_src_=prefs;preference=tgui_lock'>[(tgui_lock) ? "Primary" : "All"]</a><br>"
dat += "<b>Play admin midis:</b> <a href='?_src_=prefs;preference=hear_midis'>[(toggles & SOUND_MIDI) ? "Yes" : "No"]</a><br>"
@@ -1021,6 +1023,9 @@ var/list/preferences_datums = list()
else
UI_style = "Midnight"
if("hotkeys")
hotkeys = !hotkeys
if("tgui_fancy")
tgui_fancy = !tgui_fancy
if("tgui_lock")
@@ -194,6 +194,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ooccolor"] >> ooccolor
S["lastchangelog"] >> lastchangelog
S["UI_style"] >> UI_style
S["hotkeys"] >> hotkeys
S["tgui_fancy"] >> tgui_fancy
S["tgui_lock"] >> tgui_lock
@@ -222,6 +223,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor)))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
UI_style = sanitize_inlist(UI_style, list("Midnight", "Plasmafire", "Retro", "Slimecore", "Operative"), initial(UI_style))
hotkeys = sanitize_integer(hotkeys, 0, 1, initial(hotkeys))
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
@@ -245,6 +247,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["ooccolor"] << ooccolor
S["lastchangelog"] << lastchangelog
S["UI_style"] << UI_style
S["hotkeys"] << hotkeys
S["tgui_fancy"] << tgui_fancy
S["tgui_lock"] << tgui_lock
S["be_special"] << be_special
+1 -1
View File
@@ -25,7 +25,7 @@
var/obj/item/weapon/paper/P = new(get_turf(src))
P.name = "paper- 'Scanner Report'"
P.info = "<center><font size='6'><B>Scanner Report</B></font></center><HR><BR>"
P.info += list2text(log, "<BR>")
P.info += jointext(log, "<BR>")
P.info += "<HR><B>Notes:</B><BR>"
P.info_links = P.info
+4 -4
View File
@@ -4,7 +4,7 @@
/proc/NewStutter(phrase,stunned)
phrase = html_decode(phrase)
var/list/split_phrase = text2list(phrase," ") //Split it up into words.
var/list/split_phrase = splittext(phrase," ") //Split it up into words.
var/list/unstuttered_words = split_phrase.Copy()
var/i = rand(1,3)
@@ -35,7 +35,7 @@
split_phrase[index] = word
return sanitize(list2text(split_phrase," "))
return sanitize(jointext(split_phrase," "))
/proc/Stagger(mob/M,d) //Technically not a filter, but it relates to drunkenness.
step(M, pick(d,turn(d,90),turn(d,-90)))
@@ -45,7 +45,7 @@
if(chance >= 100) return original_msg
var/list
words = text2list(original_msg," ")
words = splittext(original_msg," ")
new_words = list()
var/new_msg = ""
@@ -57,6 +57,6 @@
continue
new_words += w
new_msg = list2text(new_words," ")
new_msg = jointext(new_words," ")
return new_msg
+19 -23
View File
@@ -150,29 +150,25 @@
/obj/machinery/computer/holodeck/Topic(href, list/href_list)
if(..())
return
if(Adjacent(usr) || istype(usr, /mob/living/silicon))
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["loadarea"])
var/typepath = text2path(href_list["loadarea"])
if(ispath(typepath,/area))
var/area/target = locate(typepath)
if(istype(target))
load_program(target)
else
world.log << "area not ready: [typepath]"
else
world.log << "bad area argument: [href_list["loadarea"]]"
else if("safety" in href_list)
var/oe = emagged
emagged = !text2num(href_list["safety"])
if(oe == emagged) return
if(program && !stat)
if(!emagged && program.restricted)
load_program(offline_program)
else
nerf(!emagged)
src.updateUsrDialog()
if(!Adjacent(usr) && !istype(usr, /mob/living/silicon))
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["loadarea"])
var/areapath = text2path(href_list["loadarea"])
if(!ispath(areapath, /area/holodeck))
return
var/area/holodeck/area = locate(areapath)
if(!istype(area))
return
if((area in program_cache) || (emagged && (area in emag_programs)))
load_program(area)
else if("safety" in href_list)
var/safe = text2num(href_list["safety"])
if(!program)
return
nerf(safe)
src.updateUsrDialog()
/obj/machinery/computer/holodeck/proc/nerf(active)
for(var/obj/item/I in spawned)
+2 -2
View File
@@ -124,7 +124,7 @@
if(!src.req_access)
src.req_access = list()
if(src.req_access_txt)
var/list/req_access_str = text2list(req_access_txt,";")
var/list/req_access_str = splittext(req_access_txt,";")
for(var/x in req_access_str)
var/n = text2num(x)
if(n)
@@ -133,7 +133,7 @@
if(!src.req_one_access)
src.req_one_access = list()
if(src.req_one_access_txt)
var/list/req_one_access_str = text2list(req_one_access_txt,";")
var/list/req_one_access_str = splittext(req_one_access_txt,";")
for(var/x in req_one_access_str)
var/n = text2num(x)
if(n)
@@ -15,8 +15,8 @@ Chaplain
outfit = /datum/outfit/job/chaplain
access = list(access_morgue, access_chapel_office, access_crematorium)
minimal_access = list(access_morgue, access_chapel_office, access_crematorium)
access = list(access_morgue, access_chapel_office, access_crematorium, access_theatre)
minimal_access = list(access_morgue, access_chapel_office, access_crematorium, access_theatre)
/datum/outfit/job/chaplain
name = "Chaplain"
-284
View File
@@ -1,284 +0,0 @@
/* Usage:
JSON.stringify(obj) - Converts lists and values into a JSON string.
JSON.parse(json) - Converts a JSON string into lists and values.
*/
/var/datum/jsonHelper/JSON = new // A namespace for procs.
// ************************************ WRITER ************************************
/datum/jsonHelper/proc/stringify(value)
return list2text(WriteValue(list(), value))
/datum/jsonHelper/proc/WriteValue(list/json, value)
. = json
if(isnum(value))
json += value // Consider num2text(value, 20) for maximum accuracy.
else if(isnull(value))
json += "null"
else if(istext(value))
WriteString(json, value)
else if(istype(value, /list))
WriteList(json, value)
else
throw EXCEPTION("Datums cannot be converted to JSON.")
/datum/jsonHelper/proc/WriteString(list/json, str)
. = json
var/quotePos = findtextEx(str, "\"")
var/bsPos = findtextEx(str, "\\")
if (quotePos == 0 && bsPos == 0)
json.Add("\"", str, "\"")
else
json += "\""
var/lastStop = 1
while(quotePos != 0 || bsPos != 0)
var/escPos
if(quotePos < bsPos && quotePos != 0 || bsPos == 0)
escPos = quotePos
else
escPos = bsPos
json.Add(copytext(str, lastStop, escPos), "\\")
lastStop = escPos
if(escPos == quotePos)
quotePos = findtextEx(str, "\"", escPos + 1)
else if(escPos == bsPos)
bsPos = findtextEx(str, "\\", escPos + 1)
json.Add(copytext(str, lastStop), "\"")
/datum/jsonHelper/proc/WriteList(list/json, list/listVal)
. = json
#define Either 0
#define CannotBeArray 1
#define CannotBeObject 2
#define BadList (CannotBeArray | CannotBeObject)
var/listType = Either
for(var/key in listVal)
if(istext(key))
if(!isnull(listVal[key]))
listType |= CannotBeArray
else
if(!isnum(key) && !isnull(listVal[key]))
listType = BadList
else
listType |= CannotBeObject
if(listType == BadList)
throw EXCEPTION("The given list cannot be converted to JSON.")
if(listType == CannotBeArray)
json += "{"
var/addComma
for(var/key in listVal)
if(addComma)
json += ","
else
addComma = TRUE
WriteString(json, key)
json += ":"
WriteValue(json, listVal[key])
json += "}"
else
json += "\["
var/addComma
for(var/key in listVal)
if(addComma)
json += ","
else
addComma = TRUE
WriteValue(json, key)
json += "]"
#undef Either
#undef CannotBeFlat
#undef CannotBeAssoc
#undef BadList
// ************************************ READER ************************************
#define aBackspace 0x08
#define aTab 0x09
#define aLineBreak 0x0A
#define aVertTab 0x0B
#define aFormFeed 0x0C
#define aCarriageReturn 0x0D
#define aSpace 0x20
#define aZero 0x30
#define aNonBreakSpace 0xA0
#define Advance if(++readPos > jsonLen) { curAscii = 0; curChar = "" } else { curAscii = text2ascii(json, readPos); curChar = ascii2text(curAscii) } // Deal with it.
#define SkipWhitespace while(curAscii in whitespace) Advance
#define AdvanceWS Advance; SkipWhitespace
/datum/jsonHelper/var
readPos
jsonLen
json
curAscii
curChar
static/list/whitespace = list(aTab, aLineBreak, aVertTab, aFormFeed, aCarriageReturn, aSpace, aNonBreakSpace)
/datum/jsonHelper/proc/parse(json)
readPos = 0
jsonLen = length(json)
src.json = json
curAscii = 0
curChar = ""
AdvanceWS
var/value = ParseValue()
if(readPos < jsonLen)
throw EXCEPTION("Expected: End of JSON")
return value
/datum/jsonHelper/proc/ParseValue()
if(curChar == "\"")
return ParseString()
else if(curChar == "-" || (curAscii >= aZero && curAscii <= aZero + 9))
return ParseNumber()
else if(curChar == "{")
return ParseObject()
else if(curChar == "\[")
return ParseArray()
else if(curChar == "t")
if(copytext(json, readPos, readPos+4) == "true")
readPos += 3
AdvanceWS
return TRUE
else
throw EXCEPTION("Expected: 'true'")
else if(curChar == "f")
if(copytext(json, readPos, readPos+5) == "false")
readPos += 4
AdvanceWS
return FALSE
else
throw EXCEPTION("Expected: 'false'")
else if(curChar == "n")
if(copytext(json, readPos, readPos+4) == "null")
readPos += 3
AdvanceWS
return null
else
throw EXCEPTION("Expected: 'null'")
else if(curChar == "")
throw EXCEPTION("Unexpected: End of JSON")
else
throw EXCEPTION("Unexpected: '[curChar]'")
/datum/jsonHelper/proc/ParseString()
ASSERT(curChar == "\"")
Advance
var/list/chars = list()
while(readPos <= jsonLen)
if(curChar == "\"")
AdvanceWS
return list2text(chars)
else if(curChar == "\\")
Advance
switch(curChar)
if("\"", "\\", "/")
chars += ascii2text(curAscii)
if("b")
chars += ascii2text(aBackspace)
if("f")
chars += ascii2text(aFormFeed)
if("n")
chars += "\n"
if("r")
chars += ascii2text(aCarriageReturn) // Should we ignore these?
if("t")
chars += "\t"
if("u")
throw EXCEPTION("JSON \\uXXXX escape sequence not supported")
else
throw EXCEPTION("Invalid escape sequence")
Advance
else
chars += ascii2text(curAscii)
Advance
throw EXCEPTION("Unterminated string")
/datum/jsonHelper/proc/ParseNumber()
var/firstPos = readPos
if(curChar == "-")
Advance
if(curAscii >= aZero + 1 && curAscii <= aZero + 9)
do
Advance
while(curAscii >= aZero && curAscii <= aZero + 9)
else if(curAscii == aZero)
Advance
else
throw EXCEPTION("Expected: digit")
if(curChar == ".")
Advance
var/found = FALSE
while(curAscii >= aZero && curAscii <= aZero + 9)
found = TRUE
Advance
if(!found)
throw EXCEPTION("Expected: digit")
if(curChar == "E" || curChar == "e")
Advance
var/found = FALSE
if(curChar == "-")
Advance
else if(curChar == "+")
Advance
while(curAscii >= aZero && curAscii <= aZero + 9)
found = TRUE
Advance
if(!found)
throw EXCEPTION("Expected: digit")
SkipWhitespace
return text2num(copytext(json, firstPos, readPos))
/datum/jsonHelper/proc/ParseObject()
ASSERT(curChar == "{")
var/list/object = list()
AdvanceWS
while(curChar == "\"")
var/key = ParseString()
if(curChar != ":")
throw EXCEPTION("Expected: ':'")
AdvanceWS
object[key] = ParseValue()
if(curChar == ",")
AdvanceWS
else
break
if(curChar != "}")
throw EXCEPTION("Expected: string or '}'")
AdvanceWS
return object
/datum/jsonHelper/proc/ParseArray()
ASSERT(curChar == "\[")
var/list/array = list()
AdvanceWS
while(curChar != "]")
array += list(ParseValue()) // Wrapped in a list in case ParseValue() returns a list.
if(curChar == ",")
AdvanceWS
else
break
if(curChar != "]")
throw EXCEPTION("Expected: ']'")
AdvanceWS
return array
#undef aBackspace
#undef aTab
#undef aLineBreak
#undef aVertTab
#undef aFormFeed
#undef aCarriageReturn
#undef aSpace
#undef aZero
#undef aNonBreakSpace
#undef Advance
#undef SkipWhitespace
#undef AdvanceWS
+33 -19
View File
@@ -167,9 +167,11 @@
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
/mob/living/carbon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
var/damage = intensity - check_eye_prot()
if(..()) // we've been flashed
if(visual)
return
if(weakeyes)
Stun(2)
switch(damage)
@@ -200,7 +202,6 @@
else
src << "<span class='warning'>Your eyes are really starting to hurt. This can't be good for you!</span>"
return 1
else if(damage == 0) // just enough protection
if(prob(20))
src << "<span class='notice'>Something bright flashes in the corner of your vision!</span>"
@@ -583,31 +584,44 @@ var/const/GALOSHES_DONT_HELP = 4
add_abilities_to_panel()
/mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood)
/mob/living/carbon/proc/vomit(var/lost_nutrition = 10, var/blood = 0, var/stun = 1, var/distance = 0, var/message = 1)
if(src.is_muzzled())
src << "<span class='warning'>The muzzle prevents you from vomiting!</span>"
if(message)
src << "<span class='warning'>The muzzle prevents you from vomiting!</span>"
return 0
Stun(4)
if(stun)
Stun(4)
if(nutrition < 100 && !blood)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing your stomach!</span>")
Weaken(10)
if(message)
visible_message("<span class='warning'>[src] dry heaves!</span>", \
"<span class='userdanger'>You try to throw up, but there's nothing your stomach!</span>")
if(stun)
Weaken(10)
else
visible_message("<span class='danger'>[src] throws up!</span>", \
"<span class='userdanger'>You throw up!</span>")
if(message)
visible_message("<span class='danger'>[src] throws up!</span>", \
"<span class='userdanger'>You throw up!</span>")
playsound(get_turf(src), 'sound/effects/splat.ogg', 50, 1)
var/turf/T = get_turf(src)
if(blood)
if(T)
T.add_blood_floor(src)
adjustBruteLoss(3)
else
if(T)
T.add_vomit_floor(src)
nutrition -= lost_nutrition
adjustToxLoss(-3)
for(var/i=0 to distance)
if(blood)
if(T)
T.add_blood_floor(src)
if(stun)
adjustBruteLoss(3)
else
if(T)
T.add_vomit_floor(src)
nutrition -= lost_nutrition
if(stun)
adjustToxLoss(-3)
T = get_step(T, dir)
if (is_blocked_turf(T))
break
return 1
/mob/living/carbon/fully_replace_character_name(oldname,newname)
..()
if(dna)
@@ -29,7 +29,7 @@
if(!gibbed)
emote("deathgasp") //let the world KNOW WE ARE DEAD
dna.species.spec_death(gibbed,src)
dna.species.spec_death(gibbed, src)
if(ticker && ticker.mode)
sql_report_death(src)
+2 -2
View File
@@ -12,7 +12,7 @@
message = dna.species.handle_speech(message,src)
if(viruses.len)
for(var/datum/disease/pierrot_throat/D in viruses)
var/list/temp_message = text2list(message, " ") //List each word in the message
var/list/temp_message = splittext(message, " ") //List each word in the message
var/list/pick_list = list()
for(var/i = 1, i <= temp_message.len, i++) //Create a second list for excluding words down the line
pick_list += i
@@ -22,7 +22,7 @@
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
temp_message[H] = "HONK"
pick_list -= H //Make sure that you dont HONK the same word twice
message = list2text(temp_message, " ")
message = jointext(temp_message, " ")
message = ..(message)
message = dna.mutations_say_mods(message)
return message
@@ -74,14 +74,12 @@ datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
return randname
var/regex/lizard_hiss = new("s+", "g")
var/regex/lizard_hiSS = new("S+", "g")
/datum/species/lizard/handle_speech(message)
if(copytext(message, 1, 2) != "*")
message = regEx_replaceall(message, "(?<!s)s(?!s)", "sss") //(?<!s) Not s before. (?!s) not s after. That way it only triples a single s instead of double ss.
message = regEx_replaceall(message, "(?<!s)ss(?!s)", "ssss")
message = regEx_replaceall(message, "(?<!S)S(?!S)", "SSS")
message = regEx_replaceall(message, "(?<!S)SS(?!S)", "SSSS")
message = lizard_hiss.Replace(message, "sss")
message = lizard_hiSS.Replace(message, "SSS")
return message
//I wag in death
@@ -414,7 +412,7 @@ datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
specflags = list(NOBREATH,HEATRES,COLDRES,NOBLOOD,RADIMMUNE)
/datum/species/zombie/handle_speech(message)
var/list/message_list = text2list(message, " ")
var/list/message_list = splittext(message, " ")
var/maxchanges = max(round(message_list.len / 1.5), 2)
for(var/i = rand(maxchanges / 2, maxchanges), i > 0, i--)
@@ -427,7 +425,7 @@ datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(prob(20) && message_list.len > 3)
message_list.Insert(insertpos, "[pick("BRAINS", "Brains", "Braaaiinnnsss", "BRAAAIIINNSSS")]...")
return list2text(message_list, " ")
return jointext(message_list, " ")
/datum/species/cosmetic_zombie
name = "Human"
+1 -1
View File
@@ -56,9 +56,9 @@
sleeping = 0
update_sight()
update_vision_overlays()
clear_fullscreens()
update_damage_hud()
update_health_hud()
update_canmove()
+4 -4
View File
@@ -193,8 +193,7 @@ Sorry Giacom. Please don't be mad :(
/mob/living/ex_act(severity, target)
..()
if(client && !eye_blind)
flick("flash", src.flash)
flash_eyes()
/mob/living/proc/updatehealth()
if(status_flags & GODMODE)
@@ -720,9 +719,10 @@ Sorry Giacom. Please don't be mad :(
floating = 0
//called when the mob receives a bright flash
/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
/mob/living/proc/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash)
if(check_eye_prot() < intensity && (override_blindness_check || !(disabilities & BLIND)))
flick("e_flash", flash)
overlay_fullscreen("flash", type)
addtimer(src, "clear_fullscreen", 25, FALSE, "flash", 25)
return 1
//this returns the mob's protection against eye damage (number between -1 and 2)
+3 -3
View File
@@ -15,8 +15,8 @@
anchored = 0 //unbolt floorbolts
update_canmove()
if(src.eyeobj)
src.eyeobj.setLoc(get_turf(src))
if(eyeobj)
eyeobj.setLoc(get_turf(src))
shuttle_caller_list -= src
SSshuttle.autoEvac()
@@ -42,7 +42,7 @@
for(var/obj/machinery/ai_status_display/O in world) //change status
if(src.key)
O.mode = 2
if (istype(loc, /obj/item/device/aicard))
if(istype(loc, /obj/item/device/aicard))
loc.icon_state = "aicard-404"
return ..()
+1 -1
View File
@@ -109,7 +109,7 @@ var/const/VOX_DELAY = 600
src << "<span class='notice'>Wireless interface disabled, unable to interact with announcement PA.</span>"
return
var/list/words = text2list(trim(message), " ")
var/list/words = splittext(trim(message), " ")
var/list/incorrect_words = list()
if(words.len > 30)
@@ -8,6 +8,4 @@
ticker.mode.remove_gangster(mind,1,remove_bosses=1)
ticker.mode.remove_thrall(mind,0)
ticker.mode.remove_shadowling(mind)
ticker.mode.remove_hog_follower(mind, 0)
winset(src, null, "mainwindow.macro=robot-default")
ticker.mode.remove_hog_follower(mind, 0)
@@ -5,6 +5,8 @@
icon_state = "robot"
maxHealth = 100
health = 100
macro_default = "robot-default"
macro_hotkeys = "robot-hotkeys"
bubble_icon = "robot"
var/sight_mode = 0
var/custom_name = ""
@@ -676,7 +678,7 @@
/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime shock
flick("noise", flash)
flash_eyes()
var/stunprob = M.powerlevel * 7 + 10
if(prob(stunprob) && M.powerlevel >= 8)
adjustBruteLoss(M.powerlevel * rand(6,10))
@@ -99,11 +99,13 @@
var/obj/item/weapon/melee/baton/B = I
if(B.bcell)
B.bcell.charge = B.bcell.maxcharge
if(istype(I, /obj/item/weapon/tank/jetpack))
var/obj/item/weapon/tank/jetpack/J = I
J.air_contents.assert_gas("co2")
J.air_contents.gases["co2"][MOLES] = (6 * ONE_ATMOSPHERE) * J.volume / (R_IDEAL_GAS_EQUATION * T20C)
R.toner = R.tonermax
return
/obj/item/weapon/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module
var/list/temp_list = modules
modules = list()
+3 -3
View File
@@ -136,9 +136,9 @@
src.take_organ_damage(20)
if(2)
src.take_organ_damage(10)
flick("noise", src:flash)
src << "<span class='userdanger'>*BZZZT*</span>"
src << "<span class='danger'>Warning: Electromagnetic pulse detected.</span>"
flash_eyes(affect_silicon = 1)
..()
/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = 0)
@@ -394,7 +394,7 @@
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
if(prob(8))
flick("noise", flash)
flash_eyes(affect_silicon = 1)
add_logs(M, src, "attacked")
adjustBruteLoss(damage)
updatehealth()
@@ -467,7 +467,7 @@
/mob/living/silicon/grabbedby(mob/living/user)
return
/mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
/mob/living/silicon/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/noise)
if(affect_silicon)
return ..()
@@ -18,6 +18,8 @@
speak_emote = list("states")
bubble_icon = "machine"
faction = list("neutral, silicon")
var/obj/machinery/bot_core/bot_core = null
var/bot_core_type = /obj/machinery/bot_core
var/list/users = list() //for dialog updates
@@ -252,6 +254,7 @@
src << "<span class='notice'>You sense your form change as you are uploaded into [src].</span>"
bot_name = name
name = paicard.pai.name
faction = user.faction
add_logs(user, paicard.pai, "uploaded to [src.bot_name],")
else
user << "<span class='warning'>[W] is inactive.</span>"
@@ -857,6 +860,7 @@ Pass a positive integer as an argument to override a bot's default speed.
paicard.pai << "<span class='notice'>You feel your control fade as [paicard] ejects from [bot_name].</span>"
paicard = null
name = bot_name
faction = initial(faction)
/mob/living/simple_animal/bot/proc/ejectpairemote(mob/user)
if(bot_core.allowed(user) && paicard)
@@ -881,3 +885,6 @@ Pass a positive integer as an argument to override a bot's default speed.
..()
if(paicard && (!client || stat == DEAD))
ejectpai(0)
/mob/living/simple_animal/bot/sentience_act()
faction -= "silicon"
@@ -171,7 +171,7 @@ var/global/mulebot_count = 0
ui = new(user, src, ui_key, "mulebot", name, 600, 375, master_ui, state)
ui.open()
/mob/living/simple_animal/bot/mulebot/get_ui_data(mob/user)
/mob/living/simple_animal/bot/mulebot/ui_data(mob/user)
var/list/data = list()
data["on"] = on
data["locked"] = locked
@@ -274,13 +274,13 @@
/mob/living/simple_animal/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
attack_threshold_check(damage,M.melee_damage_type)
apply_damage(damage, M.melee_damage_type, threshold_check = 1, threshold_message = 1)
return 1
/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj)
if(!Proj)
return
apply_damage(Proj.damage, Proj.damage_type)
apply_damage(Proj.damage, Proj.damage_type, threshold_message = 1)
Proj.on_hit(src)
return 0
@@ -330,7 +330,7 @@
M.do_attack_animation(src)
visible_message("<span class='danger'>[M] [response_harm] [src]!</span>")
playsound(loc, "punch", 25, 1, -1)
attack_threshold_check(harm_intent_damage)
apply_damage(harm_intent_damage, threshold_check = 1, threshold_message = 1)
add_logs(M, src, "attacked")
updatehealth()
return 1
@@ -339,7 +339,7 @@
if(..()) //successful monkey bite.
if(stat != DEAD)
var/damage = rand(1, 3)
attack_threshold_check(damage)
apply_damage(damage, threshold_check = 1, threshold_message = 1)
return 1
if (M.a_intent == "help")
if (health > 0)
@@ -360,7 +360,7 @@
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
attack_threshold_check(damage)
apply_damage(damage, threshold_check = 1, threshold_message = 1)
add_logs(M, src, "attacked")
return 1
@@ -369,7 +369,7 @@
var/damage = rand(5, 10)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
attack_threshold_check(damage)
apply_damage(damage, threshold_check = 1, threshold_message = 1)
return 1
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M)
@@ -377,15 +377,16 @@
var/damage = rand(15, 25)
if(M.is_adult)
damage = rand(20, 35)
attack_threshold_check(damage)
apply_damage(damage, threshold_check = 1, threshold_message = 1)
return 1
/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE)
if(damage <= force_threshold || !damage_coeff[damagetype])
visible_message("<span class='warning'>[src] looks unharmed.</span>")
/mob/living/simple_animal/apply_damage(damage = 0, damagetype = BRUTE, threshold_check = 0, threshold_message = 0)
if(!damage_coeff[damagetype] || threshold_check && damage <= force_threshold)
if(threshold_message)
visible_message("<span class='warning'>[src] looks unharmed.</span>")
return 0
else
adjustBruteLoss(damage)
updatehealth()
return ..()
/mob/living/simple_animal/attackby(obj/item/O, mob/living/user, params) //Marker -Agouri
@@ -18,7 +18,7 @@
return
if(buckled)
Feedstop(silent=1) //releases ourselves from the mob we fed on.
Feedstop(silent = 1) //releases ourselves from the mob we fed on.
stat = DEAD
overlays.len = 0
+4 -1
View File
@@ -57,4 +57,7 @@
sync_mind()
winset(src, null, "mainwindow.macro=default")
if(client.prefs.hotkeys)
winset(src, null, "mainwindow.macro=[macro_hotkeys] mapwindow.map.focus=true input.background-color=#e0e0e0")
else
winset(src, null, "mainwindow.macro=[macro_default] input.focus=true input.background-color=#d3b5b5")
+4 -2
View File
@@ -10,9 +10,8 @@
var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak
var/obj/screen/flash = null
var/obj/screen/hands = null
var/obj/screen/damageoverlay = null
/*A bunch of this stuff really needs to go under their own defines instead of being globally attached to mob.
A variable should only be globally attached to turfs/objects/whatever, when it is in fact needed as such.
The current method unnecessarily clusters up the variable list, especially for humans (although rearranging won't really clean it up a lot but the difference will be noticable for other mobs).
@@ -21,6 +20,9 @@
*/
var/zone_selected = null
var/macro_default = "default"
var/macro_hotkeys = "hotkeys"
var/damageoverlaytemp = 0
var/computer_id = null
var/lastattacker = null
+2 -2
View File
@@ -21,7 +21,7 @@ Contents:
/obj/item/clothing/mask/gas/voice/space_ninja/speechModification(message)
if(voice == "Unknown")
if(copytext(message, 1, 2) != "*")
var/list/temp_message = text2list(message, " ")
var/list/temp_message = splittext(message, " ")
var/list/pick_list = list()
for(var/i = 1, i <= temp_message.len, i++)
pick_list += i
@@ -30,7 +30,7 @@ Contents:
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
temp_message[H] = ninjaspeak(temp_message[H])
pick_list -= H
message = list2text(temp_message, " ")
message = jointext(temp_message, " ")
//The Alternate speech mod is now the main one.
message = replacetext(message, "l", "r")
+2 -2
View File
@@ -617,7 +617,7 @@
ui = new(user, src, ui_key, "apc", name, 535, 515, master_ui, state)
ui.open()
/obj/machinery/power/apc/get_ui_data(mob/user)
/obj/machinery/power/apc/ui_data(mob/user)
var/list/data = list(
"locked" = locked,
"isOperating" = operating,
@@ -625,7 +625,7 @@
"powerCellStatus" = cell ? cell.percent() : null,
"chargeMode" = chargemode,
"chargingStatus" = charging,
"totalLoad" = lastused_equip + lastused_light + lastused_environ,
"totalLoad" = lastused_total,
"coverLocked" = coverlocked,
"siliconUser" = user.has_unlimited_silicon_privilege,
"malfStatus" = get_malf_status(user),
-5
View File
@@ -114,11 +114,6 @@ By design, d1 is the smallest direction and d2 is the highest
else
icon_state = "[d1]-[d2]"
// returns the powernet this cable belongs to
/obj/structure/cable/proc/get_powernet() //TODO: remove this as it is obsolete
return powernet
//Telekinesis has no effect on a cable
/obj/structure/cable/attack_tk(mob/user)
return
+81
View File
@@ -0,0 +1,81 @@
/obj/machinery/computer/monitor
name = "power monitoring console"
desc = "It monitors power levels across the station."
icon_screen = "power"
icon_keyboard = "power_key"
use_power = 2
idle_power_usage = 20
active_power_usage = 100
circuit = /obj/item/weapon/circuitboard/powermonitor
var/obj/structure/cable/attached
var/list/history = list()
var/record_size = 60
var/record_interval = 50
var/next_record = 0
/obj/machinery/computer/monitor/New()
..()
search()
history["supply"] = list()
history["demand"] = list()
/obj/machinery/computer/monitor/process()
if(!attached)
use_power = 1
search()
else
use_power = 2
record()
/obj/machinery/computer/monitor/proc/search()
var/turf/T = get_turf(src)
attached = locate() in T
/obj/machinery/computer/monitor/proc/record()
if(world.time >= next_record)
next_record = world.time + record_interval
var/list/supply = history["supply"]
supply += attached.powernet.viewavail
if(supply.len > record_size)
supply.Cut(1, 2)
var/list/demand = history["demand"]
demand += attached.powernet.viewload
if(demand.len > record_size)
demand.Cut(1, 2)
/obj/machinery/computer/monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "power_monitor", name, 1200, 1000, master_ui, state)
ui.open()
/obj/machinery/computer/monitor/ui_data()
var/list/data = list()
data["stored"] = record_size
data["interval"] = record_interval / 10
data["attached"] = attached ? TRUE : FALSE
if(attached)
data["supply"] = attached.powernet.viewavail
data["demand"] = attached.powernet.viewload
data["history"] = history
data["areas"] = list()
for(var/obj/machinery/power/terminal/term in attached.powernet.nodes)
var/obj/machinery/power/apc/A = term.master
if(istype(A))
data["areas"] += list(list(
"name" = A.area.name,
"charge" = A.cell.percent(),
"load" = A.lastused_total,
"charging" = A.charging,
"eqp" = A.equipment,
"lgt" = A.lighting,
"env" = A.environ
))
return data
+2 -4
View File
@@ -34,7 +34,7 @@
/obj/machinery/power/proc/surplus()
if(powernet)
return powernet.avail-powernet.load
return powernet.avail - powernet.load
else
return 0
@@ -50,10 +50,8 @@
// returns true if the area has power on given channel (or doesn't require power).
// defaults to power_channel
/obj/machinery/proc/powered(var/chan = -1) // defaults to power_channel
if(!src.loc)
if(!loc)
return 0
if(!use_power)
return 1
+6 -6
View File
@@ -3,14 +3,15 @@
// each contiguous network of cables & nodes
/////////////////////////////////////
/datum/powernet
var/number // unique id
var/list/cables = list() // all cables & junctions
var/list/nodes = list() // all connected machines
var/load = 0 // the current load on the powernet, increased by each machine at processing
var/newavail = 0 // what available power was gathered last tick, then becomes...
var/avail = 0 //...the current available power in the powernet
var/viewavail = 0 // the available power as it appears on the power console (gradually updated)
var/viewload = 0 // the load as it appears on the power console (gradually updated)
var/number = 0 // Unused //TODEL
var/netexcess = 0 // excess power on the powernet (typically avail-load)///////
/datum/powernet/New()
@@ -75,7 +76,6 @@
//handles the power changes in the powernet
//called every ticks by the powernet controller
/datum/powernet/proc/reset()
//see if there's a surplus of power remaining in the powernet and stores unused power in the SMES
netexcess = avail - load
@@ -83,11 +83,11 @@
for(var/obj/machinery/power/smes/S in nodes) // find the SMESes in the network
S.restore() // and restore some of the power that was used
//updates the viewed load (as seen on power computers)
viewload = 0.8*viewload + 0.2*load
viewload = round(viewload)
// update power consoles
viewavail = round(0.8 * viewavail + 0.2 * avail)
viewload = round(0.8 * viewload + 0.2 * load)
//reset the powernet
// reset the powernet
load = 0
avail = newavail
newavail = 0
+3 -3
View File
@@ -46,7 +46,7 @@
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/smes(null)
for(var/i in 1 to 5)
component_parts += new /obj/item/weapon/stock_parts/cell/high(null)
component_parts += new /obj/item/weapon/stock_parts/cell/high/empty(null)
component_parts += new /obj/item/stack/cable_coil(null, 5)
component_parts += new /obj/item/weapon/stock_parts/capacitor(null)
RefreshParts()
@@ -78,7 +78,7 @@
MC += PC.maxcharge
C += PC.charge
capacity = MC / (15000) * 1e6
if(!initial(charge))
if(!initial(charge) && !charge)
charge = C / 15000 * 1e6
/obj/machinery/power/smes/attackby(obj/item/I, mob/user, params)
@@ -333,7 +333,7 @@
ui = new(user, src, ui_key, "smes", name, 340, 440, master_ui, state)
ui.open()
/obj/machinery/power/smes/get_ui_data()
/obj/machinery/power/smes/ui_data()
var/list/data = list(
"capacityPercent" = round(100*charge/capacity, 0.1),
"capacity" = capacity,
+1 -1
View File
@@ -363,7 +363,7 @@
ui = new(user, src, ui_key, "solar_control", name, 500, 400, master_ui, state)
ui.open()
/obj/machinery/power/solar_control/get_ui_data()
/obj/machinery/power/solar_control/ui_data()
var/data = list()
data["generated"] = round(lastgen)
@@ -155,8 +155,8 @@
src << "Missing Input"
return
var/list/startCoords = text2list(startInput, ";")
var/list/endCoords = text2list(endInput, ";")
var/list/startCoords = splittext(startInput, ";")
var/list/endCoords = splittext(endInput, ";")
if(!startCoords || !endCoords)
src << "Invalid Coords"
src << "Start Input: [startInput]"
@@ -3,6 +3,12 @@
caliber = "357"
projectile_type = /obj/item/projectile/bullet
/obj/item/ammo_casing/a762
desc = "A 7.62 bullet casing."
icon_state = "762-casing"
caliber = "a762"
projectile_type = /obj/item/projectile/bullet
/obj/item/ammo_casing/a50
desc = "A .50AE bullet casing."
caliber = ".50"
@@ -142,6 +148,12 @@
icon_state = "mshell"
projectile_type = /obj/item/projectile/bullet/meteorshot
/obj/item/ammo_casing/shotgun/breaching
name = "breaching shell"
desc = "An economic version of the meteorshot, utilizing similar technologies. Great for busting down doors."
icon_state = "mshell"
projectile_type = /obj/item/projectile/bullet/meteorshot/weak
/obj/item/ammo_casing/shotgun/pulseslug
name = "pulse slug"
desc = "A delicate device which can be loaded into a shotgun. The primer acts as a button which triggers the gain medium and fires a powerful \
@@ -166,3 +166,14 @@ obj/item/ammo_casing/energy/net
/obj/item/ammo_casing/energy/trap
projectile_type = /obj/item/projectile/energy/trap
select_name = "snare"
/obj/item/ammo_casing/energy/instakill
projectile_type = /obj/item/projectile/beam/instakill
e_cost = 0
select_name = "DESTROY"
/obj/item/ammo_casing/energy/instakill/blue
projectile_type = /obj/item/projectile/beam/instakill/blue
/obj/item/ammo_casing/energy/instakill/red
projectile_type = /obj/item/projectile/beam/instakill/red
@@ -304,6 +304,11 @@ obj/item/ammo_box/magazine/tommygunm45
icon_state = "m12gt"
ammo_type = /obj/item/ammo_casing/shotgun/dart/bioterror
/obj/item/ammo_box/magazine/m12g/breach
name = "shotgun magazine (12g breacher slugs)"
icon_state = "m12gbc"
ammo_type = /obj/item/projectile/bullet/meteorshot/weak
/obj/item/ammo_box/magazine/toy
name = "foam force META magazine"
ammo_type = /obj/item/ammo_casing/caseless/foam_dart
@@ -284,3 +284,27 @@
ammo_type = list(/obj/item/ammo_casing/energy/temp, /obj/item/ammo_casing/energy/temp/hot)
cell_type = "/obj/item/weapon/stock_parts/cell/high"
pin = null
/obj/item/weapon/gun/energy/laser/instakill
name = "instakill rifle"
icon_state = "instagib"
item_state = "instagib"
desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit."
ammo_type = list(/obj/item/ammo_casing/energy/instakill)
force = 60
origin_tech = null
/obj/item/weapon/gun/energy/laser/instakill/red
desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a red design."
icon_state = "instagibred"
item_state = "instagibred"
ammo_type = list(/obj/item/ammo_casing/energy/instakill/red)
/obj/item/weapon/gun/energy/laser/instakill/blue
desc = "A specialized ASMD laser-rifle, capable of flat-out disintegrating most targets in a single hit. This one has a blue design."
icon_state = "instagibblue"
item_state = "instagibblue"
ammo_type = list(/obj/item/ammo_casing/energy/instakill/blue)
/obj/item/weapon/gun/energy/laser/instagib/emp_act() //implying you could stop the instagib
return
+47 -40
View File
@@ -1,12 +1,12 @@
/obj/item/weapon/gun/projectile/automatic/l6_saw
name = "\improper L6 SAW"
desc = "A heavily modified 7.62 light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
desc = "A heavily modified 5.56x45mm light machine gun, designated 'L6 SAW'. Has 'Aussec Armoury - 2531' engraved on the receiver below the designation."
icon_state = "l6closed100"
item_state = "l6closedmag"
w_class = 5
slot_flags = 0
origin_tech = "combat=5;materials=1;syndicate=2"
mag_type = /obj/item/ammo_box/magazine/m762
mag_type = /obj/item/ammo_box/magazine/mm556x45
heavy_weapon = 1
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
var/cover_open = 0
@@ -27,6 +27,7 @@
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][magazine ? Ceiling(get_ammo(0)/12.5)*25 : "-empty"]"
item_state = "l6[cover_open ? "openmag" : "closedmag"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/afterattack(atom/target as mob|obj|turf, mob/living/user as mob|obj, flag, params) //what I tried to do here is just add a check to see if the cover is open or not and add an icon_state change because I can't figure out how c-20rs do it with overlays
@@ -64,70 +65,77 @@
/obj/item/projectile/bullet/saw
damage = 35
damage = 45
armour_penetration = 5
/obj/item/projectile/bullet/saw/bleeding
damage = 15
damage = 20
armour_penetration = 0
/obj/item/projectile/bullet/saw/bleeding/on_hit(atom/target, blocked = 0, hit_zone)
if((blocked != 100) && istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/H = target
H.drip(25)
H.drip(35)
/obj/item/projectile/bullet/saw/hollow
damage = 45
armour_penetration = 0
damage = 60
armour_penetration = -10
/obj/item/projectile/bullet/saw/ap
damage = 30
armour_penetration = 35
damage = 40
armour_penetration = 75
/obj/item/projectile/bullet/saw/incen
damage = 5
damage = 7
armour_penetration = 0
obj/item/projectile/bullet/saw/incen/Move()
..()
var/turf/location = get_turf(src)
if(location)
PoolOrNew(/obj/effect/hotspot, location)
location.hotspot_expose(700, 50, 1)
/obj/item/projectile/bullet/saw/incen/on_hit(atom/target, blocked = 0)
. = ..()
if(iscarbon(target))
var/mob/living/carbon/M = target
M.adjust_fire_stacks(1)
M.adjust_fire_stacks(3)
M.IgniteMob()
//magazines//
/obj/item/ammo_box/magazine/m762
name = "box magazine (7.62mm)"
/obj/item/ammo_box/magazine/mm556x45
name = "box magazine (5.56x45mm)"
icon_state = "a762-50"
origin_tech = "combat=2"
ammo_type = /obj/item/ammo_casing/a762
caliber = "a762"
ammo_type = /obj/item/ammo_casing/mm556x45
caliber = "mm55645"
max_ammo = 50
/obj/item/ammo_box/magazine/m762/bleeding
name = "box magazine (Bleeding 7.62mm)"
/obj/item/ammo_box/magazine/mm556x45/bleeding
name = "box magazine (Bleeding 5.56x45mm)"
origin_tech = "combat=3"
ammo_type = /obj/item/ammo_casing/a762/bleeding
ammo_type = /obj/item/ammo_casing/mm556x45/bleeding
/obj/item/ammo_box/magazine/m762/hollow
name = "box magazine (Hollow-Point 7.62mm)"
/obj/item/ammo_box/magazine/mm556x45/hollow
name = "box magazine (Hollow-Point 5.56x45mm)"
origin_tech = "combat=3"
ammo_type = /obj/item/ammo_casing/a762/hollow
ammo_type = /obj/item/ammo_casing/mm556x45/hollow
/obj/item/ammo_box/magazine/m762/ap
name = "box magazine (Armor Penetrating 7.62mm)"
/obj/item/ammo_box/magazine/mm556x45/ap
name = "box magazine (Armor Penetrating 5.56x45mm)"
origin_tech = "combat=4"
ammo_type = /obj/item/ammo_casing/a762/ap
ammo_type = /obj/item/ammo_casing/mm556x45/ap
/obj/item/ammo_box/magazine/m762/incen
name = "box magazine (Incendiary 7.62mm)"
/obj/item/ammo_box/magazine/mm556x45/incen
name = "box magazine (Incendiary 5.56x45mm)"
origin_tech = "combat=4"
ammo_type = /obj/item/ammo_casing/a762/incen
ammo_type = /obj/item/ammo_casing/mm556x45/incen
/obj/item/ammo_box/magazine/m762/update_icon()
/obj/item/ammo_box/magazine/mm556x45/update_icon()
..()
icon_state = "a762-[round(ammo_count(),10)]"
@@ -135,28 +143,27 @@
//casings//
/obj/item/ammo_casing/a762
desc = "A 7.62mm bullet casing."
/obj/item/ammo_casing/mm556x45
desc = "A 556x45mm bullet casing."
icon_state = "762-casing"
caliber = "a762"
caliber = "mm55645"
projectile_type = /obj/item/projectile/bullet/saw
/obj/item/ammo_casing/a762/bleeding
desc = "A 7.62mm bullet casing with specialized inner-casing, that when it makes contact with a target, release tiny shrapnel to induce internal bleeding."
/obj/item/ammo_casing/mm556x45/bleeding
desc = "A 556x45mm bullet casing with specialized inner-casing, that when it makes contact with a target, release tiny shrapnel to induce internal bleeding."
icon_state = "762-casing"
caliber = "a762"
projectile_type = /obj/item/projectile/bullet/saw/bleeding
/obj/item/ammo_casing/a762/hollow
desc = "A 7.62mm bullet casing designed to cause more damage to unarmored targets."
/obj/item/ammo_casing/mm556x45/hollow
desc = "A 556x45mm bullet casing designed to cause more damage to unarmored targets."
projectile_type = /obj/item/projectile/bullet/saw/hollow
/obj/item/ammo_casing/a762/ap
desc = "A 7.62mm bullet casing designed with a hardened-tipped core to help penetrate armored targets."
/obj/item/ammo_casing/mm556x45/ap
desc = "A 556x45mm bullet casing designed with a hardened-tipped core to help penetrate armored targets."
projectile_type = /obj/item/projectile/bullet/saw/ap
/obj/item/ammo_casing/a762/incen
desc = "A 7.62mm bullet casing designed with a chemical-filled capsule on the tip that when bursted, reacts with the atmosphere to produce a fireball, engulfing the target in flames. "
/obj/item/ammo_casing/mm556x45/incen
desc = "A 556x45mm bullet casing designed with a chemical-filled capsule on the tip that when bursted, reacts with the atmosphere to produce a fireball, engulfing the target in flames. "
projectile_type = /obj/item/projectile/bullet/saw/incen
@@ -298,7 +298,7 @@
item_state = "bulldog"
w_class = 3
origin_tech = "combat=5;materials=4;syndicate=6"
mag_type = /obj/item/ammo_box/magazine/m12g
mag_type = /obj/item/ammo_box/magazine/m12g/stun
fire_sound = 'sound/weapons/Gunshot.ogg'
can_suppress = 0
burst_size = 1
+19 -1
View File
@@ -11,7 +11,6 @@
/obj/item/projectile/beam/practice
name = "practice laser"
damage = 0
hitsound = null
nodamage = 1
/obj/item/projectile/beam/scatter
@@ -92,3 +91,22 @@
/obj/item/projectile/beam/lasertag/bluetag
icon_state = "bluelaser"
suit_types = list(/obj/item/clothing/suit/redtag)
/obj/item/projectile/beam/instakill
name = "instagib laser"
icon_state = "purple_laser"
damage = 200
damage_type = BURN
/obj/item/projectile/beam/instakill/blue
icon_state = "blue_laser"
/obj/item/projectile/beam/instakill/red
icon_state = "red_laser"
/obj/item/projectile/beam/instakill/on_hit(atom/target)
. = ..()
if(iscarbon(target))
var/mob/living/carbon/M = target
M.visible_message("<span class='danger'>[M] explodes into a shower of gibs!</span>")
M.gib()
@@ -72,7 +72,7 @@
. = ..()
if(iscarbon(target))
var/mob/living/carbon/M = target
M.adjust_fire_stacks(1)
M.adjust_fire_stacks(4)
M.IgniteMob()
@@ -101,6 +101,11 @@
stun = 8
hitsound = 'sound/effects/meteorimpact.ogg'
/obj/item/projectile/bullet/meteorshot/weak
damage = 10
weaken = 4
stun = 4
/obj/item/projectile/bullet/meteorshot/on_hit(atom/target, blocked = 0)
. = ..()
if(istype(target, /atom/movable))
@@ -80,7 +80,7 @@
ui = new(user, src, ui_key, "chem_dispenser", name, 550, 550, master_ui, state)
ui.open()
/obj/machinery/chem_dispenser/get_ui_data()
/obj/machinery/chem_dispenser/ui_data()
var/data = list()
data["amount"] = amount
data["energy"] = energy
@@ -73,7 +73,7 @@
ui = new(user, src, ui_key, "chem_heater", name, 275, 400, master_ui, state)
ui.open()
/obj/machinery/chem_heater/get_ui_data()
/obj/machinery/chem_heater/ui_data()
var/data = list()
data["targetTemp"] = target_temperature
data["isActive"] = on
@@ -2,6 +2,7 @@
/datum/reagent/blob
name = "Unknown"
description = "shouldn't exist and you should adminhelp immediately."
color = "#FFFFFF"
var/shortdesc = null //just damage and on_mob effects, doesn't include special, blob-tile only effects
var/blobbernaut_message = "slams" //blobbernaut attack verb
var/message = "The blob strikes you" //message sent to any mob hit by the blob
@@ -16,7 +17,7 @@
/datum/reagent/blob/proc/death_reaction(obj/effect/blob/B, cause) //when a blob dies, do this
return
/datum/reagent/blob/proc/expand_reaction(obj/effect/blob/B, turf/T) //when the blob expands, do this
/datum/reagent/blob/proc/expand_reaction(obj/effect/blob/B, obj/effect/blob/newB, turf/T) //when the blob expands, do this
return
//does brute and a little stamina damage
@@ -24,7 +25,7 @@
name = "Ripping Tendrils"
id = "ripping_tendrils"
description = "will do medium brute and stamina damage."
color = "#890000"
color = "#991010"
blobbernaut_message = "rips"
message_living = ", and you feel your skin ripping and tearing off"
@@ -60,12 +61,12 @@
B.overmind.blob_mobs.Add(BS)
return ..()
/datum/reagent/blob/sporing_pods/expand_reaction(obj/effect/blob/B, turf/T)
/datum/reagent/blob/sporing_pods/expand_reaction(obj/effect/blob/B, obj/effect/blob/newB, turf/T)
if(prob(10))
var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(T)
BS.overmind = B.overmind
BS.update_icons()
B.overmind.blob_mobs.Add(BS)
newB.overmind.blob_mobs.Add(BS)
//does brute damage but can replicate when damaged and has a chance of expanding again
/datum/reagent/blob/replicating_foam
@@ -82,15 +83,15 @@
/datum/reagent/blob/replicating_foam/damage_reaction(obj/effect/blob/B, original_health, damage, damage_type, cause)
if(damage > 0 && original_health - damage > 0)
var/obj/effect/blob/newB = B.expand()
var/obj/effect/blob/newB = B.expand(null, 0)
if(newB)
newB.health = original_health - damage
newB.check_health(cause)
newB.update_icon()
return ..()
/datum/reagent/blob/replicating_foam/expand_reaction(obj/effect/blob/B, turf/T)
B.expand() //do it again!
/datum/reagent/blob/replicating_foam/expand_reaction(obj/effect/blob/B, obj/effect/blob/newB, turf/T)
newB.expand() //do it again!
//does low burn and a lot of stamina damage, reacts to stamina damage
/datum/reagent/blob/energized_fibers
@@ -98,7 +99,7 @@
id = "energized_fibers"
description = "will do low burn and high stamina damage, and react to stamina damage."
shortdesc = "will do low burn and high stamina damage."
color = "#FFDC73"
color = "#EFD65A"
blobbernaut_message = "shocks"
message_living = ", and you feel a strong tingling sensation"
@@ -229,6 +230,29 @@
if(M)
M.adjustStaminaLoss(0.4*reac_volume)
//does burn damage and EMPs, slightly fragile
/datum/reagent/blob/electromagnetic_web
name = "Electromagnetic Web"
id = "electromagnetic_web"
description = "will do low burn damage and EMP targets, but is somewhat fragile."
color = "#83ECEC"
blobbernaut_message = "lashes"
message = "The blob lashes you"
message_living = ", and you hear a faint buzzing"
/datum/reagent/blob/electromagnetic_web/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
reac_volume = ..()
M.emp_act(2)
if(M)
M.apply_damage(0.6*reac_volume, BURN)
/datum/reagent/blob/electromagnetic_web/damage_reaction(obj/effect/blob/B, original_health, damage, damage_type, cause)
return damage * 1.2 //a laser will do 24 damage, which will kill any recently-made normal blob
/datum/reagent/blob/electromagnetic_web/death_reaction(obj/effect/blob/B, cause)
if(!isnull(cause))
empulse(B.loc, 2, 3) //less than screen range, so you can stand out of range to avoid it
//does brute damage, bonus damage for each nearby blob, and spreads damage out
/datum/reagent/blob/synchronous_mesh
name = "Synchronous Mesh"
@@ -261,9 +285,9 @@
for(var/obj/effect/blob/C in orange(1, B))
if(C.overmind && C.overmind.blob_reagent_datum == B.overmind.blob_reagent_datum && !istype(C, /obj/effect/blob/core)) //only hurt blobs that have the same overmind chemical and aren't cores
C.take_damage(damage/damagesplit, CLONE, B, 0)
return damage/damagesplit
return damage / damagesplit
else
return damage*1.25
return damage * 1.25
//does low brute damage, oxygen damage, and stamina damage and wets tiles when damaged
/datum/reagent/blob/pressurized_slime
@@ -241,24 +241,24 @@
build_path = /obj/item/weapon/circuitboard/rdconsole
category = list("Computer Boards")
/datum/design/ordercomp
name = "Computer Design (Supply ordering console)"
desc = "Allows for the construction of circuit boards used to build a Supply ordering console."
id = "ordercomp"
req_tech = list("programming" = 2)
build_type = IMPRINTER
materials = list(MAT_GLASS = 1000, "sacid" = 20)
build_path = /obj/item/weapon/circuitboard/ordercomp
category = list("Computer Boards")
/datum/design/supplycomp
name = "Computer Design (Supply shuttle console)"
desc = "Allows for the construction of circuit boards used to build a Supply shuttle console."
id = "supplycomp"
/datum/design/cargo
name = "Computer Design (Supply Console)"
desc = "Allows for the construction of circuit boards used to build a Supply Console."
id = "cargo"
req_tech = list("programming" = 3)
build_type = IMPRINTER
materials = list(MAT_GLASS = 1000, "sacid" = 20)
build_path = /obj/item/weapon/circuitboard/supplycomp
build_path = /obj/item/weapon/circuitboard/cargo
category = list("Computer Boards")
/datum/design/cargorequest
name = "Computer Design (Supply Request Console)"
desc = "Allows for the construction of circuit boards used to build a Supply Request Console."
id = "cargorequest"
req_tech = list("programming" = 2)
build_type = IMPRINTER
materials = list(MAT_GLASS = 1000, "sacid" = 20)
build_path = /obj/item/weapon/circuitboard/cargo/request
category = list("Computer Boards")
/datum/design/mining
+2 -2
View File
@@ -39,12 +39,12 @@
var/list/temp_list
if(!id_with_upload.len)
temp_list = list()
temp_list = text2list(id_with_upload_string, ";")
temp_list = splittext(id_with_upload_string, ";")
for(var/N in temp_list)
id_with_upload += text2num(N)
if(!id_with_download.len)
temp_list = list()
temp_list = text2list(id_with_download_string, ";")
temp_list = splittext(id_with_download_string, ";")
for(var/N in temp_list)
id_with_download += text2num(N)
@@ -36,7 +36,7 @@ var/datum/events/keycard_events = new()
ui = new(user, src, ui_key, "keycard_auth", name, 375, 125, master_ui, state)
ui.open()
/obj/machinery/keycard_auth/get_ui_data()
/obj/machinery/keycard_auth/ui_data()
var/list/data = list()
data["waiting"] = waiting
data["auth_required"] = event_source ? event_source.event : 0
+78
View File
@@ -0,0 +1,78 @@
/obj/machinery/computer/shuttle
name = "Shuttle Console"
icon_screen = "shuttle"
icon_keyboard = "tech_key"
req_access = list( )
circuit = /obj/item/weapon/circuitboard/shuttle
var/shuttleId
var/possible_destinations = ""
var/admin_controlled
var/no_destination_swap = 0
/obj/machinery/computer/shuttle/New(location, obj/item/weapon/circuitboard/shuttle/C)
..()
if(istype(C))
possible_destinations = C.possible_destinations
shuttleId = C.shuttleId
/obj/machinery/computer/shuttle/attack_hand(mob/user)
if(..(user))
return
src.add_fingerprint(usr)
var/list/options = params2list(possible_destinations)
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
var/dat = "Status: [M ? M.getStatusText() : "*Missing*"]<br><br>"
if(M)
var/destination_found
for(var/obj/docking_port/stationary/S in SSshuttle.stationary)
if(!options.Find(S.id))
continue
if(M.canDock(S))
continue
destination_found = 1
dat += "<A href='?src=\ref[src];move=[S.id]'>Send to [S.name]</A><br>"
if(!destination_found)
dat += "<B>Shuttle Locked</B><br>"
if(admin_controlled)
dat += "Authorized personnel only<br>"
dat += "<A href='?src=\ref[src];request=1]'>Request Authorization</A><br>"
dat += "<a href='?src=\ref[user];mach_close=computer'>Close</a>"
var/datum/browser/popup = new(user, "computer", M ? M.name : "shuttle", 300, 200)
popup.set_content("<center>[dat]</center>")
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/machinery/computer/shuttle/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(!allowed(usr))
usr << "<span class='danger'>Access denied.</span>"
return
if(href_list["move"])
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
if(M.launch_status == ENDGAME_LAUNCHED)
usr << "<span class='warning'>You've already escaped. Never going back to that place again!</span>"
return
if(no_destination_swap)
if(M.mode != SHUTTLE_IDLE)
usr << "<span class='warning'>Shuttle already in transit.</span>"
return
switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1))
if(0)
usr << "<span class='notice'>Shuttle received message and will be sent shortly.</span>"
if(1)
usr << "<span class='warning'>Invalid shuttle requested.</span>"
else
usr << "<span class='notice'>Unable to comply.</span>"
/obj/machinery/computer/shuttle/emag_act(mob/user)
if(!emagged)
src.req_access = list()
emagged = 1
user << "<span class='notice'>You fried the consoles ID checking system.</span>"
+76
View File
@@ -0,0 +1,76 @@
/obj/machinery/computer/emergency_shuttle
name = "emergency shuttle console"
desc = "For shuttle control."
icon_screen = "shuttle"
icon_keyboard = "tech_key"
var/auth_need = 3
var/list/authorized = list()
/obj/machinery/computer/emergency_shuttle/attackby(obj/item/weapon/card/W, mob/user, params)
if(stat & (BROKEN|NOPOWER))
return
if(!istype(W, /obj/item/weapon/card))
return
if(SSshuttle.emergency.mode != SHUTTLE_DOCKED)
return
if(!user)
return
if(SSshuttle.emergency.timeLeft() < 11)
return
if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
if (istype(W, /obj/item/device/pda))
var/obj/item/device/pda/pda = W
W = pda.id
if (!W:access) //no access
user << "The access level of [W:registered_name]\'s card is not high enough. "
return
var/list/cardaccess = W:access
if(!istype(cardaccess, /list) || !cardaccess.len) //no access
user << "The access level of [W:registered_name]\'s card is not high enough. "
return
if(!(access_heads in W:access)) //doesn't have this access
user << "The access level of [W:registered_name]\'s card is not high enough. "
return 0
var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort")
if(SSshuttle.emergency.mode != SHUTTLE_DOCKED || user.get_active_hand() != W)
return 0
var/seconds = SSshuttle.emergency.timeLeft()
if(seconds <= 10)
return 0
switch(choice)
if("Authorize")
if(!authorized.Find(W:registered_name))
authorized += W:registered_name
if(auth_need - authorized.len > 0)
message_admins("[key_name_admin(user.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) has authorized early shuttle launch ",0,1)
log_game("[key_name(user)] has authorized early shuttle launch in ([x],[y],[z])")
minor_announce("[auth_need - authorized.len] more authorization(s) needed until shuttle is launched early",null,1)
else
message_admins("[key_name_admin(user.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) has launched the emergency shuttle [seconds] seconds before launch.",0,1)
log_game("[key_name(user)] has launched the emergency shuttle in ([x],[y],[z]) [seconds] seconds before launch.")
minor_announce("The emergency shuttle will launch in 10 seconds",null,1)
SSshuttle.emergency.setTimer(100)
if("Repeal")
if(authorized.Remove(W:registered_name))
minor_announce("[auth_need - authorized.len] authorizations needed until shuttle is launched early")
if("Abort")
if(authorized.len)
minor_announce("All authorizations to launch the shuttle early have been revoked.")
authorized.Cut()
/obj/machinery/computer/emergency_shuttle/emag_act(mob/user)
if(!emagged && SSshuttle.emergency.mode == SHUTTLE_DOCKED)
var/time = SSshuttle.emergency.timeLeft()
message_admins("[key_name_admin(user.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) has emagged the emergency shuttle [time] seconds before launch.",0,1)
log_game("[key_name(user)] has emagged the emergency shuttle in ([x],[y],[z]) [time] seconds before launch.")
minor_announce("The emergency shuttle will launch in 10 seconds", "SYSTEM ERROR:",null,1)
SSshuttle.emergency.setTimer(100)
emagged = 1
+24
View File
@@ -0,0 +1,24 @@
/obj/machinery/computer/shuttle/ferry
name = "transport ferry console"
circuit = /obj/item/weapon/circuitboard/ferry
shuttleId = "ferry"
possible_destinations = "ferry_home;ferry_away"
/obj/machinery/computer/shuttle/ferry/request
name = "ferry console"
circuit = /obj/item/weapon/circuitboard/ferry/request
var/cooldown //prevents spamming admins
possible_destinations = "ferry_home"
admin_controlled = 1
/obj/machinery/computer/shuttle/ferry/request/Topic(href, href_list)
..()
if(href_list["request"])
if(cooldown)
return
cooldown = 1
usr << "<span class='notice'>Your request has been recieved by Centcom.</span>"
admins << "<b>FERRY: <font color='blue'>[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) (<A HREF='?_src_=holder;secrets=moveferry'>Move Ferry</a>)</b> is requesting to move the transport ferry to Centcom.</font>"
spawn(600) //One minute cooldown
cooldown = 0
+2 -111
View File
@@ -294,8 +294,6 @@
pixel_x = oldPY
pixel_y = (oldPX*(-1))
//this is the main proc. It instantly moves our mobile port to stationary port S1
//it handles all the generic behaviour, such as sanity checks, closing doors on the shuttle, stunning mobs, etc
/obj/docking_port/mobile/proc/dock(obj/docking_port/stationary/S1)
@@ -330,8 +328,6 @@
rotation += (rotation % 90) //diagonal rotations not allowed, round up
rotation = SimplifyDegrees(rotation)
//remove area surrounding docking port
if(areaInstance.contents.len)
var/area/A0 = locate("[area_type]")
@@ -363,7 +359,7 @@
for(var/atom/movable/AM in T0)
AM.onShuttleMove(T1, rotation)
if (rotation)
if(rotation)
T1.shuttleRotate(rotation)
//lighting stuff
@@ -529,112 +525,7 @@
dst = previous
else
dst = destination
. += " towards [dst ? dst.name : "unknown location"] ([timeLeft(600)]mins)"
/obj/machinery/computer/shuttle
name = "Shuttle Console"
icon_screen = "shuttle"
icon_keyboard = "tech_key"
req_access = list( )
circuit = /obj/item/weapon/circuitboard/shuttle
var/shuttleId
var/possible_destinations = ""
var/admin_controlled
var/no_destination_swap = 0
/obj/machinery/computer/shuttle/New(location, obj/item/weapon/circuitboard/shuttle/C)
..()
if(istype(C))
possible_destinations = C.possible_destinations
shuttleId = C.shuttleId
/obj/machinery/computer/shuttle/attack_hand(mob/user)
if(..(user))
return
src.add_fingerprint(usr)
var/list/options = params2list(possible_destinations)
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
var/dat = "Status: [M ? M.getStatusText() : "*Missing*"]<br><br>"
if(M)
var/destination_found
for(var/obj/docking_port/stationary/S in SSshuttle.stationary)
if(!options.Find(S.id))
continue
if(M.canDock(S))
continue
destination_found = 1
dat += "<A href='?src=\ref[src];move=[S.id]'>Send to [S.name]</A><br>"
if(!destination_found)
dat += "<B>Shuttle Locked</B><br>"
if(admin_controlled)
dat += "Authorized personnel only<br>"
dat += "<A href='?src=\ref[src];request=1]'>Request Authorization</A><br>"
dat += "<a href='?src=\ref[user];mach_close=computer'>Close</a>"
var/datum/browser/popup = new(user, "computer", M ? M.name : "shuttle", 300, 200)
popup.set_content("<center>[dat]</center>")
popup.set_title_image(usr.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/machinery/computer/shuttle/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
src.add_fingerprint(usr)
if(!allowed(usr))
usr << "<span class='danger'>Access denied.</span>"
return
if(href_list["move"])
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
if(M.launch_status == ENDGAME_LAUNCHED)
usr << "<span class='warning'>You've already escaped. Never going back to that place again!</span>"
return
if(no_destination_swap)
if(M.mode != SHUTTLE_IDLE)
usr << "<span class='warning'>Shuttle already in transit.</span>"
return
switch(SSshuttle.moveShuttle(shuttleId, href_list["move"], 1))
if(0)
usr << "<span class='notice'>Shuttle received message and will be sent shortly.</span>"
if(1)
usr << "<span class='warning'>Invalid shuttle requested.</span>"
else
usr << "<span class='notice'>Unable to comply.</span>"
/obj/machinery/computer/shuttle/emag_act(mob/user)
if(!emagged)
src.req_access = list()
emagged = 1
user << "<span class='notice'>You fried the consoles ID checking system.</span>"
/obj/machinery/computer/shuttle/ferry
name = "transport ferry console"
circuit = /obj/item/weapon/circuitboard/ferry
shuttleId = "ferry"
possible_destinations = "ferry_home;ferry_away"
/obj/machinery/computer/shuttle/ferry/request
name = "ferry console"
circuit = /obj/item/weapon/circuitboard/ferry/request
var/cooldown //prevents spamming admins
possible_destinations = "ferry_home"
admin_controlled = 1
/obj/machinery/computer/shuttle/ferry/request/Topic(href, href_list)
..()
if(href_list["request"])
if(cooldown)
return
cooldown = 1
usr << "<span class='notice'>Your request has been recieved by Centcom.</span>"
admins << "<b>FERRY: <font color='blue'>[key_name_admin(usr)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[usr]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[usr]'>FLW</A>) (<A HREF='?_src_=holder;secrets=moveferry'>Move Ferry</a>)</b> is requesting to move the transport ferry to Centcom.</font>"
spawn(600) //One minute cooldown
cooldown = 0
. += " towards [dst ? dst.name : "unknown location"] ([timeLeft(600)] minutes)"
#undef DOCKING_PORT_HIGHLIGHT
+40
View File
@@ -0,0 +1,40 @@
#define SYNDICATE_CHALLENGE_TIMER 12000 //20 minutes
/obj/machinery/computer/shuttle/syndicate
name = "syndicate shuttle terminal"
icon_screen = "syndishuttle"
icon_keyboard = "syndie_key"
req_access = list(access_syndicate)
shuttleId = "syndicate"
possible_destinations = "syndicate_away;syndicate_z5;syndicate_ne;syndicate_nw;syndicate_n;syndicate_se;syndicate_sw;syndicate_s"
var/challenge = FALSE
/obj/machinery/computer/shuttle/syndicate/recall
name = "syndicate shuttle recall terminal"
possible_destinations = "syndicate_away"
/obj/machinery/computer/shuttle/syndicate/Topic(href, href_list)
if(href_list["move"])
if(challenge && world.time < SYNDICATE_CHALLENGE_TIMER)
usr << "<span class='warning'>You've issued a combat challenge to the station! You've got to give them at least [round(((SYNDICATE_CHALLENGE_TIMER - world.time) / 10) / 60)] more minutes to allow them to prepare.</span>"
return 0
..()
/obj/machinery/computer/shuttle/syndicate/drop_pod
name = "syndicate assault pod control"
icon = 'icons/obj/terminals.dmi'
icon_state = "dorm_available"
req_access = list(access_syndicate)
shuttleId = "steel_rain"
possible_destinations = null
/obj/machinery/computer/shuttle/syndicate/drop_pod/Topic(href, href_list)
if(href_list["move"])
if(z != ZLEVEL_CENTCOM)
usr << "<span class='warning'>Pods are one way!</span>"
return 0
..()
#undef SYNDICATE_CHALLENGE_TIMER
+6
View File
@@ -0,0 +1,6 @@
/obj/machinery/computer/shuttle/white_ship
name = "White Ship Console"
desc = "Used to control the White Ship."
circuit = /obj/item/weapon/circuitboard/white_ship
shuttleId = "whiteship"
possible_destinations = "whiteship_away;whiteship_home;whiteship_z4"
+1 -1
View File
@@ -47,4 +47,4 @@
target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
playsound(get_turf(target), mSounds[randM], 50, 1)
flick("e_flash", target.flash)
target.flash_eyes()
+8 -1
View File
@@ -30,7 +30,7 @@
*
* return list Data to be sent to the UI.
**/
/datum/proc/get_ui_data(mob/user)
/datum/proc/ui_data(mob/user)
return list() // Not implemented.
@@ -60,6 +60,13 @@
/datum/proc/ui_host()
return src // Default src.
/**
* global
*
* Used to track the current screen.
**/
/datum/var/ui_screen = "home"
/**
* global
*
+8 -10
View File
@@ -39,7 +39,6 @@
/datum/ui_state/proc/can_use_topic(src_object, mob/user)
return UI_CLOSE // Don't allow interaction by default.
/**
* public
*
@@ -48,22 +47,21 @@
* return UI_state The state of the UI.
**/
/mob/proc/shared_ui_interaction(src_object)
if(!client || stat) // Close UIs if mindless or dead/unconcious.
if(!client) // Close UIs if mindless.
return UI_CLOSE
// Update UIs if incapicitated but concious.
else if(incapacitated() || lying)
else if(stat) // Disable UIs if unconcious.
return UI_DISABLED
else if(incapacitated() || lying) // Update UIs if incapicitated but concious.
return UI_UPDATE
return UI_INTERACTIVE
/mob/living/silicon/ai/shared_ui_interaction(src_object)
if(lacks_power()) // Close UIs if the AI is unpowered.
return UI_CLOSE
if(lacks_power()) // Disable UIs if the AI is unpowered.
return UI_DISABLED
return ..()
/mob/living/silicon/robot/shared_ui_interaction(src_object)
if(cell.charge <= 0) // Close UIs if the Borg is unpowered.
return UI_CLOSE
if(lockcharge) // Disable UIs if the Borg is locked.
if(cell.charge <= 0 || lockcharge) // Disable UIs if the Borg is unpowered or locked.
return UI_DISABLED
return ..()
@@ -92,7 +90,7 @@
* return UI_state The state of the UI.
**/
/mob/living/proc/shared_living_ui_distance(atom/movable/src_object)
if(!(src_object in view(4, src))) // If the object is out of view, close it.
if(!(src_object in view(src))) // If the object is obscured, close it.
return UI_CLOSE
var/dist = get_dist(src_object, src)
+2 -2
View File
@@ -33,7 +33,7 @@
return
// Robots can interact with anything they can see.
if(get_dist(src, src_object) <= src.client.view)
if(get_dist(src, src_object) <= client.view)
return UI_INTERACTIVE
return UI_DISABLED // Otherwise they can keep the UI open.
@@ -43,7 +43,7 @@
return
// The AI can interact with anything it can see nearby, or with cameras.
if((get_dist(src, src_object) <= src.client.view) || cameranet.checkTurfVis(get_turf_pixel(src_object)))
if((get_dist(src, src_object) <= client.view) || cameranet.checkTurfVis(get_turf_pixel(src_object)))
return UI_INTERACTIVE
return UI_CLOSE
+3 -3
View File
@@ -9,6 +9,6 @@
/datum/ui_state/z_state/can_use_topic(src_object, mob/user)
var/turf/turf_obj = get_turf(src_object)
var/turf/turf_usr = get_turf(user)
if(!turf_obj || !turf_usr || !(turf_obj.z == turf_usr.z))
return UI_CLOSE
return UI_INTERACTIVE
if(turf_obj && turf_usr && turf_obj.z == turf_usr.z)
return UI_INTERACTIVE
return UI_CLOSE
+1 -1
View File
@@ -22,7 +22,7 @@
ui = get_open_ui(user, src_object, ui_key)
if(!isnull(ui))
var/data = src_object.get_ui_data(user) // Get data from the src_object.
var/data = src_object.ui_data(user) // Get data from the src_object.
if(!force_open) // UI is already open; update it.
ui.push_data(data)
else // Re-open it anyways.
+16 -17
View File
@@ -31,7 +31,7 @@
var/list/initial_data // The data (and datastructure) used to initialize the UI.
var/status = UI_INTERACTIVE // The status/visibility of the UI.
var/datum/ui_state/state = null // Topic state used to determine status/interactability.
var/datum/tgui/master_ui // The parent UI.
var/datum/tgui/master_ui // The parent UI.
var/list/datum/tgui/children = list() // Children of this UI.
/**
@@ -80,16 +80,15 @@
* Open this UI (and initialize it with data).
**/
/datum/tgui/proc/open()
set waitfor = 0 // Don't wait on sleep()s.
if(!user.client)
return // Bail if there is no client.
update_status(push = 0) // Update the window status.
if(status == UI_CLOSE)
if(status < UI_UPDATE)
return // Bail if we're not supposed to open.
if(!initial_data)
set_initial_data(src_object.get_ui_data(user)) // Get the UI data.
set_initial_data(src_object.ui_data(user)) // Get the UI data.
var/window_size = ""
if(width && height) // If we have a width and height, use them.
@@ -129,6 +128,7 @@
children.Cut()
state = null
master_ui = null
qdel(src)
/**
* public
@@ -212,6 +212,7 @@
var/list/config_data = list(
"title" = title,
"status" = status,
"screen" = src_object.ui_screen,
"style" = style,
"interface" = interface,
"fancy" = user.client.prefs.tgui_fancy,
@@ -245,10 +246,10 @@
json_data["data"] = data
// Generate the JSON.
var/json = JSON.stringify(json_data)
var/json = json_encode(json_data)
// Strip #255/improper.
json = regex_replaceall(json, "\improper", "")
json = regex_replaceall(json, "\proper", "")
json = replacetext(json, "\proper", "")
json = replacetext(json, "\improper", "")
return json
/**
@@ -265,26 +266,24 @@
var/action = href_list["action"]
var/params = href_list; params -= "action"
// Handle any special actions.
switch(action)
if("tgui:initialize")
user << output(url_encode(get_json(initial_data)), "[window_id].browser:initialize")
initialized = TRUE
return
if("tgui:view")
if(params["screen"])
src_object.ui_screen = params["screen"]
SStgui.update_uis(src_object)
if("tgui:link")
user << link(params["url"])
return
if("tgui:fancy")
user.client.prefs.tgui_fancy = TRUE
return
if("tgui:nofrills")
user.client.prefs.tgui_fancy = FALSE
return
update_status(push = 0) // Update the window state.
var/update = src_object.ui_act(action, params, src, state) // Call ui_act() on the src_object.
if(src_object && update)
SStgui.update_uis(src_object) // If we have a src_object and its ui_act() told us to update.
else
update_status(push = 0) // Update the window state.
if(src_object.ui_act(action, params, src, state)) // Call ui_act() on the src_object.
SStgui.update_uis(src_object) // Update if the object requested it.
/**
* private
+13 -9
View File
@@ -40,13 +40,13 @@ var/global/list/uplinks = list()
ui.set_style("syndicate")
ui.open()
/obj/item/device/uplink/get_ui_data(mob/user)
/obj/item/device/uplink/ui_data(mob/user)
var/list/data = list()
data["telecrystals"] = telecrystals
data["lockable"] = lockable
var/list/uplink_items = get_uplink_items(gamemode)
data["buyable"] = list()
data["categories"] = list()
for(var/category in uplink_items)
var/list/cat = list(
"name" = category,
@@ -56,11 +56,10 @@ var/global/list/uplinks = list()
var/datum/uplink_item/I = uplink_items[category][item]
cat["items"] += list(list(
"name" = I.name,
"category" = I.category,
"cost" = I.cost,
"desc" = I.desc,
))
data["buyable"] += list(cat)
data["categories"] += list(cat)
return data
/obj/item/device/uplink/ui_act(action, params)
@@ -69,16 +68,20 @@ var/global/list/uplinks = list()
switch(action)
if("buy")
var/list/uplink_items = get_uplink_items(gamemode)
var/category = params["category"]
var/item = params["item"]
var/datum/uplink_item/I = uplink_items[category][item]
if(I)
var/list/uplink_items = get_uplink_items(gamemode)
var/list/buyable_items = list()
for(var/category in uplink_items)
buyable_items += uplink_items[category]
if(item in buyable_items)
var/datum/uplink_item/I = buyable_items[item]
I.buy(usr, src)
. = TRUE
if("lock")
active = FALSE
SStgui.close_uis(src)
return 1
/obj/item/device/uplink/ui_host()
@@ -97,6 +100,7 @@ var/global/list/uplinks = list()
user << "<span class='notice'>[I] refunded.</span>"
qdel(I)
return
..()
// A collection of pre-set uplinks, for admin spawns.
/obj/item/device/radio/uplink/New()
+27 -20
View File
@@ -190,9 +190,9 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
/datum/uplink_item/dangerous/machinegun
name = "L6 Squad Automatic Weapon"
desc = "A fully-loaded Aussec Armoury belt-fed machine gun. \
This deadly weapon has a massive 50-round magazine of devastating 7.62x51mm ammunition."
This deadly weapon has a massive 50-round magazine of devastating 5.56x45mm ammunition."
item = /obj/item/weapon/gun/projectile/automatic/l6_saw
cost = 23
cost = 18
surplus = 0
include_modes = list(/datum/game_mode/nuclear)
@@ -394,14 +394,14 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
name = "12g Slug Drum"
desc = "An additional 8-round slug magazine for use with the Bulldog shotgun. \
Now 8 times less likely to shoot your pals."
cost = 3
item = /obj/item/ammo_box/magazine/m12g
/datum/uplink_item/ammo/shotgun/slug
name = "12 Stun Slug Drum"
/datum/uplink_item/ammo/shotgun/stun
name = "12g Stun Slug Drum"
desc = "An alternative 8-round stun slug magazine for use with the Bulldog shotgun. \
Saying that they're completely non-lethal would be lying."
item = /obj/item/ammo_box/magazine/m12g/stun
cost = 3
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/shotgun/dragon
@@ -411,6 +411,13 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
item = /obj/item/ammo_box/magazine/m12g/dragon
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/shotgun/breach
name = "12g Breaching Shells"
desc = "An economic variant of the CMC meteorshot slugs, not as effective for knocking \
down targets, but still great for blasting airlocks off their frames."
item = /obj/item/ammo_box/magazine/m12g/breach
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/shotgun/bag
name = "12g Ammo Duffelbag"
desc = "A duffelbag filled with enough 12g ammo to supply an entire team, at a discounted price."
@@ -454,34 +461,34 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
include_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/ammo/machinegun/basic
name = "7.62x51mm Box Magazine"
desc = "A 50-round magazine of 7.62x51mm ammunition for use with the L6 SAW. \
name = "5.56x45mm Box Magazine"
desc = "A 50-round magazine of 5.56x45mm ammunition for use with the L6 SAW. \
By the time you need to use this, you'll already be on a pile of corpses."
item = /obj/item/ammo_box/magazine/m762
item = /obj/item/ammo_box/magazine/mm556x45
/datum/uplink_item/ammo/machinegun/bleeding
name = "7.62x51mm (Bleeding) Box Magazine"
desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW; equipped with special properties \
name = "5.56x45mm (Bleeding) Box Magazine"
desc = "A 50-round magazine of 5.56x45mm ammunition for use in the L6 SAW; equipped with special properties \
to induce internal bleeding on targets."
item = /obj/item/ammo_box/magazine/m762/bleeding
item = /obj/item/ammo_box/magazine/mm556x45/bleeding
/datum/uplink_item/ammo/machinegun/hollow
name = "7.62x51mm (Hollow-Point) Box Magazine"
desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
name = "5.56x45mm (Hollow-Point) Box Magazine"
desc = "A 50-round magazine of 5.56x45mm ammunition for use in the L6 SAW; equipped with hollow-point tips to help \
with the unarmored masses of crew."
item = /obj/item/ammo_box/magazine/m762/hollow
item = /obj/item/ammo_box/magazine/mm556x45/hollow
/datum/uplink_item/ammo/machinegun/ap
name = "7.62x51mm (Armor Penetrating) Box Magazine"
desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW; equipped with special properties \
name = "5.56x45mm (Armor Penetrating) Box Magazine"
desc = "A 50-round magazine of 5.56x45mm ammunition for use in the L6 SAW; equipped with special properties \
to puncture even the most durable armor."
item = /obj/item/ammo_box/magazine/m762/ap
item = /obj/item/ammo_box/magazine/mm556x45/ap
/datum/uplink_item/ammo/machinegun/incen
name = "7.62x51mm (Incendiary) Box Magazine"
desc = "A 50-round magazine of 7.62x51mm ammunition for use in the L6 SAW; tipped with a special flammable \
name = "5.56x45mm (Incendiary) Box Magazine"
desc = "A 50-round magazine of 5.56x45mm ammunition for use in the L6 SAW; tipped with a special flammable \
mixture that'll ignite anyone struck by the bullet. Some men just want to watch the world burn."
item = /obj/item/ammo_box/magazine/m762/incen
item = /obj/item/ammo_box/magazine/mm556x45/incen
/datum/uplink_item/ammo/sniper
cost = 4