Merge branch 'master' into cleanupTwo

This commit is contained in:
Kelenius
2016-04-21 11:41:32 +03:00
386 changed files with 7149 additions and 4820 deletions

View File

@@ -10,6 +10,7 @@
anchored = 1
use_power = 0
idle_power_usage = 5 // 5 Watts for thermostat related circuitry
circuit = /obj/item/weapon/circuitboard/unary_atmos/cooler
var/heatsink_temperature = T20C // The constant temperature reservoir into which the freezer pumps heat. Probably the hull of the station or something.
var/internal_volume = 600 // L
@@ -24,7 +25,6 @@
..()
initialize_directions = dir
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/unary_atmos/cooler(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)

View File

@@ -10,6 +10,7 @@
anchored = 1
use_power = 0
idle_power_usage = 5 //5 Watts for thermostat related circuitry
circuit = /obj/item/weapon/circuitboard/unary_atmos/heater
var/max_temperature = T20C + 680
var/internal_volume = 600 //L
@@ -25,7 +26,6 @@
initialize_directions = dir
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/unary_atmos/heater(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)

View File

@@ -0,0 +1,3 @@
// Consider these images/atoms as part of the UI/HUD
#define APPEARANCE_UI_IGNORE_ALPHA RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA
#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR

View File

@@ -25,26 +25,6 @@
#define PROCESS_KILL 26 // Used to trigger removal from a processing list.
#define MAX_GEAR_COST 10 // Used in chargen for accessory loadout limit.
// Preference toggles.
#define SOUND_ADMINHELP 0x1
#define SOUND_MIDI 0x2
#define SOUND_AMBIENCE 0x4
#define SOUND_LOBBY 0x8
#define CHAT_OOC 0x10
#define CHAT_DEAD 0x20
#define CHAT_GHOSTEARS 0x40
#define CHAT_GHOSTSIGHT 0x80
#define CHAT_PRAYER 0x100
#define CHAT_RADIO 0x200
#define CHAT_ATTACKLOGS 0x400
#define CHAT_DEBUGLOGS 0x800
#define CHAT_LOOC 0x1000
#define CHAT_GHOSTRADIO 0x2000
#define SHOW_TYPING 0x4000
#define CHAT_NOICONS 0x8000
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_ATTACKLOGS|CHAT_LOOC)
// For secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list of humans.
#define HEALTH_HUD 1 // A simple line rounding the mob's number health.
#define STATUS_HUD 2 // Alive, dead, diseased, etc.

View File

@@ -0,0 +1,4 @@
#define ASCII_ESC ascii2text(27)
#define ASCII_RED "[ASCII_ESC]\[31m"
#define ASCII_GREEN "[ASCII_ESC]\[32m"
#define ASCII_RESET "[ASCII_ESC]\[0m"

View File

@@ -244,7 +244,7 @@
var/turf/ear = get_turf(M)
if(ear)
// Ghostship is magic: Ghosts can hear radio chatter from anywhere
if(speaker_coverage[ear] || (istype(M, /mob/observer/dead) && (M.client) && (M.client.prefs.toggles & CHAT_GHOSTRADIO)))
if(speaker_coverage[ear] || (istype(M, /mob/observer/dead) && M.is_preference_enabled(/datum/client_preference/ghost_radio)))
. |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down.
return .

View File

@@ -78,7 +78,13 @@ var/global/list/socks_t = list(
"Black knee" = "black_knee", "Black thigh" = "black_thigh", "Thin knee" = "thin_knee",
"Thin thigh" = "thin_thigh", "Pantyhose" = "pantyhose", "Striped thigh" = "striped_thigh",
"Striped knee" = "striped_knee", "Rainbow knee" = "rainbow_knee", "Rainbow thigh" = "rainbow_thigh",
"Fishnets" = "fishnet", "Thin white thigh" = "thinwhite_thigh", "Thin white knee" = "thinwhite_knee", "None")
"Fishnets" = "fishnet", "Thin white thigh" = "thinwhite_thigh", "Thin white knee" = "thinwhite_knee",
"Green striped thigh" = "gstriped_thigh", "Green striped knee" = "gstriped_knee",
"Purple striped thigh" = "pstriped_thigh", "Purple striped knee" = "pstriped_knee",
"Blue striped thigh" = "bstriped_thigh", "Blue striped knee" = "bstriped_knee",
"Yellow striped thigh" = "ystriped_thigh", "Yellow striped knee" = "ystriped_knee",
"Red striped thigh" = "rstriped_thigh", "Red striped knee" = "rstriped_knee",
"Orange striped thigh" = "ostriped_thigh", "Orange striped knee" = "ostriped_knee", "None")
//Backpacks
var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Alt")

View File

@@ -30,13 +30,6 @@
return "[output][and_text][input[index]]"
/proc/ConvertReqString2List(var/list/source_list)
var/list/temp_list = params2list(source_list)
for(var/O in temp_list)
temp_list[O] = text2num(temp_list[O])
return temp_list
//Returns list element or null. Should prevent "index out of bounds" error.
proc/listgetindex(var/list/list,index)
if(istype(list) && list.len)

View File

@@ -31,7 +31,7 @@
diary << "\[[time_stamp()]]DEBUG: [text][log_end]"
for(var/client/C in admins)
if(C.prefs.toggles & CHAT_DEBUGLOGS)
if(C.is_preference_enabled(/datum/client_preference/debug/show_debug_logs))
C << "DEBUG: [text]"
@@ -82,6 +82,9 @@
/proc/log_misc(text)
diary << "\[[time_stamp()]]MISC: [text][log_end]"
/proc/log_unit_test(text)
world.log << "## UNIT_TEST: [text]"
//pretty print a direction bitflag, can be useful for debugging.
/proc/print_dir(var/dir)
var/list/comps = list()
@@ -91,7 +94,7 @@
if(dir & WEST) comps += "WEST"
if(dir & UP) comps += "UP"
if(dir & DOWN) comps += "DOWN"
return english_list(comps, nothing_text="0", and_text="|", comma_text="|")
//more or less a logging utility

View File

@@ -30,13 +30,10 @@ proc/random_hair_style(gender, species = "Human")
var/list/valid_hairstyles = list()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if(gender != NEUTER && gender != PLURAL)
if(gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
continue
if(gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
continue
if( !(species in S.species_allowed))
continue
valid_hairstyles[hairstyle] = hair_styles_list[hairstyle]
@@ -52,13 +49,10 @@ proc/random_facial_hair_style(gender, species = "Human")
var/list/valid_facialhairstyles = list()
for(var/facialhairstyle in facial_hair_styles_list)
var/datum/sprite_accessory/S = facial_hair_styles_list[facialhairstyle]
if(gender != NEUTER && gender != PLURAL)
if(gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
continue
if(gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
continue
if( !(species in S.species_allowed))
continue
@@ -171,3 +165,88 @@ Proc for attack log creation, because really why not
return 0
var/mob/living/silicon/robot/R = thing.loc
return (thing in R.module.modules)
/proc/get_exposed_defense_zone(var/atom/movable/target)
var/obj/item/weapon/grab/G = locate() in target
if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people.
return pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg")
else
return pick("chest", "groin")
/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1)
if(!user || !target)
return 0
var/user_loc = user.loc
var/target_loc = target.loc
var/holding = user.get_active_hand()
var/datum/progressbar/progbar
if (progress)
progbar = new(user, time, target)
var/endtime = world.time+time
var/starttime = world.time
. = 1
while (world.time < endtime)
sleep(1)
if (progress)
progbar.update(world.time - starttime)
if(!user || !target)
. = 0
break
if(uninterruptible)
continue
if(!user || user.incapacitated() || user.loc != user_loc)
. = 0
break
if(target.loc != target_loc)
. = 0
break
if(user.get_active_hand() != holding)
. = 0
break
if (progbar)
qdel(progbar)
/proc/do_after(mob/user, delay, atom/target = null, needhand = 1, progress = 1, var/incapacitation_flags = INCAPACITATION_DEFAULT)
if(!user)
return 0
var/atom/target_loc = null
if(target)
target_loc = target.loc
var/atom/original_loc = user.loc
var/holding = user.get_active_hand()
var/datum/progressbar/progbar
if (progress)
progbar = new(user, delay, target)
var/endtime = world.time + delay
var/starttime = world.time
. = 1
while (world.time < endtime)
sleep(1)
if (progress)
progbar.update(world.time - starttime)
if(!user || user.incapacitated(incapacitation_flags) || user.loc != original_loc)
. = 0
break
if(target_loc && (!target || target_loc != target.loc))
. = 0
break
if(needhand)
if(user.get_active_hand() != holding)
. = 0
break
if (progbar)
qdel(progbar)

View File

@@ -161,7 +161,7 @@ var/syndicate_code_response//Code response for traitors.
Obviously, some people will be better at this than others but in theory, everyone should be able to do it and it only enhances roleplay.
Can probably be done through "{ }" but I don't really see the practical benefit.
One example of an earlier system is commented below.
/N
-N
*/
/proc/generate_code_phrase()//Proc is used for phrase and response in master_controller.dm

View File

@@ -304,7 +304,7 @@ proc/TextPreview(var/string,var/len=40)
// to always create it and then throw it out.
/var/icon/text_tag_icons = new('./icons/chattags.dmi')
/proc/create_text_tag(var/tagname, var/tagdesc = tagname, var/client/C = null)
if(C && (C.prefs.toggles & CHAT_NOICONS))
if(!(C && C.is_preference_enabled(/datum/client_preference/chat_tags)))
return tagdesc
return "<IMG src='\ref[text_tag_icons.icon]' class='text_tag' iconstate='[tagname]'" + (tagdesc ? " alt='[tagdesc]'" : "") + ">"

View File

@@ -30,11 +30,21 @@ proc/isDay(var/month, var/day)
var/next_duration_update = 0
var/last_round_duration = 0
proc/round_duration()
var/round_start_time = 0
/hook/roundstart/proc/start_timer()
round_start_time = world.time
return 1
#define round_duration_in_ticks (round_start_time ? world.time - round_start_time : 0)
/proc/round_duration_as_text()
if(!round_start_time)
return "00:00"
if(last_round_duration && world.time < next_duration_update)
return last_round_duration
var/mills = world.time // 1/10 of a second, not real milliseconds but whatever
var/mills = round_duration_in_ticks // 1/10 of a second, not real milliseconds but whatever
//var/secs = ((mills % 36000) % 600) / 10 //Not really needed, but I'll leave it here for refrence.. or something
var/mins = round((mills % 36000) / 600)
var/hours = round(mills / 36000)

View File

@@ -149,6 +149,26 @@
if (rights & R_MENTOR) . += "[seperator]+MENTOR"
return .
// Converts a hexadecimal color (e.g. #FF0050) to a list of numbers for red, green, and blue (e.g. list(255,0,80) ).
/proc/hex2rgb(hex)
// Strips the starting #, in case this is ever supplied without one, so everything doesn't break.
if(findtext(hex,"#",1,2))
hex = copytext(hex, 2)
return list(hex2rgb_r(hex), hex2rgb_g(hex), hex2rgb_b(hex))
// The three procs below require that the '#' part of the hex be stripped, which hex2rgb() does automatically.
/proc/hex2rgb_r(hex)
var/hex_to_work_on = copytext(hex,1,3)
return hex2num(hex_to_work_on)
/proc/hex2rgb_g(hex)
var/hex_to_work_on = copytext(hex,3,5)
return hex2num(hex_to_work_on)
/proc/hex2rgb_b(hex)
var/hex_to_work_on = copytext(hex,5,7)
return hex2num(hex_to_work_on)
// heat2color functions. Adapted from: http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
/proc/heat2color(temp)
return rgb(heat2color_r(temp), heat2color_g(temp), heat2color_b(temp))

View File

@@ -646,47 +646,6 @@ proc/GaussRandRound(var/sigma,var/roundto)
else return get_step(ref, base_dir)
/proc/do_mob(var/mob/user, var/mob/target, var/delay = 30, var/numticks = 5, var/needhand = 1) //This is quite an ugly solution but i refuse to use the old request system.
if(!user || !target) return 0
if(numticks == 0) return 0
var/delayfraction = round(delay/numticks)
var/original_user_loc = user.loc
var/original_target_loc = target.loc
var/holding = user.get_active_hand()
for(var/i = 0, i<numticks, i++)
sleep(delayfraction)
if(!user || user.stat || user.weakened || user.stunned || user.loc != original_user_loc)
return 0
if(!target || target.loc != original_target_loc)
return 0
if(needhand && !(user.get_active_hand() == holding)) //Sometimes you don't want the user to have to keep their active hand
return 0
return 1
/proc/do_after(var/mob/user as mob, delay as num, var/numticks = 5, var/needhand = 1)
if(!user || isnull(user))
return 0
if(numticks == 0)
return 0
var/delayfraction = round(delay/numticks)
var/original_loc = user.loc
var/holding = user.get_active_hand()
for(var/i = 0, i<numticks, i++)
sleep(delayfraction)
if(!user || user.stat || user.weakened || user.stunned || user.loc != original_loc)
return 0
if(needhand && !(user.get_active_hand() == holding)) //Sometimes you don't want the user to have to keep their active hand
return 0
return 1
//Takes: Anything that could possibly have variables and a varname to check.
//Returns: 1 if found, 0 if not.
/proc/hasvar(var/datum/A, var/varname)
@@ -1351,3 +1310,15 @@ var/mob/dview/dview_mob = new
// call to generate a stack trace and print to runtime logs
/proc/crash_with(msg)
CRASH(msg)
/proc/screen_loc2turf(scr_loc, turf/origin)
var/tX = splittext(scr_loc, ",")
var/tY = splittext(tX[2], ":")
var/tZ = origin.z
tY = tY[1]
tX = splittext(tX[1], ":")
tX = tX[1]
tX = max(1, min(world.maxx, origin.x + (text2num(tX) - (world.view + 1))))
tY = max(1, min(world.maxy, origin.y + (text2num(tY) - (world.view + 1))))
return locate(tX, tY, tZ)

View File

@@ -87,6 +87,7 @@
if(in_throw_mode)
if(isturf(A) || isturf(A.loc))
throw_item(A)
trigger_aiming(TARGET_CAN_CLICK)
return 1
throw_mode_off()
@@ -94,6 +95,7 @@
if(W == A) // Handle attack_self
W.attack_self(src)
trigger_aiming(TARGET_CAN_CLICK)
update_inv_active_hand(0)
return 1
@@ -113,6 +115,8 @@
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, 1)
trigger_aiming(TARGET_CAN_CLICK)
return 1
if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that
@@ -134,12 +138,15 @@
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, 1)
trigger_aiming(TARGET_CAN_CLICK)
return
else // non-adjacent click
if(W)
W.afterattack(A, src, 0, params) // 0: not Adjacent
else
RangedAttack(A, params)
trigger_aiming(TARGET_CAN_CLICK)
return 1
/mob/proc/setClickCooldown(var/timeout)
@@ -325,3 +332,20 @@
else direction = WEST
if(direction != dir)
facedir(direction)
/obj/screen/click_catcher
icon = 'icons/mob/screen1_full.dmi'
icon_state = "passage0"
layer = 0
mouse_opacity = 2
screen_loc = "1,1"
/obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
if(modifiers["middle"] && istype(usr, /mob/living/carbon))
var/mob/living/carbon/C = usr
C.swap_hand()
else
var/turf/T = screen_loc2turf(modifiers["screen-loc"], get_turf(usr))
T.Click(location, control, params)
return 1

View File

@@ -130,6 +130,8 @@
using.layer = SCREEN_LAYER
adding += using
mymob.client.screen = list()
mymob.client.screen += adding + other
mymob.client.screen += mymob.client.void
return

View File

@@ -41,6 +41,7 @@
mymob.fire.name = "fire"
mymob.fire.screen_loc = ui_fire
mymob.client.screen = null
mymob.client.screen = list()
mymob.client.screen += list( mymob.healths, mymob.blind, mymob.flash, mymob.fire) //, mymob.rest, mymob.sleep, mymob.mach )
mymob.client.screen += src.adding + src.other
mymob.client.screen += src.adding + src.other
mymob.client.screen += mymob.client.void

View File

@@ -361,10 +361,11 @@
mymob.radio_use_icon.color = ui_color
mymob.radio_use_icon.alpha = ui_alpha
mymob.client.screen = null
mymob.client.screen = list()
mymob.client.screen += hud_elements
mymob.client.screen += src.adding + src.hotkeybuttons
mymob.client.screen += mymob.client.void
inventory_shown = 0;
return

View File

@@ -27,9 +27,10 @@
blobhealthdisplay.screen_loc = ui_internal
blobhealthdisplay.layer = 20
mymob.client.screen = null
mymob.client.screen = list()
mymob.client.screen += list(blobpwrdisplay, blobhealthdisplay)
mymob.client.screen += mymob.client.void
/datum/hud/proc/slime_hud(ui_style = 'icons/mob/screen1_Midnight.dmi')
@@ -94,8 +95,9 @@
src.adding += using
hurt_intent = using
mymob.client.screen = null
mymob.client.screen = list()
mymob.client.screen += src.adding
mymob.client.screen += mymob.client.void
return
@@ -151,6 +153,7 @@
mymob.purged.name = "purged"
mymob.purged.screen_loc = ui_construct_purge
mymob.client.screen = null
mymob.client.screen = list()
mymob.client.screen += list(mymob.fire, mymob.healths, mymob.pullin, mymob.zone_sel, mymob.purged, mymob.flash)
mymob.client.screen += mymob.client.void

View File

@@ -157,10 +157,11 @@ var/obj/screen/robot_inventory
mymob.gun_move_icon = new /obj/screen/gun/move(null)
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
mymob.client.screen = null
mymob.client.screen = list()
mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, robot_inventory, mymob.gun_setting_icon)
mymob.client.screen += src.adding + src.other
mymob.client.screen += mymob.client.void
return

