Merge remote-tracking branch 'Aurorastation/development' into SQL-backend-import

# Conflicts:
#	code/modules/admin/admin.dm
#	code/modules/admin/admin_verbs.dm

All conflicts cleared. Wind funciton needs a quick redo as a result.
This commit is contained in:
skull132
2016-02-01 16:00:54 +02:00
335 changed files with 4900 additions and 2425 deletions

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:

View File

@@ -24,6 +24,7 @@
#include "code\__HELPERS\lists.dm"
#include "code\__HELPERS\logging.dm"
#include "code\__HELPERS\maths.dm"
#include "code\__HELPERS\matrices.dm"
#include "code\__HELPERS\mobs.dm"
#include "code\__HELPERS\names.dm"
#include "code\__HELPERS\sanitize_values.dm"
@@ -44,6 +45,7 @@
#include "code\_onclick\other_mobs.dm"
#include "code\_onclick\telekinesis.dm"
#include "code\_onclick\hud\_defines.dm"
#include "code\_onclick\hud\ai.dm"
#include "code\_onclick\hud\alien_larva.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
@@ -203,7 +205,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 +314,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"
@@ -575,6 +575,7 @@
#include "code\game\objects\items\devices\flashlight.dm"
#include "code\game\objects\items\devices\floor_painter.dm"
#include "code\game\objects\items\devices\lightreplacer.dm"
#include "code\game\objects\items\devices\magnetic_lock.dm"
#include "code\game\objects\items\devices\megaphone.dm"
#include "code\game\objects\items\devices\modkit.dm"
#include "code\game\objects\items\devices\multitool.dm"
@@ -657,6 +658,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"
@@ -836,7 +838,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"
@@ -881,6 +882,7 @@
#include "code\modules\client\client defines.dm"
#include "code\modules\client\client procs.dm"
#include "code\modules\client\preferences.dm"
#include "code\modules\client\preferences_ambience.dm"
#include "code\modules\client\preferences_factions.dm"
#include "code\modules\client\preferences_gear.dm"
#include "code\modules\client\preferences_savefile.dm"
@@ -1249,6 +1251,7 @@
#include "code\modules\mob\living\silicon\ai\life.dm"
#include "code\modules\mob\living\silicon\ai\login.dm"
#include "code\modules\mob\living\silicon\ai\logout.dm"
#include "code\modules\mob\living\silicon\ai\nano.dm"
#include "code\modules\mob\living\silicon\decoy\death.dm"
#include "code\modules\mob\living\silicon\decoy\decoy.dm"
#include "code\modules\mob\living\silicon\decoy\life.dm"
@@ -1340,6 +1343,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"
@@ -1427,6 +1431,9 @@
#include "code\modules\power\singularity\particle_accelerator\particle_control.dm"
#include "code\modules\power\singularity\particle_accelerator\particle_emitter.dm"
#include "code\modules\power\singularity\particle_accelerator\particle_power.dm"
#include "code\modules\power\tesla\coil.dm"
#include "code\modules\power\tesla\energy_ball.dm"
#include "code\modules\power\tesla\generator.dm"
#include "code\modules\projectiles\ammunition.dm"
#include "code\modules\projectiles\effects.dm"
#include "code\modules\projectiles\gun.dm"
@@ -1439,6 +1446,7 @@
#include "code\modules\projectiles\guns\launcher.dm"
#include "code\modules\projectiles\guns\projectile.dm"
#include "code\modules\projectiles\guns\energy\laser.dm"
#include "code\modules\projectiles\guns\energy\lawgiver.dm"
#include "code\modules\projectiles\guns\energy\nuclear.dm"
#include "code\modules\projectiles\guns\energy\pulse.dm"
#include "code\modules\projectiles\guns\energy\special.dm"
@@ -1644,6 +1652,7 @@
#include "code\modules\spells\targeted\targeted.dm"
#include "code\modules\spells\targeted\equip\equip.dm"
#include "code\modules\spells\targeted\equip\horsemask.dm"
#include "code\modules\spells\targeted\equip\remove_horsemask.dm"
#include "code\modules\spells\targeted\projectile\dumbfire.dm"
#include "code\modules\spells\targeted\projectile\fireball.dm"
#include "code\modules\spells\targeted\projectile\magic_missile.dm"

View File

@@ -35,10 +35,9 @@ except ImportError:
try:
tiedosto = open("psycodownload.txt","r")
except:
tiedosto = open("psycodownload.txt","w")
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")
tiedosto.close()
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")
with open("replacenames.cache","r") as tiedosto:
replacenames = pickle.load(tiedosto)
tiedosto.close()
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")
with open("replacenames.cache","w") as tiedosto:
pickle.dump(replacenames,tiedosto)
tiedosto.close()
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")
with open("peopleheknows.cache","r") as tiedosto:
peopleheknows = pickle.load(tiedosto)
tiedosto.close()
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,13 +341,11 @@ if aggressive_pinging:
self_time = 0
global backup,disconnects,conn
while disconnects < 5:
if backup > self_time:
if time.time()-backup > delay:
if backup > self_time and time.time()-backup > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
else:
if time.time()-self_time > delay:
elif time.time()-self_time > delay:
conn.send("PONG "+pongtarg)
print "Ponged"
self_time = time.time()
@@ -370,8 +364,7 @@ def stop(sender,debug=1):
access_granted = True
else:
access_granted = False
if access_granted:
if debug:
if access_granted and debug:
print sender+":"+prefix+"stop"
if random.randint(0,100) == 50:
conn.privmsg(channel,"Hammertime!")
@@ -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")
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")
tiedosto.close()
else:
CALL_OFF = False
pass
@@ -576,8 +568,7 @@ while True:
time.sleep(6)
Name = origname
conn.nick(Name)
if origname in truesender:
if influx == prefix+"stop":
if origname in truesender and influx == prefix+"stop":
time.sleep(0.5) #A small delay
conn.privmsg(channel,"Shutting down.")
conn.quit()
@@ -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")
with open(targetdirectory+"suggestions/suggestions_"+str(int(time.time()))+".txt","a") as tiedosto:
tiedosto.write(arg)
tiedosto.close()
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()

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

