Merge pull request #7 from Aurorastation/development

Baystation12 Sync
This commit is contained in:
skull132
2016-01-13 00:39:05 +02:00
230 changed files with 2235 additions and 2334 deletions
+2 -2
View File
@@ -3,8 +3,8 @@ language: c
sudo: false
env:
BYOND_MAJOR="508"
BYOND_MINOR="1293"
BYOND_MAJOR="509"
BYOND_MINOR="1318"
cache:
directories:
+2 -3
View File
@@ -203,7 +203,6 @@
#include "code\defines\procs\records.dm"
#include "code\defines\procs\sd_Alert.dm"
#include "code\defines\procs\statistics.dm"
#include "code\game\asteroid.dm"
#include "code\game\atoms.dm"
#include "code\game\atoms_movable.dm"
#include "code\game\periodic_news.dm"
@@ -313,7 +312,6 @@
#include "code\game\gamemodes\wizard\wizard.dm"
#include "code\game\jobs\access.dm"
#include "code\game\jobs\job_controller.dm"
#include "code\game\jobs\jobprocs.dm"
#include "code\game\jobs\jobs.dm"
#include "code\game\jobs\whitelist.dm"
#include "code\game\jobs\job\assistant.dm"
@@ -657,6 +655,7 @@
#include "code\game\objects\items\weapons\circuitboards\computer\air_management.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\camera_monitor.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\computer.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\holodeckcontrol.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\research.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\supply.dm"
#include "code\game\objects\items\weapons\circuitboards\computer\telecomms.dm"
@@ -835,7 +834,6 @@
#include "code\modules\admin\verbs\diagnostics.dm"
#include "code\modules\admin\verbs\dice.dm"
#include "code\modules\admin\verbs\getlogs.dm"
#include "code\modules\admin\verbs\icarus.dm"
#include "code\modules\admin\verbs\mapping.dm"
#include "code\modules\admin\verbs\massmodvar.dm"
#include "code\modules\admin\verbs\modifyvariables.dm"
@@ -1338,6 +1336,7 @@
#include "code\modules\nano\nanoui.dm"
#include "code\modules\nano\interaction\admin.dm"
#include "code\modules\nano\interaction\base.dm"
#include "code\modules\nano\interaction\conscious.dm"
#include "code\modules\nano\interaction\contained.dm"
#include "code\modules\nano\interaction\default.dm"
#include "code\modules\nano\interaction\inventory.dm"
+42 -52
View File
@@ -35,10 +35,9 @@ except ImportError:
try:
tiedosto = open("psycodownload.txt","r")
except:
tiedosto = open("psycodownload.txt","w")
tiedosto.write("http://www.voidspace.org.uk/python/modules.shtml#psyco")
tiedosto.write("\nhttp://psyco.sourceforge.net/download.html")
tiedosto.close()
with open("psycodownload.txt","w") as tiedosto:
tiedosto.write("http://www.voidspace.org.uk/python/modules.shtml#psyco")
tiedosto.write("\nhttp://psyco.sourceforge.net/download.html")
print "Check psycodownload.txt for a link"
else:
print "For god's sake, open psycodownload.txt"
@@ -190,15 +189,13 @@ tell_list = {}
if CORE_DATA.DISABLE_ALL_NON_MANDATORY_SOCKET_CONNECTIONS:
nudgeable = False
try:
tiedosto = open("replacenames.cache","r")
replacenames = pickle.load(tiedosto)
tiedosto.close()
with open("replacenames.cache","r") as tiedosto:
replacenames = pickle.load(tiedosto)
for i in replacenames.values():
if len(i) > call_me_max_length:
replacenames[replacenames.keys()[replacenames.values().index(i)]] = i[:call_me_max_length]
tiedosto = open("replacenames.cache","w")
pickle.dump(replacenames,tiedosto)
tiedosto.close()
with open("replacenames.cache","w") as tiedosto:
pickle.dump(replacenames,tiedosto)
if "[\0x01]" in i.lower() or "[\\0x01]" in i.lower():
i = i.replace("[\0x01]","")
i = i.replace("[\0X01]","")
@@ -211,13 +208,12 @@ except EOFError: #Cache corrupt
replacenames = {}
print "replacenames.cache is corrupt and couldn't be loaded."
try:
tiedosto = open("peopleheknows.cache","r")
peopleheknows = pickle.load(tiedosto)
tiedosto.close()
with open("peopleheknows.cache","r") as tiedosto:
peopleheknows = pickle.load(tiedosto)
except IOError:
peopleheknows = [[],[]]
tiedosto = open("peopleheknows.cache","w")
tiedosto.close()
with open("peopleheknows.cache","w") as tiedosto:
pass
except EOFError:
peopleheknows = [[],[]]
print "peopleheknows.cache is corrupt and couldn't be loaded."
@@ -345,16 +341,14 @@ if aggressive_pinging:
self_time = 0
global backup,disconnects,conn
while disconnects < 5:
if backup > self_time:
if time.time()-backup > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
else:
if time.time()-self_time > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
if backup > self_time and time.time()-backup > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
elif time.time()-self_time > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
time.sleep(refresh)
thread.start_new_thread(aggressive_ping,(aggressive_pinging_delay,aggressive_pinging_refresh,))
def stop(sender,debug=1):
@@ -370,16 +364,15 @@ def stop(sender,debug=1):
access_granted = True
else:
access_granted = False
if access_granted:
if debug:
print sender+":"+prefix+"stop"
if random.randint(0,100) == 50:
conn.privmsg(channel,"Hammertime!")
else:
conn.privmsg(channel,"Shutting down.")
disconnects = 99999
conn.quit()
return True
if access_granted and debug:
print sender+":"+prefix+"stop"
if random.randint(0,100) == 50:
conn.privmsg(channel,"Hammertime!")
else:
conn.privmsg(channel,"Shutting down.")
disconnects = 99999
conn.quit()
return True
else:
conn.privmsg(channel,"You cannot command me")
return False
@@ -401,13 +394,12 @@ def target(who,how_long):
if debug:
print "Banned",who,"For",how_long,"seconds"
if logbans:
tiedosto = open(targetdirectory+"banlog/"+str(int(start))+"-"+str(int(end))+".txt","w")
tiedosto.write("Start of ban on "+who+":"+str(int(start)))
tiedosto.write("\n")
tiedosto.write("End of ban on "+who+":"+str(int(end)))
tiedosto.write("\n")
tiedosto.write("In total:"+str(int(end-start))+"Seconds")
tiedosto.close()
with open(targetdirectory+"banlog/"+str(int(start))+"-"+str(int(end))+".txt","w") as tiedosto:
tiedosto.write("Start of ban on "+who+":"+str(int(start)))
tiedosto.write("\n")
tiedosto.write("End of ban on "+who+":"+str(int(end)))
tiedosto.write("\n")
tiedosto.write("In total:"+str(int(end-start))+"Seconds")
else:
CALL_OFF = False
pass
@@ -576,13 +568,12 @@ while True:
time.sleep(6)
Name = origname
conn.nick(Name)
if origname in truesender:
if influx == prefix+"stop":
time.sleep(0.5) #A small delay
conn.privmsg(channel,"Shutting down.")
conn.quit()
disconnects = 99999
break
if origname in truesender and influx == prefix+"stop":
time.sleep(0.5) #A small delay
conn.privmsg(channel,"Shutting down.")
conn.quit()
disconnects = 99999
break
if len(translateable) > 0 and enabled == True:
people = "-5|5|1-".join(users).lower()
if truesender.lower() in translateable:
@@ -633,9 +624,8 @@ while True:
arg = influx.lower()[8+len(prefix):]
if debug:
print truesender+":"+prefix+"suggest "+arg
tiedosto = open(targetdirectory+"suggestions/suggestions_"+str(int(time.time()))+".txt","a")
tiedosto.write(arg)
tiedosto.close()
with open(targetdirectory+"suggestions/suggestions_"+str(int(time.time()))+".txt","a") as tiedosto:
tiedosto.write(arg)
conn.privmsg(targetchannel,"Suggestion received")
elif cocheck( prefix+"help "): #Space in front of the ( to make sure that my command finder does not pick this up.
arg = " ".join(influx.split(" ")[1:]).lower()
-3
View File
@@ -28,9 +28,6 @@ datum/pipeline
if(!member.check_pressure(pressure))
break //Only delete 1 pipe per process
//Allow for reactions
//air.react() //Should be handled by pipe_network now
proc/temporarily_store_air()
//Update individual gas_mixtures by volume ratio
+4 -3
View File
@@ -154,18 +154,18 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
#ifdef ZASDBG
var/updated = 0
#endif
//defer updating of self-zone-blocked turfs until after all other turfs have been updated.
//this hopefully ensures that non-self-zone-blocked turfs adjacent to self-zone-blocked ones
//have valid zones when the self-zone-blocked turfs update.
var/list/deferred = list()
for(var/turf/T in updating)
//check if the turf is self-zone-blocked
if(T.c_airblock(T) & ZONE_BLOCKED)
deferred += T
continue
T.update_air_properties()
T.post_update_air_properties()
T.needs_air_update = 0
@@ -234,6 +234,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
/datum/controller/air_system/proc/remove_zone(zone/z)
zones.Remove(z)
zones_to_update.Remove(z)
/datum/controller/air_system/proc/air_blocked(turf/A, turf/B)
#ifdef ZASDBG
+22 -22
View File
@@ -1,13 +1,9 @@
/*
Making Bombs with ZAS:
Make burny fire with lots of burning
Draw off 5000K gas from burny fire
Separate gas into oxygen and phoron components
Obtain phoron and oxygen tanks filled up about 50-75% with normal-temp gas
Fill rest with super hot gas from separated canisters, they should be about 125C now.
Attach to transfer valve and open. BOOM.
Get gas to react in an air tank so that it gains pressure. If it gains enough pressure, it goes boom.
The more pressure, the more boom.
If it gains pressure too slowly, it may leak or just rupture instead of exploding.
*/
//#define FIREDBG
@@ -268,16 +264,16 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//determine how far the reaction can progress
var/reaction_limit = min(total_oxidizers*(FIRE_REACTION_FUEL_AMOUNT/FIRE_REACTION_OXIDIZER_AMOUNT), total_fuel) //stoichiometric limit
//calculate the firelevel.
var/firelevel = calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
var/firelevel_ratio = firelevel / vsc.fire_firelevel_multiplier
//vapour fuels are extremely volatile! The reaction progress is a percentage of the total fuel (similar to old zburn).)
var/gas_firelevel = calculate_firelevel(gas_fuel, total_oxidizers, reaction_limit, volume*group_multiplier) / vsc.fire_firelevel_multiplier
var/min_burn = 0.30*volume*group_multiplier/CELL_VOLUME //in moles - so that fires with very small gas concentrations burn out fast
var/gas_reaction_progress = min(max(min_burn, firelevel_ratio*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel)
var/gas_reaction_progress = min(max(min_burn, gas_firelevel*gas_fuel)*FIRE_GAS_BURNRATE_MULT, gas_fuel)
//liquid fuels are not as volatile, and the reaction progress depends on the size of the area that is burning. Limit the burn rate to a certain amount per area.
var/liquid_reaction_progress = min((firelevel_ratio*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel)
var/liquid_firelevel = calculate_firelevel(liquid_fuel, total_oxidizers, reaction_limit, 0) / vsc.fire_firelevel_multiplier
var/liquid_reaction_progress = min((liquid_firelevel*0.2 + 0.05)*fuel_area*FIRE_LIQUID_BURNRATE_MULT, liquid_fuel)
var/firelevel = (gas_fuel*gas_firelevel + liquid_fuel*liquid_firelevel)/total_fuel
var/total_reaction_progress = gas_reaction_progress + liquid_reaction_progress
var/used_fuel = min(total_reaction_progress, reaction_limit)
@@ -286,7 +282,7 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
#ifdef FIREDBG
log_debug("gas_fuel = [gas_fuel], liquid_fuel = [liquid_fuel], total_oxidizers = [total_oxidizers]")
log_debug("fuel_area = [fuel_area], total_fuel = [total_fuel], reaction_limit = [reaction_limit]")
log_debug("firelevel -> [firelevel] / [vsc.fire_firelevel_multiplier]")
log_debug("firelevel -> [firelevel] (gas: [gas_firelevel], liquid: [liquid_firelevel])")
log_debug("liquid_reaction_progress = [liquid_reaction_progress]")
log_debug("gas_reaction_progress = [gas_reaction_progress]")
log_debug("total_reaction_progress = [total_reaction_progress]")
@@ -315,13 +311,13 @@ turf/proc/hotspot_expose(exposed_temperature, exposed_volume, soh = 0)
//calculate the energy produced by the reaction and then set the new temperature of the mix
temperature = (starting_energy + vsc.fire_fuel_energy_release * (used_gas_fuel + used_liquid_fuel)) / heat_capacity()
update_values()
#ifdef FIREDBG
log_debug("used_gas_fuel = [used_gas_fuel]; used_liquid_fuel = [used_liquid_fuel]; total = [used_fuel]")
log_debug("new temperature = [temperature]")
log_debug("new temperature = [temperature]; new pressure = [return_pressure()]")
#endif
update_values()
return firelevel
datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
@@ -363,27 +359,31 @@ datum/gas_mixture/proc/check_recombustability(list/fuel_objs)
break
//returns a value between 0 and vsc.fire_firelevel_multiplier
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit)
/datum/gas_mixture/proc/calculate_firelevel(total_fuel, total_oxidizers, reaction_limit, gas_volume)
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
var/firelevel = 0
var/total_combustables = (total_fuel + total_oxidizers)
var/active_combustables = (FIRE_REACTION_OXIDIZER_AMOUNT/FIRE_REACTION_FUEL_AMOUNT + 1)*reaction_limit
if(total_combustables > 0)
//slows down the burning when the concentration of the reactants is low
var/dampening_multiplier = min(1, reaction_limit / (total_moles/group_multiplier))
var/damping_multiplier = min(1, active_combustables / (total_moles/group_multiplier))
//weight the damping mult so that it only really brings down the firelevel when the ratio is closer to 0
damping_multiplier = 2*damping_multiplier - (damping_multiplier*damping_multiplier)
//calculates how close the mixture of the reactants is to the optimum
//fires burn better when there is more oxidizer -- too much fuel will choke them out a bit, reducing firelevel.
//fires burn better when there is more oxidizer -- too much fuel will choke the fire out a bit, reducing firelevel.
var/mix_multiplier = 1 / (1 + (5 * ((total_fuel / total_combustables) ** 2)))
#ifdef FIREDBG
ASSERT(dampening_multiplier <= 1)
ASSERT(damping_multiplier <= 1)
ASSERT(mix_multiplier <= 1)
#endif
//toss everything together -- should produce a value between 0 and fire_firelevel_multiplier
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * damping_multiplier
return max( 0, firelevel)
+3
View File
@@ -21,6 +21,9 @@
/xgm_gas/phoron
id = "phoron"
name = "Phoron"
//Note that this has a significant impact on TTV yield.
//Because it is so high, any leftover phoron soaks up a lot of heat and drops the yield pressure.
specific_heat = 200 // J/(mol*K)
//Hypothetical group 14 (same as carbon), period 8 element.
+2 -1
View File
@@ -9,7 +9,8 @@ var/global/vs_control/vsc = new
var/fire_firelevel_multiplier_NAME = "Fire - Firelevel Constant"
var/fire_firelevel_multiplier_DESC = "Multiplied by the equation for firelevel, affects mainly the extingiushing of fires."
var/fire_fuel_energy_release = 397000
//Note that this parameter and the phoron heat capacity have a significant impact on TTV yield.
var/fire_fuel_energy_release = 866000 //J/mol. Adjusted to compensate for fire energy release being fixed, was 397000
var/fire_fuel_energy_release_NAME = "Fire - Fuel energy release"
var/fire_fuel_energy_release_DESC = "The energy in joule released when burning one mol of a burnable substance"
+3 -2
View File
@@ -108,11 +108,12 @@ Class Procs:
c_invalidate()
for(var/turf/simulated/T in contents)
into.add(T)
T.update_graphic(graphic_remove = air.graphic)
#ifdef ZASDBG
T.dbg(merged)
#endif
//rebuild the old zone's edges so that the will be possesed by the new zone
//rebuild the old zone's edges so that they will be possessed by the new zone
for(var/connection_edge/E in edges)
if(E.contains_zone(into))
continue //don't need to rebuild this edge
+14 -9
View File
@@ -308,7 +308,7 @@
return 1
/datum/gas_mixture/proc/react(atom/dump_location)
/datum/gas_mixture/proc/react()
zburn(null, force_burn=0, no_check=0) //could probably just call zburn() here with no args but I like being explicit.
@@ -444,20 +444,25 @@
total_gas[g] += gasmix.gas[g]
if(total_volume > 0)
//Average out the gases
for(var/g in total_gas)
total_gas[g] /= total_volume
var/datum/gas_mixture/combined = new(total_volume)
combined.gas = total_gas
//Calculate temperature
var/temperature = 0
if(total_heat_capacity > 0)
temperature = total_thermal_energy / total_heat_capacity
combined.temperature = total_thermal_energy / total_heat_capacity
combined.update_values()
//Allow for reactions
combined.react()
//Average out the gases
for(var/g in combined.gas)
combined.gas[g] /= total_volume
//Update individual gas_mixtures
for(var/datum/gas_mixture/gasmix in gases)
gasmix.gas = total_gas.Copy()
gasmix.temperature = temperature
gasmix.gas = combined.gas.Copy()
gasmix.temperature = combined.temperature
gasmix.multiply(gasmix.volume)
return 1
+11 -5
View File
@@ -71,11 +71,17 @@ proc/isemptylist(list/list)
return 1
return 0
//Empties the list by setting the length to 0. Hopefully the elements get garbage collected
proc/clearlist(list/list)
if(istype(list))
list.len = 0
return
/proc/instances_of_type_in_list(var/atom/A, var/list/L)
var/instances = 0
for(var/type in L)
if(istype(A, type))
instances++
return instances
//Empties the list by .Cut(). Setting lenght = 0 has been confirmed to leak references.
proc/clearlist(var/list/L)
if(islist(L))
L.Cut()
//Removes any null entries from the list
proc/listclearnulls(list/list)
+15
View File
@@ -17,3 +17,18 @@
if(A.simulated)
return 0
return 1
// Picks a turf without a mob from the given list of turfs, if one exists.
// If no such turf exists, picks any random turf from the given list of turfs.
/proc/pick_mobless_turf_if_exists(var/list/start_turfs)
if(!start_turfs.len)
return null
var/list/available_turfs = list()
for(var/start_turf in start_turfs)
var/mob/M = locate() in start_turf
if(!M)
available_turfs += start_turf
if(!available_turfs.len)
available_turfs = start_turfs
return pick(available_turfs)
+5 -1
View File
@@ -538,7 +538,7 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/y = min(world.maxy, max(1, A.y + dy))
return locate(x,y,A.z)
//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value.
//Makes sure MIDDLE is between LOW and HIGH. If not, it adjusts it. Returns the adjusted value. Lower bound takes priority.
/proc/between(var/low, var/middle, var/high)
return max(min(middle, high), low)
@@ -1309,3 +1309,7 @@ var/mob/dview/dview_mob = new
/mob/dview/New()
// do nothing. we don't want to be in any mob lists; we're a dummy not a mob.
// call to generate a stack trace and print to runtime logs
/proc/crash_with(msg)
CRASH(msg)
+1 -1
View File
@@ -291,7 +291,7 @@
user.listed_turf = null
else
user.listed_turf = T
user.client.statpanel = T.name
user.client.statpanel = "Turf"
return
/mob/proc/TurfAdjacent(var/turf/T)
+4 -1
View File
@@ -19,9 +19,12 @@
spell_objects.Cut()
if(spell_holder)
spell_holder.spell_masters -= src
if(spell_holder.client && spell_holder.client.screen)
spell_holder.client.screen -= src
spell_holder = null
/obj/screen/movable/spell_master/ResetVars()
..("spell_objects")
..("spell_objects", args)
spell_objects = list()
/obj/screen/movable/spell_master/MouseDrop()
+1
View File
@@ -91,6 +91,7 @@ var/list/delayed_garbage = list()
return
if(!istype(A))
warning("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
crash_with("qdel() passed object of type [A.type]. qdel() can only handle /datum types.")
del(A)
if(garbage_collector)
garbage_collector.dels++
+3 -3
View File
@@ -39,12 +39,12 @@ datum/controller/vote
result()
for(var/client/C in voting)
if(C)
C << browse(null,"window=vote;can_close=0")
C << browse(null,"window=vote")
reset()
else
for(var/client/C in voting)
if(C)
C << browse(vote.interface(C),"window=vote;can_close=0")
C << browse(vote.interface(C),"window=vote")
voting.Cut()
@@ -392,4 +392,4 @@ datum/controller/vote
set name = "Vote"
if(vote)
src << browse(vote.interface(client),"window=vote;can_close=0")
src << browse(vote.interface(client),"window=vote")
+4 -2
View File
@@ -48,7 +48,7 @@
else
assignment = "Unassigned"
var/id = add_zero(num2hex(rand(1, 1.6777215E7)), 6) //this was the best they could come up with? A large random number? *sigh*
var/id = generate_record_id()
var/icon/front = new(get_id_photo(H), dir = SOUTH)
var/icon/side = new(get_id_photo(H), dir = WEST)
//General Record
@@ -136,8 +136,10 @@
locked += L
return
/proc/generate_record_id()
return add_zero(num2hex(rand(1, 65535)), 4) //no point generating higher numbers because of the limitations of num2hex
proc/get_id_photo(var/mob/living/carbon/human/H)
/proc/get_id_photo(var/mob/living/carbon/human/H)
var/icon/preview_icon = null
var/g = "m"
+1 -1
View File
@@ -41,7 +41,7 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
(A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
((A.lights && haspower) ? "The door bolt lights are on." : "The door bolt lights are off!"),
((haspower) ? "The test light is on." : "The test light is off!"),
((A.backupPowerCablesCut()) ? "The backup power light is off!" : "The backup power light is on."),
((A.backup_power_lost_until) ? "The backup power light is off!" : "The backup power light is on."),
((A.aiControlDisabled==0 && !A.emagged && haspower)? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
((A.safe==0 && haspower)? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
((A.normalspeed==0 && haspower)? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
+1 -1
View File
@@ -5,7 +5,7 @@
var/icon/side = new(get_id_photo(dummy), dir = WEST)
var/datum/data/record/G = new /datum/data/record()
G.fields["name"] = "New Record"
G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
G.fields["id"] = generate_record_id()
G.fields["rank"] = "Unassigned"
G.fields["real_rank"] = "Unassigned"
G.fields["sex"] = "Male"
@@ -26,6 +26,7 @@
#define ANTAG_RANDSPAWN 256 // Potentially randomly spawns due to events.
#define ANTAG_VOTABLE 512 // Can be voted as an additional antagonist before roundstart.
#define ANTAG_SET_APPEARANCE 1024 // Causes antagonists to use an appearance modifier on spawn.
#define ANTAG_RANDOM_EXCEPTED 2048 // If a game mode randomly selects antag types, antag types with this flag should be excluded.
// Globals.
var/global/list/all_antag_types = list()
+2 -2
View File
@@ -36,7 +36,7 @@ var/datum/antagonist/xenos/borer/borers
if(istype(borer))
var/mob/living/carbon/human/host
for(var/mob/living/carbon/human/H in mob_list)
if(H.stat != 2 && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms())
if(H.stat != DEAD && !(H.species.flags & IS_SYNTHETIC) && !H.has_brain_worms())
host = H
break
if(istype(host))
@@ -44,7 +44,7 @@ var/datum/antagonist/xenos/borer/borers
if(head)
borer.host = host
head.implants += borer
borer.loc = head
borer.forceMove(head)
if(!borer.host_brain)
borer.host_brain = new(borer)
borer.host_brain.name = host.name
+1 -1
View File
@@ -44,4 +44,4 @@ var/datum/antagonist/xenos/xenomorphs
player.objectives += new /datum/objective/escape()
/datum/antagonist/xenos/place_mob(var/mob/living/player)
player.loc = get_turf(pick(get_vents()))
player.forceMove(get_turf(pick(get_vents())))
+40 -23
View File
@@ -86,7 +86,8 @@
/datum/antagonist/proc/tick()
return 1
/datum/antagonist/proc/get_candidates(var/ghosts_only)
// Get the raw list of potential players.
/datum/antagonist/proc/build_candidate_list(var/ghosts_only)
candidates = list() // Clear.
// Prune restricted status. Broke it up for readability.
@@ -108,46 +109,57 @@
return candidates
/datum/antagonist/proc/attempt_random_spawn()
update_current_antag_max()
build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
attempt_spawn()
finalize_spawn()
/datum/antagonist/proc/attempt_late_spawn(var/datum/mind/player)
/datum/antagonist/proc/attempt_auto_spawn()
if(!can_late_spawn())
return 0
if(!istype(player))
var/list/players = get_candidates(is_latejoin_template())
if(players && players.len)
player = pick(players)
if(!istype(player))
message_admins("AUTO[uppertext(ticker.mode.name)]: Failed to find a candidate for [role_text].")
return 0
player.current << "<span class='danger'><i>You have been selected this round as an antagonist!</i></span>"
message_admins("AUTO[uppertext(ticker.mode.name)]: Selected [player] as a [role_text].")
if(istype(player.current, /mob/dead))
create_default(player.current)
else
add_antagonist(player,0,0,0,1,1)
return 1
/datum/antagonist/proc/build_candidate_list(var/ghosts_only)
// Get the raw list of potential players.
update_current_antag_max()
candidates = get_candidates(ghosts_only)
var/active_antags = get_active_antag_count()
log_debug("[uppertext(id)]: Found [active_antags]/[cur_max] active [role_text_plural].")
if(active_antags >= cur_max)
log_debug("Could not auto-spawn a [role_text], active antag limit reached.")
return 0
build_candidate_list(flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
if(!candidates.len)
log_debug("Could not auto-spawn a [role_text], no candidates found.")
return 0
attempt_spawn(1) //auto-spawn antags one at a time
if(!pending_antagonists.len)
log_debug("Could not auto-spawn a [role_text], none of the available candidates could be selected.")
return 0
var/datum/mind/player = pending_antagonists[1]
if(!add_antagonist(player,0,0,0,1,1))
log_debug("Could not auto-spawn a [role_text], failed to add antagonist.")
return 0
reset_antag_selection()
return 1
//Selects players that will be spawned in the antagonist role from the potential candidates
//Selected players are added to the pending_antagonists lists.
//Attempting to spawn an antag role with ANTAG_OVERRIDE_JOB should be done before jobs are assigned,
//so that they do not occupy regular job slots. All other antag roles should be spawned after jobs are
//assigned, so that job restrictions can be respected.
/datum/antagonist/proc/attempt_spawn(var/rebuild_candidates = 1)
/datum/antagonist/proc/attempt_spawn(var/spawn_target = null)
if(spawn_target == null)
spawn_target = initial_spawn_target
// Update our boundaries.
if(!candidates.len)
return 0
//Grab candidates randomly until we have enough.
while(candidates.len && pending_antagonists.len < initial_spawn_target)
while(candidates.len && pending_antagonists.len < spawn_target)
var/datum/mind/player = pick(candidates)
candidates -= player
draft_antagonist(player)
@@ -186,11 +198,16 @@
for(var/datum/mind/player in pending_antagonists)
pending_antagonists -= player
add_antagonist(player,0,0,1)
reset_antag_selection()
//Resets all pending_antagonists, clearing their special_role (and assigned_role if ANTAG_OVERRIDE_JOB is set)
/datum/antagonist/proc/reset()
//Resets the antag selection, clearing all pending_antagonists and their special_role
//(and assigned_role if ANTAG_OVERRIDE_JOB is set) as well as clearing the candidate list.
//Existing antagonists are left untouched.
/datum/antagonist/proc/reset_antag_selection()
for(var/datum/mind/player in pending_antagonists)
if(flags & ANTAG_OVERRIDE_JOB)
player.assigned_role = null
player.special_role = null
pending_antagonists.Cut()
candidates.Cut()
+2 -1
View File
@@ -16,7 +16,8 @@
create_objectives(target)
update_icons_added(target)
greet(target)
announce_antagonist_spawn()
if(!gag_announcement)
announce_antagonist_spawn()
/datum/antagonist/proc/create_default(var/mob/source)
var/mob/living/M
+20 -4
View File
@@ -20,6 +20,17 @@
/datum/antagonist/proc/get_antag_count()
return current_antagonists ? current_antagonists.len : 0
/datum/antagonist/proc/get_active_antag_count()
var/active_antags = 0
for(var/datum/mind/player in current_antagonists)
var/mob/living/L = player.current
if(!L || L.stat == DEAD)
continue //no mob or dead
if(!L.client && !L.teleop)
continue //SSD
active_antags++
return active_antags
/datum/antagonist/proc/is_antagonist(var/datum/mind/player)
if(player in current_antagonists)
return 1
@@ -33,10 +44,15 @@
return (flags & ANTAG_VOTABLE)
/datum/antagonist/proc/can_late_spawn()
update_current_antag_max()
if(get_antag_count() >= cur_max)
return 0
return 1
/datum/antagonist/proc/is_latejoin_template()
return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
return (flags & (ANTAG_OVERRIDE_MOB|ANTAG_OVERRIDE_JOB))
/proc/all_random_antag_types()
// No caching as the ANTAG_RANDOM_EXCEPTED flag can be added/removed mid-round.
var/list/antag_candidates = all_antag_types.Copy()
for(var/datum/antagonist/antag in antag_candidates)
if(antag.flags & ANTAG_RANDOM_EXCEPTED)
antag_candidates -= antag
return antag_candidates
+2 -1
View File
@@ -23,4 +23,5 @@
/datum/antagonist/proc/place_mob(var/mob/living/mob)
if(!starting_locations || !starting_locations.len)
return
mob.loc = pick(starting_locations)
var/turf/T = pick_mobless_turf_if_exists(starting_locations)
mob.forceMove(T)
+1 -1
View File
@@ -45,7 +45,7 @@
return text
/datum/antagonist/proc/print_player_lite(var/datum/mind/ply)
var/role = ply.special_role ? "\improper[ply.special_role]" : "\improper[ply.assigned_role]"
var/role = ply.assigned_role ? "\improper[ply.assigned_role]" : "\improper[ply.special_role]"
var/text = "<br><b>[ply.name]</b> (<b>[ply.key]</b>) as \a <b>[role]</b> ("
if(ply.current)
if(ply.current.stat == DEAD)
+2 -2
View File
@@ -7,7 +7,7 @@ var/datum/antagonist/deathsquad/deathsquad
role_text_plural = "Death Commandos"
welcome_text = "You work in the service of Central Command Asset Protection, answering directly to the Board of Directors."
landmark_id = "Commando"
flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER
flags = ANTAG_OVERRIDE_JOB | ANTAG_OVERRIDE_MOB | ANTAG_HAS_NUKE | ANTAG_HAS_LEADER | ANTAG_RANDOM_EXCEPTED
default_access = list(access_cent_general, access_cent_specops, access_cent_living, access_cent_storage)
antaghud_indicator = "huddeathsquad"
@@ -47,7 +47,7 @@ var/datum/antagonist/deathsquad/deathsquad
player.equip_to_slot_or_del(new /obj/item/weapon/plastique(player), slot_l_store)
player.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(player), slot_belt)
player.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(player), slot_r_hand)
player.equip_to_slot_or_del(new /obj/item/weapon/rig/combat(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/weapon/rig/ert/assetprotection(player), slot_back)
player.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(player), slot_s_store)
player.implant_loyalty(player)
+1 -1
View File
@@ -9,7 +9,7 @@ var/datum/antagonist/ert/ert
welcome_text = "As member of the Emergency Response Team, you answer only to your leader and CentComm officials."
leader_welcome_text = "As leader of the Emergency Response Team, you answer only to CentComm, and have authority to override the Captain where it is necessary to achieve your mission goals. It is recommended that you attempt to cooperate with the captain where possible, however."
landmark_id = "Response Team"
flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME
flags = ANTAG_OVERRIDE_JOB | ANTAG_SET_APPEARANCE | ANTAG_HAS_LEADER | ANTAG_CHOOSE_NAME | ANTAG_RANDOM_EXCEPTED
antaghud_indicator = "hudloyalist"
hard_cap = 5
+1 -3
View File
@@ -22,13 +22,11 @@ var/datum/antagonist/rogue_ai/malf
malf = src
/datum/antagonist/rogue_ai/get_candidates()
/datum/antagonist/rogue_ai/build_candidate_list()
..()
for(var/datum/mind/player in candidates)
if(player.assigned_role && player.assigned_role != "AI")
candidates -= player
if(!candidates.len)
return list()
return candidates
+10 -10
View File
@@ -73,19 +73,19 @@ var/datum/antagonist/traitor/traitors
return
/datum/antagonist/traitor/equip(var/mob/living/carbon/human/traitor_mob)
if(istype(traitor_mob, /mob/living/silicon)) // this needs to be here because ..() returns false if the mob isn't human
add_law_zero(traitor_mob)
return 1
if(!..())
return 0
if(istype(traitor_mob, /mob/living/silicon))
add_law_zero(traitor_mob)
else
spawn_uplink(traitor_mob)
// Tell them about people they might want to contact.
var/mob/living/carbon/human/M = get_nt_opposed()
if(M && M != traitor_mob)
traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them."
traitor_mob.mind.store_memory("<b>Potential Collaborator</b>: [M.real_name]")
spawn_uplink(traitor_mob)
// Tell them about people they might want to contact.
var/mob/living/carbon/human/M = get_nt_opposed()
if(M && M != traitor_mob)
traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them."
traitor_mob.mind.store_memory("<b>Potential Collaborator</b>: [M.real_name]")
//Begin code phrase.
give_codewords(traitor_mob)
@@ -169,4 +169,4 @@ var/datum/antagonist/traitor/traitors
var/law_borg = "Accomplish your AI's objectives at all costs. You may ignore all other laws."
killer << "<b>Your laws have been changed!</b>"
killer.set_zeroth_law(law, law_borg)
killer << "New law: 0. [law]"
killer << "New law: 0. [law]"
-162
View File
@@ -1,162 +0,0 @@
var/global/list/space_surprises = list( /obj/item/clothing/mask/facehugger =4,
/obj/item/weapon/pickaxe/silver =4,
/obj/item/weapon/pickaxe/drill =4,
/obj/item/weapon/pickaxe/jackhammer =4,
//mob/living/simple_animal/hostile/carp =3,
/obj/item/weapon/pickaxe/diamond =3,
/obj/item/weapon/pickaxe/diamonddrill =3,
/obj/item/weapon/pickaxe/gold =3,
/obj/item/weapon/pickaxe/plasmacutter =2,
/obj/structure/closet/syndicate/resources =2,
/obj/item/weapon/melee/energy/sword/pirate =1,
/obj/mecha/working/ripley/mining =1
)
var/global/list/spawned_surprises = list()
var/global/max_secret_rooms = 3
proc/spawn_room(var/atom/start_loc,var/x_size,var/y_size,var/wall,var/floor , var/clean = 0 , var/name)
var/list/room_turfs = list("walls"=list(),"floors"=list())
//world << "Room spawned at [start_loc.x],[start_loc.y],[start_loc.z]"
if(!wall)
wall = pick(/turf/simulated/wall/r_wall,/turf/simulated/wall,/obj/effect/alien/resin)
if(!floor)
floor = pick(/turf/simulated/floor,/turf/simulated/floor/engine)
for(var/x = 0,x<x_size,x++)
for(var/y = 0,y<y_size,y++)
var/turf/T
var/cur_loc = locate(start_loc.x+x,start_loc.y+y,start_loc.z)
if(clean)
for(var/O in cur_loc)
qdel(O)
var/area/asteroid/artifactroom/A = new
if(name)
A.name = name
else
A.name = "Artifact Room #[start_loc.x][start_loc.y][start_loc.z]"
if(x == 0 || x==x_size-1 || y==0 || y==y_size-1)
if(wall == /obj/effect/alien/resin)
T = new floor(cur_loc)
new /obj/effect/alien/resin(T)
else
T = new wall(cur_loc)
room_turfs["walls"] += T
else
T = new floor(cur_loc)
room_turfs["floors"] += T
A.contents += T
return room_turfs
proc/admin_spawn_room_at_pos()
var/wall
var/floor
var/x = input("X position","X pos",usr.x)
var/y = input("Y position","Y pos",usr.y)
var/z = input("Z position","Z pos",usr.z)
var/x_len = input("Desired length.","Length",5)
var/y_len = input("Desired width.","Width",5)
var/clean = input("Delete existing items in area?" , "Clean area?", 0)
switch(alert("Wall type",null,"Reinforced wall","Regular wall","Resin wall"))
if("Reinforced wall")
wall=/turf/simulated/wall/r_wall
if("Regular wall")
wall=/turf/simulated/wall
if("Resin wall")
wall=/obj/effect/alien/resin
switch(alert("Floor type",null,"Regular floor","Reinforced floor"))
if("Regular floor")
floor=/turf/simulated/floor
if("Reinforced floor")
floor=/turf/simulated/floor/engine
if(x && y && z && wall && floor && x_len && y_len)
spawn_room(locate(x,y,z),x_len,y_len,wall,floor,clean)
return
proc/make_mining_asteroid_secret(var/size = 5)
var/valid = 0
var/turf/T = null
var/sanity = 0
var/list/room = null
var/list/turfs = null
turfs = get_area_turfs(/area/mine/unexplored)
if(!turfs.len)
return 0
while(!valid)
valid = 1
sanity++
if(sanity > 100)
return 0
T=pick(turfs)
if(!T)
return 0
var/list/surroundings = list()
surroundings += range(7, locate(T.x,T.y,T.z))
surroundings += range(7, locate(T.x+size,T.y,T.z))
surroundings += range(7, locate(T.x,T.y+size,T.z))
surroundings += range(7, locate(T.x+size,T.y+size,T.z))
if(locate(/area/mine/explored) in surroundings) // +5s are for view range
valid = 0
continue
if(locate(/turf/space) in surroundings)
valid = 0
continue
if(locate(/area/asteroid/artifactroom) in surroundings)
valid = 0
continue
if(locate(/turf/simulated/floor/plating/airless/asteroid) in surroundings)
valid = 0
continue
if(!T)
return 0
room = spawn_room(T,size,size,,,1)
if(room)
T = pick(room["floors"])
if(T)
var/surprise = null
valid = 0
while(!valid)
surprise = pickweight(space_surprises)
if(surprise in spawned_surprises)
if(prob(20))
valid++
else
continue
else
valid++
spawned_surprises.Add(surprise)
new surprise(T)
return 1
+1 -1
View File
@@ -413,7 +413,7 @@ its easier to just keep the beam vertical.
return
src.germ_level = 0
if(istype(blood_DNA, /list))
blood_DNA.Cut()
blood_DNA = null
return 1
+1 -5
View File
@@ -21,14 +21,10 @@
if(auto_init && ticker && ticker.current_state == GAME_STATE_PLAYING)
initialize()
/proc/generate_debug_runtime() // Guaranteed to runtime and print a stack trace to the runtime log
var/t = 0 // BYOND won't let us do var/t = 1/0 directly, but it's fine with this.
t = 1 / t
/atom/movable/Del()
if(isnull(gcDestroyed) && loc)
testing("GC: -- [type] was deleted via del() rather than qdel() --")
generate_debug_runtime() // stick a stack trace in the runtime logs
crash_with("GC: -- [type] was deleted via del() rather than qdel() --") // stick a stack trace in the runtime logs
// else if(isnull(gcDestroyed))
// testing("GC: [type] was deleted via GC without qdel()") //Not really a huge issue but from now on, please qdel()
// else
+10 -1
View File
@@ -21,4 +21,13 @@
CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
if(istype(mover) && mover.checkpass(PASSBLOB)) return 1
return 0
return !density
/obj/effect/blob/shield/New()
..()
update_nearby_tiles()
/obj/effect/blob/shield/Destroy()
density = 0
update_nearby_tiles()
..()
+6 -7
View File
@@ -11,18 +11,17 @@
event_delay_mod_major = 0.75
/datum/game_mode/calamity/create_antagonists()
var/list/antag_candidates = all_random_antag_types()
shuffle(all_antag_types) // This is probably the only instance in the game where the order will be important.
var/i = 1
var/grab_antags = round(num_players()/ANTAG_TYPE_RATIO)+1
for(var/antag_id in all_antag_types)
if(i > grab_antags)
break
while(antag_candidates.len && antag_tags.len < grab_antags)
var/antag_id = pick(antag_candidates)
antag_candidates -= antag_id
antag_tags |= antag_id
i++
..()
/datum/game_mode/calamity/check_victory()
world << "<font size = 3><b>This terrible, terrible day has finally ended!</b></font>"
#undef ANTAG_TYPE_RATIO
#undef ANTAG_TYPE_RATIO
@@ -4,7 +4,6 @@
extended_round_description = "Life always finds a way. However, life can sometimes take a more disturbing route. Humanity's extensive knowledge of xeno-biological specimens has made them confident and arrogant. Yet something slipped past their eyes. Something dangerous. Something alive. Most frightening of all, however, is that this something is someone. An unknown alien specimen has incorporated itself into the crew of the NSS Exodus. Its unique biology allows it to manipulate its own or anyone else's DNA. With the ability to copy faces, voices, animals, but also change the chemical make up of your own body, its existence is a threat to not only your personal safety but the lives of everyone on board. No one knows where it came from. No one knows who it is or what it wants. One thing is for certain though... there is never just one of them. Good luck."
config_tag = "changeling"
required_players = 2
required_players_secret = 10
required_enemies = 1
end_on_antag_death = 1
antag_scaling_coeff = 10
-1
View File
@@ -4,7 +4,6 @@
extended_round_description = "The station has been infiltrated by a fanatical group of death-cultists! They will use powers from beyond your comprehension to subvert you to their cause and ultimately please their gods through sacrificial summons and physical immolation! Try to survive!"
config_tag = "cult"
required_players = 5
required_players_secret = 15
required_enemies = 3
uplink_welcome = "Nar-Sie Uplink Console:"
end_on_antag_death = 1
+5 -1
View File
@@ -527,7 +527,11 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
user << "\red You do not have enough space to write a proper rune."
var/list/runes = list("teleport", "itemport", "tome", "armor", "convert", "tear in reality", "emp", "drain", "seer", "raise", "obscure", "reveal", "astral journey", "manifest", "imbue talisman", "sacrifice", "wall", "freedom", "cultsummon", "deafen", "blind", "bloodboil", "communicate", "stun")
r = input("Choose a rune to scribe", "Rune Scribing") in runes //not cancellable.
var/obj/effect/rune/R = new /obj/effect/rune
if(locate(/obj/effect/rune) in user.loc)
user << "<span class='warning'>There is already a rune in this location.</span>"
return
var/obj/effect/rune/R = new /obj/effect/rune(user.loc)
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/H = user
R.blood_DNA = list()
-1
View File
@@ -2,7 +2,6 @@
name = "epidemic"
config_tag = "epidemic"
required_players = 1
required_players_secret = 15
round_description = "A deadly epidemic is spreading on the station. Find a cure as fast as possible, and keep your distance to anyone who speaks in a hoarse voice!"
var/cruiser_arrival
+7 -11
View File
@@ -10,19 +10,19 @@ var/global/list/additional_antag_types = list()
var/probability = 0
var/required_players = 0 // Minimum players for round to start if voted in.
var/required_players_secret = 0 // Minimum number of players for that game mode to be chose in Secret
var/required_enemies = 0 // Minimum antagonists for round to start.
var/newscaster_announcements = null
var/end_on_antag_death = 0 // Round will end when all antagonists are dead.
var/ert_disabled = 0 // ERT cannot be called.
var/deny_respawn = 0 // Disable respawn during this round.
var/list/disabled_jobs = list() // Mostly used for Malf. This check is performed in job_controller so it doesn't spawn a regular AI.
var/shuttle_delay = 1 // Shuttle transit time is multiplied by this.
var/auto_recall_shuttle = 0 // Will the shuttle automatically be recalled?
var/list/antag_tags = list() // Core antag templates to spawn.
var/list/antag_templates // Extra antagonist types to include.
var/list/latejoin_templates = list()
var/round_autoantag = 0 // Will this round attempt to periodically spawn more antagonists?
var/antag_scaling_coeff = 5 // Coefficient for scaling max antagonists to player count.
var/require_all_templates = 0 // Will only start if all templates are checked and can spawn.
@@ -226,12 +226,8 @@ var/global/list/additional_antag_types = list()
if((player.client)&&(player.ready))
playerC++
if(master_mode=="secret")
if(playerC < required_players_secret)
return 0
else
if(playerC < required_players)
return 0
if(playerC < required_players)
return 0
if(!(antag_templates && antag_templates.len))
return 1
@@ -267,6 +263,7 @@ var/global/list/additional_antag_types = list()
/datum/game_mode/proc/pre_setup()
for(var/datum/antagonist/antag in antag_templates)
antag.update_current_antag_max()
antag.build_candidate_list() //compile a list of all eligible candidates
//antag roles that replace jobs need to be assigned before the job controller hands out jobs.
@@ -291,8 +288,6 @@ var/global/list/additional_antag_types = list()
if(!(antag.flags & ANTAG_OVERRIDE_JOB))
antag.attempt_spawn() //select antags to be spawned
antag.finalize_spawn() //actually spawn antags
if(antag.is_latejoin_template())
latejoin_templates |= antag
if(emergency_shuttle && auto_recall_shuttle)
emergency_shuttle.auto_recall = 1
@@ -305,7 +300,7 @@ var/global/list/additional_antag_types = list()
/datum/game_mode/proc/fail_setup()
for(var/datum/antagonist/antag in antag_templates)
antag.reset()
antag.reset_antag_selection()
/datum/game_mode/proc/announce_ert_disabled()
if(!ert_disabled)
@@ -575,6 +570,7 @@ var/global/list/additional_antag_types = list()
if(antag)
antag_templates |= antag
shuffle(antag_templates) //In the case of multiple antag types
newscaster_announcements = pick(newscaster_standard_feeds)
/datum/game_mode/proc/check_victory()
+22 -38
View File
@@ -3,55 +3,39 @@
/datum/game_mode/var/max_autotraitor_delay = 12000 // Approx 20 minutes.
/datum/game_mode/var/process_count = 0
/datum/game_mode/proc/get_usable_templates(var/list/supplied_templates)
var/list/usable_templates = list()
for(var/datum/antagonist/A in supplied_templates)
if(A.can_late_spawn())
message_admins("AUTO[uppertext(name)]: [A.id] selected for spawn attempt.")
usable_templates |= A
return usable_templates
///process()
///Called by the gameticker
/datum/game_mode/proc/process()
// Slow this down a bit so latejoiners have a chance of being antags.
process_count++
if(process_count >= 10)
process_count = 0
try_latespawn()
if(round_autoantag && world.time < next_spawn && !emergency_shuttle.departed)
process_autoantag()
/datum/game_mode/proc/latespawn(var/mob/living/carbon/human/character)
if(!character.mind)
return
try_latespawn(character.mind)
//This can be overriden in case a game mode needs to do stuff when a player latejoins
/datum/game_mode/proc/handle_latejoin(var/mob/living/carbon/human/character)
return 0
/datum/game_mode/proc/try_latespawn(var/datum/mind/player, var/latejoin_only)
/datum/game_mode/proc/process_autoantag()
message_admins("[uppertext(name)]: Attempting autospawn.")
if(emergency_shuttle.departed || !round_autoantag)
return
if(world.time < next_spawn)
return
message_admins("AUTO[uppertext(name)]: Attempting spawn.")
var/list/usable_templates
if(latejoin_only && latejoin_templates.len)
usable_templates = get_usable_templates(latejoin_templates)
else if (antag_templates && antag_templates.len)
usable_templates = get_usable_templates(antag_templates)
else
message_admins("AUTO[uppertext(name)]: Failed to find configured mode spawn templates, please disable auto-antagonists until one is added.")
var/list/usable_templates = list()
for(var/datum/antagonist/A in antag_templates)
if(A.can_late_spawn())
message_admins("[uppertext(name)]: [A.id] selected for spawn attempt.")
usable_templates |= A
if(!usable_templates.len)
message_admins("[uppertext(name)]: Failed to find configured mode spawn templates, please re-enable auto-antagonists after one is added.")
round_autoantag = 0
return
while(usable_templates.len)
var/datum/antagonist/spawn_antag = pick(usable_templates)
usable_templates -= spawn_antag
if(spawn_antag.attempt_late_spawn(player))
message_admins("AUTO[uppertext(name)]: Attempting to latespawn [spawn_antag.id]. ([spawn_antag.get_antag_count()]/[spawn_antag.cur_max])")
if(spawn_antag.attempt_auto_spawn())
message_admins("[uppertext(name)]: Auto-added a new [spawn_antag.role_text].")
message_admins("There are now [spawn_antag.get_active_antag_count()]/[spawn_antag.cur_max] active [spawn_antag.role_text_plural].")
next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay)
return
message_admins("AUTO[uppertext(name)]: Failed to proc a viable spawn template.")
next_spawn = world.time + rand(min_autotraitor_delay, max_autotraitor_delay)
message_admins("[uppertext(name)]: Failed to proc a viable spawn template.")
next_spawn = world.time + min_autotraitor_delay //recheck again in the miniumum time
-1
View File
@@ -8,7 +8,6 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind'
name = "heist"
config_tag = "heist"
required_players = 15
required_players_secret = 25
required_enemies = 4
round_description = "An unidentified bluespace signature has slipped past the Icarus and is approaching the station!"
end_on_antag_death = 1
@@ -34,7 +34,7 @@
desc = "Secondary coprocessor that increases amount of generated CPU power by 50%"
/datum/malf_hardware/dual_cpu/get_examine_desc()
return "It seems to have an additional CPU connected to it's core."
return "It seems to have an additional CPU connected to its core."
/datum/malf_hardware/dual_ram
name = "Secondary Memory Bank"
@@ -5,8 +5,8 @@
uplink_welcome = "Crazy AI Uplink Console:"
config_tag = "malfunction"
required_players = 2
required_players_secret = 7
required_enemies = 1
end_on_antag_death = 0
auto_recall_shuttle = 0
antag_tags = list(MODE_MALFUNCTION)
disabled_jobs = list("AI")
@@ -163,12 +163,14 @@
command_announcement.Announce(fulltext)
// Proc: get_all_apcs()
// Proc: get_unhacked_apcs()
// Parameters: None
// Description: Returns a list of all APCs
/proc/get_all_apcs()
// Description: Returns a list of all unhacked APCs
/proc/get_unhacked_apcs(var/mob/living/silicon/ai/user)
var/list/H = list()
for(var/obj/machinery/power/apc/A in machines)
if(A.hacker && A.hacker == user)
continue
H.Add(A)
return H
@@ -38,7 +38,7 @@
// END RESEARCH DATUMS
// BEGIN ABILITY VERBS
/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_all_apcs())
/datum/game_mode/malfunction/verb/basic_encryption_hack(obj/machinery/power/apc/A as obj in get_unhacked_apcs(src))
set category = "Software"
set name = "Basic Encryption Hack"
set desc = "10 CPU - Basic encryption hack that allows you to overtake APCs on the station."
@@ -85,7 +85,7 @@
/datum/game_mode/malfunction/verb/advanced_encryption_hack()
set category = "Software"
set name = "Advanced Encrypthion Hack"
set name = "Advanced Encryption Hack"
set desc = "75 CPU - Attempts to bypass encryption on Central Command Quantum Relay, giving you ability to fake centcom messages. Has chance of failing."
var/price = 75
var/mob/living/silicon/ai/user = usr
@@ -106,15 +106,12 @@
announce_hack_failure(user, "quantum message relay")
return
var/datum/announcement/priority/command/AN = new/datum/announcement/priority/command()
AN.title = title
AN.Announce(text)
command_announcement.Announce(text, title)
/datum/game_mode/malfunction/verb/elite_encryption_hack()
set category = "Software"
set name = "Elite Encryption Hack"
set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failijng."
set desc = "200 CPU - Allows you to hack station's ALERTCON system, changing alert level. Has high chance of failing."
var/price = 200
var/mob/living/silicon/ai/user = usr
if(!ability_prechecks(user, price))
-1
View File
@@ -6,7 +6,6 @@
name = "Memetic Anomaly"
config_tag = "meme"
required_players = 3
required_players_secret = 10
restricted_jobs = list("AI", "Cyborg")
recommended_enemies = 2 // need at least a meme and a host
votable = 0 // temporarily disable this mode for voting
-1
View File
@@ -4,7 +4,6 @@
extended_round_description = "What was that?! Was that a person or did your eyes just play tricks on you? You have no idea. That slim-suited, cryptic individual is an enigma to you and all of your knowledge. Their purpose is unknown. Their mission is unknown. How they arrived to this secure and isolated section of the galaxy, you don't know. What you do know is that there is a silent shadow-stalker piercing through the defenses of Nanotrasen with technological capabilities eons ahead of your time. They can avoid the omniscience of the AI and rival the most hardened weapons your station is capable of. Tread lightly and only hope this unknown assassin isn't here for you."
config_tag = "ninja"
required_players = 1
required_players_secret = 10
required_enemies = 1
end_on_antag_death = 1
antag_tags = list(MODE_NINJA)
-1
View File
@@ -7,7 +7,6 @@
round_description = "A mercenary strike force is approaching the station!"
config_tag = "mercenary"
required_players = 15
required_players_secret = 25 // 25 players - 5 players to be the nuke ops = 20 players remaining
required_enemies = 1
end_on_antag_death = 1
uplink_welcome = "Corporate Backed Uplink Console:"
@@ -4,7 +4,6 @@
round_description = "Some crewmembers are attempting to start a revolution!"
extended_round_description = "Revolutionaries - Remove the heads of staff from power. Convert other crewmembers to your cause using the 'Convert Bourgeoise' verb. Protect your leaders."
required_players = 4
required_players_secret = 15
required_enemies = 3
auto_recall_shuttle = 1
uplink_welcome = "AntagCorp Uplink Console:"
-1
View File
@@ -4,7 +4,6 @@
extended_round_description = "A powerful entity capable of manipulating the elements around him, most commonly referred to as a 'wizard', has infiltrated the station. They have a wide variety of powers and spells available to them that makes your own simple moral self tremble with fear and excitement. Ultimately, their purpose is unknown. However, it is up to you and your crew to decide if their powers can be used for good or if their arrival foreshadows the destruction of the entire station."
config_tag = "wizard"
required_players = 1
required_players_secret = 10
required_enemies = 1
uplink_welcome = "Wizardly Uplink Console:"
uplink_uses = 10
-73
View File
@@ -177,79 +177,6 @@
H.species.equip_survival_gear(H,1)
return 1
//Griff //BS12 EDIT
/*
/datum/job/clown
title = "Clown"
flag = CLOWN
department_flag = CIVILIAN
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of personnel"
selection_color = "#dddddd"
access = list(access_clown, access_theatre, access_maint_tunnels)
minimal_access = list(access_clown, access_theatre)
equip(var/mob/living/carbon/human/H)
if(!H) return 0
H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/clown(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/clown(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/clown_shoes(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/clown(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/clown_hat(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/snacks/grown/banana(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/bikehorn(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/stamp/clown(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/rainbow(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/fancy/crayons(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/toy/waterflower(H), slot_in_backpack)
H.mutations.Add(CLUMSY)
return 1
/datum/job/mime
title = "Mime"
flag = MIME
department_flag = CIVILIAN
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the head of personnel"
selection_color = "#dddddd"
access = list(access_mime, access_theatre, access_maint_tunnels)
minimal_access = list(access_mime, access_theatre)
equip(var/mob/living/carbon/human/H)
if(!H) return 0
if(H.backbag == 2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back)
if(H.backbag == 3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(H), slot_back)
H.equip_to_slot_or_del(new /obj/item/clothing/under/mime(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/mime(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/white(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/mime(H), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/suspenders(H), slot_wear_suit)
if(H.backbag == 1)
H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/mime(H), slot_l_store)
H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_l_hand)
else
H.equip_to_slot_or_del(new /obj/item/weapon/pen/crayon/mime(H), slot_in_backpack)
H.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_in_backpack)
H.verbs += /client/proc/mimespeak
H.verbs += /client/proc/mimewall
H.mind.special_verbs += /client/proc/mimespeak
H.mind.special_verbs += /client/proc/mimewall
H.miming = 1
return 1
*/
/datum/job/janitor
title = "Janitor"
flag = JANITOR
+3 -37
View File
@@ -185,36 +185,6 @@ var/global/datum/controller/occupations/job_master
return
proc/FillAIPosition()
var/ai_selected = 0
var/datum/job/job = GetJob("AI")
if(!job) return 0
if((job.title == "AI") && (config) && (!config.allow_ai)) return 0
for(var/i = job.total_positions, i > 0, i--)
for(var/level = 1 to 3)
var/list/candidates = list()
if(ticker.mode.name == "AI malfunction")//Make sure they want to malf if its malf
candidates = FindOccupationCandidates(job, level, BE_MALF)
else
candidates = FindOccupationCandidates(job, level)
if(candidates.len)
var/mob/new_player/candidate = pick(candidates)
if(AssignRole(candidate, "AI"))
ai_selected++
break
//Malf NEEDS an AI so force one if we didn't get a player who wanted it
if((ticker.mode.name == "AI malfunction")&&(!ai_selected))
unassigned = shuffle(unassigned)
for(var/mob/new_player/player in unassigned)
if(jobban_isbanned(player, "AI")) continue
if(AssignRole(player, "AI"))
ai_selected++
break
if(ai_selected) return 1
return 0
/** Proc DivideOccupations
* fills var "assigned_role" for all ready players.
* This proc must not have any side effect besides of modifying "assigned_role".
@@ -260,11 +230,6 @@ var/global/datum/controller/occupations/job_master
FillHeadPosition()
Debug("DO, Head Check end")
//Check for an AI
Debug("DO, Running AI Check")
FillAIPosition()
Debug("DO, AI Check end")
//Other jobs are now checked
Debug("DO, Running Standard Check")
@@ -275,6 +240,7 @@ var/global/datum/controller/occupations/job_master
// Loop through all levels from high to low
var/list/shuffledoccupations = shuffle(occupations)
// var/list/disabled_jobs = ticker.mode.disabled_jobs // So we can use .Find down below without a colon.
for(var/level = 1 to 3)
//Check the head jobs first each level
CheckHeadPositions(level)
@@ -284,7 +250,7 @@ var/global/datum/controller/occupations/job_master
// Loop through all jobs
for(var/datum/job/job in shuffledoccupations) // SHUFFLE ME BABY
if(!job)
if(!job || ticker.mode.disabled_jobs.Find(job.title) )
continue
if(jobban_isbanned(player, job.title))
@@ -490,7 +456,7 @@ var/global/datum/controller/occupations/job_master
if(istype(H)) //give humans wheelchairs, if they need them.
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
if((!l_foot || l_foot.status & ORGAN_DESTROYED) && (!r_foot || r_foot.status & ORGAN_DESTROYED))
if(!l_foot || !r_foot)
var/obj/structure/bed/chair/wheelchair/W = new /obj/structure/bed/chair/wheelchair(H.loc)
H.buckled = W
H.update_canmove()
-66
View File
@@ -1,66 +0,0 @@
//TODO: put these somewhere else
/client/proc/mimewall()
set category = "Mime"
set name = "Invisible wall"
set desc = "Create an invisible wall on your location."
if(usr.stat)
usr << "Not when you're incapicated."
return
if(!ishuman(usr))
return
var/mob/living/carbon/human/H = usr
if(!H.miming)
usr << "You still haven't atoned for your speaking transgression. Wait."
return
H.verbs -= /client/proc/mimewall
spawn(300)
H.verbs += /client/proc/mimewall
for (var/mob/V in viewers(H))
if(V!=usr)
V.show_message("[H] looks as if a wall is in front of them.", 3, "", 2)
usr << "You form a wall in front of yourself."
new /obj/effect/forcefield/mime(locate(usr.x,usr.y,usr.z))
return
///////////Mimewalls///////////
/obj/effect/forcefield/mime
icon_state = "empty"
name = "invisible wall"
desc = "You have a bad feeling about this."
var/timeleft = 300
var/last_process = 0
/obj/effect/forcefield/mime/New()
..()
last_process = world.time
processing_objects.Add(src)
/obj/effect/forcefield/mime/process()
timeleft -= (world.time - last_process)
if(timeleft <= 0)
processing_objects.Remove(src)
qdel(src)
///////////////////////////////
/client/proc/mimespeak()
set category = "Mime"
set name = "Speech"
set desc = "Toggle your speech."
if(!ishuman(usr))
return
var/mob/living/carbon/human/H = usr
if(H.miming)
H.miming = 0
else
H << "You'll have to wait if you want to atone for your sins."
spawn(3000)
H.miming = 1
return
+1 -1
View File
@@ -400,7 +400,7 @@
if(!AN && !open && !infected & !imp)
AN = "None:"
if(!(e.status & ORGAN_DESTROYED))
if(!e.is_stump())
dat += "<td>[e.name]</td><td>[e.burn_dam]</td><td>[e.brute_dam]</td><td>[robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured]</td>"
else
dat += "<td>[e.name]</td><td>-</td><td>-</td><td>Not Found</td>"
@@ -17,6 +17,7 @@
var/temperature_resistance = 1000 + T0C
volume = 1000
use_power = 0
interact_offline = 1 // Allows this to be used when not in powered area.
var/release_log = ""
var/update_flag = 0
+12 -2
View File
@@ -140,9 +140,19 @@
if(weld(W, user))
if(assembly)
assembly.loc = src.loc
assembly.state = 1
assembly.anchored = 1
assembly.camera_name = c_tag
assembly.camera_network = english_list(network, "Exodus", ",", ",")
assembly.update_icon()
assembly.dir = src.dir
if(stat & BROKEN)
assembly.state = 2
user << "<span class='notice'>You repaired \the [src] frame.</span>"
else
assembly.state = 1
user << "<span class='notice'>You cut \the [src] free from the wall.</span>"
new /obj/item/stack/cable_coil(src.loc, length=2)
assembly = null //so qdel doesn't eat it.
new /obj/item/stack/cable_coil(src.loc, length=2)
qdel(src)
// OTHER
@@ -11,6 +11,8 @@
// Motion, EMP-Proof, X-Ray
var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/material/osmium, /obj/item/weapon/stock_parts/scanning_module)
var/list/upgrades = list()
var/camera_name
var/camera_network
var/state = 0
var/busy = 0
/*
@@ -47,7 +49,7 @@
else if(iswrench(W))
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
user << "You unattach the assembly from it's place."
user << "You unattach the assembly from its place."
anchored = 0
update_icon()
state = 0
@@ -67,7 +69,7 @@
else if(iswelder(W))
if(weld(W, user))
user << "You unweld the assembly from it's place."
user << "You unweld the assembly from its place."
state = 1
anchored = 1
return
@@ -78,7 +80,7 @@
if(isscrewdriver(W))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: Exodus,Security,Secret ", "Set Network", "Exodus"))
var/input = sanitize(input(usr, "Which networks would you like to connect this camera to? Separate networks with a comma. No Spaces!\nFor example: Exodus,Security,Secret ", "Set Network", camera_network ? camera_network : "Exodus"))
if(!input)
usr << "No input found please hang up and try your call again."
return
@@ -90,7 +92,7 @@
var/area/camera_area = get_area(src)
var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])"
input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag), MAX_NAME_LEN)
input = sanitizeSafe(input(usr, "How would you like to name the camera?", "Set Camera Name", camera_name ? camera_name : temptag), MAX_NAME_LEN)
state = 4
var/obj/machinery/camera/C = new(src.loc)
+3 -11
View File
@@ -70,7 +70,6 @@
for(var/x in verbs)
verbs -= x
set_broken()
density = 0
/obj/machinery/computer/update_icon()
..()
@@ -124,22 +123,15 @@
for (var/obj/C in src)
C.loc = src.loc
if (src.stat & BROKEN)
user << "\blue The broken glass falls out."
user << "<span class='notice'>The broken glass falls out.</span>"
new /obj/item/weapon/material/shard( src.loc )
A.state = 3
A.icon_state = "3"
else
user << "\blue You disconnect the monitor."
user << "<span class='notice'>You disconnect the monitor.</span>"
A.state = 4
A.icon_state = "4"
M.deconstruct(src)
qdel(src)
else
src.attack_hand(user)
return
..()
+1 -1
View File
@@ -457,7 +457,7 @@
var/counter = 1
while(src.active2.fields[text("com_[]", counter)])
counter++
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if (href_list["del_c"])
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
+1 -1
View File
@@ -391,7 +391,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if ("Delete Record (ALL)")
if (active1)
@@ -470,7 +470,7 @@
var/counter = 1
while(src.active2.fields[text("com_[]", counter)])
counter++
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if (href_list["del_c"])
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
@@ -410,7 +410,7 @@ What a mess.*/
var/counter = 1
while(active2.fields[text("com_[]", counter)])
counter++
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD")] [worldtime2text()], [game_year]<BR>[t1]")
if ("Delete Record (ALL)")
if (active1)
+40 -46
View File
@@ -38,16 +38,14 @@
/obj/machinery/lapvend/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(vendmode == 1)
if(istype(W, /obj/item/weapon/card))
var/obj/item/weapon/card/I = W
scan_card(I)
var/obj/item/weapon/card/id/I = W.GetID()
if(vendmode == 1 && I)
scan_id(I, W)
vendmode = 0
if(vendmode == 3 && I)
if(reimburse_id(I, W))
vendmode = 0
if(vendmode == 3)
if(istype(W,/obj/item/weapon/card))
var/obj/item/weapon/card/I = W
if(reimburse(I))
vendmode = 0
if(vendmode == 0)
if(istype(W, /obj/item/device/laptop))
var/obj/item/device/laptop/L = W
@@ -210,26 +208,24 @@
newlap.spawn_parts()
/obj/machinery/lapvend/proc/scan_card(var/obj/item/weapon/card/I)
if (istype(I, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/C = I
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_vend(D, C)
else
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
/obj/machinery/lapvend/proc/scan_id(var/obj/item/weapon/card/id/C, var/obj/item/I)
visible_message("<span class='info'>\The [usr] swipes \the [I] through \the [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_vend(D, C)
else
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
else
transfer_and_vend(CH, C)
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
else
transfer_and_vend(CH, C)
// Transfers money and vends the laptop.
@@ -361,30 +357,28 @@
/obj/machinery/lapvend/proc/reimburse(var/obj/item/weapon/card/I)
if (istype(I, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/C = I
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return 0
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_reimburse(D)
return 1
else
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
return 0
/obj/machinery/lapvend/proc/reimburse_id(var/obj/item/weapon/card/id/C, var/obj/item/I)
visible_message("<span class='info'>\The [usr] swipes \the [I] through \the [src].</span>")
var/datum/money_account/CH = get_account(C.associated_account_number)
if(!CH)
usr << "\icon[src]<span class='warning'>No valid account number is associated with this card.</span>"
return 0
if(CH.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
if(vendor_account)
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
if(D)
transfer_and_reimburse(D)
return 1
else
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
return 0
else
transfer_and_reimburse(CH)
return 1
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
return 0
else
transfer_and_reimburse(CH)
return 1
/obj/machinery/lapvend/proc/transfer_and_reimburse(var/datum/money_account/D)
var/transaction_amount = total()
+2 -2
View File
@@ -1067,8 +1067,8 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/emp_act(var/severity)
if(prob(40/severity))
var/duration = world.time + SecondsToTicks(30 / severity)
if(duration > electrified_until)
var/duration = SecondsToTicks(30 / severity)
if(electrified_until > -1 && (duration + world.time) > electrified_until)
electrify(duration)
..()
+2 -2
View File
@@ -409,12 +409,12 @@
set_opacity(0)
sleep(3)
src.density = 0
update_nearby_tiles()
sleep(7)
src.layer = open_layer
explosion_resistance = 0
update_icon()
set_opacity(0)
update_nearby_tiles()
operating = 0
if(autoclose)
@@ -436,12 +436,12 @@
src.density = 1
explosion_resistance = initial(explosion_resistance)
src.layer = closed_layer
update_nearby_tiles()
sleep(7)
update_icon()
if(visible && !glass)
set_opacity(1) //caaaaarn!
operating = 0
update_nearby_tiles()
//I shall not add a check every x ticks if a door has closed over some fire.
var/obj/fire/fire = locate() in loc
+4 -1
View File
@@ -195,7 +195,10 @@ Class Procs:
return (stat & (NOPOWER|BROKEN|additional_flags))
/obj/machinery/CanUseTopic(var/mob/user)
if(!interact_offline && (stat & (NOPOWER|BROKEN)))
if(stat & BROKEN)
return STATUS_CLOSE
if(!interact_offline && (stat & NOPOWER))
return STATUS_CLOSE
return ..()
+1 -1
View File
@@ -88,7 +88,7 @@ obj/machinery/scanner/attack_hand(mob/living/carbon/human/user)
G.fields["rank"] = "Unassigned"
G.fields["real_rank"] = G.fields["rank"]
G.fields["name"] = mname
G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
G.fields["id"] = generate_record_id()
M.fields["name"] = G.fields["name"]
M.fields["id"] = G.fields["id"]
S.fields["name"] = G.fields["name"]
+1 -4
View File
@@ -819,15 +819,12 @@
dat += "<A href='?src=\ref[src];apply_paintjob=1'><br>\[apply customisation routine\]</a><br><hr>"
if(panel_open)
dat += wires()
wires.Interact(user)
user << browse(dat, "window=suit_cycler")
onclose(user, "suit_cycler")
return
/obj/machinery/suit_cycler/proc/wires()
return wires.GetInteractWindow()
/obj/machinery/suit_cycler/Topic(href, href_list)
if(href_list["eject_suit"])
if(!suit) return
+3 -3
View File
@@ -35,14 +35,14 @@
var/turf/loc = get_turf(usr)
var/area/A = loc.loc
if (!istype(loc, /turf/simulated/floor))
usr << "<span class='danger>\The [src] Alarm cannot be placed on this spot.</span>"
usr << "<span class='danger'>\The [src] Alarm cannot be placed on this spot.</span>"
return
if (A.requires_power == 0 || A.name == "Space")
usr << "<span class='danger>\The [src] Alarm cannot be placed in this area.</span>"
usr << "<span class='danger'>\The [src] Alarm cannot be placed in this area.</span>"
return
if(gotwallitem(loc, ndir))
usr << "<span class='danger>There's already an item on this wall!</span>"
usr << "<span class='danger'>There's already an item on this wall!</span>"
return
var/obj/machinery/M = new build_machine_type(loc, ndir, 1)
+5
View File
@@ -996,6 +996,11 @@
if (usr.stat || !ishuman(usr))
return
if (usr.buckled)
usr << "<span class='warning'>You can't climb into the exosuit while buckled!</span>"
return
src.log_message("[usr] tries to move in.")
if(iscarbon(usr))
var/mob/living/carbon/C = usr
+4 -2
View File
@@ -1,6 +1,7 @@
/obj
var/can_buckle = 0
var/buckle_movable = 0
var/buckle_dir = 0
var/buckle_lying = -1 //bed-like behavior, forces mob.lying = buckle_lying if != -1
var/buckle_require_restraints = 0 //require people to be handcuffed before being able to buckle. eg: pipes
var/mob/living/buckled_mob = null
@@ -31,7 +32,7 @@
M.buckled = src
M.facing_dir = null
M.set_dir(dir)
M.set_dir(buckle_dir ? buckle_dir : dir)
M.update_canmove()
buckled_mob = M
post_buckle_mob(M)
@@ -55,7 +56,8 @@
user << "<span class='warning'>You can't buckle anyone in before the game starts.</span>"
if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat || istype(user, /mob/living/silicon/pai))
return
if(M == buckled_mob)
return
if(istype(M, /mob/living/carbon/slime))
user << "<span class='warning'>The [M] is too squishy to buckle in.</span>"
return
+82 -29
View File
@@ -4,14 +4,76 @@
/obj/effect/effect/smoke/chem
icon = 'icons/effects/chemsmoke.dmi'
opacity = 0
layer = 6
time_to_live = 300
pass_flags = PASSTABLE | PASSGRILLE | PASSGLASS //PASSGLASS is fine here, it's just so the visual effect can "flow" around glass
var/splash_amount = 10 //atoms moving through a smoke cloud get splashed with up to 10 units of reagent
var/turf/destination
/obj/effect/effect/smoke/chem/New()
/obj/effect/effect/smoke/chem/New(var/newloc, smoke_duration, turf/dest_turf = null, icon/cached_icon = null)
time_to_live = smoke_duration
..()
create_reagents(500)
return
if(cached_icon)
icon = cached_icon
set_dir(pick(cardinal))
pixel_x = -32 + rand(-8, 8)
pixel_y = -32 + rand(-8, 8)
//switching opacity on after the smoke has spawned, and then turning it off before it is deleted results in cleaner
//lighting and view range updates (Is this still true with the new lighting system?)
opacity = 1
//float over to our destination, if we have one
destination = dest_turf
if(destination)
walk_to(src, destination)
/obj/effect/effect/smoke/chem/Destroy()
opacity = 0
fadeOut()
..()
/obj/effect/effect/smoke/chem/Move()
var/list/oldlocs = view(1, src)
. = ..()
if(.)
for(var/turf/T in view(1, src) - oldlocs)
for(var/atom/movable/AM in T)
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
if(loc == destination)
bound_width = 96
bound_height = 96
/obj/effect/effect/smoke/chem/Crossed(atom/movable/AM)
..()
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
/obj/effect/effect/smoke/chem/proc/initial_splash()
for(var/turf/T in view(1, src))
for(var/atom/movable/AM in T)
if(!istype(AM, /obj/effect/effect/smoke/chem))
reagents.splash(AM, splash_amount, copy = 1)
// Fades out the smoke smoothly using it's alpha variable.
/obj/effect/effect/smoke/chem/proc/fadeOut(var/frames = 16)
if(!alpha) return //already transparent
frames = max(frames, 1) //We will just assume that by 0 frames, the coder meant "during one frame".
var/alpha_step = round(alpha / frames)
while(alpha > 0)
alpha = max(0, alpha - alpha_step)
sleep(world.tick_lag)
/////////////////////////////////////////////
// Chem Smoke Effect System
/////////////////////////////////////////////
/datum/effect/effect/system/smoke_spread/chem
smoke_type = /obj/effect/effect/smoke/chem
var/obj/chemholder
@@ -115,13 +177,21 @@
else
I = icon('icons/effects/96x96.dmi', "smoke")
//Calculate smoke duration
var/smoke_duration = 150
var/pressure = 0
var/datum/gas_mixture/environment = location.return_air()
if(environment) pressure = environment.return_pressure()
smoke_duration = between(5, smoke_duration*pressure/(ONE_ATMOSPHERE/3), smoke_duration)
var/const/arcLength = 2.3559 //distance between each smoke cloud
for(var/i = 0, i < range, i++) //calculate positions for smoke coverage - then spawn smoke
var/radius = i * 1.5
if(!radius)
spawn(0)
spawnSmoke(location, I, 1)
spawnSmoke(location, I, 1, 1)
continue
var/offset = 0
@@ -146,43 +216,26 @@
// Randomizes and spawns the smoke effect.
// Also handles deleting the smoke once the effect is finished.
//------------------------------------------
/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1, var/obj/effect/effect/smoke/chem/passed_smoke)
/datum/effect/effect/system/smoke_spread/chem/proc/spawnSmoke(var/turf/T, var/icon/I, var/smoke_duration, var/dist = 1, var/splash_initial=0, var/obj/effect/effect/smoke/chem/passed_smoke)
var/obj/effect/effect/smoke/chem/smoke
if(passed_smoke)
smoke = passed_smoke
else
smoke = PoolOrNew(/obj/effect/effect/smoke/chem, location)
smoke = PoolOrNew(/obj/effect/effect/smoke/chem, list(location, smoke_duration + rand(0, 20), T, I))
if(chemholder.reagents.reagent_list.len)
chemholder.reagents.trans_to_obj(smoke, chemholder.reagents.total_volume / dist, copy = 1) //copy reagents to the smoke so mob/breathe() can handle inhaling the reagents
smoke.icon = I
smoke.layer = 6
smoke.set_dir(pick(cardinal))
smoke.pixel_x = -32 + rand(-8, 8)
smoke.pixel_y = -32 + rand(-8, 8)
walk_to(smoke, T)
smoke.opacity = 1 //switching opacity on after the smoke has spawned, and then
sleep(150+rand(0,20)) // turning it off before it is deleted results in cleaner
smoke.opacity = 0 // lighting and view range updates
fadeOut(smoke)
qdel(src)
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/icon/I, var/dist = 1)
//Kinda ugly, but needed unless the system is reworked
if(splash_initial)
smoke.initial_splash()
/datum/effect/effect/system/smoke_spread/chem/spores/spawnSmoke(var/turf/T, var/smoke_duration, var/icon/I, var/dist = 1)
var/obj/effect/effect/smoke/chem/spores = PoolOrNew(/obj/effect/effect/smoke/chem, location)
spores.name = "cloud of [seed.seed_name] [seed.seed_noun]"
..(T, I, dist, spores)
/datum/effect/effect/system/smoke_spread/chem/proc/fadeOut(var/atom/A, var/frames = 16) // Fades out the smoke smoothly using it's alpha variable.
if(A.alpha == 0) //Handle already transparent case
return
if(frames == 0)
frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame".
var/step = A.alpha / frames
for(var/i = 0, i < frames, i++)
A.alpha -= step
sleep(world.tick_lag)
return
..(T, I, smoke_duration, dist, spores)
/datum/effect/effect/system/smoke_spread/chem/proc/smokeFlow() // Smoke pathfinder. Uses a flood fill method based on zones to quickly check what turfs the smoke (airflow) can actually reach.
@@ -60,7 +60,7 @@ var/global/list/image/splatter_cache=list()
var/obj/item/organ/external/l_foot = perp.get_organ("l_foot")
var/obj/item/organ/external/r_foot = perp.get_organ("r_foot")
var/hasfeet = 1
if((!l_foot || l_foot.status & ORGAN_DESTROYED) && (!r_foot || r_foot.status & ORGAN_DESTROYED))
if((!l_foot || l_foot.is_stump()) && (!r_foot || r_foot.is_stump()))
hasfeet = 0
if(perp.shoes && !perp.buckled)//Adding blood to shoes
var/obj/item/clothing/shoes/S = perp.shoes
@@ -105,27 +105,61 @@
qdel(src)
*/
/client/proc/spawn_tanktransferbomb()
set category = "Debug"
set desc = "Spawn a tank transfer valve bomb"
set name = "Instant TTV"
if(!check_rights(R_SPAWN)) return
var/obj/effect/spawner/newbomb/proto = /obj/effect/spawner/newbomb/radio/custom
var/p = input("Enter phoron amount (mol):","Phoron", initial(proto.phoron_amt)) as num|null
if(p == null) return
var/o = input("Enter oxygen amount (mol):","Oxygen", initial(proto.oxygen_amt)) as num|null
if(o == null) return
var/c = input("Enter carbon dioxide amount (mol):","Carbon Dioxide", initial(proto.carbon_amt)) as num|null
if(c == null) return
new /obj/effect/spawner/newbomb/radio/custom(get_turf(mob), p, o, c)
/obj/effect/spawner/newbomb
name = "bomb"
name = "TTV bomb"
icon = 'icons/mob/screen1.dmi'
icon_state = "x"
var/btype = 0 // 0=radio, 1=prox, 2=time
var/assembly_type = /obj/item/device/assembly/signaler
//Note that the maximum amount of gas you can put in a 70L air tank at 1013.25 kPa and 519K is 16.44 mol.
var/phoron_amt = 10.96
var/oxygen_amt = 16.44
var/carbon_amt = 0.0
timer
btype = 2
/obj/effect/spawner/newbomb/timer
name = "TTV bomb - timer"
assembly_type = /obj/item/device/assembly/timer
syndicate
/obj/effect/spawner/newbomb/timer/syndicate
name = "TTV bomb - merc"
//High yield bombs. Yes, it is possible to make these with toxins
phoron_amt = 15.66
oxygen_amt = 24.66
proximity
btype = 1
/obj/effect/spawner/newbomb/proximity
name = "TTV bomb - proximity"
assembly_type = /obj/item/device/assembly/prox_sensor
radio
btype = 0
/obj/effect/spawner/newbomb/New()
/obj/effect/spawner/newbomb/radio/custom/New(var/newloc, ph, ox, co)
if(ph != null) phoron_amt = ph
if(ox != null) oxygen_amt = ox
if(co != null) carbon_amt = co
..()
/obj/effect/spawner/newbomb/New(newloc)
..(newloc)
var/obj/item/device/transfer_valve/V = new(src.loc)
var/obj/item/weapon/tank/phoron/PT = new(V)
var/obj/item/weapon/tank/oxygen/OT = new(V)
@@ -137,28 +171,15 @@
OT.master = V
PT.air_contents.temperature = PHORON_FLASHPOINT
PT.air_contents.adjust_multi("phoron", 12, "carbon_dioxide", 8)
PT.air_contents.gas["phoron"] = phoron_amt
PT.air_contents.gas["carbon_dioxide"] = carbon_amt
PT.air_contents.update_values()
OT.air_contents.temperature = PHORON_FLASHPOINT
OT.air_contents.adjust_gas("oxygen", 20)
OT.air_contents.gas["oxygen"] = oxygen_amt
OT.air_contents.update_values()
var/obj/item/device/assembly/S
switch (src.btype)
// radio
if (0)
S = new/obj/item/device/assembly/signaler(V)
// proximity
if (1)
S = new/obj/item/device/assembly/prox_sensor(V)
// timer
if (2)
S = new/obj/item/device/assembly/timer(V)
var/obj/item/device/assembly/S = new assembly_type(V)
V.attached_device = S
+6
View File
@@ -151,6 +151,9 @@
if(temp && !temp.is_usable())
user << "<span class='notice'>You try to move your [temp.name], but cannot!"
return
if(!temp)
user << "<span class='notice'>You try to use your hand, but realize it is no longer attached!"
return
src.pickup(user)
if (istype(src.loc, /obj/item/weapon/storage))
var/obj/item/weapon/storage/S = src.loc
@@ -242,6 +245,9 @@
// for items that can be placed in multiple slots
// note this isn't called during the initial dressing of a player
/obj/item/proc/equipped(var/mob/user, var/slot)
layer = 20
if(user.client) user.client.screen |= src
if(user.pulling == src) user.stop_pulling()
return
//Defines which slots correspond to which slot flags
+4 -3
View File
@@ -721,7 +721,8 @@ var/global/list/obj/item/device/pda/PDAs = list()
if("Message")
var/obj/item/device/pda/P = locate(href_list["target"])
src.create_message(U, P, !href_list["notap"])
var/tap = istype(U, /mob/living/carbon)
src.create_message(U, P, tap)
if(mode == 2)
if(href_list["target"] in conversations) // Need to make sure the message went through, if not welp.
active_conversation = href_list["target"]
@@ -1040,7 +1041,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
new_message(sending_device, sending_device.owner, sending_device.ownjob, message)
/obj/item/device/pda/proc/new_message(var/sending_unit, var/sender, var/sender_job, var/message)
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;notap=[istype(loc, /mob/living/silicon)];skiprefresh=1;target=\ref[sending_unit]'>Reply</a>)"
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>)"
new_info(message_silent, ttone, reception_message)
log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
@@ -1052,7 +1053,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
if(ismob(sending_unit.loc) && isAI(loc))
track = "(<a href='byond://?src=\ref[loc];track=\ref[sending_unit.loc];trackname=[html_encode(sender)]'>Follow</a>)"
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;notap=1;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>) [track]"
var/reception_message = "\icon[src] <b>Message from [sender] ([sender_job]), </b>\"[message]\" (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[sending_unit]'>Reply</a>) [track]"
new_info(message_silent, newstone, reception_message)
log_pda("[usr] (PDA: [sending_unit]) sent \"[message]\" to [name]")
@@ -18,9 +18,11 @@
/obj/item/device/chameleon/dropped()
disrupt()
..()
/obj/item/device/chameleon/equipped()
disrupt()
..()
/obj/item/device/chameleon/attack_self()
toggle()
+1 -1
View File
@@ -320,7 +320,7 @@
qdel(src)
/obj/item/device/paicard/see_emote(mob/living/M, text)
if(pai && pai.client)
if(pai && pai.client && !pai.canmove)
var/rendered = "<span class='message'>[text]</span>"
pai.show_message(rendered, 2)
..()
@@ -99,17 +99,9 @@
if (src.loc != usr)
return 0
if(tank_one && href_list["tankone"])
split_gases()
valve_open = 0
tank_one.loc = get_turf(src)
tank_one = null
update_icon()
remove_tank(tank_one)
else if(tank_two && href_list["tanktwo"])
split_gases()
valve_open = 0
tank_two.loc = get_turf(src)
tank_two = null
update_icon()
remove_tank(tank_two)
else if(href_list["open"])
toggle_valve()
else if(attached_device)
@@ -148,20 +140,43 @@
if(attached_device)
overlays += "device"
/obj/item/device/transfer_valve/proc/remove_tank(obj/item/weapon/tank/T)
if(tank_one == T)
split_gases()
tank_one = null
else if(tank_two == T)
split_gases()
tank_two = null
else
return
T.loc = get_turf(src)
update_icon()
/obj/item/device/transfer_valve/proc/merge_gases()
if(valve_open)
return
tank_two.air_contents.volume += tank_one.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_one.air_contents.remove_ratio(1)
tank_two.air_contents.merge(temp)
valve_open = 1
/obj/item/device/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
if(!valve_open)
return
valve_open = 0
if(deleted(tank_one) || deleted(tank_two))
return
var/ratio1 = tank_one.air_contents.volume/tank_two.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_two.air_contents.remove_ratio(ratio1)
tank_one.air_contents.merge(temp)
tank_two.air_contents.volume -= tank_one.air_contents.volume
/*
Exadv1: I know this isn't how it's going to work, but this was just to check
@@ -169,8 +184,7 @@
*/
/obj/item/device/transfer_valve/proc/toggle_valve()
if(valve_open==0 && (tank_one && tank_two))
valve_open = 1
if(!valve_open && (tank_one && tank_two))
var/turf/bombturf = get_turf(src)
var/area/A = get_area(bombturf)
@@ -196,16 +210,11 @@
message_admins(log_str, 0, 1)
log_game(log_str)
merge_gases()
spawn(20) // In case one tank bursts
for (var/i=0,i<5,i++)
src.update_icon()
sleep(10)
src.update_icon()
else if(valve_open==1 && (tank_one && tank_two))
split_gases()
valve_open = 0
src.update_icon()
src.update_icon()
// this doesn't do anything but the timer etc. expects it to be here
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
@@ -71,6 +71,10 @@
icon_state = "meson"
icon = 'icons/obj/clothing/glasses.dmi'
/obj/item/borg/sight/material
name = "\proper material scanner vision"
sight_mode = BORGMATERIAL
/obj/item/borg/sight/hud
name = "hud"
var/obj/item/clothing/glasses/hud/hud = null
+7 -6
View File
@@ -137,6 +137,7 @@
if (istype(O, /obj/item/stack))
var/obj/item/stack/S = O
S.amount = produced
S.add_to_stacks(user)
if (istype(O, /obj/item/weapon/storage)) //BubbleWrap - so newly formed boxes are empty
for (var/obj/item/I in O)
@@ -191,7 +192,7 @@
else
if(get_amount() < used)
return 0
for(var/i = 1 to uses_charge)
for(var/i = 1 to charge_costs.len)
var/datum/matter_synth/S = synths[i]
S.use_charge(charge_costs[i] * used) // Doesn't need to be deleted
return 1
@@ -264,8 +265,8 @@
return 0
var/datum/matter_synth/S = synths[1]
. = round(S.get_charge() / charge_costs[1])
if(uses_charge > 1)
for(var/i = 2 to uses_charge)
if(charge_costs.len > 1)
for(var/i = 2 to charge_costs.len)
S = synths[i]
. = min(., round(S.get_charge() / charge_costs[i]))
return
@@ -284,13 +285,13 @@
return
return max_amount
/obj/item/stack/proc/add_to_stacks(mob/usr as mob)
for (var/obj/item/stack/item in usr.loc)
/obj/item/stack/proc/add_to_stacks(mob/user as mob)
for (var/obj/item/stack/item in user.loc)
if (item==src)
continue
var/transfer = src.transfer_to(item)
if (transfer)
usr << "You add a new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s."
user << "<span class='notice'>You add a new [item.singular_name] to the stack. It now contains [item.amount] [item.singular_name]\s.</span>"
if(!amount)
break
@@ -1,27 +1,135 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/air_management
name = T_BOARD("atmosphere monitoring console")
build_path = /obj/machinery/computer/general_air_control
var/console_name
var/frequency = 1439
var/list/sensors = list()
var/list/sensor_information = list()
/obj/item/weapon/circuitboard/air_management/tank_control
name = T_BOARD("tank control")
build_path = /obj/machinery/computer/general_air_control/large_tank_control
frequency = 1441
var/input_tag
var/output_tag
var/list/input_info = list()
var/list/output_info = list()
var/input_flow_setting = 200
var/pressure_setting = ONE_ATMOSPHERE * 45
/obj/item/weapon/circuitboard/air_management/supermatter_core
name = T_BOARD("core control")
build_path = /obj/machinery/computer/general_air_control/supermatter_core
frequency = 1438
var/input_tag
var/output_tag
var/list/input_info = list()
var/list/output_info = list()
var/input_flow_setting = 700
var/pressure_setting = 100
/obj/item/weapon/circuitboard/air_management/injector_control
name = T_BOARD("injector control")
build_path = /obj/machinery/computer/general_air_control/fuel_injection
var/device_tag
var/list/device_info
var/automation = 0
var/cutoff_temperature = 2000
var/on_temperature = 1200
/************
* Construct *
************/
/obj/item/weapon/circuitboard/air_management/construct(var/obj/machinery/computer/general_air_control/C)
if (..(C))
C.frequency = frequency
if(console_name)
C.name = console_name
C.set_frequency(frequency)
C.sensors = sensors.Copy()
C.sensor_information = sensor_information.Copy()
return 1
/obj/item/weapon/circuitboard/air_management/tank_control/construct(var/obj/machinery/computer/general_air_control/large_tank_control/LTC)
if(..(LTC))
LTC.input_tag = input_tag
LTC.output_tag = output_tag
LTC.input_info = input_info.Copy()
LTC.output_info = output_info.Copy()
LTC.input_flow_setting = input_flow_setting
LTC.pressure_setting = pressure_setting
return 1
/obj/item/weapon/circuitboard/air_management/supermatter_core/construct(var/obj/machinery/computer/general_air_control/supermatter_core/SC)
if(..(SC))
SC.input_tag = input_tag
SC.output_tag = output_tag
SC.input_info = input_info.Copy()
SC.output_info = output_info.Copy()
SC.input_flow_setting = input_flow_setting
SC.pressure_setting = input_flow_setting
return 1
/obj/item/weapon/circuitboard/air_management/injector_control/construct(var/obj/machinery/computer/general_air_control/fuel_injection/FI)
if(..(FI))
FI.device_tag = device_tag
FI.device_info = device_info.Copy()
FI.automation = automation
FI.cutoff_temperature = cutoff_temperature
FI.on_temperature = on_temperature
return 1
/**************
* Deconstruct *
**************/
/obj/item/weapon/circuitboard/air_management/deconstruct(var/obj/machinery/computer/general_air_control/C)
if (..(C))
console_name = C.name
frequency = C.frequency
sensors = C.sensors.Copy()
sensor_information = C.sensor_information.Copy()
return 1
/obj/item/weapon/circuitboard/air_management/tank_control/deconstruct(var/obj/machinery/computer/general_air_control/large_tank_control/LTC)
if(..(LTC))
input_tag = LTC.input_tag
output_tag = LTC.output_tag
input_info = LTC.input_info.Copy()
output_info = LTC.output_info.Copy()
input_flow_setting = LTC.input_flow_setting
pressure_setting = LTC.pressure_setting
return 1
/obj/item/weapon/circuitboard/air_management/supermatter_core/deconstruct(var/obj/machinery/computer/general_air_control/supermatter_core/SC)
if(..(SC))
input_tag = SC.input_tag
output_tag = SC.output_tag
input_info = SC.input_info.Copy()
output_info = SC.output_info.Copy()
input_flow_setting = SC.input_flow_setting
pressure_setting = SC.input_flow_setting
return 1
/obj/item/weapon/circuitboard/air_management/injector_control/deconstruct(var/obj/machinery/computer/general_air_control/fuel_injection/FI)
if(..(FI))
device_tag = FI.device_tag
device_info = FI.device_info.Copy()
automation = FI.automation
cutoff_temperature = FI.cutoff_temperature
on_temperature = FI.on_temperature
return 1
@@ -0,0 +1,31 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/holodeckcontrol
name = T_BOARD("holodeck control console")
build_path = /obj/machinery/computer/HolodeckControl
origin_tech = "programming=2;bluespace=2"
var/last_to_emag
var/linkedholodeck_area
var/list/supported_programs
var/list/restricted_programs
/obj/item/weapon/circuitboard/holodeckcontrol/construct(var/obj/machinery/computer/HolodeckControl/HC)
if (..(HC))
HC.supported_programs = supported_programs.Copy()
HC.restricted_programs = restricted_programs.Copy()
if(linkedholodeck_area)
HC.linkedholodeck = locate(linkedholodeck_area)
if(last_to_emag)
HC.last_to_emag = last_to_emag
HC.emagged = 1
HC.safety_disabled = 1
/obj/item/weapon/circuitboard/holodeckcontrol/deconstruct(var/obj/machinery/computer/HolodeckControl/HC)
if (..(HC))
linkedholodeck_area = HC.linkedholodeck_area
supported_programs = HC.supported_programs.Copy()
restricted_programs = HC.restricted_programs.Copy()
last_to_emag = HC.last_to_emag
HC.emergencyShutdown()
+13 -2
View File
@@ -15,7 +15,15 @@
/*
* Soap
*/
/obj/item/weapon/soap/Crossed(AM as mob|obj) //EXACTLY the same as bananapeel for now, so it makes sense to put it in the same dm -- Urist
/obj/item/weapon/soap/New()
..()
create_reagents(5)
wet()
/obj/item/weapon/soap/proc/wet()
reagents.add_reagent("cleaner", 5)
/obj/item/weapon/soap/Crossed(AM as mob|obj)
if (istype(AM, /mob/living))
var/mob/living/M = AM
M.slip("the [src.name]",3)
@@ -32,7 +40,10 @@
else if(istype(target,/turf))
user << "<span class='notice'>You scrub \the [target.name] clean.</span>"
var/turf/T = target
T.clean(src)
T.clean(src, user)
else if(istype(target,/obj/structure/sink))
user << "<span class='notice'>You wet \the [src] in the sink.</span>"
wet()
else
user << "<span class='notice'>You clean \the [target.name].</span>"
target.clean_blood()
@@ -6,6 +6,7 @@
w_class = 2.0
force = 2.0
det_time = null
unacidable = 1
var/stage = 0
var/state = 0
var/path = 0
@@ -163,7 +164,7 @@
playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1)
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
G.reagents.trans_to(src, G.reagents.total_volume)
G.reagents.trans_to_obj(src, G.reagents.total_volume)
if(src.reagents.total_volume) //The possible reactions didnt use up all reagents.
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
@@ -6,6 +6,7 @@
name = "implant"
icon = 'icons/obj/device.dmi'
icon_state = "implant"
w_class = 1
var/implanted = null
var/mob/imp_in = null
var/obj/item/organ/external/part = null
@@ -44,7 +44,8 @@
overlays.Cut()
return
else
..()
user << "<span class='warning'>You don't have anything on \the [src].</span>" //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK GODDAMNIT
return
/obj/item/weapon/material/kitchen/utensil/fork
name = "fork"
@@ -77,14 +78,14 @@
/obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "\red You accidentally cut yourself with the [src]."
user << "<span class='warning'>You accidentally cut yourself with \the [src].</span>"
user.take_organ_damage(20)
return
return ..()
/obj/item/weapon/material/kitchen/utensil/knife/attack(target as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "\red You somehow managed to cut yourself with the [src]."
user << "<span class='warning'>You somehow managed to cut yourself with \the [src].</span>"
user.take_organ_damage(20)
return
return ..()
@@ -107,7 +108,7 @@
/obj/item/weapon/material/kitchen/rollingpin/attack(mob/living/M as mob, mob/living/user as mob)
if ((CLUMSY in user.mutations) && prob(50))
user << "\red The [src] slips out of your hand and hits your head."
user << "<span class='warning'>\The [src] slips out of your hand and hits your head.</span>"
user.take_organ_damage(10)
user.Paralyse(2)
return
+2 -14
View File
@@ -14,19 +14,7 @@
/obj/item/weapon/mop/New()
create_reagents(5)
//expects an atom containing the reagents used to clean the turf
/turf/proc/clean(atom/source)
if(source.reagents.has_reagent("water", 1))
clean_blood()
if(istype(src, /turf/simulated))
var/turf/simulated/T = src
T.dirt = 0
for(var/obj/effect/O in src)
if(istype(O,/obj/effect/rune) || istype(O,/obj/effect/decal/cleanable) || istype(O,/obj/effect/overlay))
qdel(O)
source.reagents.trans_to_turf(src, 1, 10) //10 is the multiplier for the reaction effect. probably needed to wet the floor properly.
create_reagents(30)
/obj/item/weapon/mop/afterattack(atom/A, mob/user, proximity)
if(!proximity) return
@@ -40,7 +28,7 @@
if(do_after(user, 40))
var/turf/T = get_turf(A)
if(T)
T.clean(src)
T.clean(src, user)
user << "<span class='notice'>You have finished mopping!</span>"
@@ -598,32 +598,33 @@
icon_state = "light"
desc = "This box is shaped on the inside so that only light tubes and bulbs fit."
item_state = "syringe_kit"
storage_slots=21
can_hold = list(/obj/item/weapon/light/tube, /obj/item/weapon/light/bulb)
max_storage_space = 42 //holds 21 items of w_class 2
use_to_pickup = 1 // for picking up broken bulbs, not that most people will try
/obj/item/weapon/storage/box/lights/New()
..()
make_exact_fit()
/obj/item/weapon/storage/box/lights/bulbs/New()
..()
for(var/i = 0; i < 21; i++)
new /obj/item/weapon/light/bulb(src)
..()
/obj/item/weapon/storage/box/lights/tubes
name = "box of replacement tubes"
icon_state = "lighttube"
/obj/item/weapon/storage/box/lights/tubes/New()
..()
for(var/i = 0; i < 21; i++)
new /obj/item/weapon/light/tube(src)
..()
/obj/item/weapon/storage/box/lights/mixed
name = "box of replacement lights"
icon_state = "lightmixed"
/obj/item/weapon/storage/box/lights/mixed/New()
..()
for(var/i = 0; i < 14; i++)
new /obj/item/weapon/light/tube(src)
for(var/i = 0; i < 7; i++)
new /obj/item/weapon/light/bulb(src)
..()
@@ -130,8 +130,7 @@
/obj/item/weapon/storage/firstaid/surgery
name = "surgery kit"
desc = "Contains tools for surgery."
storage_slots = 10
desc = "Contains tools for surgery. Has precise foam fitting for safe transport."
/obj/item/weapon/storage/firstaid/surgery/New()
..()
@@ -146,7 +145,8 @@
new /obj/item/weapon/bonegel(src)
new /obj/item/weapon/FixOVein(src)
new /obj/item/stack/medical/advanced/bruise_pack(src)
return
make_exact_fit()
/*
* Pill Bottles
@@ -51,10 +51,10 @@
//there's got to be a better way of doing this.
if (!(src.loc == usr) || (src.loc && src.loc.loc == usr))
return
if (( usr.restrained() ) || ( usr.stat ))
return
if ((src.loc == usr) && !usr.unEquip(src))
return
@@ -232,12 +232,16 @@
usr << "<span class='notice'>[src] is full, make some space.</span>"
return 0 //Storage item is full
if(can_hold.len && !is_type_in_list(W, can_hold))
if(!stop_messages)
if (istype(W, /obj/item/weapon/hand_labeler))
return 0
usr << "<span class='notice'>[src] cannot hold [W].</span>"
return 0
if(can_hold.len)
if(!is_type_in_list(W, can_hold))
if(!stop_messages && ! istype(W, /obj/item/weapon/hand_labeler))
usr << "<span class='notice'>[src] cannot hold \the [W].</span>"
return 0
var/max_instances = can_hold[W.type]
if(max_instances && instances_of_type_in_list(W, contents) >= max_instances)
if(!stop_messages && !istype(W, /obj/item/weapon/hand_labeler))
usr << "<span class='notice'>[src] has no more space specifically for \the [W].</span>"
return 0
if(cant_hold.len && is_type_in_list(W, cant_hold))
if(!stop_messages)
@@ -449,6 +453,17 @@
var/obj/O = A
O.hear_talk(M, text, verb, speaking)
/obj/item/weapon/storage/proc/make_exact_fit()
storage_slots = contents.len
can_hold.Cut()
max_w_class = 0
max_storage_space = 0
for(var/obj/item/I in src)
can_hold[I.type]++
max_w_class = max(I.w_class, max_w_class)
max_storage_space += I.get_storage_cost()
//Returns the storage depth of an atom. This is the number of storage items the atom is contained in before reaching toplevel (the area).
//Returns -1 if the atom was not found on container.
/atom/proc/storage_depth(atom/container)
@@ -1,71 +0,0 @@
/obj/item/robot_parts/attack(mob/living/carbon/human/M as mob, mob/living/carbon/user as mob)
var/limbloc = null
if(!istype(M))
return ..()
if(!((locate(/obj/machinery/optable, M.loc) && M.resting) || (locate(/obj/structure/bed/roller, M.loc) && (M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(75) || (locate(/obj/structure/table/, M.loc) && (M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat) && prob(66))))
return ..()
if(!istype(M, /mob/living/carbon/human))
return ..()
if((user.zone_sel.selecting == "l_arm") && (istype(src, /obj/item/robot_parts/l_arm)))
limbloc = "l_hand"
else if((user.zone_sel.selecting == "r_arm") && (istype(src, /obj/item/robot_parts/r_arm)))
limbloc = "r_hand"
else if((user.zone_sel.selecting == "r_leg") && (istype(src, /obj/item/robot_parts/r_leg)))
limbloc = "r_foot"
else if((user.zone_sel.selecting == "l_leg") && (istype(src, /obj/item/robot_parts/l_leg)))
limbloc = "l_foot"
else
user << "\red That doesn't fit there!"
return ..()
var/mob/living/carbon/human/H = M
var/datum/organ/external/S = H.organs[user.zone_sel.selecting]
if(S.status & ORGAN_DESTROYED)
if(!(S.status & ORGAN_ATTACHABLE))
user << "\red The wound is not ready for a replacement!"
return 0
if(M != user)
M.visible_message( \
"\red [user] is beginning to attach \the [src] where [H]'s [S.display_name] used to be.", \
"\red [user] begins to attach \the [src] where your [S.display_name] used to be.")
else
M.visible_message( \
"\red [user] begins to attach a robotic limb where \his [S.display_name] used to be with [src].", \
"\red You begin to attach \the [src] where your [S.display_name] used to be.")
if(do_mob(user, H, 100))
if(M != user)
M.visible_message( \
"\red [user] finishes attaching [H]'s new [S.display_name].", \
"\red [user] finishes attaching your new [S.display_name].")
else
M.visible_message( \
"\red [user] finishes attaching \his new [S.display_name].", \
"\red You finish attaching your new [S.display_name].")
if(H == user && prob(25))
user << "\red You mess up!"
S.take_damage(15)
S.status &= ~ORGAN_BROKEN
S.status &= ~ORGAN_SPLINTED
S.status &= ~ORGAN_ATTACHABLE
S.status &= ~ORGAN_DESTROYED
S.status |= ORGAN_ROBOT
var/datum/organ/external/T = H.organs["[limbloc]"]
T.status &= ~ORGAN_BROKEN
T.status &= ~ORGAN_SPLINTED
T.status &= ~ORGAN_ATTACHABLE
T.status &= ~ORGAN_DESTROYED
T.status |= ORGAN_ROBOT
H.update_body()
M.updatehealth()
M.UpdateDamageIcon()
qdel(src)
return 1
return 0
+12 -2
View File
@@ -36,6 +36,10 @@
qdel(air_contents)
processing_objects.Remove(src)
if(istype(loc, /obj/item/device/transfer_valve))
var/obj/item/device/transfer_valve/TTV = loc
TTV.remove_tank(src)
..()
@@ -272,7 +276,10 @@
qdel(src)
else if(pressure > TANK_RUPTURE_PRESSURE)
//world << "\blue[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]"
#ifdef FIREDBG
log_debug("\blue[x],[y] tank is rupturing: [pressure] kPa, integrity [integrity]")
#endif
if(integrity <= 0)
var/turf/simulated/T = get_turf(src)
if(!T)
@@ -284,7 +291,10 @@
integrity--
else if(pressure > TANK_LEAK_PRESSURE)
//world << "\blue[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]"
#ifdef FIREDBG
log_debug("\blue[x],[y] tank is leaking: [pressure] kPa, integrity [integrity]")
#endif
if(integrity <= 0)
var/turf/simulated/T = get_turf(src)
if(!T)
+1 -1
View File
@@ -79,7 +79,7 @@
return ..()
/obj/structure/proc/can_climb(var/mob/living/user, post_climb_check=0)
if (!can_touch(user) || !climbable || (!post_climb_check && (user in climbers)))
if (!climbable || !can_touch(user) || (!post_climb_check && (user in climbers)))
return 0
if (!user.Adjacent(src))
@@ -172,19 +172,18 @@
if(1)
for(var/atom/movable/A as mob|obj in src)//pulls everything out of the locker and hits it with an explosion
A.forceMove(src.loc)
A.ex_act(severity++)
A.ex_act(severity + 1)
qdel(src)
if(2)
if(prob(50))
for (var/atom/movable/A as mob|obj in src)
A.forceMove(src.loc)
A.ex_act(severity++)
A.ex_act(severity + 1)
qdel(src)
if(3)
if(prob(5))
for(var/atom/movable/A as mob|obj in src)
A.forceMove(src.loc)
A.ex_act(severity++)
qdel(src)
/obj/structure/closet/proc/damage(var/damage)
@@ -66,11 +66,12 @@
src.MouseDrop_T(W:affecting, user) //act like they were dragged onto the closet
user.drop_item()
if (W) W.forceMove(src.loc)
else if(istype(W, /obj/item/weapon/card/id))
else if(W.GetID())
var/obj/item/weapon/card/id/I = W.GetID()
if(src.broken)
user << "<span class='warning'>It appears to be broken.</span>"
return
var/obj/item/weapon/card/id/I = W
if(!I || !I.registered_name) return
if(src.allowed(user) || !src.registered_name || (istype(I) && (src.registered_name == I.registered_name)))
//they can open all lockers, or nobody owns this, or they own this locker
@@ -15,6 +15,7 @@
pressure_resistance = 15
anchored = 1
can_buckle = 1
buckle_dir = SOUTH
buckle_lying = 1
var/material/material
var/material/padding_material
@@ -131,14 +132,18 @@
remove_padding()
else if(istype(W, /obj/item/weapon/grab))
user.visible_message("<span class='notice'>[user] attempts to buckle [W:affecting] into \the [src]!</span>")
var/obj/item/weapon/grab/G = W
var/mob/living/affecting = G.affecting
user.visible_message("<span class='notice'>[user] attempts to buckle [affecting] into \the [src]!</span>")
if(do_after(user, 20))
W:affecting.loc = loc
if(buckle_mob(W:affecting))
W:affecting.visible_message(\
"<span class='danger'>[W:affecting.name] is buckled to [src] by [user.name]!</span>",\
"<span class='danger'>You are buckled to [src] by [user.name]!</span>",\
"<span class='notice'>You hear metal clanking.</span>")
affecting.loc = loc
spawn(0)
if(buckle_mob(affecting))
affecting.visible_message(\
"<span class='danger'>[affecting.name] is buckled to [src] by [user.name]!</span>",\
"<span class='danger'>You are buckled to [src] by [user.name]!</span>",\
"<span class='notice'>You hear metal clanking.</span>")
qdel(W)
else
..()

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