View File

@@ -17,12 +17,11 @@
if(can_reenter_corpse && mind && mind.current)
if(A == mind.current || (mind.current in A)) // double click your corpse or whatever holds it
reenter_corpse() // (cloning scanner, body bag, closet, mech, etc)
return // seems legit.
return
// Things you might plausibly want to follow
if((ismob(A) && A != src) || istype(A,/obj/singularity))
if(istype(A,/atom/movable))
ManualFollow(A)
// Otherwise jump
else
following = null

View File

@@ -55,6 +55,7 @@
if(!..())
return 0
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
A.attack_generic(src,rand(5,6),"bitten")
/*
@@ -76,6 +77,9 @@
Feedstop()
return
//should have already been set if we are attacking a mob, but it doesn't hurt and will cover attacking non-mobs too
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
var/mob/living/M = A
if (istype(M))
@@ -144,6 +148,7 @@
custom_emote(1,"[friendly] [A]!")
return
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
var/damage = rand(melee_damage_lower, melee_damage_upper)
if(A.attack_generic(src,damage,attacktext,environment_smash) && loc && attack_sound)
playsound(loc, attack_sound, 50, 1, 1)

10
code/_unit_tests.dm Normal file
View File

@@ -0,0 +1,10 @@
/*
*
* This file is used by Travis to indicate that Unit Tests are to be ran.
* Do not add anything but the UNIT_TEST definition here as it will be overwritten by Travis when running tests.
*
*
* Should you wish to edit set UNIT_TEST to 1 like so:
* #define UNIT_TEST 1
*/
#define UNIT_TEST 0

View File

@@ -12,6 +12,6 @@ datum/controller/transfer_controller/Destroy()
datum/controller/transfer_controller/proc/process()
currenttick = currenttick + 1
if (world.time >= timerbuffer - 600)
if (round_duration_in_ticks >= timerbuffer - 1 MINUTE)
vote.autotransfer()
timerbuffer = timerbuffer + config.vote_autotransfer_interval
timerbuffer = timerbuffer + config.vote_autotransfer_interval

View File

@@ -9,11 +9,11 @@
*
* To add some code to be called by the hook, define a proc under the type, as so:
* @code
/hook/foo/proc/bar()
if(1)
return 1 //Sucessful
else
return 0 //Error, or runtime.
/hook/foo/proc/bar()
if(1)
return 1 //Sucessful
else
return 0 //Error, or runtime.
* @endcode
* All hooks must return nonzero on success, as runtimes will force return null.
*/

View File

@@ -317,9 +317,9 @@ var/global/datum/shuttle_controller/shuttle_controller
"Arrivals dock" = "nuke_shuttle_dock_airlock",
)
MS.announcer = "NDV Icarus"
MS.arrival_message = "Attention, [station_short], you have a large signature approaching the station - looks unarmed to surface scans. We're too far out to intercept - brace for visitors."
MS.departure_message = "Your visitors are on their way out of the system, [station_short], burning delta-v like it's nothing. Good riddance."
MS.announcer = "Automated Traffic Control"
MS.arrival_message = "Attention. A vessel is approaching the colony."
MS.departure_message = "Attention. A vessel is now leaving from the colony."
MS.interim = locate(/area/syndicate_station/transit)
MS.warmup_time = 0

View File

@@ -25,7 +25,7 @@
usr.client.debug_variables(antag)
message_admins("Admin [key_name_admin(usr)] is debugging the [antag.role_text] template.")
/client/proc/debug_controller(controller in list("Master","Ticker","Ticker Process","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event","Plants","Alarm","Nano","Chemistry"))
/client/proc/debug_controller(controller in list("Master","Ticker","Ticker Process","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data","Event","Plants","Alarm","Nano","Chemistry","Vote"))
set category = "Debug"
set name = "Debug Controller"
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
@@ -92,5 +92,8 @@
if("Chemistry")
debug_variables(chemistryProcess)
feedback_add_details("admin_verb", "DChem")
if("Vote")
debug_variables(vote)
feedback_add_details("admin_verb", "DVote")
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
return

View File