View File

@@ -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

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)

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.

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"

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

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

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)

View File

@@ -0,0 +1,26 @@
/matrix/proc/TurnTo(old_angle, new_angle)
. = new_angle - old_angle
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3)
if(!segments)
return
var/segment = 360/segments
if(!clockwise)
segment = -segment
var/list/matrices = list()
for(var/i in 1 to segments-1)
var/matrix/M = matrix(transform)
M.Turn(segment*i)
matrices += M
var/matrix/last = matrix(transform)
matrices += last
speed /= segments
animate(src, transform = matrices[1], time = speed, loops)
for(var/i in 2 to segments) //2 because 1 is covered above
animate(transform = matrices[i], time = speed)
//doesn't have an object argument because this is "Stacking" with the animate call above
//3 billion% intentional

View File

@@ -138,6 +138,14 @@
/proc/sanitize_old(var/t,var/list/repl_chars = list("\n"="#","\t"="#"))
return html_encode(replace_characters(t,repl_chars))
// Truncates text to limit if necessary.
/proc/dd_limittext(message, length)
var/size = length(message)
if (size <= length)
return message
else
return copytext(message, 1, length + 1)
/*
* Text searches
*/

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)

View File

@@ -1309,3 +1309,64 @@ 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.
//This is just so you can stop an orbit.
//orbit() can run without it (swap orbiting for A)
//but then you can never stop it and that's just silly.
/atom/movable/var/atom/orbiting = null
//A: atom to orbit
//radius: range to orbit at, radius of the circle formed by orbiting
//clockwise: whether you orbit clockwise or anti clockwise
//rotation_speed: how fast to rotate
//rotation_segments: the resolution of the orbit circle, less = a more block circle, this can be used to produce hexagons (6 segments) triangles (3 segments), and so on, 36 is the best default.
//pre_rotation: Chooses to rotate src 90 degress towards the orbit dir (clockwise/anticlockwise), useful for things to go "head first" like ghosts
//lockinorbit: Forces src to always be on A's turf, otherwise the orbit cancels when src gets too far away (eg: ghosts)
/atom/movable/proc/orbit(atom/A, radius = 10, clockwise = FALSE, rotation_speed = 20, rotation_segments = 36, pre_rotation = TRUE, lockinorbit = FALSE)
if(!istype(A))
return
if(orbiting)
stop_orbit()
orbiting = A
var/matrix/initial_transform = matrix(transform)
var/lastloc = loc
//Head first!
if(pre_rotation)
var/matrix/M = matrix(transform)
var/pre_rot = 90
if(!clockwise)
pre_rot = -90
M.Turn(pre_rot)
transform = M
var/matrix/shift = matrix(transform)
shift.Translate(0,radius)
transform = shift
SpinAnimation(rotation_speed, -1, clockwise, rotation_segments)
//we stack the orbits up client side, so we can assign this back to normal server side without it breaking the orbit
transform = initial_transform
while(orbiting && orbiting == A && A.loc)
var/targetloc = get_turf(A)
if(!lockinorbit && loc != lastloc && loc != targetloc)
break
loc = targetloc
lastloc = loc
sleep(0.6)
if (orbiting == A) //make sure we haven't started orbiting something else.
orbiting = null
SpinAnimation(0,0)
/atom/movable/proc/stop_orbit()
orbiting = null
// call to generate a stack trace and print to runtime logs
/proc/crash_with(msg)
CRASH(msg)

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)

View File

@@ -127,3 +127,22 @@
#define ui_spell_master "14:16,14:16"
#define ui_genetic_master "14:16,12:16"
// AI
#define ui_ai_camera_list "SOUTH:6+1,WEST+1:16"
#define ui_ai_track_with_camera "SOUTH:6+1,WEST+2:16"
#define ui_ai_camera_light "SOUTH:6+1,WEST+3:16"
#define ui_ai_sensor "SOUTH:6+1,WEST+4:16"
#define ui_ai_core "SOUTH:6,WEST+1:16"
#define ui_ai_crew_monitor "SOUTH:6,WEST+2:16"
#define ui_ai_crew_manifest "SOUTH:6,WEST+3:16"
#define ui_ai_alerts "SOUTH:6,WEST+4:16"
#define ui_ai_announcement "SOUTH:6,WEST+5:16"
#define ui_ai_shuttle "SOUTH:6,WEST+6:16"
#define ui_ai_state_laws "SOUTH:6,WEST+7:16"
#define ui_ai_pda_send "SOUTH:6,WEST+8:16"
#define ui_ai_pda_log "SOUTH:6,WEST+9:16"
#define ui_ai_take_picture "SOUTH:6,WEST+10:16"
#define ui_ai_view_images "SOUTH:6,WEST+11:16"

143
code/_onclick/hud/ai.dm Normal file
View File