@@ -1,9 +1,15 @@
var/datum/controller/vote/vote = new()
var/global/list/round_voters = list() //Keeps track of the individuals voting for a given round, for use in forcedrafting.
var/global/list/round_voters = list() // Keeps track of the individuals voting for a given round, for use in forcedrafting.
datum/controller/vote
var/initiator = null
#define VOTE_RESTART "restart"
#define VOTE_GAMEMODE "gamemode"
#define VOTE_CREW_TRANSFER "crew_transfer"
#define VOTE_ADD_ANTAGONIST "add_antagonist"
#define VOTE_CUSTOM "custom"
/datum/controller/vote
var/initiator = null // Key of the one who started the vote or "the server"
var/started_time = null
var/time_remaining = 0
var/mode = null
@@ -11,385 +17,366 @@ datum/controller/vote
var/list/choices = list()
var/list/gamemode_names = list()
var/list/voted = list()
var/list/voting = list()
var/list/current_votes = list()
var/list/additional_text = list()
var/auto_muted = 0
New()
if(vote != src)
if(istype(vote))
del(vote)
vote = src
/datum/controller/vote/New()
if(vote != src)
if(istype(vote))
del(vote)
vote = src
proc/process() //called by master_controller
if(mode)
// No more change mode votes after the game has started.
// 3 is GAME_STATE_PLAYING, but that #define is undefined for some reason
if(mode == "gamemode" && ticker.current_state >= 2)
world << "<b>Voting aborted due to game start.</b>"
src.reset()
return
/datum/controller/vote/proc/process() //called by master_controller
if(mode)
// No more change mode votes after the game has started.
if(mode == VOTE_GAMEMODE && ticker.current_state >= GAME_STATE_SETTING_UP)
world << "<b>Voting aborted due to game start.</b>"
src.reset()
return
// Calculate how much time is remaining by comparing current time, to time of vote start,
// plus vote duration
time_remaining = round((started_time + config.vote_period - world.time)/10)
if(time_remaining < 0)
result()
for(var/client/C in voting)
if(C)
C << browse(null,"window=vote")
reset()
else
for(var/client/C in voting)
if(C)
C << browse(vote.interface(C),"window=vote")
voting.Cut()
proc/autotransfer()
initiate_vote("crew_transfer","the server", 1)
log_debug("The server has called a crew transfer vote")
proc/autogamemode()
initiate_vote("gamemode","the server", 1)
log_debug("The server has called a gamemode vote")
proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
voting.Cut()
current_votes.Cut()
additional_text.Cut()
proc/get_result()
//get the highest number of votes
var/greatest_votes = 0
var/total_votes = 0
for(var/option in choices)
var/votes = choices[option]
total_votes += votes
if(votes > greatest_votes)
greatest_votes = votes
//default-vote for everyone who didn't vote
if(!config.vote_no_default && choices.len)
var/non_voters = (clients.len - total_votes)
if(non_voters > 0)
if(mode == "restart")
choices["Continue Playing"] += non_voters
if(choices["Continue Playing"] >= greatest_votes)
greatest_votes = choices["Continue Playing"]
else if(mode == "gamemode")
if(master_mode in choices)
choices[master_mode] += non_voters
if(choices[master_mode] >= greatest_votes)
greatest_votes = choices[master_mode]
else if(mode == "crew_transfer")
var/factor = 0.5
switch(world.time / (10 * 60)) // minutes
if(0 to 60)
factor = 0.5
if(61 to 120)
factor = 0.8
if(121 to 240)
factor = 1
if(241 to 300)
factor = 1.2
else
factor = 1.4
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
world << "<font color='purple'>Crew Transfer Factor: [factor]</font>"
greatest_votes = max(choices["Initiate Crew Transfer"], choices["Continue The Round"])
//get all options with that many votes and return them in a list
. = list()
if(greatest_votes)
for(var/option in choices)
if(choices[option] == greatest_votes)
. += option
return .
proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(winners.len > 1)
if(mode != "gamemode" || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
text = "<b>Vote Tied Between:</b>\n"
for(var/option in winners)
text += "\t[option]\n"
. = pick(winners)
for(var/key in current_votes)
if(choices[current_votes[key]] == .)
round_voters += key // Keep track of who voted for the winning round.
if((mode == "gamemode" && . == "Extended") || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes
text += "<b>Vote Result: [.]</b>"
else
if(mode != "gamemode")
text += "<b>Vote Result: [.]</b>"
else
text += "<b>The vote has ended.</b>" // What will be shown if it is a gamemode vote that isn't extended
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
if(mode == "add_antagonist")
antag_add_failed = 1
log_vote(text)
world << "<font color='purple'>[text]</font>"
return .
proc/result()
. = announce_result()
var/restart = 0
if(.)
switch(mode)
if("restart")
if(. == "Restart Round")
restart = 1
if("gamemode")
if(master_mode != .)
world.save_mode(.)
if(ticker && ticker.mode)
restart = 1
else
master_mode = .
if("crew_transfer")
if(. == "Initiate Crew Transfer")
init_shift_change(null, 1)
if("add_antagonist")
if(isnull(.) || . == "None")
antag_add_failed = 1
else
additional_antag_types |= antag_names_to_ids[.]
if(mode == "gamemode") //fire this even if the vote fails.
if(!round_progressing)
round_progressing = 1
world << "<font color='red'><b>The round will start soon.</b></font>"
if(restart)
world << "World restarting due to vote..."
feedback_set_details("end_error","restart vote")
if(blackbox) blackbox.save_all_data_to_sql()
sleep(50)
log_game("Rebooting due to restart vote")
world.Reboot()
return .
proc/submit_vote(var/ckey, var/vote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
return 0
if(vote && vote >= 1 && vote <= choices.len)
if(current_votes[ckey])
choices[choices[current_votes[ckey]]]--
voted += usr.ckey
choices[choices[vote]]++ //check this
current_votes[ckey] = vote
return vote
return 0
proc/initiate_vote(var/vote_type, var/initiator_key, var/automatic = 0)
if(!mode)
if(started_time != null && !(check_rights(R_ADMIN) || automatic))
var/next_allowed_time = (started_time + config.vote_delay)
if(next_allowed_time > world.time)
return 0
// Calculate how much time is remaining by comparing current time, to time of vote start,
// plus vote duration
time_remaining = round((started_time + config.vote_period - world.time)/10)
if(time_remaining < 0)
result()
reset()
switch(vote_type)
if("restart")
choices.Add("Restart Round","Continue Playing")
if("gamemode")
if(ticker.current_state >= 2)
return 0
choices.Add(config.votable_modes)
for (var/F in choices)
var/datum/game_mode/M = gamemode_cache[F]
if(!M)
continue
gamemode_names[M.config_tag] = capitalize(M.name) //It's ugly to put this here but it works
additional_text.Add("<td align = 'center'>[M.required_players]</td>")
gamemode_names["secret"] = "Secret"
if("crew_transfer")
if(check_rights(R_ADMIN|R_MOD, 0))
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
/datum/controller/vote/proc/autotransfer()
initiate_vote(VOTE_CREW_TRANSFER, "the server", 1)
log_debug("The server has called a crew transfer vote")
/datum/controller/vote/proc/autogamemode()
initiate_vote(VOTE_GAMEMODE, "the server", 1)
log_debug("The server has called a gamemode vote")
/datum/controller/vote/proc/reset()
initiator = null
time_remaining = 0
mode = null
question = null
choices.Cut()
voted.Cut()
current_votes.Cut()
additional_text.Cut()
/datum/controller/vote/proc/get_result() // Get the highest number of votes
var/greatest_votes = 0
var/total_votes = 0
for(var/option in choices)
var/votes = choices[option]
total_votes += votes
if(votes > greatest_votes)
greatest_votes = votes
if(!config.vote_no_default && choices.len) // Default-vote for everyone who didn't vote
var/non_voters = (clients.len - total_votes)
if(non_voters > 0)
if(mode == VOTE_RESTART)
choices["Continue Playing"] += non_voters
if(choices["Continue Playing"] >= greatest_votes)
greatest_votes = choices["Continue Playing"]
else if(mode == VOTE_GAMEMODE)
if(master_mode in choices)
choices[master_mode] += non_voters
if(choices[master_mode] >= greatest_votes)
greatest_votes = choices[master_mode]
else if(mode == VOTE_CREW_TRANSFER)
var/factor = 0.5
switch(world.time / (10 * 60)) // minutes
if(0 to 60)
factor = 0.5
if(61 to 120)
factor = 0.8
if(121 to 240)
factor = 1
if(241 to 300)
factor = 1.2
else
if (get_security_level() == "red" || get_security_level() == "delta")
initiator_key << "The current alert status is too high to call for a crew transfer!"
return 0
if(ticker.current_state <= 2)
return 0
initiator_key << "The crew transfer button has been disabled!"
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
if("add_antagonist")
if(!config.allow_extra_antags || ticker.current_state >= 2)
return 0
for(var/antag_type in all_antag_types)
var/datum/antagonist/antag = all_antag_types[antag_type]
if(!(antag.id in additional_antag_types) && antag.is_votable())
choices.Add(antag.role_text)
choices.Add("None")
if("custom")
question = sanitizeSafe(input(usr,"What is the vote for?") as text|null)
if(!question) return 0
for(var/i=1,i<=10,i++)
var/option = capitalize(sanitize(input(usr,"Please enter an option or hit cancel to finish") as text|null))
if(!option || mode || !usr.client) break
choices.Add(option)
else
return 0
mode = vote_type
initiator = initiator_key
started_time = world.time
var/text = "[capitalize(mode)] vote started by [initiator]."
if(mode == "custom")
text += "\n[question]"
factor = 1.4
choices["Initiate Crew Transfer"] = round(choices["Initiate Crew Transfer"] * factor)
world << "<font color='purple'>Crew Transfer Factor: [factor]</font>"
greatest_votes = max(choices["Initiate Crew Transfer"], choices["Continue The Round"])
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>"
switch(vote_type)
if("crew_transfer")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if("gamemode")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if("custom")
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if(mode == "gamemode" && round_progressing)
round_progressing = 0
world << "<font color='red'><b>Round start has been delayed.</b></font>"
. = list() // Get all options with that many votes and return them in a list
if(greatest_votes)
for(var/option in choices)
if(choices[option] == greatest_votes)
. += option
time_remaining = round(config.vote_period/10)
return 1
return 0
/datum/controller/vote/proc/announce_result()
var/list/winners = get_result()
var/text
if(winners.len > 0)
if(winners.len > 1)
if(mode != VOTE_GAMEMODE || ticker.hide_mode == 0) // Here we are making sure we don't announce potential game modes
text = "<b>Vote Tied Between:</b>\n"
for(var/option in winners)
text += "\t[option]\n"
. = pick(winners)
proc/interface(var/client/C)
if(!C) return
var/admin = 0
var/trialmin = 0
if(C.holder)
if(C.holder.rights & R_ADMIN)
admin = 1
trialmin = 1 // don't know why we use both of these it's really weird, but I'm 2 lasy to refactor this all to use just admin.
voting |= C
. = "<html><head><title>Voting Panel</title></head><body>"
if(mode)
if(question) . += "<h2>Vote: '[question]'</h2>"
else . += "<h2>Vote: [capitalize(mode)]</h2>"
. += "Time Left: [time_remaining] s<hr>"
. += "<table width = '100%'><tr><td align = 'center'><b>Choices</b></td><td align = 'center'><b>Votes</b></td>"
if(capitalize(mode) == "Gamemode") .+= "<td align = 'center'><b>Minimum Players</b></td></tr>"
for(var/i = 1, i <= choices.len, i++)
var/votes = choices[choices[i]]
if(!votes) votes = 0
. += "<tr>"
if(mode == "gamemode")
if(current_votes[C.ckey] == i)
. += "<td><b><a href='?src=\ref[src];vote=[i]'>[gamemode_names[choices[i]]]</a></b></td><td align = 'center'>[votes]</td>"
else
. += "<td><a href='?src=\ref[src];vote=[i]'>[gamemode_names[choices[i]]]</a></td><td align = 'center'>[votes]</td>"
else
if(current_votes[C.ckey] == i)
. += "<td><b><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a></b></td><td align = 'center'>[votes]</td>"
else
. += "<td><a href='?src=\ref[src];vote=[i]'>[choices[i]]</a></td><td align = 'center'>[votes]</td>"
if (additional_text.len >= i)
. += additional_text[i]
. += "</tr>"
. += "</table><hr>"
if(admin)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
for(var/key in current_votes)
if(choices[current_votes[key]] == .)
round_voters += key // Keep track of who voted for the winning round.
if(mode != VOTE_GAMEMODE || . == "Extended" || ticker.hide_mode == 0) // Announce Extended gamemode, but not other gamemodes
text += "<b>Vote Result: [.]</b>"
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
//restart
if(trialmin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li><li>"
if(trialmin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
. += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//gamemode
if(trialmin || config.allow_vote_mode)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(trialmin)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode?"Allowed":"Disallowed"]</a>)"
. += "</li><li>"
//extra antagonists
if(!antag_add_failed && config.allow_extra_antags)
. += "<a href='?src=\ref[src];vote=add_antagonist'>Add Antagonist Type</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li>"
//custom
if(trialmin)
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
. += "</ul><hr>"
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a></body></html>"
return .
text += "<b>The vote has ended.</b>"
else
text += "<b>Vote Result: Inconclusive - No Votes!</b>"
if(mode == VOTE_ADD_ANTAGONIST)
antag_add_failed = 1
log_vote(text)
world << "<font color='purple'>[text]</font>"
Topic(href,href_list[],hsrc)
if(!usr || !usr.client) return //not necessary but meh...just in-case somebody does something stupid
switch(href_list["vote"])
if("close")
voting -= usr.client
usr << browse(null, "window=vote")
return
if("cancel")
if(usr.client.holder)
reset()
if("toggle_restart")
if(usr.client.holder)
config.allow_vote_restart = !config.allow_vote_restart
if("toggle_gamemode")
if(usr.client.holder)
config.allow_vote_mode = !config.allow_vote_mode
if("restart")
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("restart",usr.key)
if("gamemode")
if(config.allow_vote_mode || usr.client.holder)
initiate_vote("gamemode",usr.key)
if("crew_transfer")
if(config.allow_vote_restart || usr.client.holder)
initiate_vote("crew_transfer",usr.key)
if("add_antagonist")
if(config.allow_extra_antags)
initiate_vote("add_antagonist",usr.key)
if("custom")
if(usr.client.holder)
initiate_vote("custom",usr.key)
/datum/controller/vote/proc/result()
. = announce_result()
var/restart = 0
if(.)
switch(mode)
if(VOTE_RESTART)
if(. == "Restart Round")
restart = 1
if(VOTE_GAMEMODE)
if(master_mode != .)
world.save_mode(.)
if(ticker && ticker.mode)
restart = 1
else
master_mode = .
if(VOTE_CREW_TRANSFER)
if(. == "Initiate Crew Transfer")
init_shift_change(null, 1)
if(VOTE_ADD_ANTAGONIST)
if(isnull(.) || . == "None")
antag_add_failed = 1
else
additional_antag_types |= antag_names_to_ids[.]
if(mode == VOTE_GAMEMODE) //fire this even if the vote fails.
if(!round_progressing)
round_progressing = 1
world << "<font color='red'><b>The round will start soon.</b></font>"
if(restart)
world << "World restarting due to vote..."
feedback_set_details("end_error", "restart vote")
if(blackbox)
blackbox.save_all_data_to_sql()
sleep(50)
log_game("Rebooting due to restart vote")
world.Reboot()
/datum/controller/vote/proc/submit_vote(var/ckey, var/newVote)
if(mode)
if(config.vote_no_dead && usr.stat == DEAD && !usr.client.holder)
return
if(current_votes[ckey])
choices[choices[current_votes[ckey]]]--
if(newVote && newVote >= 1 && newVote <= choices.len)
choices[choices[newVote]]++
current_votes[ckey] = newVote
else
current_votes[ckey] = null
/datum/controller/vote/proc/initiate_vote(var/vote_type, var/initiator_key, var/automatic = 0)
if(!mode)
if(started_time != null && !(check_rights(R_ADMIN) || automatic))
var/next_allowed_time = (started_time + config.vote_delay)
if(next_allowed_time > world.time)
return 0
reset()
switch(vote_type)
if(VOTE_RESTART)
choices.Add("Restart Round", "Continue Playing")
if(VOTE_GAMEMODE)
if(ticker.current_state >= GAME_STATE_SETTING_UP)
return 0
choices.Add(config.votable_modes)
for(var/F in choices)
var/datum/game_mode/M = gamemode_cache[F]
if(!M)
continue
gamemode_names[M.config_tag] = capitalize(M.name) //It's ugly to put this here but it works
additional_text.Add("<td align = 'center'>[M.required_players]</td>")
gamemode_names["secret"] = "Secret"
if(VOTE_CREW_TRANSFER)
if(!check_rights(R_ADMIN|R_MOD, 0)) // The gods care not for the affairs of the mortals
if(get_security_level() == "red" || get_security_level() == "delta")
initiator_key << "The current alert status is too high to call for a crew transfer!"
return 0
if(ticker.current_state <= GAME_STATE_SETTING_UP)
initiator_key << "The crew transfer button has been disabled!"
return 0
question = "End the shift?"
choices.Add("Initiate Crew Transfer", "Continue The Round")
if(VOTE_ADD_ANTAGONIST)
if(!config.allow_extra_antags || ticker.current_state >= GAME_STATE_SETTING_UP)
return 0
for(var/antag_type in all_antag_types)
var/datum/antagonist/antag = all_antag_types[antag_type]
if(!(antag.id in additional_antag_types) && antag.is_votable())
choices.Add(antag.role_text)
choices.Add("None")
if(VOTE_CUSTOM)
question = sanitizeSafe(input(usr, "What is the vote for?") as text|null)
if(!question)
return 0
for(var/i = 1 to 10)
var/option = capitalize(sanitize(input(usr, "Please enter an option or hit cancel to finish") as text|null))
if(!option || mode || !usr.client)
break
choices.Add(option)
else
var/t = round(text2num(href_list["vote"]))
if(t) // It starts from 1, so there's no problem
submit_vote(usr.ckey, t)
usr.vote()
return 0
mode = vote_type
initiator = initiator_key
started_time = world.time
var/text = "[capitalize(mode)] vote started by [initiator]."
if(mode == VOTE_CUSTOM)
text += "\n[question]"
/mob/verb/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>"
if(vote_type == VOTE_CREW_TRANSFER || vote_type == VOTE_GAMEMODE || vote_type == VOTE_CUSTOM)
world << sound('sound/ambience/alarm4.ogg', repeat = 0, wait = 0, volume = 50, channel = 3)
if(mode == VOTE_GAMEMODE && round_progressing)
round_progressing = 0
world << "<font color='red'><b>Round start has been delayed.</b></font>"
time_remaining = round(config.vote_period / 10)
return 1
return 0
/datum/controller/vote/proc/interface(var/client/C)
if(!istype(C))
return
var/admin = 0
if(C.holder)
if(C.holder.rights & R_ADMIN)
admin = 1
. = "<html><head><title>Voting Panel</title></head><body>"
if(mode)
if(question)
. += "<h2>Vote: '[question]'</h2>"
else
. += "<h2>Vote: [capitalize(mode)]</h2>"
. += "Time Left: [time_remaining] s<hr>"
. += "<table width = '100%'><tr><td align = 'center'><b>Choices</b></td><td align = 'center'><b>Votes</b></td>"
if(mode == VOTE_GAMEMODE)
.+= "<td align = 'center'><b>Minimum Players</b></td></tr>"
for(var/i = 1 to choices.len)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
. += "<tr>"
var/thisVote = (current_votes[C.ckey] == i)
if(mode == VOTE_GAMEMODE)
. += "<td>[thisVote ? "<b>" : ""]<a href='?src=\ref[src];vote=[i]'>[gamemode_names[choices[i]]]</a>[thisVote ? "</b>" : ""]</td><td align = 'center'>[votes]</td>"
else
. += "<td>[thisVote ? "<b>" : ""]<a href='?src=\ref[src];vote=[i]'>[choices[i]]</a>[thisVote ? "</b>" : ""]</td><td align = 'center'>[votes]</td>"
if (additional_text.len >= i)
. += additional_text[i]
. += "</tr>"
. += "<tr><td><a href='?src=\ref[src];vote=unvote'>Unvote</a></td></tr>"
. += "</table><hr>"
if(admin)
. += "(<a href='?src=\ref[src];vote=cancel'>Cancel Vote</a>) "
else
. += "<h2>Start a vote:</h2><hr><ul><li>"
if(admin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=restart'>Restart</a>"
else
. += "<font color='grey'>Restart (Disallowed)</font>"
. += "</li><li>"
if(admin || config.allow_vote_restart)
. += "<a href='?src=\ref[src];vote=crew_transfer'>Crew Transfer</a>"
else
. += "<font color='grey'>Crew Transfer (Disallowed)</font>"
if(admin)
. += "\t(<a href='?src=\ref[src];vote=toggle_restart'>[config.allow_vote_restart ? "Allowed" : "Disallowed"]</a>)"
. += "</li><li>"
if(admin || config.allow_vote_mode)
. += "<a href='?src=\ref[src];vote=gamemode'>GameMode</a>"
else
. += "<font color='grey'>GameMode (Disallowed)</font>"
if(admin)
. += "\t(<a href='?src=\ref[src];vote=toggle_gamemode'>[config.allow_vote_mode ? "Allowed" : "Disallowed"]</a>)"
. += "</li><li>"
if(!antag_add_failed && config.allow_extra_antags)
. += "<a href='?src=\ref[src];vote=add_antagonist'>Add Antagonist Type</a>"
else
. += "<font color='grey'>Add Antagonist (Disallowed)</font>"
. += "</li>"
if(admin)
. += "<li><a href='?src=\ref[src];vote=custom'>Custom</a></li>"
. += "</ul><hr>"
. += "<a href='?src=\ref[src];vote=close' style='position:absolute;right:50px'>Close</a></body></html>"
/datum/controller/vote/Topic(href, href_list[])
if(!usr || !usr.client)
return
switch(href_list["vote"])
if("close")
usr << browse(null, "window=vote")
return
if("cancel")
if(usr.client.holder)
reset()
if("toggle_restart")
if(usr.client.holder)
config.allow_vote_restart = !config.allow_vote_restart
if("toggle_gamemode")
if(usr.client.holder)
config.allow_vote_mode = !config.allow_vote_mode
if(VOTE_RESTART)
if(config.allow_vote_restart || usr.client.holder)
initiate_vote(VOTE_RESTART, usr.key)
if(VOTE_GAMEMODE)
if(config.allow_vote_mode || usr.client.holder)
initiate_vote(VOTE_GAMEMODE, usr.key)
if(VOTE_CREW_TRANSFER)
if(config.allow_vote_restart || usr.client.holder)
initiate_vote(VOTE_CREW_TRANSFER, usr.key)
if(VOTE_ADD_ANTAGONIST)
if(config.allow_extra_antags || usr.client.holder)
initiate_vote(VOTE_ADD_ANTAGONIST, usr.key)
if(VOTE_CUSTOM)
if(usr.client.holder)
initiate_vote(VOTE_CUSTOM, usr.key)
if("unvote")
submit_vote(usr.ckey, null)
else
var/t = round(text2num(href_list["vote"]))
if(t) // It starts from 1, so there's no problem
submit_vote(usr.ckey, t)
usr.client.vote()
/client/verb/vote()
set category = "OOC"
set name = "Vote"
if(vote)
src << browse(vote.interface(client),"window=vote")
src << browse(vote.interface(src), "window=vote;size=500x[300 + vote.choices.len * 25]")

View File

@@ -74,11 +74,21 @@
if(real_rank in civilian_positions)
civ[name] = rank
department = 1
if(real_rank in nonhuman_positions)
bot[name] = rank
department = 1
if(!department && !(name in heads))
misc[name] = rank
// Synthetics don't have actual records, so we will pull them from here.
for(var/mob/living/silicon/ai/ai in mob_list)
bot[ai.name] = "Artificial Intelligence"
for(var/mob/living/silicon/robot/robot in mob_list)
// No combat/syndicate cyborgs, no drones.
if(robot.module && robot.module.hide_on_manifest)
continue
bot[robot.name] = "[robot.modtype] [robot.braintype]"
if(heads.len > 0)
dat += "<tr><th colspan=3>Heads</th></tr>"
for(name in heads)

View File

@@ -61,10 +61,13 @@
//put this here for easier tracking ingame
var/datum/money_account/initial_account
//used for antag tcrystal trading, more info in code\game\objects\items\telecrystals.dm
var/accept_tcrystals = 0
//used for optional self-objectives that antagonists can give themselves, which are displayed at the end of the round.
var/ambitions
/datum/mind/New(var/key)
src.key = key
@@ -106,6 +109,8 @@
output += "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
obj_count++
if(ambitions)
output += "<HR><B>Ambitions:</B> [ambitions]<br>"
recipient << browse(output,"window=memory")
/datum/mind/proc/edit_memory()
@@ -139,7 +144,8 @@
else
out += "None."
out += "<br><a href='?src=\ref[src];obj_add=1'>\[add\]</a>"
out += "<br><a href='?src=\ref[src];obj_add=1'>\[add\]</a><br><br>"
out += "<b>Ambitions:</b> [ambitions ? ambitions : "None"] <a href='?src=\ref[src];amb_edit=\ref[src]'>\[edit\]</a></br>"
usr << browse(out, "window=edit_memory[src]")
/datum/mind/Topic(href, href_list)
@@ -147,7 +153,7 @@
if(href_list["add_antagonist"])
var/datum/antagonist/antag = all_antag_types[href_list["add_antagonist"]]
if(antag)
if(antag)
if(antag.add_antagonist(src, 1, 1, 0, 1, 1)) // Ignore equipment and role type for this.
log_admin("[key_name_admin(usr)] made [key_name(src)] into a [antag.role_text].")
else
@@ -179,6 +185,18 @@
if (isnull(new_memo)) return
memory = new_memo
else if (href_list["amb_edit"])
var/datum/mind/mind = locate(href_list["amb_edit"])
if(!mind)
return
var/new_ambition = input("Enter a new ambition", "Memory", mind.ambitions) as null|message
if(isnull(new_ambition))
return
if(mind)
mind.ambitions = sanitize(new_ambition)
mind.current << "<span class='warning'>Your ambitions have been changed by higher powers, they are now: [mind.ambitions]</span>"
log_and_message_admins("made [key_name(mind.current)]'s ambitions be '[mind.ambitions]'.")
else if (href_list["obj_edit"] || href_list["obj_add"])
var/datum/objective/objective
var/objective_pos

View File

@@ -0,0 +1,43 @@
/datum/progressbar
var/goal = 1
var/image/bar
var/shown = 0
var/mob/user
var/client/client
/datum/progressbar/New(mob/user, goal_number, atom/target)
. = ..()
if(!target) target = user
if (!istype(target))
EXCEPTION("Invalid target given")
if (goal_number)
goal = goal_number
bar = image('icons/effects/progessbar.dmi', target, "prog_bar_0")
bar.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
bar.pixel_y = 32
src.user = user
if(user)
client = user.client
/datum/progressbar/Destroy()
if (client)
client.images -= bar
qdel(bar)
. = ..()
/datum/progressbar/proc/update(progress)
//world << "Update [progress] - [goal] - [(progress / goal)] - [((progress / goal) * 100)] - [round(((progress / goal) * 100), 5)]"
if (!user || !user.client)
shown = 0
return
if (user.client != client)
if (client)
client.images -= bar
shown = 0
client = user.client
progress = Clamp(progress, 0, goal)
bar.icon_state = "prog_bar_[round(((progress / goal) * 100), 5)]"
if (!shown && user.is_preference_enabled(/datum/client_preference/show_progress_bar))
user.client.images += bar
shown = 1

View File

@@ -74,18 +74,33 @@
if (items && items.len)
var/list/checklist = list()
checklist = items.Copy() // You should really trust Copy
for(var/obj/O in container)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
continue // Fruit is handled in check_fruit().
var/found = 0
for(var/i = 1; i < checklist.len+1; i++)
var/item_type = checklist[i]
if (istype(O,item_type))
checklist.Cut(i, i+1)
found = 1
break
if (!found)
. = 0
if(istype(container, /obj/machinery))
var/obj/machinery/machine = container
for(var/obj/O in (machine.contents - machine.component_parts))
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
continue // Fruit is handled in check_fruit().
var/found = 0
for(var/i = 1; i < checklist.len+1; i++)
var/item_type = checklist[i]
if (istype(O,item_type))
checklist.Cut(i, i+1)
found = 1
break
if (!found)
. = 0
else
for(var/obj/O in container.contents)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/grown))
continue // Fruit is handled in check_fruit().
var/found = 0
for(var/i = 1; i < checklist.len+1; i++)
var/item_type = checklist[i]
if (istype(O,item_type))
checklist.Cut(i, i+1)
found = 1
break
if (!found)
. = 0
if (checklist.len)
. = -1
return .
@@ -93,9 +108,15 @@
//general version
/datum/recipe/proc/make(var/obj/container as obj)
var/obj/result_obj = new result(container)
for (var/obj/O in (container.contents-result_obj))
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
if(istype(container, /obj/machinery))
var/obj/machinery/machine = container
for (var/obj/O in ((machine.contents-result_obj)-machine.component_parts))
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
else
for (var/obj/O in (container.contents-result_obj))
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
container.reagents.clear_reagents()
return result_obj
@@ -105,12 +126,21 @@
world << "<span class='danger'>Recipe [type] is defined without a result, please bug this.</span>"
return
var/obj/result_obj = new result(container)
for (var/obj/O in (container.contents-result_obj))
if (O.reagents)
O.reagents.del_reagent("nutriment")
O.reagents.update_total()
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
if(istype(container, /obj/machinery))
var/obj/machinery/machine = container
for (var/obj/O in ((machine.contents-result_obj)-machine.component_parts))
if (O.reagents)
O.reagents.del_reagent("nutriment")
O.reagents.update_total()
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
else
for (var/obj/O in (container.contents-result_obj))
if (O.reagents)
O.reagents.del_reagent("nutriment")
O.reagents.update_total()
O.reagents.trans_to_obj(result_obj, O.reagents.total_volume)
qdel(O)
container.reagents.clear_reagents()
return result_obj

View File

@@ -221,6 +221,12 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
name = "Janitorial supplies"
contains = list(/obj/item/weapon/reagent_containers/glass/bucket,
/obj/item/weapon/mop,
/obj/item/clothing/under/rank/janitor,
/obj/item/weapon/cartridge/janitor,
/obj/item/clothing/gloves/black,
/obj/item/clothing/head/soft/purple,
/obj/item/weapon/storage/belt/janitor,
/obj/item/clothing/shoes/galoshes,
/obj/item/weapon/caution,
/obj/item/weapon/caution,
/obj/item/weapon/caution,
@@ -609,7 +615,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/solar_assembly,
/obj/item/solar_assembly,
/obj/item/solar_assembly,
/obj/item/solar_assembly, // 21 Solar Assemblies. 1 Extra for the controller
/obj/item/solar_assembly, // 21 Solar Assemblies. 1 Extra for the controller,
/obj/item/weapon/circuitboard/solar_control,
/obj/item/weapon/tracker_electronics,
/obj/item/weapon/paper/solar)
@@ -671,8 +677,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/mecha_ripley
name = "Circuit Crate (\"Ripley\" APLU)"
contains = list(/obj/item/weapon/book/manual/ripley_build_and_repair,
/obj/item/weapon/circuitboard/mecha/ripley/main, //TEMPORARY due to lack of circuitboard printer
/obj/item/weapon/circuitboard/mecha/ripley/peripherals) //TEMPORARY due to lack of circuitboard printer
/obj/item/weapon/circuitboard/mecha/ripley/main,
/obj/item/weapon/circuitboard/mecha/ripley/peripherals)
cost = 30
containertype = /obj/structure/closet/crate/secure
containername = "APLU \"Ripley\" Circuit Crate"
@@ -681,8 +687,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/mecha_odysseus
name = "Circuit Crate (\"Odysseus\")"
contains = list(/obj/item/weapon/circuitboard/mecha/odysseus/peripherals, //TEMPORARY due to lack of circuitboard printer
/obj/item/weapon/circuitboard/mecha/odysseus/main) //TEMPORARY due to lack of circuitboard printer
contains = list(/obj/item/weapon/circuitboard/mecha/odysseus/peripherals,
/obj/item/weapon/circuitboard/mecha/odysseus/main)
cost = 25
containertype = /obj/structure/closet/crate/secure
containername = "\"Odysseus\" Circuit Crate"
@@ -1001,7 +1007,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
containername = "Security barrier crate"
group = "Security"
/datum/supply_packs/securitybarriers
/datum/supply_packs/securityshieldgen
name = "Wall shield Generators"
contains = list(/obj/machinery/shieldwallgen,
/obj/machinery/shieldwallgen,
@@ -1635,6 +1641,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
num_contained = 4
contains = list(/obj/item/clothing/accessory/storage/black_vest,
/obj/item/clothing/accessory/storage/brown_vest,
/obj/item/clothing/accessory/storage/white_vest,
/obj/item/clothing/accessory/storage/webbing)
cost = 15
containertype = "/obj/structure/closet/crate"
@@ -1729,7 +1736,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/device/camera_film,
/obj/item/device/camera_film,
/obj/item/weapon/storage/photo_album,
/obj/item/device/reagent_scanner)
/obj/item/device/reagent_scanner,
/obj/item/device/flashlight/maglight)
cost = 35
containertype = "/obj/structure/closet/crate/secure"
containername = "Forensic equipment"
@@ -1785,7 +1793,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/clothing/accessory/storage/black_vest,
/obj/item/clothing/head/soft/sec/corp,
/obj/item/clothing/under/rank/security/corp,
/obj/item/weapon/gun/energy/taser)
/obj/item/weapon/gun/energy/taser,
/obj/item/device/flashlight/maglight)
cost = 30
containertype = "/obj/structure/closet/crate/secure"
containername = "Officer equipment"
@@ -1811,7 +1820,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/reagent_containers/spray/pepper,
/obj/item/weapon/melee/baton/loaded,
/obj/item/weapon/storage/box/holobadge,
/obj/item/clothing/head/beret/sec/corporate/warden)
/obj/item/clothing/head/beret/sec/corporate/warden,
/obj/item/device/flashlight/maglight)
cost = 45
containertype = "/obj/structure/closet/crate/secure"
containername = "Warden equipment"
@@ -1835,7 +1845,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/clothing/accessory/holster/waist,
/obj/item/weapon/melee/telebaton,
/obj/item/weapon/shield/riot/tele,
/obj/item/clothing/head/beret/sec/corporate/hos)
/obj/item/clothing/head/beret/sec/corporate/hos,
/obj/item/device/flashlight/maglight)
cost = 65
containertype = "/obj/structure/closet/crate/secure"
containername = "Head of security equipment"
@@ -2069,7 +2080,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/device/healthanalyzer,
/obj/item/weapon/cartridge/medical,
/obj/item/device/flashlight/pen,
/obj/item/weapon/reagent_containers/syringe)
/obj/item/weapon/reagent_containers/syringe,
/obj/item/clothing/accessory/storage/white_vest)
cost = 20
containertype = "/obj/structure/closet/crate/secure"
containername = "Paramedic equipment"