@@ -0,0 +1,143 @@
/datum/hud/proc/ai_hud()
adding = list()
other = list()
var/obj/screen/using
//AI core
using = new /obj/screen()
using.name = "AI Core"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "ai_core"
using.screen_loc = ui_ai_core
using.layer = 20
adding += using
//Camera list
using = new /obj/screen()
using.name = "Show Camera List"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "camera"
using.screen_loc = ui_ai_camera_list
using.layer = 20
adding += using
//Track
using = new /obj/screen()
using.name = "Track With Camera"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "track"
using.screen_loc = ui_ai_track_with_camera
using.layer = 20
adding += using
//Camera light
using = new /obj/screen()
using.name = "Toggle Camera Light"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "camera_light"
using.screen_loc = ui_ai_camera_light
using.layer = 20
adding += using
//Crew Monitorting
using = new /obj/screen()
using.name = "Crew Monitoring"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "crew_monitor"
using.screen_loc = ui_ai_crew_monitor
using.layer = 20
adding += using
//Crew Manifest
using = new /obj/screen()
using.name = "Show Crew Manifest"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "manifest"
using.screen_loc = ui_ai_crew_manifest
using.layer = 20
adding += using
//Alerts
using = new /obj/screen()
using.name = "Show Alerts"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "alerts"
using.screen_loc = ui_ai_alerts
using.layer = 20
adding += using
//Announcement
using = new /obj/screen()
using.name = "Announcement"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "announcement"
using.screen_loc = ui_ai_announcement
using.layer = 20
adding += using
//Shuttle
using = new /obj/screen()
using.name = "Call Emergency Shuttle"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "call_shuttle"
using.screen_loc = ui_ai_shuttle
using.layer = 20
adding += using
//Laws
using = new /obj/screen()
using.name = "State Laws"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "state_laws"
using.screen_loc = ui_ai_state_laws
using.layer = 20
adding += using
//PDA message
using = new /obj/screen()
using.name = "PDA - Send Message"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "pda_send"
using.screen_loc = ui_ai_pda_send
using.layer = 20
adding += using
//PDA log
using = new /obj/screen()
using.name = "PDA - Show Message Log"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "pda_receive"
using.screen_loc = ui_ai_pda_log
using.layer = 20
adding += using
//Take image
using = new /obj/screen()
using.name = "Take Image"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "take_picture"
using.screen_loc = ui_ai_take_picture
using.layer = 20
adding += using
//View images
using = new /obj/screen()
using.name = "View Images"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "view_images"
using.screen_loc = ui_ai_view_images
using.layer = 20
adding += using
//Medical/Security sensors
using = new /obj/screen()
using.name = "Set Sensor Augmentation"
using.icon = 'icons/mob/screen_ai.dmi'
using.icon_state = "ai_sensor"
using.screen_loc = ui_ai_sensor
using.layer = 20
adding += using
mymob.client.screen += adding + other
return

View File

@@ -13,9 +13,6 @@
mymob.blind.screen_loc = "1,1"
mymob.blind.layer = 0
/datum/hud/proc/ai_hud()
return
/datum/hud/proc/blob_hud(ui_style = 'icons/mob/screen1_Midnight.dmi')
blobpwrdisplay = new /obj/screen()

View File

@@ -478,6 +478,83 @@
usr.client.AllowTargetRadio()
gun_click_time = world.time
if("AI Core")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.view_core()
if("Show Camera List")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
var/camera = input(AI) in AI.get_camera_list()
AI.ai_camera_list(camera)
if("Track With Camera")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
var/target_name = input(AI) in AI.trackable_mobs()
AI.ai_camera_track(target_name)
if("Toggle Camera Light")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.toggle_camera_light()
if("Crew Monitoring")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.subsystem_crew_monitor()
if("Show Crew Manifest")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.show_station_manifest()
if("Show Alerts")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.subsystem_alarm_monitor()
if("Announcement")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.ai_announcement()
if("Call Emergency Shuttle")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.ai_call_shuttle()
if("State Laws")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.subsystem_law_manager()
if("PDA - Send Message")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.aiPDA.cmd_send_pdamesg(usr)
if("PDA - Show Message Log")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.aiPDA.cmd_show_message_log(usr)
if("Take Image")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.aiCamera.toggle_camera_mode()
if("View Images")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.aiCamera.viewpictures()
if("Set Sensor Augmentation")
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.sensor_mode()
else
return 0
return 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()

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++

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()
@@ -258,6 +258,9 @@ datum/controller/vote
log_vote(text)
world << "<font color='purple'><b>[text]</b>\nType <b>vote</b> or click <a href='?src=\ref[src]'>here</a> to place your votes.\nYou have [config.vote_period/10] seconds to vote.</font>"
for(var/client/C in clients)
if(C.prefs.asfx_togs & ASFX_VOTE) //Personal mute
C << sound('sound/effects/vote.ogg')
switch(vote_type)
if("crew_transfer")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
@@ -392,4 +395,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")

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"

View File

@@ -1220,6 +1220,32 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
access = access_hydroponics
group = "Hydroponics"
/datum/supply_packs/aliengloves
name = "Non-Human Glove Kit"
contains = list(/obj/item/clothing/gloves/yellow/specialt,
/obj/item/clothing/gloves/yellow/specialt,
/obj/item/clothing/gloves/yellow/specialt,
/obj/item/clothing/gloves/yellow/specialu,
/obj/item/clothing/gloves/yellow/specialu,
/obj/item/clothing/gloves/yellow/specialu)
cost = 25
containertype = /obj/structure/closet/crate
containername = "speciality gloves kit"
group = "Supply"
/datum/supply_packs/alienmedicalgloves
name = "Non-Human Sterile Glove Kit"
contains = list(/obj/item/clothing/gloves/latex/unathi,
/obj/item/clothing/gloves/latex/unathi,
/obj/item/clothing/gloves/latex/unathi,
/obj/item/clothing/gloves/latex/tajara,
/obj/item/clothing/gloves/latex/tajara,
/obj/item/clothing/gloves/latex/tajara)
cost = 25
containertype = /obj/structure/closet/crate
containername = "speciality sterile gloves kit"
group = "Medical"
/datum/supply_packs/cardboard_sheets
contains = list(/obj/item/stack/material/cardboard)
name = "50 cardboard sheets"

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."),

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"

View File

@@ -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()

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

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())))

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)
@@ -187,10 +199,15 @@
pending_antagonists -= player
add_antagonist(player,0,0,1)
//Resets all pending_antagonists, clearing their special_role (and assigned_role if ANTAG_OVERRIDE_JOB is set)
/datum/antagonist/proc/reset()
reset_antag_selection()
//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()

View File

@@ -16,6 +16,7 @@
create_objectives(target)
update_icons_added(target)
greet(target)
if(!gag_announcement)
announce_antagonist_spawn()
/datum/antagonist/proc/create_default(var/mob/source)

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))
/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

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)

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)

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)

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

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