View File

@@ -11,7 +11,7 @@ var/const/AALARM_WIRE_AALARM = 16
/datum/wires/alarm/CanUse(var/mob/living/L)
var/obj/machinery/alarm/A = holder
if(A.wiresexposed && A.buildstage == 2)
if(A.wiresexposed)
return 1
return 0

View File

@@ -62,9 +62,8 @@ using /datum/datacore/proc/manifest_inject( ), or manifest_insert( )
*/
var/global/list/PDA_Manifest = list()
var/global/ManifestJSON
/datum/datacore/proc/get_manifest_json()
/datum/datacore/proc/get_manifest_list()
if(PDA_Manifest.len)
return
var/heads[0]
@@ -146,7 +145,6 @@ var/global/ManifestJSON
"bot" = bot,\
"misc" = misc\
)
ManifestJSON = json_encode(PDA_Manifest)
return

View File

@@ -128,6 +128,13 @@
icon_state = "nullrod"
item_state = "foldcane"
/obj/item/weapon/cane/whitecane
name = "white cane"
desc = "A cane used by the blind."
icon = 'icons/obj/weapons.dmi'
icon_state = "whitecane"
item_state = "whitecane"
/obj/item/weapon/disk
name = "disk"
icon = 'icons/obj/items.dmi'
@@ -268,21 +275,6 @@
throw_range = 5
w_class = 2.0
/obj/item/weapon/wire
desc = "This is just a simple piece of regular insulated wire."
name = "wire"
icon = 'icons/obj/power.dmi'
icon_state = "item_wire"
var/amount = 1.0
var/laying = 0.0
var/old_lay = null
matter = list(DEFAULT_WALL_MATERIAL = 40)
attack_verb = list("whipped", "lashed", "disciplined", "tickled")
suicide_act(mob/user)
viewers(user) << "<span class='warning'><b>[user] is strangling \himself with \the [src]! It looks like \he's trying to commit suicide.</b></span>"
return (OXYLOSS)
/obj/item/weapon/module
icon = 'icons/obj/module.dmi'
icon_state = "std_module"
@@ -598,3 +590,29 @@
icon = 'icons/obj/stock_parts.dmi'
icon_state = "smes_coil"
origin_tech = list(TECH_MATERIAL = 19, TECH_ENGINEERING = 19, TECH_PHORON = 19, TECH_POWER = 19, TECH_BLUESPACE = 19, TECH_BIO = 19, TECH_COMBAT = 19, TECH_MAGNET = 19, TECH_DATA = 19, TECH_ILLEGAL = 19, TECH_ARCANE = 19)
// Additional construction stock parts
/obj/item/weapon/stock_parts/gear
name = "gear"
desc = "A gear used for construction."
icon = 'icons/obj/stock_parts.dmi'
icon_state = "gear"
origin_tech = list(TECH_ENGINEERING = 1)
matter = list(DEFAULT_WALL_MATERIAL = 50)
/obj/item/weapon/stock_parts/motor
name = "motor"
desc = "A motor used for construction."
icon = 'icons/obj/stock_parts.dmi'
icon_state = "motor"
origin_tech = list(TECH_ENGINEERING = 1)
matter = list(DEFAULT_WALL_MATERIAL = 60, "glass" = 10)
/obj/item/weapon/stock_parts/spring
name = "spring"
desc = "A spring used for construction."
icon = 'icons/obj/stock_parts.dmi'
icon_state = "spring"
origin_tech = list(TECH_ENGINEERING = 1)
matter = list(DEFAULT_WALL_MATERIAL = 40)

View File

@@ -30,6 +30,12 @@
if(faction_verb && player.current)
player.current.verbs |= faction_verb
spawn(1 SECOND) //Added a delay so that this should pop up at the bottom and not the top of the text flood the new antag gets.
player.current << "<span class='notice'>Once you decide on a goal to pursue, you can optionally display it to \
everyone at the end of the shift with the <b>Set Ambition</b> verb, located in the IC tab. You can change this at any time, \
and it otherwise has no bearing on your round.</span>"
player.current.verbs |= /mob/living/proc/write_ambition
// Handle only adding a mind and not bothering with gear etc.
if(nonstandard_role_type)
faction_members |= player
@@ -50,5 +56,8 @@
player.special_role = null
update_icons_removed(player)
BITSET(player.current.hud_updateflag, SPECIALROLE_HUD)
if(!is_special_character(player))
player.current.verbs -= /mob/living/proc/write_ambition
player.ambitions = ""
return 1
return 0

View File

@@ -104,12 +104,6 @@
create_nuke()
show_objectives(player)
// Clown clumsiness check, I guess downstream might use it.
if (player.current.mind)
if (player.current.mind.assigned_role == "Clown")
player.current << "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself."
player.current.mutations.Remove(CLUMSY)
return 1
/datum/antagonist/proc/set_antag_name(var/mob/living/player)

View File

@@ -30,3 +30,26 @@
world << "<span class='danger'><font size = 3>[loss_text]</font></span>"
if(loss_feedback_tag) feedback_set_details("round_end_result","[loss_feedback_tag]")
/mob/living/proc/write_ambition()
set name = "Set Ambition"
set category = "IC"
set src = usr
if(!mind)
return
if(!is_special_character(mind))
src << "<span class='warning'>While you may perhaps have goals, this verb's meant to only be visible \
to antagonists. Please make a bug report!</span>"
return
var/new_ambitions = input(src, "Write a short sentence of what your character hopes to accomplish \
today as an antagonist. Remember that this is purely optional. It will be shown at the end of the \
round for everybody else.", "Ambitions", mind.ambitions) as null|message
if(isnull(new_ambitions))
return
mind.ambitions = new_ambitions
new_ambitions = sanitize(new_ambitions)
if(new_ambitions)
src << "<span class='notice'>You've set your goal to be '[new_ambitions]'.</span>"
else
src << "<span class='notice'>You leave your ambitions behind.</span>"
log_and_message_admins("has set their ambitions to now be: [new_ambitions].")

View File

@@ -7,6 +7,9 @@
for(var/datum/mind/P in current_antagonists)
text += print_player_full(P)
text += get_special_objective_text(P)
if(P.ambitions)
text += "<br>Their goals for today were..."
text += "<br><span class='notice'>[P.ambitions]</span>"
if(!global_objectives.len && P.objectives && P.objectives.len)
var/failed
var/num = 1

View File

@@ -27,7 +27,7 @@ var/datum/antagonist/raider/raiders
/obj/item/clothing/under/serviceoveralls,
/obj/item/clothing/under/captain_fly,
/obj/item/clothing/under/det,
/obj/item/clothing/under/brown,
/obj/item/clothing/under/color/brown,
)
var/list/raider_shoes = list(

View File

@@ -76,7 +76,7 @@ var/datum/antagonist/wizard/wizards
return 0
wizard_mob.equip_to_slot_or_del(new /obj/item/device/radio/headset(wizard_mob), slot_l_ear)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/lightpurple(wizard_mob), slot_w_uniform)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/under/color/lightpurple(wizard_mob), slot_w_uniform)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(wizard_mob), slot_shoes)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe(wizard_mob), slot_wear_suit)
wizard_mob.equip_to_slot_or_del(new /obj/item/clothing/head/wizard(wizard_mob), slot_head)

View File

@@ -838,6 +838,10 @@ area/space/atmosalert()
/area/maintenance/engineering
name = "Engineering Maintenance"
icon_state = "maint_engineering"
/area/maintenance/engineering/pumpstation
name = "Engineering Pump Station"
icon_state = "maint_pumpstation"
/area/maintenance/evahallway
name = "\improper EVA Maintenance"
@@ -2757,12 +2761,12 @@ var/list/the_station_areas = list (
/area/rnd,
/area/storage,
/area/construction,
/area/ai_monitored/storage/eva, //do not try to simplify to "/area/ai_monitored" --rastaf0
/area/ai_monitored/storage/eva,
/area/ai_monitored/storage/secure,
/area/ai_monitored/storage/emergency,
/area/ai_upload, //do not try to simplify to "/area" --rastaf0
/area/ai_monitored/storage/emergency,
/area/ai_upload,
/area/ai_upload_foyer,
/area/ai,
/area/ai
)

View File

@@ -243,7 +243,7 @@ var/list/mob/living/forced_ambiance_list = new
/area/proc/play_ambience(var/mob/living/L)
// 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.toggles & SOUND_AMBIENCE))) return
if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance))) return
// If we previously were in an area with force-played ambiance, stop it.
if(L in forced_ambiance_list)

View File

@@ -47,6 +47,7 @@
idle_power_usage = 50
active_power_usage = 300
interact_offline = 1
circuit = /obj/item/weapon/circuitboard/clonescanner
var/locked = 0
var/mob/living/carbon/occupant = null
var/obj/item/weapon/reagent_containers/glass/beaker = null
@@ -55,7 +56,6 @@
/obj/machinery/dna_scannernew/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/clonescanner(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)

View File

@@ -0,0 +1,12 @@
/datum/absorbed_dna
var/name
var/datum/dna/dna
var/speciesName
var/list/languages
/datum/absorbed_dna/New(var/newName, var/newDNA, var/newSpecies, var/newLanguages)
..()
name = newName
dna = newDNA
speciesName = newSpecies
languages = newLanguages

View File

@@ -1,5 +1,5 @@
/datum/game_mode/changeling
name = "changeling"
name = "Changeling"
round_description = "There are alien changelings on the station. Do not let the changelings succeed!"
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 \

View File

@@ -1,9 +1,8 @@
var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")
/datum/changeling //stores changeling powers, changeling recharge thingie, changeling absorbed DNA and changeling ID (for changeling hivemind)
var/list/absorbed_dna = list()
var/list/absorbed_species = list()
var/list/absorbed_languages = list()
var/list/datum/absorbed_dna/absorbed_dna = list()
var/list/absorbed_languages = list() // Necessary because of set_species stuff
var/absorbedcount = 0
var/chem_charges = 20
var/chem_recharge_rate = 0.5
@@ -23,25 +22,36 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
/datum/changeling/New(var/gender=FEMALE)
..()
var/honorific = (gender == FEMALE) ? "Ms." : "Mr."
if(possible_changeling_IDs.len)
changelingID = pick(possible_changeling_IDs)
possible_changeling_IDs -= changelingID
changelingID = "[honorific] [changelingID]"
changelingID = "[changelingID]"
else
changelingID = "[honorific] [rand(1,999)]"
changelingID = "[rand(1,999)]"
/datum/changeling/proc/regenerate()
chem_charges = min(max(0, chem_charges+chem_recharge_rate), chem_storage)
geneticdamage = max(0, geneticdamage-1)
/datum/changeling/proc/GetDNA(var/dna_owner)
var/datum/dna/chosen_dna
for(var/datum/dna/DNA in absorbed_dna)
if(dna_owner == DNA.real_name)
chosen_dna = DNA
break
return chosen_dna
for(var/datum/absorbed_dna/DNA in absorbed_dna)
if(dna_owner == DNA.name)
return DNA
/mob/proc/absorbDNA(var/datum/absorbed_dna/newDNA)
var/datum/changeling/changeling = null
if(src.mind && src.mind.changeling)
changeling = src.mind.changeling
if(!changeling)
return
for(var/language in newDNA.languages)
changeling.absorbed_languages |= language
changeling_update_languages(changeling.absorbed_languages)
if(!changeling.GetDNA(newDNA.name)) // Don't duplicate - I wonder if it's possible for it to still be a different DNA? DNA code could use a rewrite
changeling.absorbed_dna += newDNA
//Restores our verbs. It will only restore verbs allowed during lesser (monkey) form if we are not human
/mob/proc/make_changeling()
@@ -70,14 +80,13 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!(P in src.verbs))
src.verbs += P.verbpath
mind.changeling.absorbed_dna |= dna
for(var/language in languages)
mind.changeling.absorbed_languages |= language
var/mob/living/carbon/human/H = src
if(istype(H))
mind.changeling.absorbed_species += H.species.name
for(var/language in languages)
mind.changeling.absorbed_languages |= language
var/datum/absorbed_dna/newDNA = new(H.real_name, H.dna, H.species.name, H.languages)
absorbDNA(newDNA)
return 1
@@ -118,10 +127,8 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
return changeling
//Used to dump the languages from the changeling datum into the actual mob.
/mob/proc/changeling_update_languages(var/updated_languages)
languages = list()
for(var/language in updated_languages)
languages += language
@@ -129,8 +136,6 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
//This isn't strictly necessary but just to be safe...
add_language("Changeling")
return
//////////
//STINGS// //They get a pretty header because there's just so fucking many of them ;_;
//////////
@@ -171,9 +176,3 @@ var/global/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","E
if(!T.mind || !T.mind.changeling) return T //T will be affected by the sting
T << "<span class='warning'>You feel a tiny prick.</span>"
return

View File

@@ -65,33 +65,21 @@
src << "<span class='notice'>We have absorbed [T]!</span>"
src.visible_message("<span class='danger'>[src] sucks the fluids from [T]!</span>")
T << "<span class='danger'>You have been absorbed by the changeling!</span>"
T.dna.real_name = T.real_name //Set this again, just to be sure that it's properly set.
changeling.absorbed_dna |= T.dna
if(src.nutrition < 400)
src.nutrition = min((src.nutrition + T.nutrition), 400)
changeling.chem_charges += 10
// changeling.geneticpoints += 2
src.verbs += /mob/proc/changeling_respec
src << "<span class='notice'>We can now re-adapt, reverting our evolution so that we may start anew, if needed.</span>"
//Steal all of their languages!
for(var/language in T.languages)
if(!(language in changeling.absorbed_languages))
changeling.absorbed_languages += language
changeling_update_languages(changeling.absorbed_languages)
//Steal their species!
if(T.species && !(T.species.name in changeling.absorbed_species))
changeling.absorbed_species += T.species.name
var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages)
absorbDNA(newDNA)
if(T.mind && T.mind.changeling)
if(T.mind.changeling.absorbed_dna)
for(var/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot
for(var/datum/absorbed_dna/dna_data in T.mind.changeling.absorbed_dna) //steal all their loot
if(dna_data in changeling.absorbed_dna)
continue
changeling.absorbed_dna += dna_data
absorbDNA(dna_data)
changeling.absorbedcount++
T.mind.changeling.absorbed_dna.len = 1

View File

@@ -56,7 +56,7 @@
/obj/item/weapon/melee/arm_blade/dropped(mob/user)
visible_message("<span class='warning'>With a sickening crunch, [creator] reforms their arm blade into an arm!</span>",
"<span class='notice'>We assimilate the weapon back into our body.</span>",
"<span class='italics>You hear organic matter ripping and tearing!</span>")
"<span class='italics'>You hear organic matter ripping and tearing!</span>")
playsound(src, 'sound/effects/blobattack.ogg', 30, 1)
spawn(1)
if(src)

View File

@@ -19,6 +19,9 @@
var/mob/living/carbon/human/T = changeling_sting(40, /mob/proc/changeling_extract_dna_sting)
if(!T)
return
if(!istype(T) || T.isSynthetic())
src << "<span class='warning'>\The [T] is not compatible with our biology.</span>"
return 0
@@ -31,10 +34,8 @@
src << "<span class='warning'>This creature's DNA is ruined beyond useability!</span>"
return 0
T.dna.real_name = T.real_name
changeling.absorbed_dna |= T.dna
if(T.species && !(T.species.name in changeling.absorbed_species))
changeling.absorbed_species += T.species.name
var/datum/absorbed_dna/newDNA = new(T.real_name, T.dna, T.species.name, T.languages)
absorbDNA(newDNA)
feedback_add_details("changeling_powers","ED")
return 1

View File

@@ -27,9 +27,9 @@ var/list/datum/dna/hivemind_bank = list()
if(!changeling) return
var/list/names = list()
for(var/datum/dna/DNA in changeling.absorbed_dna)
for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
if(!(DNA in hivemind_bank))
names += DNA.real_name
names += DNA.name
if(names.len <= 0)
src << "<span class='notice'>The airwaves already have all of our DNA.</span>"
@@ -38,7 +38,7 @@ var/list/datum/dna/hivemind_bank = list()
var/S = input("Select a DNA to channel: ", "Channel DNA", null) as null|anything in names
if(!S) return
var/datum/dna/chosen_dna = changeling.GetDNA(S)
var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
@@ -57,9 +57,9 @@ var/list/datum/dna/hivemind_bank = list()
if(!changeling) return
var/list/names = list()
for(var/datum/dna/DNA in hivemind_bank)
for(var/datum/absorbed_dna/DNA in hivemind_bank)
if(!(DNA in changeling.absorbed_dna))
names[DNA.real_name] = DNA
names[DNA.name] = DNA
if(names.len <= 0)
src << "<span class='notice'>There's no new DNA to absorb from the air.</span>"
@@ -67,12 +67,12 @@ var/list/datum/dna/hivemind_bank = list()
var/S = input("Select a DNA absorb from the air: ", "Absorb DNA", null) as null|anything in names
if(!S) return
var/datum/dna/chosen_dna = names[S]
var/datum/absorbed_dna/chosen_dna = names[S]
if(!chosen_dna)
return
changeling.chem_charges -= 20
changeling.absorbed_dna += chosen_dna
absorbDNA(chosen_dna)
src << "<span class='notice'>We absorb the DNA of [S] from the air.</span>"
feedback_add_details("changeling_powers","HD")
return 1

View File

@@ -48,7 +48,7 @@
new /obj/effect/gibspawner/human(T)
visible_message("<span class='warning'>With a sickening squish, [src] reforms their whole body, casting their old parts on the floor!</span>",
"<span class='notice'>We reform our body. We are whole once more.</span>",
"<span class='italics>You hear organic matter ripping and tearing!</span>")
"<span class='italics'>You hear organic matter ripping and tearing!</span>")
feedback_add_details("changeling_powers","RR")
return 1

View File

@@ -1,8 +1,8 @@
/datum/power/changeling/self_respiration
name = "Self Respiration"
desc = "We evolve our body to no longer require drawing oxygen from the atmosphere.."
desc = "We evolve our body to no longer require drawing oxygen from the atmosphere."
helptext = "We will no longer require internals, and we cannot inhale any gas, including harmful ones."
genomecost = 1
genomecost = 0
isVerb = 0
verbpath = /mob/proc/changeling_self_respiration

View File

@@ -4,12 +4,6 @@
genomecost = 0
verbpath = /mob/proc/changeling_transform
/datum/power/changeling/change_species
name = "Change Species"
desc = "We take on the apperance of a species that we have absorbed."
genomecost = 0
verbpath = /mob/proc/changeling_change_species
//Change our DNA to that of somebody we've absorbed.
/mob/proc/changeling_transform()
set category = "Changeling"
@@ -19,73 +13,42 @@
if(!changeling) return
var/list/names = list()
for(var/datum/dna/DNA in changeling.absorbed_dna)
names += "[DNA.real_name]"
for(var/datum/absorbed_dna/DNA in changeling.absorbed_dna)
names += "[DNA.name]"
var/S = input("Select the target DNA: ", "Target DNA", null) as null|anything in names
if(!S) return
var/datum/dna/chosen_dna = changeling.GetDNA(S)
var/datum/absorbed_dna/chosen_dna = changeling.GetDNA(S)
if(!chosen_dna)
return
changeling.chem_charges -= 5
src.visible_message("<span class='warning'>[src] transforms!</span>")
changeling.geneticdamage = 5
src.dna = chosen_dna.Clone()
if(ishuman(src))
var/mob/living/carbon/human/H = src
var/newSpecies = chosen_dna.speciesName
H.set_species(newSpecies,1)
src.dna = chosen_dna.dna.Clone()
src.dna.b_type = "AB+" //This is needed to avoid blood rejection bugs. The fact that the blood type might not match up w/ records could be a *FEATURE* too.
if(ishuman(src))
var/mob/living/carbon/human/H = src
H.b_type = "AB+" //For some reason we have two blood types on the mob.
for(var/flavor in H.flavor_texts) //Nulls out flavor text, so we don't keep our previous mob's flavor.
flavor = null
src.real_name = chosen_dna.real_name
src.real_name = chosen_dna.name
src.flavor_text = ""
src.UpdateAppearance()
domutcheck(src, null)
changeling_update_languages(changeling.absorbed_languages)
src.verbs -= /mob/proc/changeling_transform
spawn(10) src.verbs += /mob/proc/changeling_transform
spawn(10)
src.verbs += /mob/proc/changeling_transform
src.regenerate_icons()
feedback_add_details("changeling_powers","TR")
return 1
//Used to switch species based on the changeling datum.
/mob/proc/changeling_change_species()
set category = "Changeling"
set name = "Change Species (5)"
var/mob/living/carbon/human/H = src
if(!istype(H))
src << "<span class='warning'>We may only use this power while in humanoid form.</span>"
return
var/datum/changeling/changeling = changeling_power(5,1,0)
if(!changeling) return
if(changeling.absorbed_species.len < 2)
src << "<span class='warning'>We do not know of any other species genomes to use.</span>"
return
var/S = input("Select the target species: ", "Target Species", null) as null|anything in changeling.absorbed_species
if(!S) return
domutcheck(src, null)
changeling.chem_charges -= 5
changeling.geneticdamage = 5
src.visible_message("<span class='warning'>[src] transforms!</span>")
src.verbs -= /mob/proc/changeling_change_species
H.set_species(S,1) //Until someone moves body colour into DNA, they're going to have to use the default.
spawn(10)
src.verbs += /mob/proc/changeling_change_species
src.regenerate_icons()
changeling_update_languages(changeling.absorbed_languages)
feedback_add_details("changeling_powers","TR")
return 1

View File