View File

@@ -73,13 +73,13 @@ 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()

View File

@@ -234,6 +234,10 @@ var/list/mob/living/forced_ambiance_list = new
L.update_floating( L.Check_Dense_Object() )
L.lastarea = newarea
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(!(L && L.client && (L.client.prefs.asfx_togs & ASFX_AMBIENCE))) return
play_ambience(L)
/area/proc/play_ambience(var/mob/living/L)
@@ -285,4 +289,3 @@ var/list/mob/living/forced_ambiance_list = new
H.AdjustStunned(1)
H.AdjustWeakened(1)
mob << "<span class='notice'>The sudden appearance of gravity makes you fall to the floor!</span>"

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

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

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

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()
..()

View File

@@ -11,15 +11,14 @@
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()

View File

@@ -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

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

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()

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

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,10 +226,6 @@ 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
@@ -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()

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
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(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.")
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

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

View File

@@ -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"

View File

@@ -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")

View File

@@ -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

View File

@@ -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))

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

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)

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:"

View File

@@ -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:"

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

View File

@@ -10,7 +10,8 @@
selection_color = "#dddddd"
access = list() //See /datum/job/assistant/get_access()
minimal_access = list() //See /datum/job/assistant/get_access()
alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Visitor")
//alt_titles = list("Technical Assistant","Medical Intern","Research Assistant","Security Cadet", "Visitor")
alt_titles = list("Visitor")
/datum/job/assistant/equip(var/mob/living/carbon/human/H)
if(!H) return 0

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

View File

@@ -31,6 +31,11 @@
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/head_of_security(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/heads/hos(H), slot_belt)
if(H.species.name == "Tajaran")
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/tajara(H), slot_gloves)
if(H.species.name == "Unathi")
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/unathi(H), slot_gloves)
else
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
// H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses)
@@ -68,6 +73,11 @@
H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/warden(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/jackboots(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/warden(H), slot_belt)
if(H.species.name == "Tajaran")
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/tajara(H), slot_gloves)
if(H.species.name == "Unathi")
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/unathi(H), slot_gloves)
else
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses/sechud(H), slot_glasses)
// H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas(H), slot_wear_mask) //Grab one from the armory you donk
@@ -106,6 +116,11 @@
H.equip_to_slot_or_del(new /obj/item/clothing/under/det(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/brown(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/device/pda/detective(H), slot_belt)
if(H.species.name == "Tajaran")
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/tajara(H), slot_gloves)
if(H.species.name == "Unathi")
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black/unathi(H), slot_gloves)
else
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/black(H), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/weapon/flame/lighter/zippo(H), slot_l_store)
if(H.backbag == 1)//Why cant some of these things spawn in his office?

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()

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

View File

@@ -11,6 +11,8 @@ var/const/ENGINEER =(1<<6)
var/const/ATMOSTECH =(1<<7)
var/const/AI =(1<<8)
var/const/CYBORG =(1<<9)
var/const/INTERN_SEC =(1<<10)
var/const/INTERN_ENG =(1<<11)
var/const/MEDSCI =(1<<1)
@@ -26,7 +28,8 @@ var/const/PSYCHIATRIST =(1<<7)
var/const/ROBOTICIST =(1<<8)
var/const/XENOBIOLOGIST =(1<<9)
var/const/PARAMEDIC =(1<<10)
var/const/INTERN_MED =(1<<11)
var/const/INTERN_SCI =(1<<12)
var/const/CIVILIAN =(1<<2)
@@ -64,6 +67,7 @@ var/list/engineering_positions = list(
"Chief Engineer",
"Station Engineer",
"Atmospheric Technician",
"Engineering Apprentice"
)
@@ -73,7 +77,8 @@ var/list/medical_positions = list(
"Geneticist",
"Psychiatrist",
"Chemist",
"Paramedic"
"Paramedic",
"Nursing Intern"
)
@@ -82,7 +87,8 @@ var/list/science_positions = list(
"Scientist",
"Geneticist", //Part of both medical and science
"Roboticist",
"Xenobiologist"
"Xenobiologist",
"Lab Assistant"
)
//BS12 EDIT
@@ -106,7 +112,8 @@ var/list/security_positions = list(
"Head of Security",
"Warden",
"Detective",
"Security Officer"
"Security Officer",
"Security Cadet"
)
@@ -140,3 +147,5 @@ var/list/nonhuman_positions = list(
titles = J.alt_titles
return titles
//Mahzel : Job preview not added because code don't exist in BS12

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>"

View File

@@ -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

View File

@@ -140,9 +140,19 @@
if(weld(W, user))
if(assembly)
assembly.loc = src.loc
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
assembly = null //so qdel doesn't eat it.
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.
qdel(src)
// OTHER

View File

@@ -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)

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
..()

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"])]))

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)

View File

@@ -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"])]))

View File

@@ -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)

View File

@@ -38,15 +38,13 @@
/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)
if(istype(W,/obj/item/weapon/card))
var/obj/item/weapon/card/I = W
if(reimburse(I))
if(vendmode == 3 && I)
if(reimburse_id(I, W))
vendmode = 0
if(vendmode == 0)
if(istype(W, /obj/item/device/laptop))
@@ -210,10 +208,8 @@
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>")
/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>"
@@ -225,7 +221,7 @@
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>"
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
else
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
else
@@ -361,10 +357,8 @@
/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>")
/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>"
@@ -377,7 +371,7 @@
transfer_and_reimburse(D)
return 1
else
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
return 0
else
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"

View File