@@ -36,7 +36,7 @@
desc = "A hood worn by the followers of Nar-Sie."
flags_inv = HIDEFACE
body_parts_covered = HEAD
armor = list(melee = 30, bullet = 10, laser = 5,energy = 5, bomb = 0, bio = 0, rad = 0)
armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0)
cold_protection = HEAD
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE
siemens_coefficient = 0
@@ -61,7 +61,7 @@
item_state = "cultrobes"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade)
armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0)
armor = list(melee = 50, bullet = 30, laser = 50, energy = 20, bomb = 25, bio = 10, rad = 0)
flags_inv = HIDEJUMPSUIT
siemens_coefficient = 0
@@ -84,7 +84,7 @@
name = "cult helmet"
desc = "A space worthy helmet used by the followers of Nar-Sie"
icon_state = "cult_helmet"
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0
/obj/item/clothing/head/helmet/space/cult/cultify()
@@ -98,7 +98,7 @@
w_class = 3
allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit)
slowdown = 1
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
armor = list(melee = 60, bullet = 50, laser = 30, energy = 15, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS

View File

@@ -185,7 +185,6 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
throw_range = 5
w_class = 2.0
unique = 1
var/notedat = ""
var/tomedat = ""
var/list/words = list("ire" = "ire", "ego" = "ego", "nahlizet" = "nahlizet", "certum" = "certum", "veri" = "veri", "jatkaa" = "jatkaa", "balaq" = "balaq", "mgar" = "mgar", "karazet" = "karazet", "geeri" = "geeri")
@@ -285,57 +284,12 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
</html>
"}
Topic(href,href_list[])
if (src.loc == usr)
var/number = text2num(href_list["number"])
if (usr.stat|| usr.restrained())
return
switch(href_list["action"])
if("clear")
words[words[number]] = words[number]
if("change")
words[words[number]] = input("Enter the translation for [words[number]]", "Word notes") in engwords
for (var/w in words)
if ((words[w] == words[words[number]]) && (w != words[number]))
words[w] = w
notedat = {"
<br><b>Word translation notes</b> <br>
[words[1]] is <a href='byond://?src=\ref[src];number=1;action=change'>[words[words[1]]]</A> <A href='byond://?src=\ref[src];number=1;action=clear'>Clear</A><BR>
[words[2]] is <A href='byond://?src=\ref[src];number=2;action=change'>[words[words[2]]]</A> <A href='byond://?src=\ref[src];number=2;action=clear'>Clear</A><BR>
[words[3]] is <a href='byond://?src=\ref[src];number=3;action=change'>[words[words[3]]]</A> <A href='byond://?src=\ref[src];number=3;action=clear'>Clear</A><BR>
[words[4]] is <a href='byond://?src=\ref[src];number=4;action=change'>[words[words[4]]]</A> <A href='byond://?src=\ref[src];number=4;action=clear'>Clear</A><BR>
[words[5]] is <a href='byond://?src=\ref[src];number=5;action=change'>[words[words[5]]]</A> <A href='byond://?src=\ref[src];number=5;action=clear'>Clear</A><BR>
[words[6]] is <a href='byond://?src=\ref[src];number=6;action=change'>[words[words[6]]]</A> <A href='byond://?src=\ref[src];number=6;action=clear'>Clear</A><BR>
[words[7]] is <a href='byond://?src=\ref[src];number=7;action=change'>[words[words[7]]]</A> <A href='byond://?src=\ref[src];number=7;action=clear'>Clear</A><BR>
[words[8]] is <a href='byond://?src=\ref[src];number=8;action=change'>[words[words[8]]]</A> <A href='byond://?src=\ref[src];number=8;action=clear'>Clear</A><BR>
[words[9]] is <a href='byond://?src=\ref[src];number=9;action=change'>[words[words[9]]]</A> <A href='byond://?src=\ref[src];number=9;action=clear'>Clear</A><BR>
[words[10]] is <a href='byond://?src=\ref[src];number=10;action=change'>[words[words[10]]]</A> <A href='byond://?src=\ref[src];number=10;action=clear'>Clear</A><BR>
"}
usr << browse("[notedat]", "window=notes")
// call(/obj/item/weapon/book/tome/proc/edit_notes)()
else
usr << browse(null, "window=notes")
return
// proc/edit_notes() FUCK IT. Cant get it to work properly. - K0000
// world << "its been called! [usr]"
// notedat = {"
// <br><b>Word translation notes</b> <br>
// [words[1]] is <a href='byond://?src=\ref[src];number=1;action=change'>[words[words[1]]]</A> <A href='byond://?src=\ref[src];number=1;action=clear'>Clear</A><BR>
// [words[2]] is <A href='byond://?src=\ref[src];number=2;action=change'>[words[words[2]]]</A> <A href='byond://?src=\ref[src];number=2;action=clear'>Clear</A><BR>
// [words[3]] is <a href='byond://?src=\ref[src];number=3;action=change'>[words[words[3]]]</A> <A href='byond://?src=\ref[src];number=3;action=clear'>Clear</A><BR>
// [words[4]] is <a href='byond://?src=\ref[src];number=4;action=change'>[words[words[4]]]</A> <A href='byond://?src=\ref[src];number=4;action=clear'>Clear</A><BR>
// [words[5]] is <a href='byond://?src=\ref[src];number=5;action=change'>[words[words[5]]]</A> <A href='byond://?src=\ref[src];number=5;action=clear'>Clear</A><BR>
// [words[6]] is <a href='byond://?src=\ref[src];number=6;action=change'>[words[words[6]]]</A> <A href='byond://?src=\ref[src];number=6;action=clear'>Clear</A><BR>
// [words[7]] is <a href='byond://?src=\ref[src];number=7;action=change'>[words[words[7]]]</A> <A href='byond://?src=\ref[src];number=7;action=clear'>Clear</A><BR>
// [words[8]] is <a href='byond://?src=\ref[src];number=8;action=change'>[words[words[8]]]</A> <A href='byond://?src=\ref[src];number=8;action=clear'>Clear</A><BR>
// [words[9]] is <a href='byond://?src=\ref[src];number=9;action=change'>[words[words[9]]]</A> <A href='byond://?src=\ref[src];number=9;action=clear'>Clear</A><BR>
// [words[10]] is <a href='byond://?src=\ref[src];number=10;action=change'>[words[words[10]]]</A> <A href='byond://?src=\ref[src];number=10;action=clear'>Clear</A><BR>
// "}
// usr << "whatev"
// usr << browse(null, "window=tank")
New()
..()
if(!cultwords["travel"])
runerandom()
for(var/V in cultwords)
words[cultwords[V]] = V
attack(mob/living/M as mob, mob/living/user as mob)
@@ -378,7 +332,7 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
alert("The cloth of reality can't take that much of a strain. Remove some runes first!")
return
else
switch(alert("You open the tome",,"Read it","Scribe a rune", "Notes")) //Fuck the "Cancel" option. Rewrite the whole tome interface yourself if you want it to work better. And input() is just ugly. - K0000
switch(alert("You open the tome",,"Read it","Scribe a rune", "Cancel"))
if("Cancel")
return
if("Read it")
@@ -386,25 +340,6 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
return
user << browse("[tomedat]", "window=Arcane Tome")
return
if("Notes")
if(usr.get_active_hand() != src)
return
notedat = {"
<br><b>Word translation notes</b> <br>
[words[1]] is <a href='byond://?src=\ref[src];number=1;action=change'>[words[words[1]]]</A> <A href='byond://?src=\ref[src];number=1;action=clear'>Clear</A><BR>
[words[2]] is <A href='byond://?src=\ref[src];number=2;action=change'>[words[words[2]]]</A> <A href='byond://?src=\ref[src];number=2;action=clear'>Clear</A><BR>
[words[3]] is <a href='byond://?src=\ref[src];number=3;action=change'>[words[words[3]]]</A> <A href='byond://?src=\ref[src];number=3;action=clear'>Clear</A><BR>
[words[4]] is <a href='byond://?src=\ref[src];number=4;action=change'>[words[words[4]]]</A> <A href='byond://?src=\ref[src];number=4;action=clear'>Clear</A><BR>
[words[5]] is <a href='byond://?src=\ref[src];number=5;action=change'>[words[words[5]]]</A> <A href='byond://?src=\ref[src];number=5;action=clear'>Clear</A><BR>
[words[6]] is <a href='byond://?src=\ref[src];number=6;action=change'>[words[words[6]]]</A> <A href='byond://?src=\ref[src];number=6;action=clear'>Clear</A><BR>
[words[7]] is <a href='byond://?src=\ref[src];number=7;action=change'>[words[words[7]]]</A> <A href='byond://?src=\ref[src];number=7;action=clear'>Clear</A><BR>
[words[8]] is <a href='byond://?src=\ref[src];number=8;action=change'>[words[words[8]]]</A> <A href='byond://?src=\ref[src];number=8;action=clear'>Clear</A><BR>
[words[9]] is <a href='byond://?src=\ref[src];number=9;action=change'>[words[words[9]]]</A> <A href='byond://?src=\ref[src];number=9;action=clear'>Clear</A><BR>
[words[10]] is <a href='byond://?src=\ref[src];number=10;action=change'>[words[words[10]]]</A> <A href='byond://?src=\ref[src];number=10;action=clear'>Clear</A><BR>
"}
// call(/obj/item/weapon/book/tome/proc/edit_notes)()
user << browse("[notedat]", "window=notes")
return
if(usr.get_active_hand() != src)
return
@@ -489,21 +424,6 @@ var/global/list/rnwords = list("ire","ego","nahlizet","certum","veri","jatkaa","
user << "The book seems full of illegible scribbles. Is this a joke?"
return
attackby(obj/item/weapon/book/tome/T as obj, mob/living/user as mob)
if(istype(T, /obj/item/weapon/book/tome)) // sanity check to prevent a runtime error
switch(alert("Copy the runes from your tome?",,"Copy", "Cancel"))
if("cancel")
return
// var/list/nearby = viewers(1,src) //- Fuck this as well. No clue why this doesnt work. -K0000
// if (T.loc != user)
// return
// for(var/mob/M in nearby)
// if(M == user)
for(var/entry in words)
words[entry] = T.words[entry]
user << "You copy the translation notes from your tome."
examine(mob/user)
if(!iscultist(user))
user << "An old, dusty tome with frayed edges and a sinister looking cover."

View File

@@ -423,7 +423,7 @@ var/list/sacrificed = list()
L.ajourn=0
return
else
L.take_organ_damage(10, 0)
L.take_organ_damage(3, 0)
sleep(100)
return fizzle()

View File

@@ -1,5 +1,5 @@
/datum/game_mode/epidemic
name = "epidemic"
name = "Epidemic"
config_tag = "epidemic"
required_players = 1
required_players_secret = 15

View File

@@ -39,10 +39,6 @@ var/global/list/additional_antag_types = list()
/datum/game_mode/New()
..()
// Enforce some formatting.
// This will probably break something.
name = capitalize(lowertext(name))
config_tag = lowertext(config_tag)
/datum/game_mode/Topic(href, href_list[])
if(..())

View File

@@ -112,7 +112,7 @@ var/global/datum/controller/gameticker/ticker
tmpmodes+=M.name
tmpmodes = sortList(tmpmodes)
if(tmpmodes.len)
world << "<B>Possibilities:</B> [english_list(tmpmodes)]"
world << "<B>Possibilities:</B> [english_list(tmpmodes, and_text= "; ", comma_text = "; ")]"
else
src.mode.announce()

View File

@@ -5,7 +5,7 @@ VOX HEIST ROUNDTYPE
var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective. Clumsy, rewrite sometime.
/datum/game_mode/heist
name = "heist"
name = "Heist"
config_tag = "heist"
required_players = 15
required_players_secret = 15

View File

@@ -1,5 +1,5 @@
/datum/game_mode/malfunction
name = "AI malfunction"
name = "AI Malfunction"
round_description = "The AI is behaving abnormally and must be stopped."
extended_round_description = "The AI will attempt to hack the APCs around the station in order to gain as much control as possible."
config_tag = "malfunction"

View File

@@ -1,5 +1,5 @@
/datum/game_mode/conflux
name = "conflux"
name = "Wizard & Cult"
round_description = "A space wizard and a cult have invaded the station!"
extended_round_description = "Cultists and wizards spawn during this round."
config_tag = "conflux"

View File

@@ -1,5 +1,5 @@
/datum/game_mode/infestation
name = "infestation"
name = "Borers & Changelings"
round_description = "There's something in the walls!"
extended_round_description = "Two alien antagonists (Cortical Borers or Changelings) spawn during this round."
config_tag = "infestation"

View File

@@ -1,11 +1,11 @@
/datum/game_mode/intrigue
name = "Intrigue"
name = "Traitors & Ninja"
round_description = "Crewmembers are contacted by external elements while another infiltrates the colony."
extended_round_description = "Traitors and a ninja spawn during this round."
config_tag = "intrigue"
required_players = 15
required_players_secret = 15
required_enemies = 4
required_players = 6
required_players_secret = 8
required_enemies = 3
end_on_antag_death = 0
antag_tags = list(MODE_NINJA, MODE_AUTOTRAITOR)
round_autoantag = 1

View File

@@ -1,11 +1,11 @@
/datum/game_mode/lizard
name = "lizard"
name = "Wizard & Changelings"
round_description = "A space wizard and changelings have invaded the station!"
extended_round_description = "Changelings and a wizard spawn during this round."
config_tag = "lizard"
required_players = 15
required_players_secret = 15
required_enemies = 4
required_players = 2
required_players_secret = 8
required_enemies = 3
end_on_antag_death = 0
antag_tags = list(MODE_WIZARD, MODE_CHANGELING)
require_all_templates = 1

View File

@@ -0,0 +1,11 @@
/datum/game_mode/mercren
name = "Mercenaries & Renegades"
round_description = "A mercenary team has invaded the station, as well as other having brought their own form protection."
extended_round_description = "Mercenaries and traitors spawn during this round."
config_tag = "mercren"
required_players = 16 //What could possibly go wrong?
required_players_secret = 15
required_enemies = 8
end_on_antag_death = 0
antag_tags = list(MODE_MERCENARY, MODE_RENEGADE)
require_all_templates = 1

View File

@@ -0,0 +1,11 @@
/datum/game_mode/mercwiz
name = "Mercenaries & Wizard"
round_description = "A mercenary team and a wizard have invaded the station!"
extended_round_description = "Mercenaries and wizard spawn during this round."
config_tag = "mercwiz"
required_players = 15 //I don't think we can have it lower and not need an ERT every round.
required_players_secret = 15 //I don't think we can have it lower and not need an ERT every round.
required_enemies = 7
end_on_antag_death = 0
antag_tags = list(MODE_MERCENARY, MODE_WIZARD)
require_all_templates = 1

View File

@@ -1,5 +1,5 @@
/datum/game_mode/paranoia
name = "paranoia"
name = "Malf AI, Renegades & Changelings"
round_description = "The AI has malfunctioned, and subversive elements infest the crew..."
extended_round_description = "Rampant AIs, renegades and changelings spawn in this mode."
config_tag = "paranoia"

View File

@@ -1,5 +1,5 @@
/datum/game_mode/traitorling
name = "traitorling"
name = "Traitors & Changelings"
round_description = "There are traitors and alien changelings on the station. Do not let the changelings succeed!"
extended_round_description = "Traitors and changelings both spawn during this mode."
config_tag = "traitorling"

View File

@@ -0,0 +1,11 @@
/datum/game_mode/traitorren
name = "Traitors & Renegades"
round_description = "Subversive elements have invaded the station, and certain individuals are feeling uncertain about their safety."
extended_round_description = "Traitors and renegades spawn during this round."
config_tag = "traitorren"
required_players = 10 //I don't think we can have it lower and not need an ERT every round.
required_players_secret = 11 //I don't think we can have it lower and not need an ERT every round.
required_enemies = 4
end_on_antag_death = 0
antag_tags = list(MODE_TRAITOR, MODE_RENEGADE)
require_all_templates = 1

View File

@@ -1,5 +1,5 @@
/datum/game_mode/uprising
name = "uprising"
name = "Revolution & Cult"
config_tag = "uprising"
round_description = "Some crewmembers are attempting to start a revolution while a cult plots in the shadows!"
extended_round_description = "Cultists and revolutionaries spawn in this round."

View File

@@ -1,10 +1,10 @@
/datum/game_mode/visitors
name = "Visitors"
name = "Wizard & Ninja"
round_description = "A space wizard and a ninja have invaded the station!"
extended_round_description = "A ninja and wizard spawn during this round."
config_tag = "visitors"
required_players = 10
required_players_secret = 10
required_players = 6
required_players_secret = 6
required_enemies = 2
end_on_antag_death = 0
antag_tags = list(MODE_WIZARD, MODE_NINJA)

View File

@@ -1,5 +1,5 @@
/datum/game_mode/ninja
name = "ninja"
name = "Ninja"
round_description = "An agent of the Spider Clan is onboard the station!"
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. \

View File

@@ -1,5 +1,5 @@
/datum/game_mode/sandbox
name = "sandbox"
name = "Sandbox"
config_tag = "sandbox"
required_players = 0
votable = 0

View File

@@ -19,6 +19,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
minimal_player_age = 14
economic_modifier = 20
minimum_character_age = 25
ideal_character_age = 70 // Old geezer captains ftw
@@ -67,6 +68,8 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
req_admin_notify = 1
minimal_player_age = 10
economic_modifier = 10
minimum_character_age = 25
ideal_character_age = 50
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,

View File

@@ -188,12 +188,13 @@
department = "Civilian"
department_flag = CIVILIAN
faction = "Station"
total_positions = 1
spawn_positions = 1
total_positions = 2
spawn_positions = 2
supervisors = "the head of personnel"
selection_color = "#dddddd"
access = list(access_janitor, access_maint_tunnels)
minimal_access = list(access_janitor, access_maint_tunnels)
alt_titles = list("Custodian")
equip(var/mob/living/carbon/human/H)

View File

@@ -13,6 +13,7 @@
req_admin_notify = 1
economic_modifier = 10
minimum_character_age = 25
ideal_character_age = 50

View File

@@ -19,6 +19,7 @@
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
minimum_character_age = 25
minimal_player_age = 10
ideal_character_age = 50

View File

@@ -21,6 +21,7 @@
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch)
minimum_character_age = 25
minimal_player_age = 14
ideal_character_age = 50
@@ -124,7 +125,7 @@
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/rank/roboticist(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/roboticist(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/toolbox/mechanical(H), slot_l_hand)
H.equip_to_slot_or_del(new /obj/item/device/pda/roboticist(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(H), slot_belt)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/toggle/labcoat(H), slot_wear_suit)
return 1
return 1

View File

@@ -20,6 +20,7 @@
access_forensics_lockers, access_morgue, access_maint_tunnels, access_all_personal_lockers,
access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_external_airlocks)
minimum_character_age = 25
minimal_player_age = 14
equip(var/mob/living/carbon/human/H)
@@ -92,7 +93,7 @@
spawn_positions = 2
supervisors = "the head of security"
selection_color = "#ffeeee"
alt_titles = list("Forensic Technician")
alt_titles = list("Forensic Technician","Investigator")
access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks)
minimal_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_eva, access_external_airlocks)
economic_modifier = 5
@@ -119,6 +120,7 @@
else
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_trench(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/head/det(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/weapon/storage/briefcase/crimekit(H), slot_r_hand)
return 1

View File

@@ -111,7 +111,7 @@ var/global/datum/controller/occupations/job_master
if(istype(job, GetJob("Assistant"))) // We don't want to give him assistant, that's boring!
continue
if(job in command_positions) //If you want a command position, select it!
if(job.title in command_positions) //If you want a command position, select it!
continue
if(jobban_isbanned(player, job.title))
@@ -331,7 +331,6 @@ var/global/datum/controller/occupations/job_master
var/list/custom_equip_slots = list() //If more than one item takes the same slot, all after the first one spawn in storage.
var/list/custom_equip_leftovers = list()
if(H.client.prefs.gear && H.client.prefs.gear.len && job.title != "Cyborg" && job.title != "AI")
for(var/thing in H.client.prefs.gear)
var/datum/gear/G = gear_datums[thing]
if(G)
@@ -353,10 +352,11 @@ var/global/datum/controller/occupations/job_master
if(G.slot && !(G.slot in custom_equip_slots))
// This is a miserable way to fix the loadout overwrite bug, but the alternative requires
// adding an arg to a bunch of different procs. Will look into it after this merge. ~ Z
var/metadata = H.client.prefs.gear[G.display_name]
if(G.slot == slot_wear_mask || G.slot == slot_wear_suit || G.slot == slot_head)
custom_equip_leftovers += thing
else if(H.equip_to_slot_or_del(new G.path(H), G.slot))
H << "<span class='notice'>Equipping you with [thing]!</span>"
else if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
H << "<span class='notice'>Equipping you with \the [thing]!</span>"
custom_equip_slots.Add(G.slot)
else
custom_equip_leftovers.Add(thing)
@@ -375,8 +375,9 @@ var/global/datum/controller/occupations/job_master
if(G.slot in custom_equip_slots)
spawn_in_storage += thing
else
if(H.equip_to_slot_or_del(new G.path(H), G.slot))
H << "<span class='notice'>Equipping you with [thing]!</span>"
var/metadata = H.client.prefs.gear[G.display_name]
if(H.equip_to_slot_or_del(G.spawn_item(H, metadata), G.slot))
H << "<span class='notice'>Equipping you with \the [thing]!</span>"
custom_equip_slots.Add(G.slot)
else
spawn_in_storage += thing
@@ -439,9 +440,10 @@ var/global/datum/controller/occupations/job_master
if(!isnull(B))
for(var/thing in spawn_in_storage)
H << "<span class='notice'>Placing [thing] in your [B]!</span>"
H << "<span class='notice'>Placing \the [thing] in your [B.name]!</span>"
var/datum/gear/G = gear_datums[thing]
new G.path(B)
var/metadata = H.client.prefs.gear[G.display_name]
G.spawn_item(B, metadata)
else
H << "<span class='danger'>Failed to locate a storage object on your mob, either you spawned with no arms and no backpack or this is a bug.</span>"

View File

@@ -54,6 +54,7 @@
var/wiresexposed = 0 // If it's been screwdrivered open.
var/aidisabled = 0
var/shorted = 0
circuit = /obj/item/weapon/circuitboard/airalarm
var/datum/wires/alarm/wires
@@ -61,7 +62,6 @@
var/screen = AALARM_SCREEN_MAIN
var/area_uid
var/area/alarm_area
var/buildstage = 2 //2 is built, 1 is building, 0 is frame.
var/target_temperature = T0C+20
var/regulating_temperature = 0
@@ -105,23 +105,8 @@
wires = null
return ..()
/obj/machinery/alarm/New(var/loc, var/dir, var/building = 0)
/obj/machinery/alarm/New()
..()
if(building)
if(loc)
src.loc = loc
if(dir)
src.set_dir(dir)
buildstage = 0
wiresexposed = 1
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
update_icon()
return
first_run()
/obj/machinery/alarm/proc/first_run()
@@ -148,7 +133,7 @@
elect_master()
/obj/machinery/alarm/process()
if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2)
if((stat & (NOPOWER|BROKEN)) || shorted)
return
var/turf/simulated/location = loc
@@ -605,9 +590,6 @@
data["thresholds"] = thresholds
/obj/machinery/alarm/CanUseTopic(var/mob/user, var/datum/topic_state/state, var/href_list = list())
if(buildstage != 2)
return STATUS_CLOSE
if(aidisabled && isAI(user))
user << "<span class='warning'>AI control for \the [src] interface has been disabled.</span>"
return STATUS_CLOSE
@@ -763,73 +745,43 @@
/obj/machinery/alarm/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)
if(istype(W, /obj/item/weapon/screwdriver)) // Opening that Air Alarm up.
//user << "You pop the Air Alarm's maintence panel open."
wiresexposed = !wiresexposed
user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
update_icon()
return
switch(buildstage)
if(2)
if(istype(W, /obj/item/weapon/screwdriver)) // Opening that Air Alarm up.
//user << "You pop the Air Alarm's maintence panel open."
wiresexposed = !wiresexposed
user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
update_icon()
return
if (wiresexposed && istype(W, /obj/item/weapon/wirecutters))
user.visible_message("<span class='warning'>[user] has cut the wires inside \the [src]!</span>", "You have cut the wires inside \the [src].")
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
new/obj/item/stack/cable_coil(get_turf(src), 5)
var/obj/structure/frame/A = new /obj/structure/frame( src.loc )
var/obj/item/weapon/circuitboard/M = new circuit( A )
A.frame_type = "airalarm"
A.pixel_x = pixel_x
A.pixel_y = pixel_y
A.set_dir(dir)
A.circuit = M
A.anchored = 1
for (var/obj/C in src)
C.forceMove(loc)
A.state = 2
A.icon_state = "airalarm_2"
M.deconstruct(src)
qdel(src)
return
if (wiresexposed && istype(W, /obj/item/weapon/wirecutters))
user.visible_message("<span class='warning'>[user] has cut the wires inside \the [src]!</span>", "You have cut the wires inside \the [src].")
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
new/obj/item/stack/cable_coil(get_turf(src), 5)
buildstage = 1
update_icon()
return
if (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card
if(stat & (NOPOWER|BROKEN))
user << "It does nothing"
return
else
if(allowed(usr) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN))
locked = !locked
user << "<span class='notice'>You [ locked ? "lock" : "unlock"] the Air Alarm interface.</span>"
else
user << "<span class='warning'>Access denied.</span>"
if (istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))// trying to unlock the interface with an ID card
if(stat & (NOPOWER|BROKEN))
user << "It does nothing"
return
if(1)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if (C.use(5))
user << "<span class='notice'>You wire \the [src].</span>"
buildstage = 2
update_icon()
first_run()
return
else
user << "<span class='warning'>You need 5 pieces of cable to do wire \the [src].</span>"
return
else if(istype(W, /obj/item/weapon/crowbar))
user << "You start prying out the circuit."
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
if(do_after(user,20))
user << "You pry out the circuit!"
var/obj/item/weapon/airalarm_electronics/circuit = new /obj/item/weapon/airalarm_electronics()
circuit.loc = user.loc
buildstage = 0
update_icon()
return
if(0)
if(istype(W, /obj/item/weapon/airalarm_electronics))
user << "You insert the circuit!"
qdel(W)
buildstage = 1
update_icon()
return
else if(istype(W, /obj/item/weapon/wrench))
user << "You remove the fire alarm assembly from the wall!"
new /obj/item/frame/air_alarm(get_turf(user))
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
qdel(src)
else
if(allowed(usr) && !wires.IsIndexCut(AALARM_WIRE_IDSCAN))
locked = !locked
user << "<span class='notice'>You [ locked ? "lock" : "unlock"] the Air Alarm interface.</span>"
else
user << "<span class='warning'>Access denied.</span>"
return ..()
/obj/machinery/alarm/power_change()
@@ -839,14 +791,10 @@
/obj/machinery/alarm/examine(mob/user)
..(user)
if (buildstage < 2)
user << "It is not wired."
if (buildstage < 1)
user << "The circuit is missing."
/*
AIR ALARM CIRCUIT
Just a object used in constructing air alarms
*/
/obj/item/weapon/airalarm_electronics
name = "air alarm electronics"
icon = 'icons/obj/doors/door_assembly.dmi'
@@ -854,7 +802,7 @@ Just a object used in constructing air alarms
desc = "Looks like a circuit. Probably is."
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
*/
/*
FIRE ALARM
*/
@@ -875,20 +823,13 @@ FIRE ALARM
power_channel = ENVIRON
var/last_process = 0
var/wiresexposed = 0
var/buildstage = 2 // 2 = complete, 1 = no wires, 0 = circuit gone
var/seclevel
circuit = /obj/item/weapon/circuitboard/firealarm
/obj/machinery/firealarm/update_icon()
overlays.Cut()
if(wiresexposed)
switch(buildstage)
if(2)
icon_state="fire_b2"
if(1)
icon_state="fire_b1"
if(0)
icon_state="fire_b0"
set_light(0)
return
@@ -932,56 +873,36 @@ FIRE ALARM
/obj/machinery/firealarm/attackby(obj/item/W as obj, mob/user as mob)
src.add_fingerprint(user)
if (istype(W, /obj/item/weapon/screwdriver) && buildstage == 2)
if (istype(W, /obj/item/weapon/screwdriver))
wiresexposed = !wiresexposed
update_icon()
return
if(wiresexposed)
switch(buildstage)
if(2)
if (istype(W, /obj/item/device/multitool))
src.detecting = !( src.detecting )
if (src.detecting)
user.visible_message("<span class='notice'>\The [user] has reconnected [src]'s detecting unit!</span>", "<span class='notice'>You have reconnected [src]'s detecting unit.</span>")
else
user.visible_message("<span class='notice'>\The [user] has disconnected [src]'s detecting unit!</span>", "<span class='notice'>You have disconnected [src]'s detecting unit.</span>")
else if (istype(W, /obj/item/weapon/wirecutters))
user.visible_message("<span class='notice'>\The [user] has cut the wires inside \the [src]!</span>", "<span class='notice'>You have cut the wires inside \the [src].</span>")
new/obj/item/stack/cable_coil(get_turf(src), 5)
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
buildstage = 1
update_icon()
if(1)
if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if (C.use(5))
user << "<span class='notice'>You wire \the [src].</span>"
buildstage = 2
return
else
user << "<span class='warning'>You need 5 pieces of cable to wire \the [src].</span>"
return
else if(istype(W, /obj/item/weapon/crowbar))
user << "You pry out the circuit!"
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
spawn(20)
var/obj/item/weapon/firealarm_electronics/circuit = new /obj/item/weapon/firealarm_electronics()
circuit.loc = user.loc
buildstage = 0
update_icon()
if(0)
if(istype(W, /obj/item/weapon/firealarm_electronics))
user << "You insert the circuit!"
qdel(W)
buildstage = 1
update_icon()
else if(istype(W, /obj/item/weapon/wrench))
user << "You remove the fire alarm assembly from the wall!"
new /obj/item/frame/fire_alarm(get_turf(user))
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
qdel(src)
if (istype(W, /obj/item/device/multitool))
src.detecting = !( src.detecting )
if (src.detecting)
user.visible_message("<span class='notice'>\The [user] has reconnected [src]'s detecting unit!</span>", "<span class='notice'>You have reconnected [src]'s detecting unit.</span>")
else
user.visible_message("<span class='notice'>\The [user] has disconnected [src]'s detecting unit!</span>", "<span class='notice'>You have disconnected [src]'s detecting unit.</span>")
else if (istype(W, /obj/item/weapon/wirecutters))
user.visible_message("<span class='notice'>\The [user] has cut the wires inside \the [src]!</span>", "<span class='notice'>You have cut the wires inside \the [src].</span>")
new/obj/item/stack/cable_coil(get_turf(src), 5)
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
var/obj/structure/frame/A = new /obj/structure/frame( src.loc )
var/obj/item/weapon/circuitboard/M = new circuit( A )
A.frame_type = "firealarm"
A.pixel_x = pixel_x
A.pixel_y = pixel_y
A.set_dir(dir)
A.circuit = M
A.anchored = 1
for (var/obj/C in src)
C.forceMove(loc)
A.state = 2
A.icon_state = "firealarm_2"
M.deconstruct(src)
qdel(src)
return
src.alarm()
@@ -1016,9 +937,6 @@ FIRE ALARM
if(user.stat || stat & (NOPOWER|BROKEN))
return
if (buildstage != 2)
return
user.set_machine(src)
var/area/A = src.loc
var/d1
@@ -1061,9 +979,6 @@ FIRE ALARM
if (usr.stat || stat & (BROKEN|NOPOWER))
return
if (buildstage != 2)
return
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
usr.set_machine(src)
if (href_list["reset"])
@@ -1106,23 +1021,6 @@ FIRE ALARM
//playsound(src.loc, 'sound/ambience/signal.ogg', 75, 0)
return
/obj/machinery/firealarm/New(loc, dir, building)
..()
if(loc)
src.loc = loc
if(dir)
src.set_dir(dir)
if(building)
buildstage = 0
wiresexposed = 1
pixel_x = (dir & 3)? 0 : (dir == 4 ? -24 : 24)
pixel_y = (dir & 3)? (dir ==1 ? -24 : 24) : 0
/obj/machinery/firealarm/proc/set_security_level(var/newlevel)
if(seclevel != newlevel)
seclevel = newlevel
@@ -1135,7 +1033,7 @@ FIRE ALARM
/*
FIRE ALARM CIRCUIT
Just a object used in constructing fire alarms
*/
/obj/item/weapon/firealarm_electronics
name = "fire alarm electronics"
icon = 'icons/obj/doors/door_assembly.dmi'
@@ -1143,7 +1041,7 @@ Just a object used in constructing fire alarms
desc = "A circuit. It has a label on it, it says \"Can handle heat levels up to 40 degrees celsius!\""
w_class = 2.0
matter = list(DEFAULT_WALL_MATERIAL = 50, "glass" = 50)
*/
/obj/machinery/partyalarm
name = "\improper PARTY BUTTON"
desc = "Cuban Pete is in the house!"