@@ -30,7 +30,7 @@
var/hasShocked = 0 //Prevents multiple shocks from happening
var/secured_wires = 0
var/datum/wires/airlock/wires = null
var/obj/item/device/magnetic_lock/bracer = null
var/open_sound_powered = 'sound/machines/airlock.ogg'
var/open_sound_unpowered = 'sound/machines/airlock_creaking.ogg'
@@ -481,7 +481,6 @@ About the new airlock wires panel:
else
return 0
/obj/machinery/door/airlock/update_icon()
if(overlays) overlays.Cut()
if(density)
@@ -728,10 +727,10 @@ About the new airlock wires panel:
else if (activate && !src.lights)
lights = 1
usr << "The door bolt lights have been enabled."
update_icon()
return 1
/obj/machinery/door/airlock/attackby(C as obj, mob/user as mob)
//world << text("airlock attackby src [] obj [] mob []", src, C, user)
if(!istype(usr, /mob/living/silicon))
@@ -740,8 +739,14 @@ About the new airlock wires panel:
return
if(istype(C, /obj/item/device/detective_scanner) || istype(C, /obj/item/taperoll))
return
src.add_fingerprint(user)
if (istype(C, /obj/item/device/magnetic_lock))
if (bracer)
user << "<span class='notice'>There is already a [bracer] on [src]!</span>"
return
var/obj/item/device/magnetic_lock/newbracer = C
newbracer.attachto(src, user)
return
if(!repairing && (istype(C, /obj/item/weapon/weldingtool) && !( src.operating > 0 ) && src.density))
var/obj/item/weapon/weldingtool/W = C
if(W.remove_fuel(0,user))
@@ -792,16 +797,13 @@ About the new airlock wires panel:
da.state = 1
da.created_name = src.name
da.update_state()
if(operating == -1 || (stat & BROKEN))
new /obj/item/weapon/circuitboard/broken(src.loc)
operating = 0
else
if (!electronics) create_electronics()
electronics.loc = src.loc
electronics = null
qdel(src)
return
else if(arePowerSystemsOn())
@@ -819,6 +821,7 @@ About the new airlock wires panel:
user << "<span class='notice'>The airlock's bolts prevent it from being forced.</span>"
else if( !welded && !operating )
if(density)
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(F.wielded)
spawn(0) open(1)
@@ -830,7 +833,6 @@ About the new airlock wires panel:
spawn(0) close(1)
else
user << "<span class='warning'>You need to be wielding \the [C] to do that.</span>"
else
..()
return
@@ -852,12 +854,12 @@ About the new airlock wires panel:
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
update_icon()
return
/obj/machinery/door/airlock/open(var/forced=0)
if(!can_open(forced))
return 0
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
@@ -875,7 +877,9 @@ About the new airlock wires panel:
if(!forced)
if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR))
return 0
if (bracer)
visible_message("<span class='notice'>[src]'s actuators whirr, but the door does not open.</span>")
return 0
if(locked || welded)
return 0
return ..()
@@ -883,12 +887,10 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/can_close(var/forced=0)
if(locked || welded)
return 0
if(!forced)
//despite the name, this wire is for general door control.
if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR))
return 0
return ..()
/atom/movable/proc/blocks_airlock()
@@ -941,22 +943,20 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/close(var/forced=0)
if(!can_close(forced))
return 0
if(safe)
for(var/turf/turf in locs)
for(var/atom/movable/AM in turf)
if(AM.blocks_airlock())
if(world.time > next_beep_at)
playsound(src.loc, 'sound/machines/buzz-two.ogg', 50, 0)
next_beep_at = world.time + SecondsToTicks(10)
close_door_at = world.time + 6
return
for(var/turf/turf in locs)
for(var/atom/movable/AM in turf)
if(AM.airlock_crush(DOOR_CRUSH_DAMAGE))
take_damage(DOOR_CRUSH_DAMAGE)
use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
if(arePowerSystemsOn())
playsound(src.loc, open_sound_powered, 100, 1)
@@ -972,9 +972,7 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/proc/lock(var/forced=0)
if(locked)
return 0
if (operating && !forced) return 0
src.locked = 1
for(var/mob/M in range(1,src))
M.show_message("You hear a click from the bottom of the door.", 2)
@@ -984,10 +982,8 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/proc/unlock(var/forced=0)
if(!src.locked)
return
if (!forced)
if(operating || !src.arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS)) return
src.locked = 0
for(var/mob/M in range(1,src))
M.show_message("You hear a click from the bottom of the door.", 2)
@@ -1067,8 +1063,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)
..()
@@ -1081,6 +1077,8 @@ About the new airlock wires panel:
update_icon()
/obj/machinery/door/airlock/proc/prison_open()
if (bracer)
return
src.unlock()
src.open()
src.lock()

View File

@@ -26,7 +26,10 @@
var/timing = 1 // boolean, true/1 timer is on, false/0 means it's not timing
var/picture_state // icon_state of alert picture, if not displaying text/numbers
var/list/obj/machinery/targets = list()
var/list/obj/item/clothing/under/color/orange/uniforms = list()
var/timetoset = 0 // Used to set releasetime upon starting the timer
var/alerted = 0
var/spamcheck = 0
maptext_height = 26
maptext_width = 32
@@ -47,6 +50,10 @@
if(C.id == src.id)
targets += C
for(var/obj/item/clothing/under/color/orange/D in world)
if(D.id == id)
uniforms += D
if(targets.len==0)
stat |= BROKEN
update_icon()
@@ -68,6 +75,8 @@
if(timeleft > 1e5)
src.releasetime = 0
if(timeleft < 30 && !alerted)
alertuniforms()
if(world.timeofday > src.releasetime)
src.timer_end() // open doors, reset timer, clear status screen
@@ -152,6 +161,35 @@
/obj/machinery/door_timer/attack_ai(var/mob/user as mob)
return src.attack_hand(user)
// Alert the uniform wearers that their timer is about to end up
/obj/machinery/door_timer/proc/alertuniforms()
if(stat & (NOPOWER|BROKEN)) return
if(!uniforms.len)
alerted = 1
return
for(var/obj/item/clothing/under/color/orange/D in uniforms)
if(!ishuman(D.loc)) continue
D.loc << "A speaker in the collar of your suit pings:\n\blue Your cell timer will expire in 30 seconds or less. Please go to your cell to speed up processing."
alerted = 1
return
// Alert the uniform wearers that they are needed at their cell
/obj/machinery/door_timer/proc/summonuniforms()
if(stat & (NOPOWER|BROKEN)) return
if(spamcheck) return
if(!uniforms.len) return
for(var/obj/item/clothing/under/color/orange/D in uniforms)
if(!ishuman(D.loc)) continue
D.loc << "A speaker in the collar of your suit pings:\n\red You have been summoned to your cell!"
spamcheck = 1
spawn(30)
spamcheck = 0
return
//Allows humans to use door_timer
//Opens dialog window when someone clicks on door timer
@@ -249,7 +287,8 @@
if(href_list["change"])
src.timer_start()
if(href_list["summon"])
summonuniforms()
src.add_fingerprint(usr)
src.updateUsrDialog()
src.update_icon()

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

View File

@@ -106,6 +106,15 @@
move_into_gibber(user,G.affecting)
// Grab() process should clean up the grab item, no need to del it.
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/M = user
if(M.h_style == "Floorlength Braid" || M.h_style == "Very Long Hair")
if(prob(10))
M.apply_damage(30, BRUTE, "head")
M.apply_damage(45, HALLOSS)
M.visible_message("\red [user]'s hair catches in the [src]!", "\red Your hair gets caught in the [src]!")
M.say("*scream")
/obj/machinery/gibber/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.restrained())
return
@@ -235,5 +244,3 @@
thing.throw_at(get_edge_target_turf(src,gib_throw_dir),rand(0,3),emagged ? 100 : 50) // Being pelted with bits of meat and bone would hurt.
update_icon()

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 ..()

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"]

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

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)

View File

@@ -553,6 +553,14 @@
/obj/machinery/mecha_part_fabricator/attack_hand(mob/user as mob)
var/dat, left_part
if(istype(user, /mob/living/carbon/human))
var/mob/living/carbon/human/M = user
if(M.h_style == "Floorlength Braid" || M.h_style == "Very Long Hair")
if(prob(10))
M.apply_damage(30, BRUTE, "head")
M.apply_damage(45, HALLOSS)
M.visible_message("\red [user]'s hair catches in the [src]!", "\red Your hair gets caught in the [src]!")
M.say("*scream")
if (..())
return
if(!operation_allowed(user))
@@ -851,3 +859,42 @@
else
user << "The fabricator cannot hold more [sname]."
return
/obj/machinery/mecha_part_fabricator/MouseDrop_T(mob/living/carbon/human/target as mob, mob/user as mob)
if (!istype(target) || target.buckled || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
return
if(target == user)
if(target.h_style == "Floorlength Braid" || target.h_style == "Very Long Hair")
user.visible_message("\blue [user] looks like they're about to feed their own hair into the [src], but think better of it.", "\blue You grasp your hair and are about to feed it into the [src], but stop and come to your sense.")
return
src.add_fingerprint(user)
var/target_loc = target.loc
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
if(target.h_style != "Cut Hair" || target.h_style != "Short Hair" || target.h_style != "Skinhead" || target.h_style != "Buzzcut" || target.h_style != "Crewcut" || target.h_style != "Bald" || target.h_style != "Balding Hair")
user.visible_message("\red [user] starts feeding [target]'s hair into the [src]!", "\red You start feeding [target]'s hair into the [src]!")
if(!do_after(usr, 50))
return
if(target_loc != target.loc)
return
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
user.visible_message("\red [user] feeds the [target]'s hair into the [src] and flicks it on!", "\red You turn the [src] on!")
target.apply_damage(30, BRUTE, "head")
target.apply_damage(25, HALLOSS)
target.say("*scream")
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Has fed [target.name]'s ([target.ckey]) hair into a [src].</font>")
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has had their hair fed into [src] by [user.name] ([user.ckey])</font>")
msg_admin_attack("[key_name_admin(user.ckey)] fed [key_name_admin(target)] in a [src]. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)")
else
return
if(!do_after(usr, 35))
return
if(target_loc != target.loc)
return
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
user.visible_message("\red [user] starts tugging on [target]'s head as the [src] keeps running!", "\red You start tugging on [target]'s head!")
target.apply_damage(25, BRUTE, "head")
target.apply_damage(10, HALLOSS)
target.say("*scream")
spawn(10)
user.visible_message("\red [user] stops the [src] and leaves [target] resting as they are.", "\red You turn the [src] off and let go of [target].")

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

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

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(var/newloc, smoke_duration, turf/dest_turf = null, icon/cached_icon = null)
time_to_live = smoke_duration
/obj/effect/effect/smoke/chem/New()
..()
create_reagents(500)
return
create_reagents(500)
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.

View File

@@ -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

View File

@@ -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
timer
btype = 2
var/assembly_type = /obj/item/device/assembly/signaler
syndicate
//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
proximity
btype = 1
/obj/effect/spawner/newbomb/timer
name = "TTV bomb - timer"
assembly_type = /obj/item/device/assembly/timer
radio
btype = 0
/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
/obj/effect/spawner/newbomb/proximity
name = "TTV bomb - proximity"
assembly_type = /obj/item/device/assembly/prox_sensor
/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

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

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]")

View File

@@ -18,9 +18,11 @@
/obj/item/device/chameleon/dropped()
disrupt()
..()
/obj/item/device/chameleon/equipped()
disrupt()
..()
/obj/item/device/chameleon/attack_self()
toggle()

View File