View File

@@ -7,7 +7,7 @@
use_power = 1
idle_power_usage = 10
active_power_usage = 2000
circuit = /obj/item/weapon/circuitboard/autolathe
var/list/machine_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0)
@@ -30,14 +30,13 @@
wires = new(src)
//Create parts for lathe.
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/autolathe(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/console_screen(src)
RefreshParts()
/obj/machinery/autolathe/Destroy()
qdel(wires)
wires = null

View File

@@ -158,12 +158,12 @@
/datum/autolathe/recipe/airalarm
name = "air alarm electronics"
path = /obj/item/weapon/airalarm_electronics
path = /obj/item/weapon/circuitboard/airalarm
category = "Engineering"
/datum/autolathe/recipe/firealarm
name = "fire alarm electronics"
path = /obj/item/weapon/firealarm_electronics
path = /obj/item/weapon/circuitboard/firealarm
category = "Engineering"
/datum/autolathe/recipe/powermodule
@@ -171,6 +171,96 @@
path = /obj/item/weapon/module/power_control
category = "Engineering"
/datum/autolathe/recipe/statusdisplay
name = "status display electronics"
path = /obj/item/weapon/circuitboard/status_display
category = "Engineering"
/datum/autolathe/recipe/aistatusdisplay
name = "ai status display electronics"
path = /obj/item/weapon/circuitboard/ai_status_display
category = "Engineering"
/datum/autolathe/recipe/newscaster
name = "newscaster electronics"
path = /obj/item/weapon/circuitboard/newscaster
category = "Engineering"
/datum/autolathe/recipe/atm
name = "atm electronics"
path = /obj/item/weapon/circuitboard/atm
category = "Engineering"
/datum/autolathe/recipe/intercom
name = "intercom electronics"
path = /obj/item/weapon/circuitboard/intercom
category = "Engineering"
/datum/autolathe/recipe/holopad
name = "holopad electronics"
path = /obj/item/weapon/circuitboard/holopad
category = "Engineering"
/datum/autolathe/recipe/guestpass
name = "guestpass console electronics"
path = /obj/item/weapon/circuitboard/guestpass
category = "Engineering"
/datum/autolathe/recipe/entertainment
name = "entertainment camera electronics"
path = /obj/item/weapon/circuitboard/security/telescreen/entertainment
category = "Engineering"
/datum/autolathe/recipe/keycard
name = "keycard authenticator electronics"
path = /obj/item/weapon/circuitboard/keycard_auth
category = "Engineering"
/datum/autolathe/recipe/photocopier
name = "photocopier electronics"
path = /obj/item/weapon/circuitboard/photocopier
category = "Engineering"
/datum/autolathe/recipe/fax
name = "fax machine electronics"
path = /obj/item/weapon/circuitboard/fax
category = "Engineering"
/datum/autolathe/recipe/conveyor
name = "conveyor electronics"
path = /obj/item/weapon/circuitboard/conveyor
category = "Engineering"
/datum/autolathe/recipe/microwave
name = "microwave electronics"
path = /obj/item/weapon/circuitboard/microwave
category = "Engineering"
/datum/autolathe/recipe/vending
name = "vending machine electronics"
path = /obj/item/weapon/circuitboard/vending
category = "Engineering"
/datum/autolathe/recipe/washing
name = "washing machine electronics"
path = /obj/item/weapon/circuitboard/washing
category = "Engineering"
/datum/autolathe/recipe/motor
name = "motor"
path = /obj/item/weapon/stock_parts/motor
category = "Engineering"
/datum/autolathe/recipe/gear
name = "gear"
path = /obj/item/weapon/stock_parts/gear
category = "Engineering"
/datum/autolathe/recipe/spring
name = "spring"
path = /obj/item/weapon/stock_parts/spring
category = "Engineering"
/datum/autolathe/recipe/rcd_ammo
name = "matter cartridge"
path = /obj/item/weapon/rcd_ammo

View File

@@ -5,6 +5,7 @@
icon_state = "biogen-stand"
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/biogenerator
use_power = 1
idle_power_usage = 40
var/processing = 0
@@ -23,7 +24,6 @@
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/biogenerator(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
@@ -106,9 +106,9 @@
dat += "<A href='?src=\ref[src];action=create;item=milk;cost=20'>10 milk</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=meat;cost=50'>Slab of meat</A> <FONT COLOR=blue>([round(50/build_eff)])</FONT><BR>"
dat += "Nutrient<BR>"
dat += "<A href='?src=\ref[src];action=create;item=ez;cost=10'>E-Z-Nutrient</A> <FONT COLOR=blue>([round(10/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=ez5;cost=50'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=l4z;cost=20'>Left 4 Zed</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=l4z5;cost=100'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=rh;cost=25'>Robust Harvest</A> <FONT COLOR=blue>([round(25/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=rh5;cost=125'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=ez;cost=60'>E-Z-Nutrient</A> <FONT COLOR=blue>([round(10/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=ez5;cost=300'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=l4z;cost=120'>Left 4 Zed</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=l4z5;cost=600'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=rh;cost=150'>Robust Harvest</A> <FONT COLOR=blue>([round(25/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=rh5;cost=750'>x5</A><BR>"
dat += "Leather<BR>"
dat += "<A href='?src=\ref[src];action=create;item=wallet;cost=100'>Wallet</A> <FONT COLOR=blue>([round(100/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=gloves;cost=250'>Botanical gloves</A> <FONT COLOR=blue>([round(250/build_eff)])</FONT><BR>"
@@ -179,29 +179,29 @@
if("meat")
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
if("ez")
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
if("l4z")
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
if("rh")
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
if("ez5") //It's not an elegant method, but it's safe and easy. -Cheridan
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
if("l4z5")
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
if("rh5")
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
if("wallet")
new/obj/item/weapon/storage/wallet(loc)
if("gloves")

View File

@@ -30,6 +30,7 @@
desc = "An electronically-lockable pod for growing organic tissue."
density = 1
anchored = 1
circuit = /obj/item/weapon/circuitboard/clonepod
icon = 'icons/obj/cloning.dmi'
icon_state = "pod_0"
req_access = list(access_genetics) //For premature unlocking.
@@ -47,7 +48,6 @@
/obj/machinery/clonepod/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/clonepod(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/scanning_module(src)

View File

@@ -393,14 +393,14 @@
dat += "<br>You ran out of food and starved."
if(emagged)
user.nutrition = 0 //yeah you pretty hongry
user << "<span class='danger'><font size=3>Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor.</span>"
user << "<span class='danger'><font size=3>Your body instantly contracts to that of one who has not eaten in months. Agonizing cramps seize you as you fall to the floor.</font></span>"
if(fuel <= 0)
dat += "<br>You ran out of fuel, and drift, slowly, into a star."
if(emagged)
var/mob/living/M = user
M.adjust_fire_stacks(5)
M.IgniteMob() //flew into a star, so you're on fire
user << "<span class='danger'><font size=3>You feel an immense wave of heat emanate from \the [src]. Your skin bursts into flames.</span>"
user << "<span class='danger'><font size=3>You feel an immense wave of heat emanate from \the [src]. Your skin bursts into flames.</font></span>"
dat += "<br><P ALIGN=Right><a href='byond://?src=\ref[src];menu=1'>OK...</a></P>"
if(emagged)

View File

@@ -215,7 +215,8 @@
icon_screen = "entertainment"
light_color = "#FFEEDB"
light_range_on = 2
circuit = null
network = list(NETWORK_THUNDER)
circuit = /obj/item/weapon/circuitboard/security/telescreen/entertainment
/obj/machinery/computer/security/wooden_tv
name = "security camera monitor"
desc = "An old TV hooked into the stations camera network."

View File

@@ -7,7 +7,7 @@
use_power = 1
idle_power_usage = 300
active_power_usage = 300
var/circuit = null //The path to the circuit board type. If circuit==null, the computer can't be disassembled.
frame_type = "computer"
var/processing = 0
var/icon_keyboard = "generic_key"
@@ -98,23 +98,28 @@
/obj/machinery/computer/attackby(I as obj, user as mob)
if(istype(I, /obj/item/weapon/screwdriver) && circuit)
user << "<span class='notice'>You start disconnecting the monitor.</span>"
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, 20))
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
var/obj/structure/frame/A = new /obj/structure/frame( src.loc )
var/obj/item/weapon/circuitboard/M = new circuit( A )
A.circuit = M
A.anchored = 1
A.density = 1
A.frame_type = M.board_type
for (var/obj/C in src)
C.loc = src.loc
C.forceMove(loc)
if (src.stat & BROKEN)
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"
A.icon_state = "[A.frame_type]_3"
else
user << "<span class='notice'>You disconnect the monitor.</span>"
A.state = 4
A.icon_state = "4"
A.icon_state = "[A.frame_type]_4"
A.pixel_x = pixel_x
A.pixel_y = pixel_y
M.deconstruct(src)
qdel(src)
else

View File

@@ -46,6 +46,7 @@
icon_keyboard = null
icon_screen = "pass"
density = 0
circuit = /obj/item/weapon/circuitboard/guestpass
var/obj/item/weapon/card/id/giver
var/list/accesses = list()
@@ -60,10 +61,29 @@
..()
uid = "[rand(100,999)]-G[rand(10,99)]"
/obj/machinery/computer/guestpass/attackby(obj/O, mob/user)
if(istype(O, /obj/item/weapon/card/id))
if(!giver && user.removeItem(O, src))
giver = O
/obj/machinery/computer/guestpass/attackby(obj/I, mob/user)
if(istype(I, /obj/item/weapon/screwdriver) && circuit)
user << "<span class='notice'>You start disconnecting the monitor.</span>"
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, 20))
var/obj/structure/frame/A = new /obj/structure/frame( src.loc )
var/obj/item/weapon/circuitboard/M = new circuit( A )
A.frame_type = "guestpass"
A.pixel_x = pixel_x
A.pixel_y = pixel_y
A.circuit = M
A.anchored = 1
for (var/obj/C in src)
C.forceMove(loc)
user << "<span class='notice'>You disconnect the monitor.</span>"
A.state = 4
A.icon_state = "guestpass_4"
M.deconstruct(src)
qdel(src)
return
if(istype(I, /obj/item/weapon/card/id))
if(!giver && user.removeItem(I, src))
giver = I
updateUsrDialog()
else if(giver)
user << "<span class='warning'>There is already ID card inside.</span>"
@@ -134,8 +154,12 @@
var/A = text2num(href_list["access"])
if (A in accesses)
accesses.Remove(A)
else
accesses.Add(A)
else
if(A in giver.access) //Let's make sure the ID card actually has the access.
accesses.Add(A)
else
usr << "<span class='warning'>Invalid selection, please consult technical support if there are any issues.</span>"
log_debug("[key_name_admin(usr)] tried selecting an invalid guest pass terminal option.")
if (href_list["action"])
switch(href_list["action"])
if ("id")