@@ -68,6 +68,24 @@
if(safety <= 0)
M.Weaken(10)
flick("e_flash", M.flash)
//Vaurca damage 15/01/16
var/mob/living/carbon/human/H = M
if(H.species.flags & IS_BUG)
var/obj/item/organ/eyes/E = H.internal_organs_by_name["eyes"]
if(!E)
return
usr << "\red Your eyes burn with the intense light of the flash!."
E.damage += rand(10, 11)
if(E.damage > 12)
M.eye_blurry += rand(3,6)
if (E.damage >= E.min_broken_damage)
M.sdisabilities |= BLIND
else if (E.damage >= E.min_bruised_damage)
M.eye_blind = 5
M.eye_blurry = 5
M.disabilities |= NEARSIGHTED
spawn(100)
M.disabilities &= ~NEARSIGHTED
if(ishuman(M) && ishuman(user) && M.stat!=DEAD)
if(user.mind && user.mind in revs.current_antagonists)

View File

@@ -0,0 +1,323 @@
#define STATUS_INACTIVE 0
#define STATUS_ACTIVE 1
#define STATUS_BROKEN 2
#define LAYER_ATTACHED 3.2
#define LAYER_NORMAL 3
/obj/item/device/magnetic_lock
name = "magnetic door lock"
desc = "A large, ID locked device used for completely locking down airlocks."
icon = 'icons/obj/magnetic_locks/centcom.dmi'
icon_state = "inactive"
w_class = 3
req_access = list(103)
health = 90
var/department = "CENTCOM"
var/status = 0
var/constructionstate = 0
var/drainamount = 20
var/obj/machinery/door/airlock/target = null
var/obj/item/weapon/cell/powercell
/obj/item/device/magnetic_lock/security
icon = 'icons/obj/magnetic_locks/security.dmi'
department = "Security"
req_access = list(1)
/obj/item/device/magnetic_lock/engineering
icon = 'icons/obj/magnetic_locks/engineering.dmi'
department = "Engineering"
req_access = null
req_one_access = list(11, 24)
/obj/item/device/magnetic_lock/New()
..()
powercell = new /obj/item/weapon/cell/high()
/obj/item/device/magnetic_lock/examine()
..()
if (status == STATUS_BROKEN)
usr << "<span class='danger'>It looks broken!</span>"
else
if (powercell)
var/power = round(powercell.charge / powercell.maxcharge * 100)
usr << "\blue The powercell is at [power]% charge."
else
usr << "\red It has no powercell to power it!"
/obj/item/device/magnetic_lock/attack_hand(var/mob/user)
if (status == STATUS_ACTIVE)
ui_interact(user)
else
..()
/obj/item/device/magnetic_lock/bullet_act(var/obj/item/projectile/Proj)
takedamage(Proj.damage)
..()
/obj/item/device/magnetic_lock/attackby(var/obj/item/I, var/mob/user)
if (status == STATUS_BROKEN)
user << "<span class='danger'>[src] is broken beyond repair!</span>"
return
if (istype(I, /obj/item/weapon) && user.a_intent == "hurt")
if (I.force >= 8)
user.visible_message("<span class='danger'>[user] bashes [src] with [I]!</span>", "<span class='danger'>You strike [src] with [I], damaging it!</span>")
takedamage(I.force)
return
else
user.visible_message("<span class='notice'>[user] hits [src] with [I] to no visible effect.</span>", "<span class='notice'>You hit [src] with [I], but it appears to have no effect.</span>")
return
switch (constructionstate)
if (0)
if (istype(I, /obj/item/weapon/card/emag))
var/obj/item/weapon/card/emag/emagcard = I
emagcard.uses--
visible_message("<span class='danger'>[src] sparks and falls off the door!</span>", "<span class='danger'>You emag [src], frying its circuitry[status == STATUS_ACTIVE ? " and making it drop onto the floor" : ""]!</span>")
setstatus(STATUS_BROKEN)
return
if (status == STATUS_ACTIVE && istype(I, /obj/item/weapon/card/id))
if (check_access(I) && !constructionstate)
user << "<span class='notice'>You swipe your [I] through [src], making it drop onto the floor with a thud.</span>"
setstatus(STATUS_INACTIVE)
return
else if (constructionstate)
user << "<span class='danger'>You cannot swipe your [I] through [src] with it partially dismantled!</span>"
return
else
user << "<span class='danger'>A red light flashes on [src] as you swipe your [I] through it.</span>"
flick("deny",src)
return
if (istype(I, /obj/item/weapon/screwdriver))
user << "<span class='notice'>You unfasten and remove the plastic cover from [src], revealing a thick metal shell.</span>"
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
setconstructionstate(1)
return
if (1)
if (istype(I, /obj/item/weapon/screwdriver))
user << "<span class='notice'>You put the metal cover of back onto [src], and screw it tight.</span>"
playsound(loc, 'sound/items/Screwdriver.ogg', 50, 1)
setconstructionstate(0)
return
if (istype(I, /obj/item/weapon/cell))
user.drop_item()
I.loc = src
powercell = I
return
if (istype(I, /obj/item/weapon/crowbar))
user << "<span class='notice'>You remove \the [powercell] from \the [src].</span>"
powercell.loc = loc
powercell = null
return
if (istype(I, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = I
if (WT.remove_fuel(1, user))
user.visible_message("<span class='notice'>[user] starts welding through the metal shell of [src].</span>", "<span class='notice'>You start welding through the metal covering of [src]</span>")
playsound(loc, 'sound/items/Welder.ogg', 50, 1)
if (do_after(user, 25))
user << "<span class='notice'>You are able to weld through the metal shell of [src].</span>"
setconstructionstate(2)
return
if (2)
if (istype(I, /obj/item/weapon/crowbar))
user << "<span class='notice'>You pry off the metal covering from [src].</span>"
playsound(loc, 'sound/items/Crowbar.ogg', 50, 1)
setconstructionstate(3)
return
if (3)
if (istype(I, /obj/item/weapon/wirecutters))
user << "<span class='notice'>You cut the wires connecting the [src]'s magnets to their powersupply, [target ? "making the device fall off [target] and rendering it unusable." : "rendering the device unusable."]</span>"
playsound(loc, 'sound/items/Wirecutter.ogg', 50, 1)
setconstructionstate(4)
return
/obj/item/device/magnetic_lock/process()
if (powercell && powercell.charge > drainamount)
powercell.charge -= drainamount
else
if (powercell)
powercell.charge = 0
visible_message("<span class='danger'>[src] beeps loudly and falls off \the [target]; its powercell having run out of power.</span>")
setstatus(STATUS_INACTIVE)
/obj/item/device/magnetic_lock/proc/attachto(var/obj/machinery/door/airlock/newtarget, var/mob/user as mob)
if (status == STATUS_BROKEN)
user << "<span class='danger'>[src] is damaged beyond repair! It cannot be used!</span>"
return
if (!newtarget.density || newtarget.operating)
user << "<span class='danger'>[newtarget] must be closed before you can attach [src] to it!</span>"
return
if (newtarget.p_open)
user << "<span class='danger'>You must close [newtarget]'s maintenance panel before attaching [src] to it!</span>"
return
user.visible_message("<span class='notice'>[user] starts mounting [src] onto [newtarget].</span>", "<span class='notice'>You begin mounting [src] onto [newtarget].</span>")
if (do_after(user, 35, 1))
if (status == STATUS_BROKEN)
user << "<span class='danger'>[src] is damaged beyond repair! It cannot be used!</span>"
return
if (!newtarget.density)
user << "<span class='danger'>[newtarget] must be closed before you can attach [src] to it!</span>"
return
if (newtarget.p_open)
user << "<span class='danger'>You must close [newtarget]'s maintenance panel before attaching [src] to it!</span>"
return
user.visible_message("<span class='notice'>[user] attached [src] onto [newtarget] and flicks it on. The magnetic lock now seals [newtarget].</span>", "<span class='notice'>You attached [src] onto [newtarget] and switched on the magnetic lock.</span>")
user.drop_item()
setstatus(STATUS_ACTIVE, newtarget)
return
/obj/item/device/magnetic_lock/proc/setstatus(var/newstatus, var/obj/machinery/door/airlock/newtarget as obj)
switch (newstatus)
if (STATUS_INACTIVE)
if (status != STATUS_ACTIVE)
return
if (!target)
return
detach()
icon_state = "inactive"
status = newstatus
if (STATUS_ACTIVE)
if (status != STATUS_INACTIVE)
return
if (!newtarget)
return
attach(newtarget)
icon_state = "active"
status = newstatus
if (STATUS_BROKEN)
spark()
if (target)
var/playflick = 1
if (constructionstate)
playflick = 0
detach(playflick)
icon_state = "broken"
status = newstatus
/obj/item/device/magnetic_lock/proc/setconstructionstate(var/newstate)
constructionstate = newstate
if (newstate == 0)
if (status == STATUS_ACTIVE)
icon_state = "active"
else
icon_state = "inactive"
else if (newstate == 2)
flick("deconstruct_2_anim", src)
else if (newstate == 4)
setstatus(STATUS_BROKEN)
else
icon_state = "deconstruct_[constructionstate]"
/obj/item/device/magnetic_lock/proc/detach(var/playflick = 1)
if (target)
if (playflick)
spawn(-15) flick("release", src)
adjustsprite(null)
layer = LAYER_NORMAL
target.bracer = null
processing_objects.Remove(src)
anchored = 0
/obj/item/device/magnetic_lock/proc/attach(var/obj/machinery/door/airlock/newtarget as obj)
adjustsprite(newtarget)
layer = LAYER_ATTACHED
flick("deploy", src)
newtarget.bracer = src
target = newtarget
processing_objects.Add(src)
anchored = 1
/obj/item/device/magnetic_lock/proc/adjustsprite(var/obj/target as obj)
if (target)
switch (get_dir(src, target))
if (NORTH)
pixel_x = 0
pixel_y = 32
if (NORTHEAST)
pixel_x = 32
pixel_y = 32
if (EAST)
pixel_x = 32
pixel_y = 0
if (SOUTHEAST)
pixel_x = 32
pixel_y = -32
if (SOUTH)
pixel_x = 0
pixel_y = -32
if (SOUTHWEST)
pixel_x = -32
pixel_y = -32
if (WEST)
pixel_x = -32
pixel_y = 0
if (NORTHWEST)
pixel_x = -32
pixel_y = 32
else
pixel_x = 0
pixel_y = 0
/obj/item/device/magnetic_lock/proc/takedamage(var/damage)
health -= damage
if (damage >= 40 && prob(50))
health = 0
if (health <= 0)
visible_message("<span class='danger'>[src] sparks[target ? " and falls off of \the [target]!" : "!"] It is now completely unusable!</span>")
setstatus(STATUS_BROKEN)
return
if (prob(50))
spark()
/obj/item/device/magnetic_lock/proc/spark()
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
if (target)
s.set_up(5, 1, target)
else
s.set_up(5, 1, src)
s.start()
spawn(5)
del(s)
#undef STATUS_INACTIVE
#undef STATUS_ACTIVE
#undef STATUS_BROKEN
#undef LAYER_ATTACHED
#undef LAYER_NORMAL

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)
..()

View File

@@ -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,29 +140,51 @@
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
it explodes properly when it gets a signal (and it does).
*/
/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,15 +210,10 @@
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()
// this doesn't do anything but the timer etc. expects it to be here

View File

@@ -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

View File

@@ -0,0 +1,17 @@
/obj/item/shoe_cover
name = "strange fabric"
desc = "A fabirc that allows for silent walking."
icon = 'icons/obj/items.dmi'
icon_state = "sheet-cloth"
/obj/item/shoe_cover/afterattack(var/obj/A as obj, mob/user as mob, proximity)
if(!proximity)
return
if (istype(A, /obj/item/clothing/shoes) && get_dist(src,A) <= 1)
var/obj/item/clothing/shoes/S = A
user << "You attahed the [src] to [S] making movement silent"
S.silent = 1
S.desc += " They appear to have some type of fabric soles"
user.drop_from_inventory(src)
del(src)

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