View File

@@ -26,32 +26,6 @@ var/prison_shuttle_timeleft = 0
attack_ai(var/mob/user as mob)
return src.attack_hand(user)
attackby(I as obj, user as mob)
if(istype(I, /obj/item/weapon/screwdriver))
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
if(do_after(user, 20))
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
var/obj/item/weapon/circuitboard/prison_shuttle/M = new /obj/item/weapon/circuitboard/prison_shuttle( A )
for (var/obj/C in src)
C.loc = src.loc
A.circuit = M
A.anchored = 1
if (src.stat & BROKEN)
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 << "<span class='notice'>You disconnect the monitor.</span>"
A.state = 4
A.icon_state = "4"
qdel(src)
else
return src.attack_hand(user)
attack_hand(var/mob/user as mob)
if(!src.allowed(user) && (!hacked))
user << "<span class='warning'>Access Denied.</span>"

View File

@@ -91,7 +91,7 @@
if(!target || !istype(target))
return
var/istraitor = traitors.is_antagonist(target.mind)
var/istraitor = target.mind.special_role
if (istraitor)
target.lockcharge = !target.lockcharge
if (target.lockcharge)
@@ -187,7 +187,7 @@
robot["name"] = R.name
if(R.stat)
robot["status"] = "Not Responding"
else if (!R.canmove)
else if (R.lockcharge)
robot["status"] = "Lockdown"
else
robot["status"] = "Operational"

View File

@@ -29,7 +29,7 @@
// when you had to search the list to find what you had.
// Mostly decorative, holds the OS rom
var/obj/item/part/computer/circuitboard/circuit
var/obj/item/part/computer/circuitboard/circuitb
// Storage
var/obj/item/part/computer/storage/hdd/hdd = null
@@ -97,11 +97,11 @@
overlays += kb
if(!built)
if(!circuit || !istype(circuit))
circuit = new(src)
if(circuit.OS)
os = circuit.OS
circuit.OS.computer = src
if(!circuitb || !istype(circuitb))
circuitb = new(src)
if(circuitb.OS)
os = circuitb.OS
circuitb.OS.computer = src
else
os = null
@@ -121,10 +121,10 @@
floppy.addfile(P)
program = P
else
circuit.OS = P
circuit.OS.computer = src
os = circuit.OS
circuit.name = "Circuitboard ([P])"
circuitb.OS = P
circuitb.OS.computer = src
os = circuitb.OS
circuitb.name = "Circuitboard ([P])"
if(hdd) // Spawn files

View File

@@ -26,7 +26,7 @@
New()
..(built=0)
os = program
circuit.OS = os
circuitb.OS = os
/obj/machinery/computer3/security/mining

View File

@@ -63,10 +63,9 @@
return 1
/obj/machinery/atmospherics/unary/cryo_cell/relaymove(mob/user as mob)
if(user.stat)
return
go_out()
return
// note that relaymove will also be called for mobs outside the cell with UI open
if(src.occupant == user && !user.stat)
go_out()
/obj/machinery/atmospherics/unary/cryo_cell/attack_hand(mob/user)
ui_interact(user)

View File

@@ -219,7 +219,7 @@
var/disallow_occupant_types = list()
var/mob/occupant = null // Person waiting to be despawned.
var/time_till_despawn = 18000 // 30 minutes-ish safe period before being despawned.
var/time_till_despawn = 9000 // Down to 15 minutes //30 minutes-ish is too long
var/time_entered = 0 // Used to keep track of the safe period.
var/obj/item/device/radio/intercom/announce //
@@ -486,32 +486,33 @@
if(istype(G, /obj/item/weapon/grab))
var/obj/item/weapon/grab/grab = G
if(occupant)
user << "<span class='notice'>\The [src] is in use.</span>"
return
if(!ismob(G:affecting))
if(!ismob(grab.affecting))
return
if(!check_occupant_allowed(G:affecting))
if(!check_occupant_allowed(grab.affecting))
return
var/willing = null //We don't want to allow people to be forced into despawning.
var/mob/M = G:affecting
var/mob/M = grab.affecting
if(M.client)
if(alert(M,"Would you like to enter long-term storage?",,"Yes","No") == "Yes")
if(!M || !G || !G:affecting) return
if(!M || !grab || !grab:affecting) return
willing = 1
else
willing = 1
if(willing)
visible_message("[user] starts putting [G:affecting:name] into \the [src].", 3)
visible_message("\The [user] starts putting [grab:affecting:name] into \the [src].", 3)
if(do_after(user, 20))
if(!M || !G || !G:affecting) return
if(!M || !grab || !grab:affecting) return
M.forceMove(src)

View File

@@ -808,23 +808,23 @@ About the new airlock wires panel:
else
spawn(0) close(1)
else if(istype(C, /obj/item/weapon/material/twohanded/fireaxe) && !arePowerSystemsOn())
// Check if we're using a crowbar or armblade, and if the airlock's unpowered for whatever reason (off, broken, etc).
else if( (istype(C, /obj/item/weapon/material/twohanded/fireaxe) || istype(C, /obj/item/weapon/melee/arm_blade) ) && !arePowerSystemsOn())
if(locked)
user << "<span class='notice'>The airlock's bolts prevent it from being forced.</span>"
else if( !welded && !operating )
if(istype(C, /obj/item/weapon/material/twohanded/fireaxe)) // If this is a fireaxe, make sure it's held in two hands.
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(!F.wielded)
user << "<span class='warning'>You need to be wielding \the [F] to do that.</span>"
return
// At this point, it's an armblade or a fireaxe that passed the wielded test, let's try to open it.
if(density)
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(F.wielded)
spawn(0) open(1)
else
user << "<span class='warning'>You need to be wielding \the [C] to do that.</span>"
spawn(0)
open(1)
else
var/obj/item/weapon/material/twohanded/fireaxe/F = C
if(F.wielded)
spawn(0) close(1)
else
user << "<span class='warning'>You need to be wielding \the [C] to do that.</span>"
spawn(0)
close(1)
else
..()
return

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