Merge branch 'master' into upstream-merge-29741
This commit is contained in:
@@ -19,3 +19,6 @@
|
||||
#define ANTAG_DATUM_IAA_AI_CUSTOM /datum/antagonist/traitor/AI/internal_affairs/custom
|
||||
#define ANTAG_DATUM_IAA_AI /datum/antagonist/traitor/AI/internal_affairs
|
||||
#define ANTAG_DATUM_BROTHER /datum/antagonist/brother
|
||||
#define ANTAG_DATUM_ABDUCTOR /datum/antagonist/abductor
|
||||
#define ANTAG_DATUM_ABDUCTOR_SCIENTIST /datum/antagonist/abductor/scientist
|
||||
#define ANTAG_DATUM_ABDUCTOR_AGENT /datum/antagonist/abductor/agent
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#define CINEMATIC_DEFAULT 1
|
||||
#define CINEMATIC_SELFDESTRUCT 2
|
||||
#define CINEMATIC_SELFDESTRUCT_MISS 3
|
||||
#define CINEMATIC_NUKE_WIN 4
|
||||
#define CINEMATIC_NUKE_MISS 5
|
||||
#define CINEMATIC_ANNIHILATION 6
|
||||
#define CINEMATIC_MALF 7
|
||||
#define CINEMATIC_CULT 8
|
||||
#define CINEMATIC_NUKE_FAKE 9
|
||||
#define CINEMATIC_NUKE_NO_CORE 10
|
||||
#define CINEMATIC_NUKE_FAR 11
|
||||
@@ -12,6 +12,7 @@
|
||||
#define HIGH_TURF_LAYER 2.03
|
||||
#define ABOVE_OPEN_TURF_LAYER 2.04
|
||||
#define CLOSED_TURF_LAYER 2.05
|
||||
#define BULLET_HOLE_LAYER 2.06
|
||||
#define ABOVE_NORMAL_TURF_LAYER 2.08
|
||||
#define LATTICE_LAYER 2.2
|
||||
#define DISPOSAL_PIPE_LAYER 2.3
|
||||
|
||||
@@ -474,7 +474,7 @@
|
||||
#error Remie said that lummox was adding a way to get a lists
|
||||
#error contents via list.values, if that is true remove this
|
||||
#error otherwise, update the version and bug lummox
|
||||
#elseif
|
||||
#endif
|
||||
//Flattens a keyed list into a list of it's contents
|
||||
/proc/flatten_list(list/key_list)
|
||||
if(!islist(key_list))
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
/client/proc/file_spam_check()
|
||||
var/time_to_wait = GLOB.fileaccess_timer - world.time
|
||||
if(time_to_wait > 0)
|
||||
to_chat(src, "<font color='red'>Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.</font>")
|
||||
to_chat(src, "<font color='red'>Error: file_spam_check(): Spam. Please wait [DisplayTimeText(time_to_wait)].</font>")
|
||||
return 1
|
||||
GLOB.fileaccess_timer = world.time + FTPDELAY
|
||||
return 0
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
SEND_SOUND(M, 'sound/misc/notice2.ogg') //Alerting them to their consideration
|
||||
if(flashwindow)
|
||||
window_flash(M.client)
|
||||
switch(ignore_category ? askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(M,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time))
|
||||
switch(ignore_category ? askuser(M,Question,"Please answer in [DisplayTimeText(poll_time)]!","Yes","No","Never for this round", StealFocus=0, Timeout=poll_time) : askuser(M,Question,"Please answer in [DisplayTimeText(poll_time)]!","Yes","No", StealFocus=0, Timeout=poll_time))
|
||||
if(1)
|
||||
to_chat(M, "<span class='notice'>Choice registered: Yes.</span>")
|
||||
if(time_passed + poll_time <= world.time)
|
||||
|
||||
@@ -219,3 +219,8 @@ GLOBAL_LIST_INIT(sqrtTable, list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4,
|
||||
new_x = Clamp(new_x, 0, world.maxx)
|
||||
new_y = Clamp(new_y, 0, world.maxy)
|
||||
return locate(new_x, new_y, starting.z)
|
||||
|
||||
/proc/round_down(num)
|
||||
if(round(num) != num)
|
||||
return round(num--)
|
||||
else return num
|
||||
|
||||
@@ -465,13 +465,17 @@ Proc for attack log creation, because really why not
|
||||
if(H.dna && istype(H.dna.species, species_datum))
|
||||
. = TRUE
|
||||
|
||||
/proc/spawn_atom_to_turf(spawn_type, target, amount, admin_spawn=FALSE)
|
||||
/proc/spawn_atom_to_turf(spawn_type, target, amount, admin_spawn=FALSE, list/extra_args)
|
||||
var/turf/T = get_turf(target)
|
||||
if(!T)
|
||||
CRASH("attempt to spawn atom type: [spawn_type] in nullspace")
|
||||
|
||||
for(var/j in 1 to amount)
|
||||
var/atom/X = new spawn_type(T)
|
||||
var/list/new_args = list(T)
|
||||
if(extra_args)
|
||||
new_args += extra_args
|
||||
|
||||
for(var/j in 1 to amount)
|
||||
var/atom/X = new spawn_type(arglist(new_args))
|
||||
X.admin_spawned = admin_spawn
|
||||
|
||||
/proc/spawn_and_random_walk(spawn_type, target, amount, walk_chance=100, max_walk=3, always_max_walk=FALSE, admin_spawn=FALSE)
|
||||
|
||||
+150
-25
@@ -414,34 +414,159 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
end = temp
|
||||
return end
|
||||
|
||||
|
||||
/proc/parsepencode(t, mob/user=null, signfont=SIGNFONT)
|
||||
if(length(t) < 1) //No input means nothing needs to be parsed
|
||||
/proc/parsemarkdown_basic_step1(t, limited=FALSE)
|
||||
if(length(t) <= 0)
|
||||
return
|
||||
|
||||
t = replacetext(t, "\[center\]", "<center>")
|
||||
t = replacetext(t, "\[/center\]", "</center>")
|
||||
t = replacetext(t, "\[br\]", "<BR>")
|
||||
t = replacetext(t, "\[b\]", "<B>")
|
||||
t = replacetext(t, "\[/b\]", "</B>")
|
||||
t = replacetext(t, "\[i\]", "<I>")
|
||||
t = replacetext(t, "\[/i\]", "</I>")
|
||||
t = replacetext(t, "\[u\]", "<U>")
|
||||
t = replacetext(t, "\[/u\]", "</U>")
|
||||
t = replacetext(t, "\[large\]", "<font size=\"4\">")
|
||||
t = replacetext(t, "\[/large\]", "</font>")
|
||||
if(user)
|
||||
t = replacetext(t, "\[sign\]", "<font face=\"[signfont]\"><i>[user.real_name]</i></font>")
|
||||
else
|
||||
t = replacetext(t, "\[sign\]", "")
|
||||
t = replacetext(t, "\[field\]", "<span class=\"paper_field\"></span>")
|
||||
// This parses markdown with no custom rules
|
||||
|
||||
t = replacetext(t, "\[*\]", "<li>")
|
||||
t = replacetext(t, "\[hr\]", "<HR>")
|
||||
t = replacetext(t, "\[small\]", "<font size = \"1\">")
|
||||
t = replacetext(t, "\[/small\]", "</font>")
|
||||
t = replacetext(t, "\[list\]", "<ul>")
|
||||
t = replacetext(t, "\[/list\]", "</ul>")
|
||||
// Escape backslashed
|
||||
|
||||
t = replacetext(t, "$", "$-")
|
||||
t = replacetext(t, "\\\\", "$1")
|
||||
t = replacetext(t, "\\**", "$2")
|
||||
t = replacetext(t, "\\*", "$3")
|
||||
t = replacetext(t, "\\__", "$4")
|
||||
t = replacetext(t, "\\_", "$5")
|
||||
t = replacetext(t, "\\^", "$6")
|
||||
t = replacetext(t, "\\((", "$7")
|
||||
t = replacetext(t, "\\))", "$8")
|
||||
t = replacetext(t, "\\|", "$9")
|
||||
t = replacetext(t, "\\%", "$0")
|
||||
|
||||
// Escape single characters that will be used
|
||||
|
||||
t = replacetext(t, "!", "$a")
|
||||
|
||||
// Parse hr and small
|
||||
|
||||
if(!limited)
|
||||
t = replacetext(t, "((", "<font size=\"1\">")
|
||||
t = replacetext(t, "))", "</font>")
|
||||
t = replacetext(t, regex("^-{3,}$", "gm"), "<hr>")
|
||||
t = replacetext(t, regex("^\\(-{3,})$", "gm"), "$1")
|
||||
|
||||
// Parse lists
|
||||
|
||||
var/list/tlist = splittext(t, "\n")
|
||||
var/tlistlen = tlist.len
|
||||
var/listlevel = -1
|
||||
var/singlespace = -1 // if 0, double spaces are used before asterisks, if 1, single are
|
||||
for(var/i = 1, i <= tlistlen, i++)
|
||||
var/line = tlist[i]
|
||||
var/count_asterisk = length(replacetext(line, regex("\[^\\*\]+", "g"), ""))
|
||||
if(count_asterisk % 2 == 1 && findtext(line, regex("^\\s*\\*", "g"))) // there is an extra asterisk in the beggining
|
||||
|
||||
var/count_w = length(replacetext(line, regex("^( *)\\*.*$", "g"), "$1")) // whitespace before asterisk
|
||||
line = replacetext(line, regex("^ *(\\*.*)$", "g"), "$1")
|
||||
|
||||
if(singlespace == -1 && count_w == 2)
|
||||
if(listlevel == 0)
|
||||
singlespace = 0
|
||||
else
|
||||
singlespace = 1
|
||||
|
||||
if(singlespace == 0)
|
||||
count_w = count_w % 2 ? round(count_w / 2 + 0.25) : count_w / 2
|
||||
|
||||
line = replacetext(line, regex("\\*", ""), "<li>")
|
||||
while(listlevel < count_w)
|
||||
line = "<ul>" + line
|
||||
listlevel++
|
||||
while(listlevel > count_w)
|
||||
line = "</ul>" + line
|
||||
listlevel--
|
||||
|
||||
else while(listlevel >= 0)
|
||||
line = "</ul>" + line
|
||||
listlevel--
|
||||
|
||||
tlist[i] = line
|
||||
// end for
|
||||
|
||||
t = tlist[1]
|
||||
for(var/i = 2, i <= tlistlen, i++)
|
||||
t += "\n" + tlist[i]
|
||||
|
||||
while(listlevel >= 0)
|
||||
t += "</ul>"
|
||||
listlevel--
|
||||
|
||||
else
|
||||
t = replacetext(t, "((", "")
|
||||
t = replacetext(t, "))", "")
|
||||
|
||||
// Parse headers
|
||||
|
||||
t = replacetext(t, regex("^#(?!#) ?(.+)$", "gm"), "<h2>$1</h2>")
|
||||
t = replacetext(t, regex("^##(?!#) ?(.+)$", "gm"), "<h3>$1</h3>")
|
||||
t = replacetext(t, regex("^###(?!#) ?(.+)$", "gm"), "<h4>$1</h4>")
|
||||
t = replacetext(t, regex("^#### ?(.+)$", "gm"), "<h5>$1</h5>")
|
||||
|
||||
// Parse most rules
|
||||
|
||||
t = replacetext(t, regex("\\*(\[^\\*\]*)\\*", "g"), "<i>$1</i>")
|
||||
t = replacetext(t, regex("_(\[^_\]*)_", "g"), "<i>$1</i>")
|
||||
t = replacetext(t, "<i></i>", "!")
|
||||
t = replacetext(t, "</i><i>", "!")
|
||||
t = replacetext(t, regex("\\!(\[^\\!\]+)\\!", "g"), "<b>$1</b>")
|
||||
t = replacetext(t, regex("\\^(\[^\\^\]+)\\^", "g"), "<font size=\"4\">$1</font>")
|
||||
t = replacetext(t, regex("\\|(\[^\\|\]+)\\|", "g"), "<center>$1</center>")
|
||||
t = replacetext(t, "!", "</i><i>")
|
||||
|
||||
return t
|
||||
|
||||
/proc/parsemarkdown_basic_step2(t)
|
||||
if(length(t) <= 0)
|
||||
return
|
||||
|
||||
// Restore the single characters used
|
||||
|
||||
t = replacetext(t, "$a", "!")
|
||||
|
||||
// Redo the escaping
|
||||
|
||||
t = replacetext(t, "$1", "\\")
|
||||
t = replacetext(t, "$2", "**")
|
||||
t = replacetext(t, "$3", "*")
|
||||
t = replacetext(t, "$4", "__")
|
||||
t = replacetext(t, "$5", "_")
|
||||
t = replacetext(t, "$6", "^")
|
||||
t = replacetext(t, "$7", "((")
|
||||
t = replacetext(t, "$8", "))")
|
||||
t = replacetext(t, "$9", "|")
|
||||
t = replacetext(t, "$0", "%")
|
||||
t = replacetext(t, "$-", "$")
|
||||
|
||||
return t
|
||||
|
||||
/proc/parsemarkdown_basic(t, limited=FALSE)
|
||||
t = parsemarkdown_basic_step1(t, limited)
|
||||
t = parsemarkdown_basic_step2(t)
|
||||
return t
|
||||
|
||||
/proc/parsemarkdown(t, mob/user=null, limited=FALSE)
|
||||
if(length(t) <= 0)
|
||||
return
|
||||
|
||||
// Premanage whitespace
|
||||
|
||||
t = replacetext(t, regex("\[^\\S\\r\\n \]", "g"), " ")
|
||||
|
||||
t = parsemarkdown_basic_step1(t)
|
||||
|
||||
t = replacetext(t, regex("%s(?:ign)?(?=\\s|$)", "igm"), user ? "<font face=\"[SIGNFONT]\"><i>[user.real_name]</i></font>" : "<span class=\"paper_field\"></span>")
|
||||
t = replacetext(t, regex("%f(?:ield)?(?=\\s|$)", "igm"), "<span class=\"paper_field\"></span>")
|
||||
|
||||
t = parsemarkdown_basic_step2(t)
|
||||
|
||||
// Manage whitespace
|
||||
|
||||
t = replacetext(t, regex("(?:\\r\\n?|\\n)", "g"), "<br>")
|
||||
|
||||
t = replacetext(t, " ", " ")
|
||||
|
||||
// Done
|
||||
|
||||
return t
|
||||
|
||||
|
||||
+148
-52
@@ -1,52 +1,148 @@
|
||||
//Returns the world time in english
|
||||
/proc/worldtime2text()
|
||||
return gameTimestamp("hh:mm:ss", world.time)
|
||||
|
||||
/proc/time_stamp(format = "hh:mm:ss", show_ds)
|
||||
var/time_string = time2text(world.timeofday, format)
|
||||
return show_ds ? "[time_string]:[world.timeofday % 10]" : time_string
|
||||
|
||||
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
|
||||
if(!wtime)
|
||||
wtime = world.time
|
||||
return time2text(wtime - GLOB.timezoneOffset + SSticker.gametime_offset - SSticker.round_start_time, format)
|
||||
|
||||
/* Returns 1 if it is the selected month and day */
|
||||
/proc/isDay(month, day)
|
||||
if(isnum(month) && isnum(day))
|
||||
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
if(month == MM && day == DD)
|
||||
return 1
|
||||
|
||||
// Uncomment this out when debugging!
|
||||
//else
|
||||
//return 1
|
||||
|
||||
//returns timestamp in a sql and ISO 8601 friendly format
|
||||
/proc/SQLtime(timevar)
|
||||
if(!timevar)
|
||||
timevar = world.realtime
|
||||
return time2text(timevar, "YYYY-MM-DD hh:mm:ss")
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(midnight_rollovers, 0)
|
||||
GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
|
||||
/proc/update_midnight_rollover()
|
||||
if (world.timeofday < GLOB.rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS!
|
||||
return GLOB.midnight_rollovers++
|
||||
return GLOB.midnight_rollovers
|
||||
|
||||
/proc/weekdayofthemonth()
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
switch(DD)
|
||||
if(8 to 13)
|
||||
return 2
|
||||
if(14 to 20)
|
||||
return 3
|
||||
if(21 to 27)
|
||||
return 4
|
||||
if(28 to INFINITY)
|
||||
return 5
|
||||
else
|
||||
return 1
|
||||
//Returns the world time in english
|
||||
/proc/worldtime2text()
|
||||
return gameTimestamp("hh:mm:ss", world.time)
|
||||
|
||||
/proc/time_stamp(format = "hh:mm:ss", show_ds)
|
||||
var/time_string = time2text(world.timeofday, format)
|
||||
return show_ds ? "[time_string]:[world.timeofday % 10]" : time_string
|
||||
|
||||
/proc/gameTimestamp(format = "hh:mm:ss", wtime=null)
|
||||
if(!wtime)
|
||||
wtime = world.time
|
||||
return time2text(wtime - GLOB.timezoneOffset + SSticker.gametime_offset - SSticker.round_start_time, format)
|
||||
|
||||
/* Returns 1 if it is the selected month and day */
|
||||
/proc/isDay(month, day)
|
||||
if(isnum(month) && isnum(day))
|
||||
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
if(month == MM && day == DD)
|
||||
return 1
|
||||
|
||||
// Uncomment this out when debugging!
|
||||
//else
|
||||
//return 1
|
||||
|
||||
//returns timestamp in a sql and ISO 8601 friendly format
|
||||
/proc/SQLtime(timevar)
|
||||
if(!timevar)
|
||||
timevar = world.realtime
|
||||
return time2text(timevar, "YYYY-MM-DD hh:mm:ss")
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(midnight_rollovers, 0)
|
||||
GLOBAL_VAR_INIT(rollovercheck_last_timeofday, 0)
|
||||
/proc/update_midnight_rollover()
|
||||
if (world.timeofday < GLOB.rollovercheck_last_timeofday) //TIME IS GOING BACKWARDS!
|
||||
return GLOB.midnight_rollovers++
|
||||
return GLOB.midnight_rollovers
|
||||
|
||||
/proc/weekdayofthemonth()
|
||||
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
|
||||
switch(DD)
|
||||
if(8 to 13)
|
||||
return 2
|
||||
if(14 to 20)
|
||||
return 3
|
||||
if(21 to 27)
|
||||
return 4
|
||||
if(28 to INFINITY)
|
||||
return 5
|
||||
else
|
||||
return 1
|
||||
|
||||
//Takes a value of time in deciseconds.
|
||||
//Returns a text value of that number in hours, minutes, or seconds.
|
||||
/proc/DisplayTimeText(time_value)
|
||||
var/second = time_value*0.1
|
||||
var/second_adjusted = null
|
||||
var/second_rounded = FALSE
|
||||
var/minute = null
|
||||
var/hour = null
|
||||
var/day = null
|
||||
|
||||
if(!second)
|
||||
return "0 seconds"
|
||||
if(second >= 60)
|
||||
minute = round_down(second/60)
|
||||
second = round(second - (minute*60), 0.1)
|
||||
second_rounded = TRUE
|
||||
if(second) //check if we still have seconds remaining to format, or if everything went into minute.
|
||||
second_adjusted = round(second) //used to prevent '1 seconds' being shown
|
||||
if(day || hour || minute)
|
||||
if(second_adjusted == 1 && second >= 1)
|
||||
second = " and 1 second"
|
||||
else if(second > 1)
|
||||
second = " and [second_adjusted] seconds"
|
||||
else //shows a fraction if seconds is < 1
|
||||
if(second_rounded) //no sense rounding again if it's already done
|
||||
second = " and [second] seconds"
|
||||
else
|
||||
second = " and [round(second, 0.1)] seconds"
|
||||
else
|
||||
if(second_adjusted == 1 && second >= 1)
|
||||
second = "1 second"
|
||||
else if(second > 1)
|
||||
second = "[second_adjusted] seconds"
|
||||
else
|
||||
if(second_rounded)
|
||||
second = "[second] seconds"
|
||||
else
|
||||
second = "[round(second, 0.1)] seconds"
|
||||
else
|
||||
second = null
|
||||
|
||||
if(!minute)
|
||||
return "[second]"
|
||||
if(minute >= 60)
|
||||
hour = round_down(minute/60,1)
|
||||
minute = (minute - (hour*60))
|
||||
if(minute) //alot simpler from here since you don't have to worry about fractions
|
||||
if(minute != 1)
|
||||
if((day || hour) && second)
|
||||
minute = ", [minute] minutes"
|
||||
else if((day || hour) && !second)
|
||||
minute = " and [minute] minutes"
|
||||
else
|
||||
minute = "[minute] minutes"
|
||||
else
|
||||
if((day || hour) && second)
|
||||
minute = ", 1 minute"
|
||||
else if((day || hour) && !second)
|
||||
minute = " and 1 minute"
|
||||
else
|
||||
minute = "1 minute"
|
||||
else
|
||||
minute = null
|
||||
|
||||
if(!hour)
|
||||
return "[minute][second]"
|
||||
if(hour >= 24)
|
||||
day = round_down(hour/24,1)
|
||||
hour = (hour - (day*24))
|
||||
if(hour)
|
||||
if(hour != 1)
|
||||
if(day && (minute || second))
|
||||
hour = ", [hour] hours"
|
||||
else if(day && (!minute || !second))
|
||||
hour = " and [hour] hours"
|
||||
else
|
||||
hour = "[hour] hours"
|
||||
else
|
||||
if(day && (minute || second))
|
||||
hour = ", 1 hour"
|
||||
else if(day && (!minute || !second))
|
||||
hour = " and 1 hour"
|
||||
else
|
||||
hour = "1 hour"
|
||||
else
|
||||
hour = null
|
||||
|
||||
if(!day)
|
||||
return "[hour][minute][second]"
|
||||
if(day > 1)
|
||||
day = "[day] days"
|
||||
else
|
||||
day = "1 day"
|
||||
|
||||
return "[day][hour][minute][second]"
|
||||
|
||||
@@ -502,28 +502,12 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
var/y=arcsin(x/sqrt(1+x*x))
|
||||
return y
|
||||
|
||||
/atom/proc/GetAllContents(list/ignore_typecache)
|
||||
var/list/processing_list = list(src)
|
||||
var/list/assembled = list()
|
||||
if(ignore_typecache) //If there's a typecache, use it.
|
||||
while(processing_list.len)
|
||||
var/atom/A = processing_list[1]
|
||||
processing_list -= A
|
||||
if(ignore_typecache[A.type])
|
||||
continue
|
||||
processing_list |= (A.contents - assembled)
|
||||
assembled |= A
|
||||
|
||||
else //If there's none, only make this check once for performance.
|
||||
while(processing_list.len)
|
||||
var/atom/A = processing_list[1]
|
||||
processing_list -= A
|
||||
|
||||
processing_list |= (A.contents - assembled)
|
||||
|
||||
assembled |= A
|
||||
|
||||
return assembled
|
||||
/atom/proc/GetAllContents(list/output=list())
|
||||
. = output
|
||||
output += src
|
||||
for(var/i in 1 to contents.len)
|
||||
var/atom/thing = contents[i]
|
||||
thing.GetAllContents(output)
|
||||
|
||||
//Step-towards method of determining whether one atom can see another. Similar to viewers()
|
||||
/proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate.
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#define MAX_CHARTER_LEN 80
|
||||
|
||||
//MINOR TWEAKS/MISC
|
||||
#define AGE_MIN 17 //youngest a character can be
|
||||
#define AGE_MIN 18 //youngest a character can be
|
||||
#define AGE_MAX 85 //oldest a character can be
|
||||
#define WIZARD_AGE_MIN 30 //youngest a wizard can be
|
||||
#define SHOES_SLOWDOWN 0 //How much shoes slow you down by default. Negative values speed you up
|
||||
|
||||
@@ -33,6 +33,8 @@ GLOBAL_LIST_EMPTY(department_security_spawns) //list of all department security
|
||||
GLOBAL_LIST_EMPTY(generic_event_spawns) //list of all spawns for events
|
||||
|
||||
GLOBAL_LIST_EMPTY(wizardstart)
|
||||
GLOBAL_LIST_EMPTY(nukeop_start)
|
||||
GLOBAL_LIST_EMPTY(nukeop_leader_start)
|
||||
GLOBAL_LIST_EMPTY(newplayer_start)
|
||||
GLOBAL_LIST_EMPTY(prisonwarp) //prisoners go to these
|
||||
GLOBAL_LIST_EMPTY(holdingfacility) //captured people go here
|
||||
|
||||
+435
-5
@@ -172,6 +172,27 @@
|
||||
spread = 30 //should be 40 for XCOM memes, but since its adminspawn only, might as well make it useable
|
||||
recoil = 1
|
||||
|
||||
///toy memes///
|
||||
|
||||
/obj/item/ammo_box/magazine/toy/x9
|
||||
name = "foam force X9 magazine"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "toy9magazine"
|
||||
max_ammo = 30
|
||||
multiple_sprites = 2
|
||||
|
||||
/obj/item/gun/ballistic/automatic/x9/toy
|
||||
name = "donksoft X9"
|
||||
desc = "An old but reliable assault rifle made for combat against unknown enemies. Appears to be hastily converted. Ages 8 and up."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "toy9"
|
||||
can_suppress = 0
|
||||
needs_permit = 0
|
||||
mag_type = /obj/item/ammo_box/magazine/toy/x9
|
||||
casing_ejector = 0
|
||||
spread = 45 //MAXIMUM XCOM MEMES (actually that'd be 90 spread)
|
||||
|
||||
|
||||
////////XCOM2 Magpistol/////////
|
||||
|
||||
//////projectiles//////
|
||||
@@ -213,7 +234,7 @@
|
||||
|
||||
//////magazines/////
|
||||
|
||||
/obj/item/ammo_box/magazine/mmags
|
||||
/obj/item/ammo_box/magazine/mmag/small
|
||||
name = "magpistol magazine (non-lethal disabler)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "nlmagmag"
|
||||
@@ -223,7 +244,7 @@
|
||||
max_ammo = 7
|
||||
multiple_sprites = 2
|
||||
|
||||
/obj/item/ammo_box/magazine/mmags/lethal
|
||||
/obj/item/ammo_box/magazine/mmag/small/lethal
|
||||
name = "magpistol magazine (lethal)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "smallmagmag"
|
||||
@@ -239,7 +260,7 @@
|
||||
icon_state = "magpistol"
|
||||
force = 10
|
||||
fire_sound = 'sound/weapons/magpistol.ogg'
|
||||
mag_type = /obj/item/ammo_box/magazine/mmags
|
||||
mag_type = /obj/item/ammo_box/magazine/mmag/small
|
||||
can_suppress = 0
|
||||
casing_ejector = 0
|
||||
fire_delay = 5
|
||||
@@ -276,7 +297,7 @@
|
||||
req_tech = list("combat" = 5, "magnets" = 6, "materials" = 5, "syndicate" = 3)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 4000, MAT_SILVER = 500)
|
||||
build_path = /obj/item/ammo_box/magazine/mmags/lethal
|
||||
build_path = /obj/item/ammo_box/magazine/mmag/small/lethal
|
||||
category = list("Ammo")
|
||||
|
||||
/datum/design/mag_magpistol/nl
|
||||
@@ -285,7 +306,7 @@
|
||||
id = "mag_magpistol_nl"
|
||||
req_tech = list("combat" = 5, "magnets" = 6, "materials" = 5)
|
||||
materials = list(MAT_METAL = 3000, MAT_SILVER = 250, MAT_TITANIUM = 250)
|
||||
build_path = /obj/item/ammo_box/magazine/mmags
|
||||
build_path = /obj/item/ammo_box/magazine/mmag/small
|
||||
|
||||
//////toy memes/////
|
||||
|
||||
@@ -339,3 +360,412 @@
|
||||
materials = list(MAT_METAL = 7500, MAT_GLASS = 1000)
|
||||
build_path = /obj/item/gun/ballistic/shotgun/toy/mag
|
||||
category = list("hacked", "Misc")
|
||||
|
||||
//////Magrifle//////
|
||||
|
||||
///projectiles///
|
||||
|
||||
/obj/item/projectile/bullet/magrifle
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magjectile-large"
|
||||
damage = 30
|
||||
armour_penetration = 25
|
||||
light_range = 3
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/obj/item/projectile/bullet/nlmagrifle //non-lethal boolets
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magjectile-large-nl"
|
||||
damage = 5
|
||||
knockdown = 30
|
||||
stamina = 75
|
||||
armour_penetration = 0
|
||||
light_range = 3
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
///ammo casings///
|
||||
|
||||
/obj/item/ammo_casing/caseless/amagm
|
||||
desc = "A large ferromagnetic slug intended to be launched out of a compatible weapon."
|
||||
caliber = "magm"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mag-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/magrifle
|
||||
|
||||
/obj/item/ammo_casing/caseless/anlmagm
|
||||
desc = "A large, specialized ferromagnetic slug designed with a less-than-lethal payload."
|
||||
caliber = "magm"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mag-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/nlmagrifle
|
||||
|
||||
///magazines///
|
||||
|
||||
/obj/item/ammo_box/magazine/mmag/
|
||||
name = "magrifle magazine (non-lethal disabler)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mediummagmag"
|
||||
origin_tech = "magnets=6"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/anlmagm
|
||||
caliber = "magm"
|
||||
max_ammo = 15
|
||||
multiple_sprites = 2
|
||||
|
||||
/obj/item/ammo_box/magazine/mmag/lethal
|
||||
name = "magrifle magazine (lethal)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mediummagmag"
|
||||
origin_tech = "combat=6"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/amagm
|
||||
|
||||
///the gun itself///
|
||||
|
||||
/obj/item/gun/ballistic/automatic/magrifle
|
||||
name = "\improper Magnetic Rifle"
|
||||
desc = "A simple upscalling of the technologies used in the magpistol, the magrifle is capable of firing slightly larger slugs in bursts. Compatible with the magpistol's slugs."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magrifle"
|
||||
item_state = "arg"
|
||||
slot_flags = 0
|
||||
origin_tech = "combat=6;engineering=6;magnets=6"
|
||||
mag_type = /obj/item/ammo_box/magazine/mmag
|
||||
fire_sound = 'sound/weapons/magrifle.ogg'
|
||||
can_suppress = 0
|
||||
burst_size = 3
|
||||
fire_delay = 2
|
||||
spread = 15
|
||||
recoil = 1
|
||||
casing_ejector = 0
|
||||
|
||||
///research///
|
||||
|
||||
/obj/item/gun/ballistic/automatic/magrifle/nopin
|
||||
pin = null
|
||||
|
||||
/datum/design/magrifle
|
||||
name = "Magrifle"
|
||||
desc = "An upscaled Magpistol in rifle form."
|
||||
id = "magrifle"
|
||||
req_tech = list("combat" = 7, "magnets" = 7, "powerstorage" = 7)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 10000, MAT_GLASS = 2000, MAT_URANIUM = 2000, MAT_TITANIUM = 10000, MAT_SILVER = 4000, MAT_GOLD = 2000)
|
||||
build_path = /obj/item/gun/ballistic/automatic/magrifle/nopin
|
||||
category = list("Weapons")
|
||||
|
||||
/datum/design/mag_magrifle
|
||||
name = "Magrifle Magazine (Lethal)"
|
||||
desc = "A 15 round magazine for the Magrifle."
|
||||
id = "mag_magrifle"
|
||||
req_tech = list("combat" = 7, "magnets" = 7, "materials" = 5, "syndicate" = 4)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 8000, MAT_SILVER = 1000)
|
||||
build_path = /obj/item/ammo_box/magazine/mmag/lethal
|
||||
category = list("Ammo")
|
||||
|
||||
/datum/design/mag_magrifle/nl
|
||||
name = "Magrifle Magazine (Non-Lethal)"
|
||||
desc = "A 15 round non-lethal magazine for the Magrifle."
|
||||
id = "mag_magrifle_nl"
|
||||
req_tech = list("combat" = 7, "magnets" = 7, "materials" = 5)
|
||||
materials = list(MAT_METAL = 6000, MAT_SILVER = 500, MAT_TITANIUM = 500)
|
||||
build_path = /obj/item/ammo_box/magazine/mmag
|
||||
|
||||
//////Hyper-Burst Rifle//////
|
||||
|
||||
///projectiles///
|
||||
|
||||
/obj/item/projectile/bullet/mags/hyper
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magjectile"
|
||||
damage = 10
|
||||
armour_penetration = 10
|
||||
stamina = 10
|
||||
forcedodge = TRUE
|
||||
range = 6
|
||||
light_range = 1
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/obj/item/projectile/bullet/mags/hyper/inferno
|
||||
icon_state = "magjectile-large"
|
||||
stamina = 0
|
||||
forcedodge = FALSE
|
||||
range = 25
|
||||
light_range = 4
|
||||
|
||||
/obj/item/projectile/bullet/mags/hyper/inferno/on_hit(atom/target, blocked = FALSE)
|
||||
..()
|
||||
explosion(target, -1, 1, 2, 4, 5)
|
||||
return 1
|
||||
|
||||
///ammo casings///
|
||||
|
||||
/obj/item/ammo_casing/caseless/ahyper
|
||||
desc = "A large block of speciallized ferromagnetic material designed to be fired out of the experimental Hyper-Burst Rifle."
|
||||
caliber = "hypermag"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "hyper-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/mags/hyper
|
||||
pellets = 12
|
||||
variance = 40
|
||||
|
||||
/obj/item/ammo_casing/caseless/ahyper/inferno
|
||||
projectile_type = /obj/item/projectile/bullet/mags/hyper/inferno
|
||||
pellets = 1
|
||||
variance = 0
|
||||
|
||||
///magazines///
|
||||
|
||||
/obj/item/ammo_box/magazine/mhyper
|
||||
name = "hyper-burst rifle magazine"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "hypermag-4"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/ahyper
|
||||
caliber = "hypermag"
|
||||
desc = "A magazine for the Hyper-Burst Rifle. Loaded with a special slug that fragments into 12 smaller shards which can absolutely puncture anything, but has rather short effective range."
|
||||
max_ammo = 4
|
||||
|
||||
/obj/item/ammo_box/magazine/mhyper/update_icon()
|
||||
..()
|
||||
icon_state = "hypermag-[ammo_count() ? "4" : "0"]"
|
||||
|
||||
/obj/item/ammo_box/magazine/mhyper/inferno
|
||||
name = "hyper-burst rifle magazine (inferno)"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/ahyper/inferno
|
||||
desc = "A magazine for the Hyper-Burst Rifle. Loaded with a special slug that violently reacts with whatever surface it strikes, generating a massive amount of heat and light."
|
||||
|
||||
///gun itself///
|
||||
|
||||
/obj/item/gun/ballistic/automatic/hyperburst
|
||||
name = "\improper Hyper-Burst Rifle"
|
||||
desc = "An extremely beefed up version of a stolen Nanotrasen weapon prototype, this 'rifle' is more like a cannon, with an extremely large bore barrel capable of generating several smaller magnetic 'barrels' to simultaneously launch multiple projectiles at once."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "hyperburst"
|
||||
item_state = "arg"
|
||||
slot_flags = 0
|
||||
origin_tech = "combat=6;engineering=6;magnets=6;syndicate=6"
|
||||
mag_type = /obj/item/ammo_box/magazine/mhyper
|
||||
fire_sound = 'sound/weapons/magburst.ogg'
|
||||
can_suppress = 0
|
||||
burst_size = 1
|
||||
fire_delay = 40
|
||||
recoil = 2
|
||||
casing_ejector = 0
|
||||
weapon_weight = WEAPON_HEAVY
|
||||
|
||||
/obj/item/gun/ballistic/automatic/hyperburst/update_icon()
|
||||
..()
|
||||
icon_state = "hyperburst[magazine ? "-[get_ammo()]" : ""][chambered ? "" : "-e"]"
|
||||
|
||||
/* made redundant by reskinnable stetchkins
|
||||
//////Stealth Pistol//////
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/stealth
|
||||
name = "stealth pistol"
|
||||
desc = "A unique bullpup pistol with a compact frame. Has an integrated surpressor."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "stealthpistol"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
origin_tech = "combat=3;materials=3;syndicate=4"
|
||||
mag_type = /obj/item/ammo_box/magazine/m10mm
|
||||
can_suppress = 0
|
||||
fire_sound = 'sound/weapons/gunshot_silenced.ogg'
|
||||
suppressed = 1
|
||||
burst_size = 1
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/stealth/update_icon()
|
||||
..()
|
||||
if(magazine)
|
||||
cut_overlays()
|
||||
add_overlay("stealthpistol-magazine")
|
||||
else
|
||||
cut_overlays()
|
||||
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
|
||||
|
||||
*/
|
||||
|
||||
//////10mm soporific bullets//////
|
||||
|
||||
obj/item/projectile/bullet/c10mm/soporific
|
||||
name ="10mm soporific bullet"
|
||||
armour_penetration = 0
|
||||
nodamage = TRUE
|
||||
dismemberment = 0
|
||||
knockdown = 0
|
||||
|
||||
/obj/item/projectile/bullet/c10mm/soporific/on_hit(atom/target, blocked = FALSE)
|
||||
if((blocked != 100) && isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.blur_eyes(6)
|
||||
if(L.staminaloss >= 40)
|
||||
L.Sleeping(250)
|
||||
else
|
||||
L.adjustStaminaLoss(58)
|
||||
return 1
|
||||
|
||||
/obj/item/ammo_casing/c10mm/soporific
|
||||
name = ".10mm soporific bullet casing"
|
||||
desc = "A 10mm soporific bullet casing."
|
||||
projectile_type = /obj/item/projectile/bullet/c10mm/soporific
|
||||
|
||||
/obj/item/ammo_box/magazine/m10mm/soporific
|
||||
name = "pistol magazine (10mm soporific)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "9x19pS"
|
||||
desc = "A gun magazine. Loaded with rounds which inject the target with a variety of illegal substances to induce sleep in the target."
|
||||
ammo_type = /obj/item/ammo_casing/c10mm/soporific
|
||||
|
||||
/obj/item/ammo_box/c10mm/soporific
|
||||
name = "ammo box (10mm soporific)"
|
||||
ammo_type = /obj/item/ammo_casing/c10mm/soporific
|
||||
max_ammo = 24
|
||||
|
||||
//////Flechette Launcher//////
|
||||
|
||||
///projectiles///
|
||||
|
||||
/obj/item/projectile/bullet/cflechetteap //shreds armor
|
||||
name = "flechette (armor piercing)"
|
||||
damage = 8
|
||||
armour_penetration = 80
|
||||
|
||||
/obj/item/projectile/bullet/cflechettes //shreds flesh and forces bleeding
|
||||
name = "flechette (serrated)"
|
||||
damage = 8
|
||||
dismemberment = 10
|
||||
armour_penetration = -80
|
||||
|
||||
/obj/item/projectile/bullet/cflechettes/on_hit(atom/target, blocked = FALSE)
|
||||
if((blocked != 100) && iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
C.bleed(10)
|
||||
return ..()
|
||||
|
||||
///ammo casings (CASELESS AMMO CASINGS WOOOOOOOO)///
|
||||
|
||||
/obj/item/ammo_casing/caseless/flechetteap
|
||||
name = "flechette (armor piercing)"
|
||||
desc = "A flechette made with a tungsten alloy."
|
||||
projectile_type = /obj/item/projectile/bullet/cflechetteap
|
||||
caliber = "flechette"
|
||||
throwforce = 1
|
||||
throw_speed = 3
|
||||
|
||||
/obj/item/ammo_casing/caseless/flechettes
|
||||
name = "flechette (serrated)"
|
||||
desc = "A serrated flechette made of a special alloy intended to deform drastically upon penetration of human flesh."
|
||||
projectile_type = /obj/item/projectile/bullet/cflechettes
|
||||
caliber = "flechette"
|
||||
throwforce = 2
|
||||
throw_speed = 3
|
||||
embed_chance = 75
|
||||
|
||||
///magazine///
|
||||
|
||||
/obj/item/ammo_box/magazine/flechette
|
||||
name = "flechette magazine (armor piercing)"
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "flechettemag"
|
||||
origin_tech = "combat=5;syndicate=1"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/flechetteap
|
||||
caliber = "flechette"
|
||||
max_ammo = 40
|
||||
multiple_sprites = 2
|
||||
|
||||
/obj/item/ammo_box/magazine/flechette/s
|
||||
name = "flechette magazine (serrated)"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/flechettes
|
||||
|
||||
///the gun itself///
|
||||
|
||||
/obj/item/gun/ballistic/automatic/flechette
|
||||
name = "\improper CX Flechette Launcher"
|
||||
desc = "A flechette launching machine pistol with an unconventional bullpup frame."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "flechettegun"
|
||||
item_state = "gun"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
slot_flags = 0
|
||||
/obj/item/device/firing_pin/implant/pindicate
|
||||
origin_tech = "combat=6;materials=2;syndicate=5"
|
||||
mag_type = /obj/item/ammo_box/magazine/flechette/
|
||||
fire_sound = 'sound/weapons/gunshot_smg.ogg'
|
||||
can_suppress = 0
|
||||
burst_size = 5
|
||||
fire_delay = 1
|
||||
casing_ejector = 0
|
||||
spread = 20
|
||||
|
||||
/obj/item/gun/ballistic/automatic/flechette/update_icon()
|
||||
..()
|
||||
if(magazine)
|
||||
cut_overlays()
|
||||
add_overlay("flechettegun-magazine")
|
||||
else
|
||||
cut_overlays()
|
||||
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
|
||||
|
||||
///unique variant///
|
||||
|
||||
/obj/item/projectile/bullet/cflechetteshredder
|
||||
name = "flechette (shredder)"
|
||||
damage = 5
|
||||
dismemberment = 40
|
||||
|
||||
/obj/item/ammo_casing/caseless/flechetteshredder
|
||||
name = "flechette (shredder)"
|
||||
desc = "A serrated flechette made of a special alloy that forms a monofilament edge."
|
||||
projectile_type = /obj/item/projectile/bullet/cflechettes
|
||||
|
||||
/obj/item/ammo_box/magazine/flechette/shredder
|
||||
name = "flechette magazine (shredder)"
|
||||
icon_state = "shreddermag"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/flechetteshredder
|
||||
|
||||
/obj/item/gun/ballistic/automatic/flechette/shredder
|
||||
name = "\improper CX Shredder"
|
||||
desc = "A flechette launching machine pistol made of ultra-light CFRP optimized for firing serrated monofillament flechettes."
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
mag_type = /obj/item/ammo_box/magazine/flechette/shredder
|
||||
spread = 30
|
||||
|
||||
/obj/item/gun/ballistic/automatic/flechette/shredder/update_icon()
|
||||
..()
|
||||
if(magazine)
|
||||
cut_overlays()
|
||||
add_overlay("shreddergun-magazine")
|
||||
else
|
||||
cut_overlays()
|
||||
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
|
||||
|
||||
//////modular pistol////// (reskinnable stetchkins)
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/modular
|
||||
name = "modular pistol"
|
||||
desc = "A small, easily concealable 10mm handgun. Has a threaded barrel for suppressors."
|
||||
icon = 'icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "cde"
|
||||
can_unsuppress = TRUE
|
||||
unique_rename = TRUE
|
||||
unique_reskin = list("Default" = "cde",
|
||||
"NT-99" = "n99",
|
||||
"Stealth" = "stealthpistol",
|
||||
"HKVP-78" = "vp78",
|
||||
"Luger" = "p08b",
|
||||
"Mk.58" = "secguncomp",
|
||||
"PX4 Storm" = "px4"
|
||||
)
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/modular/update_icon()
|
||||
..()
|
||||
if(current_skin)
|
||||
icon_state = "[unique_reskin[current_skin]][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)][chambered ? "" : "-e"][suppressed ? "-suppressed" : ""]"
|
||||
if(magazine && suppressed)
|
||||
cut_overlays()
|
||||
add_overlay("[unique_reskin[current_skin]]-magazine-sup") //Yes, this means the default iconstate can't have a magazine overlay
|
||||
else if (magazine)
|
||||
cut_overlays()
|
||||
add_overlay("[unique_reskin[current_skin]]-magazine")
|
||||
else
|
||||
cut_overlays()
|
||||
@@ -0,0 +1,198 @@
|
||||
#undef CURRENT_RESIDENT_FILE
|
||||
|
||||
#define LIST_MODE_NUM 0
|
||||
#define LIST_MODE_TEXT 1
|
||||
#define LIST_MODE_FLAG 2
|
||||
|
||||
/datum/config_entry
|
||||
var/name //read-only, this is determined by the last portion of the derived entry type
|
||||
var/value
|
||||
var/default //read-only, just set value directly
|
||||
|
||||
var/resident_file //the file which this belongs to, must be set
|
||||
var/modified = FALSE //set to TRUE if the default has been overridden by a config entry
|
||||
|
||||
var/protection = NONE
|
||||
var/abstract_type = /datum/config_entry //do not instantiate if type matches this
|
||||
|
||||
var/dupes_allowed = FALSE
|
||||
|
||||
/datum/config_entry/New()
|
||||
if(!resident_file)
|
||||
CRASH("Config entry [type] has no resident_file set")
|
||||
if(type == abstract_type)
|
||||
CRASH("Abstract config entry [type] instatiated!")
|
||||
name = lowertext(type2top(type))
|
||||
if(islist(value))
|
||||
var/list/L = value
|
||||
default = L.Copy()
|
||||
else
|
||||
default = value
|
||||
|
||||
/datum/config_entry/Destroy()
|
||||
config.RemoveEntry(src)
|
||||
return ..()
|
||||
|
||||
/datum/config_entry/can_vv_get(var_name)
|
||||
. = ..()
|
||||
if(var_name == "value" || var_name == "default")
|
||||
. &= !(protection & CONFIG_ENTRY_HIDDEN)
|
||||
|
||||
/datum/config_entry/vv_edit_var(var_name, var_value)
|
||||
var/static/list/banned_edits = list("name", "default", "resident_file", "protection", "abstract_type", "modified", "dupes_allowed")
|
||||
if(var_name == "value")
|
||||
if(protection & CONFIG_ENTRY_LOCKED)
|
||||
return FALSE
|
||||
. = ValidateAndSet("[var_value]")
|
||||
if(.)
|
||||
var_edited = TRUE
|
||||
return
|
||||
if(var_name in banned_edits)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/datum/config_entry/proc/VASProcCallGuard(str_val)
|
||||
. = !(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "ValidateAndSet" && GLOB.LastAdminCalledTargetRef == "\ref[src]")
|
||||
if(!.)
|
||||
log_admin_private("Config set of [type] to [str_val] attempted by [key_name(usr)]")
|
||||
|
||||
/datum/config_entry/proc/ValidateAndSet(str_val)
|
||||
VASProcCallGuard(str_val)
|
||||
CRASH("Invalid config entry type!")
|
||||
|
||||
/datum/config_entry/proc/ValidateKeyedList(str_val, list_mode, splitter)
|
||||
str_val = trim(str_val)
|
||||
var/key_pos = findtext(str_val, splitter)
|
||||
var/key_name = null
|
||||
var/key_value = null
|
||||
|
||||
if(key_pos || list_mode == LIST_MODE_FLAG)
|
||||
key_name = lowertext(copytext(str_val, 1, key_pos))
|
||||
key_value = copytext(str_val, key_pos + 1)
|
||||
var/temp
|
||||
var/continue_check
|
||||
switch(list_mode)
|
||||
if(LIST_MODE_FLAG)
|
||||
temp = TRUE
|
||||
continue_check = TRUE
|
||||
if(LIST_MODE_NUM)
|
||||
temp = text2num(key_value)
|
||||
continue_check = !isnull(temp)
|
||||
if(LIST_MODE_TEXT)
|
||||
temp = key_value
|
||||
continue_check = temp
|
||||
if(continue_check && ValidateKeyName(key_name))
|
||||
value[key_name] = temp
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/config_entry/proc/ValidateKeyName(key_name)
|
||||
return TRUE
|
||||
|
||||
/datum/config_entry/string
|
||||
value = ""
|
||||
abstract_type = /datum/config_entry/string
|
||||
var/auto_trim = TRUE
|
||||
|
||||
/datum/config_entry/string/vv_edit_var(var_name, var_value)
|
||||
return var_name != "auto_trim" && ..()
|
||||
|
||||
/datum/config_entry/string/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
value = auto_trim ? trim(str_val) : str_val
|
||||
return TRUE
|
||||
|
||||
/datum/config_entry/number
|
||||
value = 0
|
||||
abstract_type = /datum/config_entry/number
|
||||
var/integer = TRUE
|
||||
var/max_val = INFINITY
|
||||
var/min_val = -INFINITY
|
||||
|
||||
/datum/config_entry/number/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
var/temp = text2num(trim(str_val))
|
||||
if(!isnull(temp))
|
||||
value = Clamp(integer ? round(temp) : temp, min_val, max_val)
|
||||
if(value != temp && !var_edited)
|
||||
log_config("Changing [name] from [temp] to [value]!")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/config_entry/number/vv_edit_var(var_name, var_value)
|
||||
var/static/list/banned_edits = list("max_val", "min_val", "integer")
|
||||
return !(var_name in banned_edits) && ..()
|
||||
|
||||
/datum/config_entry/flag
|
||||
value = FALSE
|
||||
abstract_type = /datum/config_entry/flag
|
||||
|
||||
/datum/config_entry/flag/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
value = text2num(trim(str_val)) != 0
|
||||
return TRUE
|
||||
|
||||
/datum/config_entry/number_list
|
||||
abstract_type = /datum/config_entry/number_list
|
||||
value = list()
|
||||
|
||||
/datum/config_entry/number_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
str_val = trim(str_val)
|
||||
var/list/new_list = list()
|
||||
var/list/values = splittext(str_val," ")
|
||||
for(var/I in values)
|
||||
var/temp = text2num(I)
|
||||
if(isnull(temp))
|
||||
return FALSE
|
||||
new_list += temp
|
||||
if(!new_list.len)
|
||||
return FALSE
|
||||
value = new_list
|
||||
return TRUE
|
||||
|
||||
/datum/config_entry/keyed_flag_list
|
||||
abstract_type = /datum/config_entry/keyed_flag_list
|
||||
value = list()
|
||||
dupes_allowed = TRUE
|
||||
|
||||
/datum/config_entry/keyed_flag_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
return ValidateKeyedList(str_val, LIST_MODE_FLAG, " ")
|
||||
|
||||
/datum/config_entry/keyed_number_list
|
||||
abstract_type = /datum/config_entry/keyed_number_list
|
||||
value = list()
|
||||
dupes_allowed = TRUE
|
||||
var/splitter = " "
|
||||
|
||||
/datum/config_entry/keyed_number_list/vv_edit_var(var_name, var_value)
|
||||
return var_name != "splitter" && ..()
|
||||
|
||||
/datum/config_entry/keyed_number_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
return ValidateKeyedList(str_val, LIST_MODE_NUM, splitter)
|
||||
|
||||
/datum/config_entry/keyed_string_list
|
||||
abstract_type = /datum/config_entry/keyed_string_list
|
||||
value = list()
|
||||
dupes_allowed = TRUE
|
||||
var/splitter = " "
|
||||
|
||||
/datum/config_entry/keyed_string_list/vv_edit_var(var_name, var_value)
|
||||
return var_name != "splitter" && ..()
|
||||
|
||||
/datum/config_entry/keyed_string_list/ValidateAndSet(str_val)
|
||||
if(!VASProcCallGuard(str_val))
|
||||
return FALSE
|
||||
return ValidateKeyedList(str_val, LIST_MODE_TEXT, splitter)
|
||||
|
||||
#undef LIST_MODE_NUM
|
||||
#undef LIST_MODE_TEXT
|
||||
#undef LIST_MODE_FLAG
|
||||
@@ -0,0 +1,287 @@
|
||||
GLOBAL_VAR_INIT(config_dir, "config/")
|
||||
GLOBAL_PROTECT(config_dir)
|
||||
|
||||
/datum/controller/configuration
|
||||
name = "Configuration"
|
||||
|
||||
var/hiding_entries_by_type = TRUE //Set for readability, admins can set this to FALSE if they want to debug it
|
||||
var/list/entries
|
||||
var/list/entries_by_type
|
||||
|
||||
var/list/maplist
|
||||
var/datum/map_config/defaultmap
|
||||
|
||||
var/list/modes // allowed modes
|
||||
var/list/gamemode_cache
|
||||
var/list/votable_modes // votable modes
|
||||
var/list/mode_names
|
||||
var/list/mode_reports
|
||||
var/list/mode_false_report_weight
|
||||
|
||||
/datum/controller/configuration/New()
|
||||
config = src
|
||||
var/list/config_files = InitEntries()
|
||||
LoadModes()
|
||||
for(var/I in config_files)
|
||||
LoadEntries(I)
|
||||
if(Get(/datum/config_entry/flag/maprotation))
|
||||
loadmaplist(CONFIG_MAPS_FILE)
|
||||
|
||||
/datum/controller/configuration/Destroy()
|
||||
entries_by_type.Cut()
|
||||
QDEL_LIST_ASSOC_VAL(entries)
|
||||
QDEL_LIST_ASSOC_VAL(maplist)
|
||||
QDEL_NULL(defaultmap)
|
||||
|
||||
config = null
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/controller/configuration/proc/InitEntries()
|
||||
var/list/_entries = list()
|
||||
entries = _entries
|
||||
var/list/_entries_by_type = list()
|
||||
entries_by_type = _entries_by_type
|
||||
|
||||
. = list()
|
||||
|
||||
for(var/I in typesof(/datum/config_entry)) //typesof is faster in this case
|
||||
var/datum/config_entry/E = I
|
||||
if(initial(E.abstract_type) == I)
|
||||
continue
|
||||
E = new I
|
||||
_entries_by_type[I] = E
|
||||
var/esname = E.name
|
||||
var/datum/config_entry/test = _entries[esname]
|
||||
if(test)
|
||||
log_config("Error: [test.type] has the same name as [E.type]: [esname]! Not initializing [E.type]!")
|
||||
qdel(E)
|
||||
continue
|
||||
_entries[esname] = E
|
||||
.[E.resident_file] = TRUE
|
||||
|
||||
/datum/controller/configuration/proc/RemoveEntry(datum/config_entry/CE)
|
||||
entries -= CE.name
|
||||
entries_by_type -= CE.type
|
||||
|
||||
/datum/controller/configuration/proc/LoadEntries(filename)
|
||||
log_config("Loading config file [filename]...")
|
||||
var/list/lines = world.file2list("[GLOB.config_dir][filename]")
|
||||
var/list/_entries = entries
|
||||
for(var/L in lines)
|
||||
if(!L)
|
||||
continue
|
||||
|
||||
if(copytext(L, 1, 2) == "#")
|
||||
continue
|
||||
|
||||
var/pos = findtext(L, " ")
|
||||
var/entry = null
|
||||
var/value = null
|
||||
|
||||
if(pos)
|
||||
entry = lowertext(copytext(L, 1, pos))
|
||||
value = copytext(L, pos + 1)
|
||||
else
|
||||
entry = lowertext(L)
|
||||
|
||||
if(!entry)
|
||||
continue
|
||||
|
||||
var/datum/config_entry/E = _entries[entry]
|
||||
if(!E)
|
||||
log_config("Unknown setting in configuration: '[entry]'")
|
||||
continue
|
||||
|
||||
if(filename != E.resident_file)
|
||||
log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.")
|
||||
continue
|
||||
|
||||
var/validated = E.ValidateAndSet(value)
|
||||
if(!validated)
|
||||
log_config("Failed to validate setting \"[value]\" for [entry]")
|
||||
else if(E.modified && !E.dupes_allowed)
|
||||
log_config("Duplicate setting for [entry] ([value]) detected! Using latest.")
|
||||
|
||||
if(validated)
|
||||
E.modified = TRUE
|
||||
|
||||
/datum/controller/configuration/can_vv_get(var_name)
|
||||
return (var_name != "entries_by_type" || !hiding_entries_by_type) && ..()
|
||||
|
||||
/datum/controller/configuration/vv_edit_var(var_name, var_value)
|
||||
return !(var_name in list("entries_by_type", "entries")) && ..()
|
||||
|
||||
/datum/controller/configuration/stat_entry()
|
||||
if(!statclick)
|
||||
statclick = new/obj/effect/statclick/debug(null, "Edit", src)
|
||||
stat("[name]:", statclick)
|
||||
|
||||
/datum/controller/configuration/proc/Get(entry_type)
|
||||
if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Get" && GLOB.LastAdminCalledTargetRef == "\ref[src]")
|
||||
log_admin_private("Config access of [entry_type] attempted by [key_name(usr)]")
|
||||
return
|
||||
var/datum/config_entry/E = entry_type
|
||||
var/entry_is_abstract = initial(E.abstract_type) == entry_type
|
||||
if(entry_is_abstract)
|
||||
CRASH("Tried to retrieve an abstract config_entry: [entry_type]")
|
||||
E = entries_by_type[entry_type]
|
||||
if(!E)
|
||||
CRASH("Missing config entry for [entry_type]!")
|
||||
return E.value
|
||||
|
||||
/datum/controller/configuration/proc/Set(entry_type, new_val)
|
||||
if(IsAdminAdvancedProcCall() && GLOB.LastAdminCalledProc == "Set" && GLOB.LastAdminCalledTargetRef == "\ref[src]")
|
||||
log_admin_private("Config rewrite of [entry_type] to [new_val] attempted by [key_name(usr)]")
|
||||
return
|
||||
var/datum/config_entry/E = entry_type
|
||||
var/entry_is_abstract = initial(E.abstract_type) == entry_type
|
||||
if(entry_is_abstract)
|
||||
CRASH("Tried to retrieve an abstract config_entry: [entry_type]")
|
||||
E = entries_by_type[entry_type]
|
||||
if(!E)
|
||||
CRASH("Missing config entry for [entry_type]!")
|
||||
return E.ValidateAndSet(new_val)
|
||||
|
||||
/datum/controller/configuration/proc/LoadModes()
|
||||
gamemode_cache = typecacheof(/datum/game_mode, TRUE)
|
||||
modes = list()
|
||||
mode_names = list()
|
||||
mode_reports = list()
|
||||
mode_false_report_weight = list()
|
||||
votable_modes = list()
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability)
|
||||
for(var/T in gamemode_cache)
|
||||
// I wish I didn't have to instance the game modes in order to look up
|
||||
// their information, but it is the only way (at least that I know of).
|
||||
var/datum/game_mode/M = new T()
|
||||
|
||||
if(M.config_tag)
|
||||
if(!(M.config_tag in modes)) // ensure each mode is added only once
|
||||
modes += M.config_tag
|
||||
mode_names[M.config_tag] = M.name
|
||||
probabilities[M.config_tag] = M.probability
|
||||
mode_reports[M.config_tag] = M.generate_report()
|
||||
mode_false_report_weight[M.config_tag] = M.false_report_weight
|
||||
if(M.votable)
|
||||
votable_modes += M.config_tag
|
||||
qdel(M)
|
||||
votable_modes += "secret"
|
||||
|
||||
/datum/controller/configuration/proc/loadmaplist(filename)
|
||||
filename = "[GLOB.config_dir][filename]"
|
||||
var/list/Lines = world.file2list(filename)
|
||||
|
||||
var/datum/map_config/currentmap = null
|
||||
for(var/t in Lines)
|
||||
if(!t)
|
||||
continue
|
||||
|
||||
t = trim(t)
|
||||
if(length(t) == 0)
|
||||
continue
|
||||
else if(copytext(t, 1, 2) == "#")
|
||||
continue
|
||||
|
||||
var/pos = findtext(t, " ")
|
||||
var/command = null
|
||||
var/data = null
|
||||
|
||||
if(pos)
|
||||
command = lowertext(copytext(t, 1, pos))
|
||||
data = copytext(t, pos + 1)
|
||||
else
|
||||
command = lowertext(t)
|
||||
|
||||
if(!command)
|
||||
continue
|
||||
|
||||
if (!currentmap && command != "map")
|
||||
continue
|
||||
|
||||
switch (command)
|
||||
if ("map")
|
||||
currentmap = new ("_maps/[data].json")
|
||||
if(currentmap.defaulted)
|
||||
log_config("Failed to load map config for [data]!")
|
||||
if ("minplayers","minplayer")
|
||||
currentmap.config_min_users = text2num(data)
|
||||
if ("maxplayers","maxplayer")
|
||||
currentmap.config_max_users = text2num(data)
|
||||
if ("weight","voteweight")
|
||||
currentmap.voteweight = text2num(data)
|
||||
if ("default","defaultmap")
|
||||
defaultmap = currentmap
|
||||
if ("endmap")
|
||||
LAZYINITLIST(maplist)
|
||||
maplist[currentmap.map_name] = currentmap
|
||||
currentmap = null
|
||||
if ("disabled")
|
||||
currentmap = null
|
||||
else
|
||||
WRITE_FILE(GLOB.config_error_log, "Unknown command in map vote config: '[command]'")
|
||||
|
||||
|
||||
/datum/controller/configuration/proc/pick_mode(mode_name)
|
||||
// I wish I didn't have to instance the game modes in order to look up
|
||||
// their information, but it is the only way (at least that I know of).
|
||||
// ^ This guy didn't try hard enough
|
||||
for(var/T in gamemode_cache)
|
||||
var/datum/game_mode/M = T
|
||||
var/ct = initial(M.config_tag)
|
||||
if(ct && ct == mode_name)
|
||||
return new T
|
||||
return new /datum/game_mode/extended()
|
||||
|
||||
/datum/controller/configuration/proc/get_runnable_modes()
|
||||
var/list/datum/game_mode/runnable_modes = new
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability)
|
||||
var/list/min_pop = Get(/datum/config_entry/keyed_number_list/min_pop)
|
||||
var/list/max_pop = Get(/datum/config_entry/keyed_number_list/max_pop)
|
||||
var/list/repeated_mode_adjust = Get(/datum/config_entry/number_list/repeated_mode_adjust)
|
||||
for(var/T in gamemode_cache)
|
||||
var/datum/game_mode/M = new T()
|
||||
if(!(M.config_tag in modes))
|
||||
qdel(M)
|
||||
continue
|
||||
if(probabilities[M.config_tag]<=0)
|
||||
qdel(M)
|
||||
continue
|
||||
if(min_pop[M.config_tag])
|
||||
M.required_players = min_pop[M.config_tag]
|
||||
if(max_pop[M.config_tag])
|
||||
M.maximum_players = max_pop[M.config_tag]
|
||||
if(M.can_start())
|
||||
var/final_weight = probabilities[M.config_tag]
|
||||
if(SSpersistence.saved_modes.len == 3 && repeated_mode_adjust.len == 3)
|
||||
var/recent_round = min(SSpersistence.saved_modes.Find(M.config_tag),3)
|
||||
var/adjustment = 0
|
||||
while(recent_round)
|
||||
adjustment += repeated_mode_adjust[recent_round]
|
||||
recent_round = SSpersistence.saved_modes.Find(M.config_tag,recent_round+1,0)
|
||||
final_weight *= ((100-adjustment)/100)
|
||||
runnable_modes[M] = final_weight
|
||||
return runnable_modes
|
||||
|
||||
/datum/controller/configuration/proc/get_runnable_midround_modes(crew)
|
||||
var/list/datum/game_mode/runnable_modes = new
|
||||
var/list/probabilities = Get(/datum/config_entry/keyed_number_list/probability)
|
||||
var/list/min_pop = Get(/datum/config_entry/keyed_number_list/min_pop)
|
||||
var/list/max_pop = Get(/datum/config_entry/keyed_number_list/max_pop)
|
||||
for(var/T in (gamemode_cache - SSticker.mode.type))
|
||||
var/datum/game_mode/M = new T()
|
||||
if(!(M.config_tag in modes))
|
||||
qdel(M)
|
||||
continue
|
||||
if(probabilities[M.config_tag]<=0)
|
||||
qdel(M)
|
||||
continue
|
||||
if(min_pop[M.config_tag])
|
||||
M.required_players = min_pop[M.config_tag]
|
||||
if(max_pop[M.config_tag])
|
||||
M.maximum_players = max_pop[M.config_tag]
|
||||
if(M.required_players <= crew)
|
||||
if(M.maximum_players >= 0 && M.maximum_players < crew)
|
||||
continue
|
||||
runnable_modes[M] = probabilities[M.config_tag]
|
||||
return runnable_modes
|
||||
@@ -69,7 +69,7 @@
|
||||
can_fire = 0
|
||||
flags |= SS_NO_FIRE
|
||||
Master.subsystems -= src
|
||||
|
||||
return ..()
|
||||
|
||||
//Queue it to run.
|
||||
// (we loop thru a linked list until we get to the end or find the right point)
|
||||
|
||||
@@ -322,7 +322,7 @@ SUBSYSTEM_DEF(air)
|
||||
EG.dismantle()
|
||||
CHECK_TICK
|
||||
|
||||
var/msg = "HEY! LISTEN! [(world.timeofday - timer)/10] Seconds were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start."
|
||||
var/msg = "HEY! LISTEN! [DisplayTimeText(world.timeofday - timer)] were wasted processing [starting_ats] turf(s) (connected to [ending_ats] other turfs) with atmos differences at round start."
|
||||
to_chat(world, "<span class='boldannounce'>[msg]</span>")
|
||||
warning(msg)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ SUBSYSTEM_DEF(server_maint)
|
||||
var/cmob = C.mob
|
||||
if(!(isobserver(cmob) || (isdead(cmob) && C.holder)))
|
||||
log_access("AFK: [key_name(C)]")
|
||||
to_chat(C, "<span class='danger'>You have been inactive for more than [config.afk_period / 600] minutes and have been disconnected.</span>")
|
||||
to_chat(C, "<span class='danger'>You have been inactive for more than [DisplayTimeText(config.afk_period)] and have been disconnected.</span>")
|
||||
qdel(C)
|
||||
|
||||
if (!(!C || world.time - C.connection_time < PING_BUFFER_TIME || C.inactivity >= (wait-1)))
|
||||
|
||||
@@ -178,7 +178,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
emergency = backup_shuttle
|
||||
|
||||
if(world.time - SSticker.round_start_time < config.shuttle_refuel_delay)
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait another [abs(round(((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)/600))] minutes before trying again.")
|
||||
to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText((world.time - SSticker.round_start_time) - config.shuttle_refuel_delay)] before trying again.")
|
||||
return
|
||||
|
||||
switch(emergency.mode)
|
||||
|
||||
@@ -11,6 +11,7 @@ SUBSYSTEM_DEF(squeak)
|
||||
|
||||
/datum/controller/subsystem/squeak/Initialize(timeofday)
|
||||
trigger_migration(config.mice_roundstart)
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/squeak/proc/trigger_migration(num_mice=10)
|
||||
if(!num_mice)
|
||||
|
||||
@@ -57,6 +57,9 @@ SUBSYSTEM_DEF(throwing)
|
||||
var/pure_diagonal
|
||||
var/diagonal_error
|
||||
var/datum/callback/callback
|
||||
var/paused = FALSE
|
||||
var/delayed_time = 0
|
||||
var/last_move = 0
|
||||
|
||||
/datum/thrownthing/proc/tick()
|
||||
var/atom/movable/AM = thrownthing
|
||||
@@ -64,14 +67,20 @@ SUBSYSTEM_DEF(throwing)
|
||||
finalize()
|
||||
return
|
||||
|
||||
if(paused)
|
||||
delayed_time += world.time - last_move
|
||||
return
|
||||
|
||||
if (dist_travelled && hitcheck()) //to catch sneaky things moving on our tile while we slept
|
||||
finalize()
|
||||
return
|
||||
|
||||
var/atom/step
|
||||
|
||||
last_move = world.time
|
||||
|
||||
//calculate how many tiles to move, making up for any missed ticks.
|
||||
var/tilestomove = Ceiling(min(((((world.time+world.tick_lag) - start_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait))
|
||||
var/tilestomove = Ceiling(min(((((world.time+world.tick_lag) - start_time + delayed_time) * speed) - (dist_travelled ? dist_travelled : -1)), speed*MAX_TICKS_TO_MAKE_UP) * (world.tick_lag * SSthrowing.wait))
|
||||
while (tilestomove-- > 0)
|
||||
if ((dist_travelled >= maxrange || AM.loc == target_turf) && AM.has_gravity(AM.loc))
|
||||
finalize()
|
||||
|
||||
@@ -51,14 +51,14 @@ SUBSYSTEM_DEF(ticker)
|
||||
var/queue_delay = 0
|
||||
var/list/queued_players = list() //used for join queues when the server exceeds the hard population cap
|
||||
|
||||
var/obj/screen/cinematic = null //used for station explosion cinematic
|
||||
|
||||
var/maprotatechecked = 0
|
||||
|
||||
var/news_report
|
||||
|
||||
var/late_join_disabled
|
||||
|
||||
var/roundend_check_paused = FALSE
|
||||
|
||||
var/round_start_time = 0
|
||||
var/list/round_start_events
|
||||
var/mode_result = "undefined"
|
||||
@@ -137,7 +137,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
scripture_states = scripture_unlock_alert(scripture_states)
|
||||
SSshuttle.autoEnd()
|
||||
|
||||
if(!mode.explosion_in_progress && mode.check_finished(force_ending) || force_ending)
|
||||
if(!roundend_check_paused && mode.check_finished(force_ending) || force_ending)
|
||||
current_state = GAME_STATE_FINISHED
|
||||
toggle_ooc(TRUE) // Turn it on
|
||||
toggle_dooc(TRUE)
|
||||
@@ -273,144 +273,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
qdel(bomb)
|
||||
if(epi)
|
||||
explosion(epi, 0, 256, 512, 0, TRUE, TRUE, 0, TRUE)
|
||||
|
||||
//Plus it provides an easy way to make cinematics for other events. Just use this as a template
|
||||
/datum/controller/subsystem/ticker/proc/station_explosion_cinematic(station_missed=0, override = null, atom/bomb = null)
|
||||
if( cinematic )
|
||||
return //already a cinematic in progress!
|
||||
|
||||
for (var/datum/html_interface/hi in GLOB.html_interfaces)
|
||||
hi.closeAll()
|
||||
SStgui.close_all_uis()
|
||||
|
||||
//Turn off the shuttles, there's no escape now
|
||||
if(!station_missed && bomb)
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
SSshuttle.lockdown = TRUE
|
||||
|
||||
//initialise our cinematic screen object
|
||||
cinematic = new /obj/screen{icon='icons/effects/station_explosion.dmi';icon_state="station_intact";layer=21;mouse_opacity = MOUSE_OPACITY_TRANSPARENT;screen_loc="1,0";}(src)
|
||||
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
M.notransform = TRUE //stop everything moving
|
||||
if(M.client)
|
||||
M.client.screen += cinematic //show every client the cinematic
|
||||
|
||||
var/actually_blew_up = TRUE
|
||||
//Now animate the cinematic
|
||||
switch(station_missed)
|
||||
if(NUKE_NEAR_MISS) //nuke was nearby but (mostly) missed
|
||||
if(mode && !override )
|
||||
override = mode.name
|
||||
switch( override )
|
||||
if("nuclear emergency") //Nuke wasn't on station when it blew up
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb)
|
||||
flick("station_intact_fade_red",cinematic)
|
||||
cinematic.icon_state = "summary_nukefail"
|
||||
if("cult")
|
||||
cinematic.icon_state = null
|
||||
flick("intro_cult",cinematic)
|
||||
sleep(25)
|
||||
SEND_SOUND(world, sound('sound/magic/enter_blood.ogg'))
|
||||
sleep(28)
|
||||
SEND_SOUND(world, sound('sound/machines/terminal_off.ogg'))
|
||||
sleep(20)
|
||||
flick("station_corrupted",cinematic)
|
||||
SEND_SOUND(world, sound('sound/effects/ghost.ogg'))
|
||||
actually_blew_up = FALSE
|
||||
if("fake") //The round isn't over, we're just freaking people out for fun
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
SEND_SOUND(world, sound('sound/items/bikehorn.ogg'))
|
||||
flick("summary_selfdes",cinematic)
|
||||
actually_blew_up = FALSE
|
||||
else
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb)
|
||||
|
||||
|
||||
if(NUKE_MISS_STATION || NUKE_SYNDICATE_BASE) //nuke was nowhere nearby //TODO: a really distant explosion animation
|
||||
sleep(50)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb)
|
||||
actually_blew_up = station_missed == NUKE_SYNDICATE_BASE //don't kill everyone on station if it detonated off station
|
||||
else //station was destroyed
|
||||
if( mode && !override )
|
||||
override = mode.name
|
||||
switch( override )
|
||||
if("nuclear emergency") //Nuke Ops successfully bombed the station
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb)
|
||||
cinematic.icon_state = "summary_nukewin"
|
||||
if("AI malfunction") //Malf (screen,explosion,summary)
|
||||
flick("intro_malf",cinematic)
|
||||
sleep(76)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb) //TODO: If we ever decide to actually detonate the vault bomb
|
||||
cinematic.icon_state = "summary_malf"
|
||||
if("blob") //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb) //TODO: no idea what this case could be
|
||||
cinematic.icon_state = "summary_selfdes"
|
||||
if("cult") //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",cinematic)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb) //TODO: no idea what this case could be
|
||||
cinematic.icon_state = "summary_cult"
|
||||
if("no_core") //Nuke failed to detonate as it had no core
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_intact",cinematic)
|
||||
SEND_SOUND(world, sound('sound/ambience/signal.ogg'))
|
||||
addtimer(CALLBACK(src, .proc/finish_cinematic, null, FALSE), 100)
|
||||
return //Faster exit, since nothing happened
|
||||
else //Station nuked (nuke,explosion,summary)
|
||||
flick("intro_nuke",cinematic)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red", cinematic)
|
||||
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
|
||||
station_explosion_detonation(bomb)
|
||||
cinematic.icon_state = "summary_selfdes"
|
||||
//If its actually the end of the round, wait for it to end.
|
||||
//Otherwise if its a verb it will continue on afterwards.
|
||||
|
||||
var/bombloc = null
|
||||
if(actually_blew_up)
|
||||
if(bomb && bomb.loc)
|
||||
bombloc = bomb.z
|
||||
else if(!station_missed)
|
||||
bombloc = ZLEVEL_STATION_PRIMARY
|
||||
|
||||
if(mode)
|
||||
mode.explosion_in_progress = 0
|
||||
to_chat(world, "<B>The station was destoyed by the nuclear blast!</B>")
|
||||
mode.station_was_nuked = (station_missed<2) //station_missed==1 is a draw. the station becomes irradiated and needs to be evacuated.
|
||||
|
||||
addtimer(CALLBACK(src, .proc/finish_cinematic, bombloc, actually_blew_up), 300)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/finish_cinematic(killz, actually_blew_up)
|
||||
if(cinematic)
|
||||
qdel(cinematic) //end the cinematic
|
||||
cinematic = null
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
M.notransform = FALSE
|
||||
if(actually_blew_up && !isnull(killz) && M.stat != DEAD && M.z == killz)
|
||||
M.gib()
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/create_characters()
|
||||
for(var/mob/dead/new_player/player in GLOB.player_list)
|
||||
if(player.ready == PLAYER_READY_TO_PLAY && player.mind)
|
||||
@@ -505,7 +368,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
end_state.count()
|
||||
var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
|
||||
|
||||
to_chat(world, "<BR>[GLOB.TAB]Shift Duration: <B>[round(world.time / 36000)]:[add_zero("[world.time / 600 % 60]", 2)]:[world.time / 100 % 6][world.time / 100 % 10]</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB]Shift Duration: <B>[DisplayTimeText(world.time - SSticker.round_start_time)]</B>")
|
||||
to_chat(world, "<BR>[GLOB.TAB]Station Integrity: <B>[mode.station_was_nuked ? "<font color='red'>Destroyed</font>" : "[station_integrity]%"]</B>")
|
||||
if(mode.station_was_nuked)
|
||||
SSticker.news_report = STATION_DESTROYED_NUKE
|
||||
@@ -711,13 +574,11 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
queue_delay = SSticker.queue_delay
|
||||
queued_players = SSticker.queued_players
|
||||
cinematic = SSticker.cinematic
|
||||
maprotatechecked = SSticker.maprotatechecked
|
||||
round_start_time = SSticker.round_start_time
|
||||
|
||||
queue_delay = SSticker.queue_delay
|
||||
queued_players = SSticker.queued_players
|
||||
cinematic = SSticker.cinematic
|
||||
maprotatechecked = SSticker.maprotatechecked
|
||||
|
||||
modevoted = SSticker.modevoted
|
||||
|
||||
@@ -169,7 +169,7 @@ SUBSYSTEM_DEF(vote)
|
||||
admin = TRUE
|
||||
|
||||
if(next_allowed_time > world.time && !admin)
|
||||
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait roughly [(next_allowed_time-world.time)/10] seconds before a new vote can be started!</span>")
|
||||
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait [DisplayTimeText(next_allowed_time-world.time)] before a new vote can be started!</span>")
|
||||
return 0
|
||||
|
||||
reset()
|
||||
@@ -198,7 +198,7 @@ SUBSYSTEM_DEF(vote)
|
||||
if(mode == "custom")
|
||||
text += "\n[question]"
|
||||
log_vote(text)
|
||||
to_chat(world, "\n<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>")
|
||||
to_chat(world, "\n<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 [DisplayTimeText(config.vote_period)] to vote.</font>")
|
||||
time_remaining = round(config.vote_period/10)
|
||||
for(var/c in GLOB.clients)
|
||||
var/client/C = c
|
||||
|
||||
+17
-13
@@ -485,7 +485,7 @@
|
||||
|
||||
/datum/action/spell_action/New(Target)
|
||||
..()
|
||||
var/obj/effect/proc_holder/spell/S = target
|
||||
var/obj/effect/proc_holder/S = target
|
||||
S.action = src
|
||||
name = S.name
|
||||
desc = S.desc
|
||||
@@ -495,36 +495,40 @@
|
||||
button.name = name
|
||||
|
||||
/datum/action/spell_action/Destroy()
|
||||
var/obj/effect/proc_holder/spell/S = target
|
||||
var/obj/effect/proc_holder/S = target
|
||||
S.action = null
|
||||
return ..()
|
||||
|
||||
/datum/action/spell_action/Trigger()
|
||||
if(!..())
|
||||
return 0
|
||||
return FALSE
|
||||
if(target)
|
||||
var/obj/effect/proc_holder/spell = target
|
||||
spell.Click()
|
||||
return 1
|
||||
var/obj/effect/proc_holder/S = target
|
||||
S.Click()
|
||||
return TRUE
|
||||
|
||||
/datum/action/spell_action/IsAvailable()
|
||||
if(!target)
|
||||
return 0
|
||||
var/obj/effect/proc_holder/spell/spell = target
|
||||
if(owner)
|
||||
return spell.can_cast(owner)
|
||||
return 0
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/spell_action/spell/IsAvailable()
|
||||
if(!target)
|
||||
return FALSE
|
||||
var/obj/effect/proc_holder/spell/S = target
|
||||
if(owner)
|
||||
return S.can_cast(owner)
|
||||
return FALSE
|
||||
|
||||
/datum/action/spell_action/alien
|
||||
|
||||
/datum/action/spell_action/alien/IsAvailable()
|
||||
if(!target)
|
||||
return 0
|
||||
return FALSE
|
||||
var/obj/effect/proc_holder/alien/ab = target
|
||||
if(owner)
|
||||
return ab.cost_check(ab.check_turf,owner,1)
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/datum/antagonist/abductor
|
||||
name = "Abductor"
|
||||
var/datum/objective_team/abductor_team/team
|
||||
var/sub_role
|
||||
var/outfit
|
||||
var/landmark_type
|
||||
var/greet_text
|
||||
|
||||
/datum/antagonist/abductor/agent
|
||||
sub_role = "Agent"
|
||||
outfit = /datum/outfit/abductor/agent
|
||||
landmark_type = /obj/effect/landmark/abductor/agent
|
||||
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
|
||||
|
||||
/datum/antagonist/abductor/scientist
|
||||
sub_role = "Scientist"
|
||||
outfit = /datum/outfit/abductor/scientist
|
||||
landmark_type = /obj/effect/landmark/abductor/scientist
|
||||
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
|
||||
|
||||
/datum/antagonist/abductor/New(datum/mind/new_owner, datum/objective_team/abductor_team/T)
|
||||
team = T
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/on_gain()
|
||||
SSticker.mode.abductors += owner
|
||||
owner.special_role = "[name] [sub_role]"
|
||||
owner.objectives += team.objectives
|
||||
finalize_abductor()
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/on_removal()
|
||||
SSticker.mode.abductors -= owner
|
||||
team.members -= owner
|
||||
owner.objectives -= team.objectives
|
||||
if(owner.current)
|
||||
to_chat(owner.current,"<span class='userdanger'>You are no longer the [owner.special_role]!</span>")
|
||||
owner.special_role = null
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/abductor/greet()
|
||||
to_chat(owner.current, "<span class='notice'>You are the [owner.special_role]!</span>")
|
||||
to_chat(owner.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(owner.current, "<span class='notice'>[greet_text]</span>")
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/abductor/proc/finalize_abductor()
|
||||
//Equip
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
H.set_species(/datum/species/abductor)
|
||||
H.real_name = "[team.name] [sub_role]"
|
||||
H.equipOutfit(outfit)
|
||||
|
||||
//Teleport to ship
|
||||
for(var/obj/effect/landmark/abductor/LM in GLOB.landmarks_list)
|
||||
if(istype(LM, landmark_type) && LM.team_number == team.team_number)
|
||||
H.forceMove(LM.loc)
|
||||
break
|
||||
|
||||
SSticker.mode.update_abductor_icons_added(owner)
|
||||
@@ -1,6 +1,5 @@
|
||||
/datum/antagonist/ninja
|
||||
name = "Ninja"
|
||||
var/team
|
||||
var/helping_station = 0
|
||||
var/give_objectives = TRUE
|
||||
|
||||
@@ -19,36 +18,8 @@
|
||||
..(new_owner)
|
||||
helping_station = rand(0,1)
|
||||
|
||||
/datum/antagonist/ninja/proc/equip_space_ninja(mob/living/carbon/human/H = owner.current, safety=0)//Safety in case you need to unequip stuff for existing characters.
|
||||
if(safety)
|
||||
qdel(H.w_uniform)
|
||||
qdel(H.wear_suit)
|
||||
qdel(H.wear_mask)
|
||||
qdel(H.head)
|
||||
qdel(H.shoes)
|
||||
qdel(H.gloves)
|
||||
|
||||
var/obj/item/clothing/suit/space/space_ninja/theSuit = new(H)
|
||||
var/obj/item/dash/energy_katana/EK = new(H)
|
||||
theSuit.energyKatana = EK
|
||||
|
||||
H.equip_to_slot_or_del(new /obj/item/device/radio/headset(H), slot_ears)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(H), slot_w_uniform)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/space_ninja(H), slot_shoes)
|
||||
H.equip_to_slot_or_del(theSuit, slot_wear_suit)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/space_ninja(H), slot_gloves)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/head/helmet/space/space_ninja(H), slot_head)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/space_ninja(H), slot_wear_mask)
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/night(H), slot_glasses)
|
||||
H.equip_to_slot_or_del(EK, slot_belt)
|
||||
H.equip_to_slot_or_del(new /obj/item/grenade/plastic/x4(H), slot_l_store)
|
||||
H.equip_to_slot_or_del(new /obj/item/tank/internals/emergency_oxygen(H), slot_s_store)
|
||||
H.equip_to_slot_or_del(new /obj/item/tank/jetpack/carbondioxide(H), slot_back)
|
||||
theSuit.randomize_param()
|
||||
|
||||
var/obj/item/implant/explosive/E = new/obj/item/implant/explosive(H)
|
||||
E.implant(H)
|
||||
return 1
|
||||
/datum/antagonist/ninja/proc/equip_space_ninja(mob/living/carbon/human/H = owner.current)
|
||||
return H.equipOutfit(/datum/outfit/ninja)
|
||||
|
||||
/datum/antagonist/ninja/proc/addMemories()
|
||||
owner.store_memory("I am an elite mercenary assassin of the mighty Spider Clan. A <font color='red'><B>SPACE NINJA</B></font>!")
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
GLOBAL_LIST_EMPTY(cinematics)
|
||||
|
||||
// Use to play cinematics.
|
||||
// Watcher can be world,mob, or a list of mobs
|
||||
// Blocks until sequence is done.
|
||||
/proc/Cinematic(id,watcher,datum/callback/special_callback)
|
||||
var/datum/cinematic/playing
|
||||
for(var/V in subtypesof(/datum/cinematic))
|
||||
var/datum/cinematic/C = V
|
||||
if(initial(C.id) == id)
|
||||
playing = new V()
|
||||
break
|
||||
if(!playing)
|
||||
CRASH("Cinematic type not found")
|
||||
if(special_callback)
|
||||
playing.special_callback = special_callback
|
||||
if(watcher == world)
|
||||
playing.is_global = TRUE
|
||||
watcher = GLOB.mob_list
|
||||
playing.play(watcher)
|
||||
|
||||
/obj/screen/cinematic
|
||||
icon = 'icons/effects/station_explosion.dmi'
|
||||
icon_state = "station_intact"
|
||||
layer = 21
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
screen_loc = "1,1"
|
||||
|
||||
/datum/cinematic
|
||||
var/id = CINEMATIC_DEFAULT
|
||||
var/list/watching = list() //List of clients watching this
|
||||
var/list/locked = list() //Who had notransform set during the cinematic
|
||||
var/is_global = FALSE //Global cinematics will override mob-specific ones
|
||||
var/obj/screen/cinematic/screen
|
||||
var/datum/callback/special_callback //For special effects synced with animation (explosions after the countdown etc)
|
||||
var/cleanup_time = 300 //How long for the final screen to remain
|
||||
|
||||
/datum/cinematic/New()
|
||||
GLOB.cinematics += src
|
||||
screen = new(src)
|
||||
|
||||
/datum/cinematic/Destroy()
|
||||
GLOB.cinematics -= src
|
||||
QDEL_NULL(screen)
|
||||
for(var/mob/M in locked)
|
||||
M.notransform = FALSE
|
||||
return ..()
|
||||
|
||||
/datum/cinematic/proc/play(watchers)
|
||||
//Check if you can actually play it (stop mob cinematics for global ones) and create screen objects
|
||||
for(var/A in GLOB.cinematics)
|
||||
var/datum/cinematic/C = A
|
||||
if(C == src)
|
||||
continue
|
||||
if(C.is_global || !is_global)
|
||||
return //Can't play two global or local cinematics at the same time
|
||||
|
||||
//Close all open windows if global
|
||||
if(is_global)
|
||||
for (var/datum/html_interface/hi in GLOB.html_interfaces)
|
||||
hi.closeAll()
|
||||
SStgui.close_all_uis()
|
||||
|
||||
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(M in watchers)
|
||||
M.notransform = TRUE //Should this be done for non-global cinematics or even at all ?
|
||||
locked += M
|
||||
//Close watcher ui's
|
||||
SStgui.close_user_uis(M)
|
||||
if(M.client)
|
||||
watching += M.client
|
||||
M.client.screen += screen
|
||||
else
|
||||
if(is_global)
|
||||
M.notransform = TRUE
|
||||
locked += M
|
||||
|
||||
//Actually play it
|
||||
content()
|
||||
//Cleanup
|
||||
sleep(cleanup_time)
|
||||
qdel(src)
|
||||
|
||||
//Sound helper
|
||||
/datum/cinematic/proc/cinematic_sound(s)
|
||||
if(is_global)
|
||||
SEND_SOUND(world,s)
|
||||
else
|
||||
for(var/C in watching)
|
||||
SEND_SOUND(C,s)
|
||||
|
||||
//Fire up special callback for actual effects synchronized with animation (eg real nuke explosion happens midway)
|
||||
/datum/cinematic/proc/special()
|
||||
if(special_callback)
|
||||
special_callback.Invoke()
|
||||
|
||||
//Actual cinematic goes in here
|
||||
/datum/cinematic/proc/content()
|
||||
sleep(50)
|
||||
|
||||
/datum/cinematic/nuke_win
|
||||
id = CINEMATIC_NUKE_WIN
|
||||
|
||||
/datum/cinematic/nuke_win/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",screen)
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
screen.icon_state = "summary_nukewin"
|
||||
|
||||
/datum/cinematic/nuke_miss
|
||||
id = CINEMATIC_NUKE_MISS
|
||||
|
||||
/datum/cinematic/nuke_miss/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
flick("station_intact_fade_red",screen)
|
||||
screen.icon_state = "summary_nukefail"
|
||||
|
||||
//Also used for blob
|
||||
/datum/cinematic/nuke_selfdestruct
|
||||
id = CINEMATIC_SELFDESTRUCT
|
||||
|
||||
/datum/cinematic/nuke_selfdestruct/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red", screen)
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
screen.icon_state = "summary_selfdes"
|
||||
|
||||
/datum/cinematic/nuke_selfdestruct_miss
|
||||
id = CINEMATIC_SELFDESTRUCT_MISS
|
||||
|
||||
/datum/cinematic/nuke_selfdestruct_miss/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
screen.icon_state = "station_intact"
|
||||
|
||||
/datum/cinematic/malf
|
||||
id = CINEMATIC_MALF
|
||||
|
||||
/datum/cinematic/malf/content()
|
||||
flick("intro_malf",screen)
|
||||
sleep(76)
|
||||
flick("station_explode_fade_red",screen)
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
screen.icon_state = "summary_malf"
|
||||
|
||||
/datum/cinematic/cult
|
||||
id = CINEMATIC_CULT
|
||||
|
||||
/datum/cinematic/cult/content()
|
||||
screen.icon_state = null
|
||||
flick("intro_cult",screen)
|
||||
sleep(25)
|
||||
cinematic_sound(sound('sound/magic/enter_blood.ogg'))
|
||||
sleep(28)
|
||||
cinematic_sound(sound('sound/machines/terminal_off.ogg'))
|
||||
sleep(20)
|
||||
flick("station_corrupted",screen)
|
||||
cinematic_sound(sound('sound/effects/ghost.ogg'))
|
||||
sleep(70)
|
||||
special()
|
||||
|
||||
/datum/cinematic/nuke_annihilation
|
||||
id = CINEMATIC_ANNIHILATION
|
||||
|
||||
/datum/cinematic/nuke_annihilation/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
flick("station_explode_fade_red",screen)
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
screen.icon_state = "summary_totala"
|
||||
|
||||
/datum/cinematic/fake
|
||||
id = CINEMATIC_NUKE_FAKE
|
||||
cleanup_time = 100
|
||||
|
||||
/datum/cinematic/fake/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
cinematic_sound(sound('sound/items/bikehorn.ogg'))
|
||||
flick("summary_selfdes",screen) //???
|
||||
special()
|
||||
|
||||
/datum/cinematic/no_core
|
||||
id = CINEMATIC_NUKE_NO_CORE
|
||||
cleanup_time = 100
|
||||
|
||||
/datum/cinematic/no_core/content()
|
||||
flick("intro_nuke",screen)
|
||||
sleep(35)
|
||||
flick("station_intact",screen)
|
||||
cinematic_sound(sound('sound/ambience/signal.ogg'))
|
||||
sleep(100)
|
||||
|
||||
/datum/cinematic/nuke_far
|
||||
id = CINEMATIC_NUKE_FAR
|
||||
cleanup_time = 0
|
||||
|
||||
/datum/cinematic/nuke_far/content()
|
||||
cinematic_sound(sound('sound/effects/explosion_distant.ogg'))
|
||||
special()
|
||||
|
||||
/* Intended usage.
|
||||
Nuke.Explosion()
|
||||
-> Cinematic(NUKE_BOOM,world)
|
||||
-> ActualExplosion()
|
||||
-> Mode.OnExplosion()
|
||||
|
||||
|
||||
Narsie()
|
||||
-> Cinematic(CULT,world)
|
||||
*/
|
||||
@@ -94,7 +94,8 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
|
||||
* Allows the component to react to ownership transfers
|
||||
1. `/datum/component/proc/_RemoveNoSignal()` (private, final)
|
||||
* Internal, clears the parent var and removes the component from the parents component list
|
||||
1. `/datum/component/proc/RegisterSignal(signal(string), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz)
|
||||
1. `/datum/component/proc/RegisterSignal(signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final) (Consider removing for performance gainz)
|
||||
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
|
||||
* Makes a component listen for the specified `signal` on it's `parent` datum.
|
||||
* When that signal is recieved `proc_ref` will be called on the component, along with associated arguments
|
||||
* Example proc ref: `.proc/OnEvent`
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
P.datum_components = null
|
||||
parent = null
|
||||
|
||||
/datum/component/proc/RegisterSignal(sig_type, proc_on_self, override = FALSE)
|
||||
/datum/component/proc/RegisterSignal(sig_type_or_types, proc_on_self, override = FALSE)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
var/list/procs = signal_procs
|
||||
@@ -103,12 +103,14 @@
|
||||
procs = list()
|
||||
signal_procs = procs
|
||||
|
||||
if(!override)
|
||||
. = procs[sig_type]
|
||||
if(.)
|
||||
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
|
||||
|
||||
procs[sig_type] = CALLBACK(src, proc_on_self)
|
||||
var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types)
|
||||
for(var/sig_type in sig_types)
|
||||
if(!override)
|
||||
. = procs[sig_type]
|
||||
if(.)
|
||||
stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning")
|
||||
|
||||
procs[sig_type] = CALLBACK(src, proc_on_self)
|
||||
|
||||
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
|
||||
return
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
/datum/component/slippery/Initialize(_intensity, _lube_flags = NONE)
|
||||
intensity = max(_intensity, 0)
|
||||
lube_flags = _lube_flags
|
||||
if(ismovableatom(parent))
|
||||
RegisterSignal(COMSIG_MOVABLE_CROSSED, .proc/Slip)
|
||||
else
|
||||
RegisterSignal(COMSIG_ATOM_ENTERED, .proc/Slip)
|
||||
RegisterSignal(list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip)
|
||||
|
||||
/datum/component/slippery/proc/Slip(atom/movable/AM)
|
||||
var/mob/victim = AM
|
||||
|
||||
@@ -24,22 +24,9 @@
|
||||
if(use_delay_override)
|
||||
use_delay = use_delay_override
|
||||
|
||||
if(istype(parent, /atom))
|
||||
RegisterSignal(COMSIG_ATOM_BLOB_ACT, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_ATOM_HULK_ATTACK, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/play_squeak)
|
||||
if(istype(parent, /atom/movable))
|
||||
RegisterSignal(COMSIG_MOVABLE_CROSSED, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_MOVABLE_COLLIDE, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_MOVABLE_IMPACT, .proc/play_squeak)
|
||||
if(istype(parent, /obj/item))
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK, .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK_OBJ, .proc/play_squeak)
|
||||
if(istype(parent, /obj/item/clothing/shoes))
|
||||
RegisterSignal(COMSIG_SHOES_STEP_ACTION, .proc/step_squeak)
|
||||
else
|
||||
RegisterSignal(COMSIG_ATOM_ENTERED, .proc/play_squeak)
|
||||
RegisterSignal(list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_CROSSED, COMSIG_MOVABLE_COLLIDE, COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_ATTACK_OBJ), .proc/play_squeak)
|
||||
RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak)
|
||||
RegisterSignal(COMSIG_SHOES_STEP_ACTION, .proc/step_squeak)
|
||||
|
||||
/datum/component/squeak/proc/play_squeak()
|
||||
if(prob(squeak_chance))
|
||||
|
||||
@@ -1,103 +1,111 @@
|
||||
#define FORWARD -1
|
||||
#define BACKWARD 1
|
||||
|
||||
/datum/construction
|
||||
var/list/steps
|
||||
var/atom/holder
|
||||
var/result
|
||||
var/list/steps_desc
|
||||
|
||||
/datum/construction/New(atom)
|
||||
..()
|
||||
holder = atom
|
||||
if(!holder) //don't want this without a holder
|
||||
qdel(src)
|
||||
set_desc(steps.len)
|
||||
return
|
||||
|
||||
/datum/construction/proc/next_step()
|
||||
steps.len--
|
||||
if(!steps.len)
|
||||
spawn_result()
|
||||
else
|
||||
set_desc(steps.len)
|
||||
return
|
||||
|
||||
/datum/construction/proc/action(atom/used_atom,mob/user)
|
||||
return
|
||||
|
||||
/datum/construction/proc/check_step(atom/used_atom,mob/user) //check last step only
|
||||
var/valid_step = is_right_key(used_atom)
|
||||
if(valid_step)
|
||||
if(custom_action(valid_step, used_atom, user))
|
||||
next_step()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/construction/proc/is_right_key(atom/used_atom) // returns current step num if used_atom is of the right type.
|
||||
var/list/L = steps[steps.len]
|
||||
if(istype(used_atom, L["key"]))
|
||||
return steps.len
|
||||
return 0
|
||||
|
||||
/datum/construction/proc/custom_action(step, used_atom, user)
|
||||
return 1
|
||||
|
||||
/datum/construction/proc/check_all_steps(atom/used_atom,mob/user) //check all steps, remove matching one.
|
||||
for(var/i=1;i<=steps.len;i++)
|
||||
var/list/L = steps[i];
|
||||
if(istype(used_atom, L["key"]))
|
||||
if(custom_action(i, used_atom, user))
|
||||
steps[i]=null;//stupid byond list from list removal...
|
||||
listclearnulls(steps);
|
||||
if(!steps.len)
|
||||
spawn_result()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/construction/proc/spawn_result()
|
||||
if(result)
|
||||
new result(get_turf(holder))
|
||||
qdel(holder)
|
||||
return
|
||||
|
||||
/datum/construction/proc/set_desc(index as num)
|
||||
var/list/step = steps[index]
|
||||
holder.desc = step["desc"]
|
||||
return
|
||||
|
||||
/datum/construction/reversible
|
||||
var/index
|
||||
|
||||
/datum/construction/reversible/New(atom)
|
||||
..()
|
||||
index = steps.len
|
||||
return
|
||||
|
||||
/datum/construction/reversible/proc/update_index(diff as num)
|
||||
index+=diff
|
||||
if(index==0)
|
||||
spawn_result()
|
||||
else
|
||||
set_desc(index)
|
||||
return
|
||||
|
||||
/datum/construction/reversible/is_right_key(atom/used_atom) // returns index step
|
||||
var/list/L = steps[index]
|
||||
if(istype(used_atom, L["key"]))
|
||||
return FORWARD //to the first step -> forward
|
||||
else if(L["backkey"] && istype(used_atom, L["backkey"]))
|
||||
return BACKWARD //to the last step -> backwards
|
||||
return 0
|
||||
|
||||
/datum/construction/reversible/check_step(atom/used_atom,mob/user)
|
||||
var/diff = is_right_key(used_atom)
|
||||
if(diff)
|
||||
if(custom_action(index, diff, used_atom, user))
|
||||
update_index(diff)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/construction/reversible/custom_action(index, diff, used_atom, user)
|
||||
return 1
|
||||
#define FORWARD -1
|
||||
#define BACKWARD 1
|
||||
|
||||
/datum/construction
|
||||
var/list/steps
|
||||
var/atom/holder
|
||||
var/result
|
||||
var/list/steps_desc
|
||||
|
||||
/datum/construction/New(atom)
|
||||
..()
|
||||
holder = atom
|
||||
if(!holder) //don't want this without a holder
|
||||
qdel(src)
|
||||
set_desc(steps.len)
|
||||
return
|
||||
|
||||
/datum/construction/proc/next_step()
|
||||
steps.len--
|
||||
if(!steps.len)
|
||||
spawn_result()
|
||||
else
|
||||
set_desc(steps.len)
|
||||
return
|
||||
|
||||
/datum/construction/proc/action(atom/used_atom,mob/user)
|
||||
return
|
||||
|
||||
/datum/construction/proc/check_step(atom/used_atom,mob/user) //check last step only
|
||||
var/valid_step = is_right_key(used_atom)
|
||||
if(valid_step)
|
||||
if(custom_action(valid_step, used_atom, user))
|
||||
next_step()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/construction/proc/is_right_key(atom/used_atom) // returns current step num if used_atom is of the right type.
|
||||
var/list/L = steps[steps.len]
|
||||
if(istype(used_atom, L["key"]))
|
||||
return steps.len
|
||||
return 0
|
||||
|
||||
/datum/construction/proc/custom_action(step, used_atom, user)
|
||||
return 1
|
||||
|
||||
/datum/construction/proc/check_all_steps(atom/used_atom,mob/user) //check all steps, remove matching one.
|
||||
for(var/i=1;i<=steps.len;i++)
|
||||
var/list/L = steps[i];
|
||||
if(istype(used_atom, L["key"]))
|
||||
if(custom_action(i, used_atom, user))
|
||||
steps[i]=null;//stupid byond list from list removal...
|
||||
listclearnulls(steps);
|
||||
if(!steps.len)
|
||||
spawn_result()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/construction/proc/spawn_result()
|
||||
if(result)
|
||||
new result(get_turf(holder))
|
||||
qdel(holder)
|
||||
return
|
||||
|
||||
/datum/construction/proc/spawn_mecha_result()
|
||||
if(result)
|
||||
var/obj/mecha/m = new result(get_turf(holder))
|
||||
var/obj/item/oldcell = locate (/obj/item/stock_parts/cell) in m
|
||||
QDEL_NULL(oldcell)
|
||||
m.CheckParts(holder.contents)
|
||||
QDEL_NULL(holder)
|
||||
|
||||
/datum/construction/proc/set_desc(index as num)
|
||||
var/list/step = steps[index]
|
||||
holder.desc = step["desc"]
|
||||
return
|
||||
|
||||
/datum/construction/reversible
|
||||
var/index
|
||||
|
||||
/datum/construction/reversible/New(atom)
|
||||
..()
|
||||
index = steps.len
|
||||
return
|
||||
|
||||
/datum/construction/reversible/proc/update_index(diff as num)
|
||||
index+=diff
|
||||
if(index==0)
|
||||
spawn_result()
|
||||
else
|
||||
set_desc(index)
|
||||
return
|
||||
|
||||
/datum/construction/reversible/is_right_key(atom/used_atom) // returns index step
|
||||
var/list/L = steps[index]
|
||||
if(istype(used_atom, L["key"]))
|
||||
return FORWARD //to the first step -> forward
|
||||
else if(L["backkey"] && istype(used_atom, L["backkey"]))
|
||||
return BACKWARD //to the last step -> backwards
|
||||
return 0
|
||||
|
||||
/datum/construction/reversible/check_step(atom/used_atom,mob/user)
|
||||
var/diff = is_right_key(used_atom)
|
||||
if(diff)
|
||||
if(custom_action(index, diff, used_atom, user))
|
||||
update_index(diff)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/construction/reversible/custom_action(index, diff, used_atom, user)
|
||||
return 1
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/datum/action/neck_chop/Trigger()
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't use [name] while you're incapacitated.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if (H.mind.martial_art.streak == "neck_chop")
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
/datum/action/leg_sweep/Trigger()
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't use [name] while you're incapacitated.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if (H.mind.martial_art.streak == "leg_sweep")
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
/datum/action/lung_punch/Trigger()
|
||||
if(owner.incapacitated())
|
||||
to_chat(owner, "<span class='warning'>You can't use Krav Maga while you're incapacitated.</span>")
|
||||
to_chat(owner, "<span class='warning'>You can't use [name] while you're incapacitated.</span>")
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if (H.mind.martial_art.streak == "quick_choke")
|
||||
@@ -57,14 +57,14 @@
|
||||
|
||||
/datum/martial_art/krav_maga/teach(mob/living/carbon/human/H,make_temporary=0)
|
||||
if(..())
|
||||
to_chat(H, "<span class = 'userdanger'>You know the arts of Krav Maga!</span>")
|
||||
to_chat(H, "<span class = 'userdanger'>You know the arts of [name]!</span>")
|
||||
to_chat(H, "<span class = 'danger'>Place your cursor over a move at the top of the screen to see what it does.</span>")
|
||||
neckchop.Grant(H)
|
||||
legsweep.Grant(H)
|
||||
lungpunch.Grant(H)
|
||||
|
||||
/datum/martial_art/krav_maga/on_remove(mob/living/carbon/human/H)
|
||||
to_chat(H, "<span class = 'userdanger'>You suddenly forget the arts of Krav Maga...</span>")
|
||||
to_chat(H, "<span class = 'userdanger'>You suddenly forget the arts of [name]...</span>")
|
||||
neckchop.Remove(H)
|
||||
legsweep.Remove(H)
|
||||
lungpunch.Remove(H)
|
||||
@@ -140,7 +140,7 @@
|
||||
playsound(get_turf(D), 'sound/effects/hit_punch.ogg', 50, 1, -1)
|
||||
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
|
||||
add_logs(A, D, "[picked_hit_type] with Krav Maga")
|
||||
add_logs(A, D, "[picked_hit_type] with [name]")
|
||||
return 1
|
||||
|
||||
/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
|
||||
|
||||
+1
-55
@@ -590,8 +590,6 @@
|
||||
if(src in SSticker.mode.abductors)
|
||||
text += "<b>Abductor</b> | <a href='?src=\ref[src];abductor=clear'>human</a>"
|
||||
text += " | <a href='?src=\ref[src];common=undress'>undress</a> | <a href='?src=\ref[src];abductor=equip'>equip</a>"
|
||||
else
|
||||
text += "<a href='?src=\ref[src];abductor=abductor'>abductor</a> | <b>human</b>"
|
||||
|
||||
if(current && current.client && (ROLE_ABDUCTOR in current.client.prefs.be_special))
|
||||
text += " | Enabled in Prefs"
|
||||
@@ -1244,13 +1242,6 @@
|
||||
if("clear")
|
||||
to_chat(usr, "Not implemented yet. Sorry!")
|
||||
//SSticker.mode.update_abductor_icons_removed(src)
|
||||
if("abductor")
|
||||
if(!ishuman(current))
|
||||
to_chat(usr, "<span class='warning'>This only works on humans!</span>")
|
||||
return
|
||||
make_Abductor()
|
||||
log_admin("[key_name(usr)] turned [current] into abductor.")
|
||||
SSticker.mode.update_abductor_icons_added(src)
|
||||
if("equip")
|
||||
if(!ishuman(current))
|
||||
to_chat(usr, "<span class='warning'>This only works on humans!</span>")
|
||||
@@ -1496,52 +1487,7 @@
|
||||
take_uplink()
|
||||
var/fail = 0
|
||||
fail |= !SSticker.mode.equip_revolutionary(current)
|
||||
|
||||
/datum/mind/proc/make_Abductor()
|
||||
var/role = alert("Abductor Role ?","Role","Agent","Scientist")
|
||||
var/team = input("Abductor Team ?","Team ?") in list(1,2,3,4)
|
||||
var/teleport = alert("Teleport to ship ?","Teleport","Yes","No")
|
||||
|
||||
if(!role || !team || !teleport)
|
||||
return
|
||||
|
||||
if(!ishuman(current))
|
||||
return
|
||||
|
||||
SSticker.mode.abductors |= src
|
||||
|
||||
var/datum/objective/experiment/O = new
|
||||
O.owner = src
|
||||
objectives += O
|
||||
|
||||
var/mob/living/carbon/human/H = current
|
||||
|
||||
H.set_species(/datum/species/abductor)
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
|
||||
if(role == "Scientist")
|
||||
S.scientist = TRUE
|
||||
S.team = team
|
||||
|
||||
var/list/obj/effect/landmark/abductor/agent_landmarks = new
|
||||
var/list/obj/effect/landmark/abductor/scientist_landmarks = new
|
||||
agent_landmarks.len = 4
|
||||
scientist_landmarks.len = 4
|
||||
for(var/obj/effect/landmark/abductor/A in GLOB.landmarks_list)
|
||||
if(istype(A, /obj/effect/landmark/abductor/agent))
|
||||
agent_landmarks[text2num(A.team)] = A
|
||||
else if(istype(A, /obj/effect/landmark/abductor/scientist))
|
||||
scientist_landmarks[text2num(A.team)] = A
|
||||
|
||||
var/obj/effect/landmark/L
|
||||
if(teleport=="Yes")
|
||||
switch(role)
|
||||
if("Agent")
|
||||
L = agent_landmarks[team]
|
||||
if("Scientist")
|
||||
L = scientist_landmarks[team]
|
||||
H.forceMove(L.loc)
|
||||
|
||||
|
||||
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
|
||||
spell_list += S
|
||||
S.action.Grant(current)
|
||||
|
||||
@@ -102,10 +102,10 @@
|
||||
if(implants)
|
||||
for(var/implant_type in implants)
|
||||
var/obj/item/implant/I = new implant_type(H)
|
||||
I.implant(H, null, silent=TRUE)
|
||||
I.implant(H, null, TRUE)
|
||||
|
||||
H.update_body()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/outfit/proc/apply_fingerprints(mob/living/carbon/human/H)
|
||||
if(!istype(H))
|
||||
|
||||
@@ -225,6 +225,17 @@
|
||||
A.CollidedWith(src)
|
||||
|
||||
/atom/movable/proc/forceMove(atom/destination)
|
||||
. = FALSE
|
||||
if(destination)
|
||||
. = doMove(destination)
|
||||
else
|
||||
CRASH("No valid destination passed into forceMove")
|
||||
|
||||
/atom/movable/proc/moveToNullspace()
|
||||
return doMove(null)
|
||||
|
||||
/atom/movable/proc/doMove(atom/destination)
|
||||
. = FALSE
|
||||
if(destination)
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
@@ -251,8 +262,17 @@
|
||||
AM.Crossed(src, oldloc)
|
||||
|
||||
Moved(oldloc, 0)
|
||||
return 1
|
||||
return 0
|
||||
. = TRUE
|
||||
|
||||
//If no destination, move the atom into nullspace (don't do this unless you know what you're doing)
|
||||
else
|
||||
. = TRUE
|
||||
var/atom/oldloc = loc
|
||||
var/area/old_area = get_area(oldloc)
|
||||
oldloc.Exited(src, null)
|
||||
if(old_area)
|
||||
old_area.Exited(src, null)
|
||||
loc = null
|
||||
|
||||
/mob/living/forceMove(atom/destination)
|
||||
stop_pulling()
|
||||
@@ -261,9 +281,10 @@
|
||||
if(has_buckled_mobs())
|
||||
unbuckle_all_mobs(force=1)
|
||||
. = ..()
|
||||
if(client)
|
||||
reset_perspective(destination)
|
||||
update_canmove() //if the mob was asleep inside a container and then got forceMoved out we need to make them fall.
|
||||
if(.)
|
||||
if(client)
|
||||
reset_perspective(destination)
|
||||
update_canmove() //if the mob was asleep inside a container and then got forceMoved out we need to make them fall.
|
||||
|
||||
/mob/living/brain/forceMove(atom/destination)
|
||||
if(container)
|
||||
|
||||
@@ -203,9 +203,9 @@
|
||||
var/mob/living/silicon/robot/R
|
||||
switch(borg_to_spawn)
|
||||
if("Medical")
|
||||
R = new /mob/living/silicon/robot/syndicate/medical(T)
|
||||
R = new /mob/living/silicon/robot/modules/syndicate/medical(T)
|
||||
else
|
||||
R = new /mob/living/silicon/robot/syndicate(T) //Assault borg by default
|
||||
R = new /mob/living/silicon/robot/modules/syndicate(T) //Assault borg by default
|
||||
|
||||
var/brainfirstname = pick(GLOB.first_names_male)
|
||||
if(prob(50))
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
if(!placed)
|
||||
if(manualplace_min_time && world.time >= manualplace_min_time)
|
||||
to_chat(src, "<b><span class='big'><font color=\"#EE4000\">You may now place your blob core.</font></span></b>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [round((autoplace_max_time - world.time)/600, 0.5)] minutes.</font></span>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [DisplayTimeText(autoplace_max_time - world.time)].</font></span>")
|
||||
manualplace_min_time = 0
|
||||
if(autoplace_max_time && world.time >= autoplace_max_time)
|
||||
place_blob_core(base_point_rate, 1)
|
||||
|
||||
@@ -365,5 +365,5 @@
|
||||
to_chat(src, "<b>Shortcuts:</b> Click = Expand Blob <b>|</b> Middle Mouse Click = Rally Spores <b>|</b> Ctrl Click = Create Shield Blob <b>|</b> Alt Click = Remove Blob")
|
||||
to_chat(src, "Attempting to talk will send a message to all other overminds, allowing you to coordinate with them.")
|
||||
if(!placed && autoplace_max_time <= world.time)
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [round((autoplace_max_time - world.time)/600, 0.5)] minutes.</font></span>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You will automatically place your blob core in [DisplayTimeText(autoplace_max_time - world.time)].</font></span>")
|
||||
to_chat(src, "<span class='big'><font color=\"#EE4000\">You [manualplace_min_time ? "will be able to":"can"] manually place your blob core by pressing the Place Blob Core button in the bottom right corner of the screen.</font></span>")
|
||||
|
||||
@@ -207,7 +207,7 @@
|
||||
time_duration = round(time_duration * (2 * efficiency), 1)
|
||||
CO.active = TRUE //you'd be active in a second but you should update immediately
|
||||
invoker.visible_message("<span class='warning'>The air in front of [invoker] ripples before suddenly tearing open!</span>", \
|
||||
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [time_duration / 10] seconds and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
|
||||
"<span class='brass'>With a word, you rip open a [two_way ? "two-way":"one-way"] rift to [input_target_key]. It will last for [DisplayTimeText(time_duration)] and has [gateway_uses] use[gateway_uses > 1 ? "s" : ""].</span>")
|
||||
var/obj/effect/clockwork/spatial_gateway/S1 = new(issrcobelisk ? get_turf(src) : get_step(get_turf(invoker), invoker.dir))
|
||||
var/obj/effect/clockwork/spatial_gateway/S2 = new(istargetobelisk ? get_turf(target) : get_step(get_turf(target), target.dir))
|
||||
|
||||
|
||||
@@ -195,6 +195,19 @@
|
||||
textlist += "HONOR RATVAR "
|
||||
textlist += "</b></font>"
|
||||
else
|
||||
var/servants = 0
|
||||
var/production_time = SLAB_PRODUCTION_TIME
|
||||
for(var/mob/living/M in GLOB.living_mob_list)
|
||||
if(is_servant_of_ratvar(M) && (ishuman(M) || issilicon(M)))
|
||||
servants++
|
||||
if(servants > SCRIPT_SERVANT_REQ)
|
||||
servants -= SCRIPT_SERVANT_REQ
|
||||
production_time += min(SLAB_SERVANT_SLOWDOWN * servants, SLAB_SLOWDOWN_MAXIMUM)
|
||||
if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM)
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>, which increases for each human or silicon Servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
else
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>"
|
||||
|
||||
textlist = list("<font color=#BE8700 size=3><b><center>[text2ratvar("Purge all untruths and honor Engine.")]</center></b></font><br>\
|
||||
\
|
||||
<b><i>NOTICE:</b> This information is out of date. Read the Ark & You primer in your backpack or read the wiki page for current info.</i><br>\
|
||||
@@ -287,12 +300,24 @@
|
||||
dat += "<font color=#BE8700><b>Transmission:</b></font> Drains and stores power for clockwork structures. Feeding it brass sheets will create additional power.<br><br>"
|
||||
dat += "<font color=#BE8700 size=3>-=-=-=-=-=-</font>"
|
||||
if("Components")
|
||||
var/servants = 0 //Calculate the current production time for slab components
|
||||
var/production_time = SLAB_PRODUCTION_TIME
|
||||
for(var/mob/living/M in GLOB.living_mob_list)
|
||||
if(is_servant_of_ratvar(M) && (ishuman(M) || issilicon(M)))
|
||||
servants++
|
||||
if(servants > SCRIPT_SERVANT_REQ)
|
||||
servants -= SCRIPT_SERVANT_REQ
|
||||
production_time += min(SLAB_SERVANT_SLOWDOWN * servants, SLAB_SLOWDOWN_MAXIMUM)
|
||||
if(production_time != SLAB_PRODUCTION_TIME+SLAB_SLOWDOWN_MAXIMUM)
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>, which increases for each human or silicon Servant above <b>[SCRIPT_SERVANT_REQ]</b>"
|
||||
else
|
||||
production_time = "<b>[DisplayTimeText(production_time)]</b>"
|
||||
dat += "<font color=#BE8700 size=3>Components & Their Uses</font><br><br>"
|
||||
dat += "<b>Components</b> are your primary resource as a Servant. There are five types of component, with each one being used in different roles:<br><br>"
|
||||
dat += "Although this is a good rule of thumb, their effects become much more nuanced when used together. For instance, a turret might have both belligerent eyes and \
|
||||
vanguard cogwheels as construction requirements, because it defends its allies by harming its enemies.<br><br>"
|
||||
dat += "Components' primary use is fueling <b>scripture</b> (covered in its own section), and they can be created through various ways. This clockwork slab, for instance, \
|
||||
will make a random component of every type - or a specific one, if you choose a target component from the interface - every <b>remove me already</b>. This number will increase \
|
||||
will make a random component of every type - or a specific one, if you choose a target component from the interface - every [production_time]. This number will increase \
|
||||
as the amount of Servants in the covenant increase; additionally, slabs can only produce components when held by a Servant, and holding more than one slab will cause both \
|
||||
of them to halt progress until one of them is removed from their person.<br><br>"
|
||||
dat += "Your slab has an internal storage of components, but it isn't meant to be the main one. Instead, there's a <b>global storage</b> of components that can be \
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
autoping = FALSE
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
force_replace_ai_name = TRUE
|
||||
overrides_aicore_laws = TRUE
|
||||
|
||||
/obj/item/device/mmi/posibrain/soul_vessel/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
..()
|
||||
if(is_servant_of_ratvar(user) || isobserver(user))
|
||||
if(linkedwall)
|
||||
to_chat(user, "<span class='brass'>It is linked to a Clockwork Wall and will generate a component every <b>[round(get_production_time() * 0.1, 0.1)]</b> seconds!</span>")
|
||||
to_chat(user, "<span class='brass'>It is linked to a Clockwork Wall and will generate a component every <b>[DisplayTimeText(get_production_time())]</b>!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='alloy'>It is unlinked! Construct a Clockwork Wall nearby to generate components!</span>")
|
||||
to_chat(user, "<b>Stored components:</b>")
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
/proc/pollCultists(var/mob/living/Nominee) //Cult Master Poll
|
||||
if(world.time < CULT_POLL_WAIT)
|
||||
to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [round((CULT_POLL_WAIT-world.time)/10)] seconds.")
|
||||
to_chat(Nominee, "It would be premature to select a leader while everyone is still settling in, try again in [DisplayTimeText(CULT_POLL_WAIT-world.time)].")
|
||||
return
|
||||
GLOB.cult_vote_called = TRUE //somebody's trying to be a master, make sure we don't let anyone else try
|
||||
for(var/datum/mind/B in SSticker.mode.cult)
|
||||
@@ -232,7 +232,7 @@
|
||||
return FALSE
|
||||
if(cooldown > world.time)
|
||||
if(!CM.active)
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can mark another target!</b></span>")
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [DisplayTimeText(cooldown - world.time)] before you can mark another target!</b></span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -324,7 +324,7 @@
|
||||
return FALSE
|
||||
if(cooldown > world.time)
|
||||
if(!PM.active)
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can pulse again!</b></span>")
|
||||
to_chat(owner, "<span class='cultlarge'><b>You need to wait [DisplayTimeText(cooldown - world.time)] before you can pulse again!</b></span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>\The [src] is [anchored ? "":"not "]secured to the floor.</span>")
|
||||
if((iscultist(user) || isobserver(user)) && cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is too weak, [p_they()] will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is too weak, [p_they()] will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
|
||||
/obj/structure/destructible/cult/examine_status(mob/user)
|
||||
if(iscultist(user) || isobserver(user))
|
||||
@@ -50,13 +50,6 @@
|
||||
animate(src, color = previouscolor, time = 8)
|
||||
addtimer(CALLBACK(src, /atom/proc/update_atom_colour), 8)
|
||||
|
||||
/obj/structure/destructible/cult/proc/getETA()
|
||||
var/time = (cooldowntime - world.time)/600
|
||||
var/eta = "[round(time, 1)] minutes"
|
||||
if(time <= 1)
|
||||
time = (cooldowntime - world.time)*0.1
|
||||
eta = "[round(time, 1)] seconds"
|
||||
return eta
|
||||
|
||||
/obj/structure/destructible/cult/talisman
|
||||
name = "altar"
|
||||
@@ -72,7 +65,7 @@
|
||||
to_chat(user, "<span class='cultitalic'>You need to anchor [src] to the floor with a tome first.</span>")
|
||||
return
|
||||
if(cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
return
|
||||
var/choice = alert(user,"You study the schematics etched into the forge...",,"Eldritch Whetstone","Zealot's Blindfold","Flask of Unholy Water")
|
||||
var/pickedtype
|
||||
@@ -105,7 +98,7 @@
|
||||
to_chat(user, "<span class='cultitalic'>You need to anchor [src] to the floor with a tome first.</span>")
|
||||
return
|
||||
if(cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
return
|
||||
var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Nar-Sien Hardsuit")
|
||||
var/pickedtype
|
||||
@@ -212,7 +205,7 @@
|
||||
to_chat(user, "<span class='cultitalic'>You need to anchor [src] to the floor with a tome first.</span>")
|
||||
return
|
||||
if(cooldowntime > world.time)
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [getETA()].</span>")
|
||||
to_chat(user, "<span class='cultitalic'>The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].</span>")
|
||||
return
|
||||
var/choice = alert(user,"You flip through the black pages of the archives...",,"Supply Talisman","Shuttle Curse","Veil Walker Set")
|
||||
var/list/pickedtype = list()
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
var/probability = 0
|
||||
var/false_report_weight = 0 //How often will this show up incorrectly in a centcom report?
|
||||
var/station_was_nuked = 0 //see nuclearbomb.dm and malfunction.dm
|
||||
var/explosion_in_progress = 0 //sit back and relax
|
||||
var/round_ends_with_antag_death = 0 //flags the "one verse the station" antags as such
|
||||
var/list/datum/mind/modePlayer = new
|
||||
var/list/datum/mind/antag_candidates = list() // List of possible starting antags goes here
|
||||
@@ -562,3 +561,8 @@
|
||||
|
||||
/datum/game_mode/proc/generate_report() //Generates a small text blurb for the gamemode in centcom report
|
||||
return "Gamemode report for [name] not set. Contact a coder."
|
||||
|
||||
//By default nuke just ends the round
|
||||
/datum/game_mode/proc/OnNukeExplosion(off_station)
|
||||
if(off_station < 2)
|
||||
station_was_nuked = TRUE //Will end the round on next check.
|
||||
@@ -1,5 +1,17 @@
|
||||
/datum/objective_team/abductor_team
|
||||
member_name = "abductor"
|
||||
var/list/objectives = list()
|
||||
var/team_number
|
||||
|
||||
/datum/objective_team/abductor_team/is_solo()
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/abductor_team/proc/add_objective(datum/objective/O)
|
||||
O.team = src
|
||||
O.update_explanation_text()
|
||||
objectives += O
|
||||
|
||||
/datum/game_mode
|
||||
var/abductor_teams = 0
|
||||
var/list/datum/mind/abductors = list()
|
||||
var/list/datum/mind/abductees = list()
|
||||
|
||||
@@ -12,12 +24,8 @@
|
||||
required_players = 15
|
||||
maximum_players = 50
|
||||
var/max_teams = 4
|
||||
abductor_teams = 1
|
||||
var/list/datum/mind/scientists = list()
|
||||
var/list/datum/mind/agents = list()
|
||||
var/list/datum/objective/team_objectives = list()
|
||||
var/list/team_names = list()
|
||||
var/finished = 0
|
||||
var/list/datum/objective_team/abductor_team/abductor_teams = list()
|
||||
var/finished = FALSE
|
||||
|
||||
/datum/game_mode/abduction/announce()
|
||||
to_chat(world, "<B>The current game mode is - Abduction!</B>")
|
||||
@@ -26,163 +34,78 @@
|
||||
to_chat(world, "<b>Crew</b> - don't get abducted and stop the abductors.")
|
||||
|
||||
/datum/game_mode/abduction/pre_setup()
|
||||
abductor_teams = max(1, min(max_teams,round(num_players()/config.abductor_scaling_coeff)))
|
||||
var/possible_teams = max(1,round(antag_candidates.len / 2))
|
||||
abductor_teams = min(abductor_teams,possible_teams)
|
||||
var/num_teams = max(1, min(max_teams, round(num_players() / config.abductor_scaling_coeff)))
|
||||
var/possible_teams = max(1, round(antag_candidates.len / 2))
|
||||
num_teams = min(num_teams, possible_teams)
|
||||
|
||||
abductors.len = 2*abductor_teams
|
||||
scientists.len = abductor_teams
|
||||
agents.len = abductor_teams
|
||||
team_objectives.len = abductor_teams
|
||||
team_names.len = abductor_teams
|
||||
for(var/i = 1 to num_teams)
|
||||
if(!make_abductor_team())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
for(var/i=1,i<=abductor_teams,i++)
|
||||
if(!make_abductor_team(i))
|
||||
return 0
|
||||
/datum/game_mode/abduction/proc/make_abductor_team(datum/mind/agent, datum/mind/scientist)
|
||||
var/team_number = abductor_teams.len+1
|
||||
|
||||
return 1
|
||||
var/datum/objective_team/abductor_team/team = new
|
||||
team.team_number = team_number
|
||||
team.name = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names
|
||||
team.add_objective(new/datum/objective/experiment)
|
||||
|
||||
/datum/game_mode/abduction/proc/make_abductor_team(team_number,preset_agent=null,preset_scientist=null)
|
||||
//Team Name
|
||||
team_names[team_number] = "Mothership [pick(GLOB.possible_changeling_IDs)]" //TODO Ensure unique and actual alieny names
|
||||
//Team Objective
|
||||
var/datum/objective/experiment/team_objective = new
|
||||
team_objective.team_number = team_number
|
||||
team_objectives[team_number] = team_objective
|
||||
//Team Members
|
||||
if(antag_candidates.len < (!agent + !scientist))
|
||||
return
|
||||
|
||||
if(!preset_agent || !preset_scientist)
|
||||
if(antag_candidates.len <=2)
|
||||
return 0
|
||||
|
||||
var/datum/mind/scientist
|
||||
var/datum/mind/agent
|
||||
|
||||
if(!preset_scientist)
|
||||
if(!scientist)
|
||||
scientist = pick(antag_candidates)
|
||||
antag_candidates -= scientist
|
||||
else
|
||||
scientist = preset_scientist
|
||||
antag_candidates -= scientist
|
||||
team.members |= scientist
|
||||
scientist.assigned_role = "Abductor Scientist"
|
||||
log_game("[scientist.key] (ckey) has been selected as [team.name] abductor scientist.")
|
||||
|
||||
if(!preset_agent)
|
||||
if(!agent)
|
||||
agent = pick(antag_candidates)
|
||||
antag_candidates -= agent
|
||||
else
|
||||
agent = preset_agent
|
||||
antag_candidates -= agent
|
||||
team.members |= agent
|
||||
agent.assigned_role = "Abductor Agent"
|
||||
log_game("[agent.key] (ckey) has been selected as [team.name] abductor agent.")
|
||||
|
||||
|
||||
scientist.assigned_role = "abductor scientist"
|
||||
scientist.special_role = "abductor scientist"
|
||||
log_game("[scientist.key] (ckey) has been selected as an abductor team [team_number] scientist.")
|
||||
|
||||
agent.assigned_role = "abductor agent"
|
||||
agent.special_role = "abductor agent"
|
||||
log_game("[agent.key] (ckey) has been selected as an abductor team [team_number] agent.")
|
||||
|
||||
abductors |= agent
|
||||
abductors |= scientist
|
||||
scientists[team_number] = scientist
|
||||
agents[team_number] = agent
|
||||
return 1
|
||||
abductor_teams += team
|
||||
return team
|
||||
|
||||
/datum/game_mode/abduction/post_setup()
|
||||
for(var/team_number=1,team_number<=abductor_teams,team_number++)
|
||||
post_setup_team(team_number)
|
||||
for(var/datum/objective_team/abductor_team/team in abductor_teams)
|
||||
post_setup_team(team)
|
||||
return ..()
|
||||
|
||||
//Used for create antag buttons
|
||||
/datum/game_mode/abduction/proc/post_setup_team(team_number)
|
||||
var/list/obj/effect/landmark/abductor/agent_landmarks = list()
|
||||
var/list/obj/effect/landmark/abductor/scientist_landmarks = list()
|
||||
agent_landmarks.len = max_teams
|
||||
scientist_landmarks.len = max_teams
|
||||
for(var/obj/effect/landmark/abductor/A in GLOB.landmarks_list)
|
||||
if(istype(A, /obj/effect/landmark/abductor/agent))
|
||||
agent_landmarks[text2num(A.team)] = A
|
||||
else if(istype(A, /obj/effect/landmark/abductor/scientist))
|
||||
scientist_landmarks[text2num(A.team)] = A
|
||||
|
||||
var/team_name = team_names[team_number]
|
||||
|
||||
var/datum/mind/agent
|
||||
var/obj/effect/landmark/L
|
||||
var/datum/mind/scientist
|
||||
var/mob/living/carbon/human/H
|
||||
var/datum/species/abductor/S
|
||||
|
||||
agent = agents[team_number]
|
||||
H = agent.current
|
||||
L = agent_landmarks[team_number]
|
||||
H.forceMove(L.loc)
|
||||
H.set_species(/datum/species/abductor)
|
||||
S = H.dna.species
|
||||
S.team = team_number
|
||||
H.real_name = team_name + " Agent"
|
||||
H.equipOutfit(/datum/outfit/abductor/agent)
|
||||
greet_agent(agent,team_number)
|
||||
|
||||
|
||||
scientist = scientists[team_number]
|
||||
H = scientist.current
|
||||
L = scientist_landmarks[team_number]
|
||||
H.forceMove(L.loc)
|
||||
H.set_species(/datum/species/abductor)
|
||||
S = H.dna.species
|
||||
S.scientist = TRUE
|
||||
S.team = team_number
|
||||
H.real_name = team_name + " Scientist"
|
||||
H.equipOutfit(/datum/outfit/abductor/scientist)
|
||||
greet_scientist(scientist,team_number)
|
||||
|
||||
|
||||
|
||||
/datum/game_mode/abduction/proc/greet_agent(datum/mind/abductor,team_number)
|
||||
abductor.objectives += team_objectives[team_number]
|
||||
var/team_name = team_names[team_number]
|
||||
|
||||
to_chat(abductor.current, "<span class='notice'>You are an agent of [team_name]!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve.</span>")
|
||||
|
||||
abductor.announce_objectives()
|
||||
|
||||
/datum/game_mode/abduction/proc/greet_scientist(datum/mind/abductor,team_number)
|
||||
abductor.objectives += team_objectives[team_number]
|
||||
var/team_name = team_names[team_number]
|
||||
|
||||
to_chat(abductor.current, "<span class='notice'>You are a scientist of [team_name]!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>With the help of your teammate, kidnap and experiment on station crew members!</span>")
|
||||
to_chat(abductor.current, "<span class='notice'>Use your tool and ship consoles to support the agent and retrieve human specimens.</span>")
|
||||
|
||||
abductor.announce_objectives()
|
||||
|
||||
/datum/game_mode/abduction/proc/get_team_console(team_number)
|
||||
for(var/obj/machinery/abductor/console/C in GLOB.machines)
|
||||
if(C.team == team_number)
|
||||
return C
|
||||
/datum/game_mode/abduction/proc/post_setup_team(datum/objective_team/abductor_team/team)
|
||||
for(var/datum/mind/M in team.members)
|
||||
if(M.assigned_role == "Abductor Scientist")
|
||||
M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_SCIENTIST, team)
|
||||
else
|
||||
M.add_antag_datum(ANTAG_DATUM_ABDUCTOR_AGENT, team)
|
||||
|
||||
/datum/game_mode/abduction/check_finished()
|
||||
if(!finished)
|
||||
for(var/team_number=1,team_number<=abductor_teams,team_number++)
|
||||
var/obj/machinery/abductor/console/con = get_team_console(team_number)
|
||||
var/datum/objective/objective = team_objectives[team_number]
|
||||
if (con.experiment.points >= objective.target_amount)
|
||||
SSshuttle.emergency.request(null, set_coefficient = 0.5)
|
||||
finished = 1
|
||||
return ..()
|
||||
for(var/datum/objective_team/abductor_team/team in abductor_teams)
|
||||
for(var/datum/objective/O in team.objectives)
|
||||
if(O.check_completion())
|
||||
SSshuttle.emergency.request(null, set_coefficient = 0.5)
|
||||
finished = TRUE
|
||||
return ..()
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/abduction/declare_completion()
|
||||
for(var/team_number=1,team_number<=abductor_teams,team_number++)
|
||||
var/obj/machinery/abductor/console/console = get_team_console(team_number)
|
||||
var/datum/objective/objective = team_objectives[team_number]
|
||||
var/team_name = team_names[team_number]
|
||||
if(console.experiment.points >= objective.target_amount)
|
||||
to_chat(world, "<span class='greenannounce'>[team_name] team fulfilled its mission!</span>")
|
||||
for(var/datum/objective_team/abductor_team/team in abductor_teams)
|
||||
var/won = TRUE
|
||||
for(var/datum/objective/O in team.objectives)
|
||||
if(!O.check_completion())
|
||||
won = FALSE
|
||||
if(won)
|
||||
to_chat(world, "<span class='greenannounce'>[team.name] team fulfilled its mission!</span>")
|
||||
else
|
||||
to_chat(world, "<span class='boldannounce'>[team_name] team failed its mission.</span>")
|
||||
to_chat(world, "<span class='boldannounce'>[team.name] team failed its mission.</span>")
|
||||
..()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_abduction()
|
||||
var/text = ""
|
||||
@@ -200,40 +123,28 @@
|
||||
text += "<br>"
|
||||
to_chat(world, text)
|
||||
|
||||
//Landmarks
|
||||
// TODO: Split into separate landmarks for prettier ships
|
||||
// LANDMARKS
|
||||
/obj/effect/landmark/abductor
|
||||
var/team = 1
|
||||
var/team_number = 1
|
||||
|
||||
/obj/effect/landmark/abductor/agent
|
||||
/obj/effect/landmark/abductor/scientist
|
||||
|
||||
|
||||
// OBJECTIVES
|
||||
/datum/objective/experiment
|
||||
target_amount = 6
|
||||
var/team_number
|
||||
|
||||
/datum/objective/experiment/New()
|
||||
explanation_text = "Experiment on [target_amount] humans."
|
||||
|
||||
/datum/objective/experiment/check_completion()
|
||||
var/ab_team = team_number
|
||||
if(owner)
|
||||
if(!owner.current || !ishuman(owner.current))
|
||||
return 0
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(H.dna.species.id != "abductor")
|
||||
return 0
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
ab_team = S.team
|
||||
for(var/obj/machinery/abductor/experiment/E in GLOB.machines)
|
||||
if(E.team == ab_team)
|
||||
if(E.points >= target_amount)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
return 0
|
||||
if(!istype(team, /datum/objective_team/abductor_team))
|
||||
return FALSE
|
||||
var/datum/objective_team/abductor_team/T = team
|
||||
if(E.team_number == T.team_number)
|
||||
return E.points >= target_amount
|
||||
return FALSE
|
||||
|
||||
/datum/game_mode/proc/update_abductor_icons_added(datum/mind/alien_mind)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR]
|
||||
|
||||
@@ -328,7 +328,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
return
|
||||
|
||||
/obj/item/paper/guides/antag/abductor/AltClick()
|
||||
return
|
||||
return //otherwise it would fold into a paperplane.
|
||||
|
||||
#define BATON_STUN 0
|
||||
#define BATON_SLEEP 1
|
||||
|
||||
@@ -5,20 +5,14 @@
|
||||
back = /obj/item/storage/backpack
|
||||
ears = /obj/item/device/radio/headset/abductor
|
||||
|
||||
/datum/outfit/abductor/proc/get_team_console(team_number)
|
||||
for(var/obj/machinery/abductor/console/C in GLOB.machines)
|
||||
if(C.team == team_number)
|
||||
return C
|
||||
|
||||
/datum/outfit/abductor/proc/link_to_console(mob/living/carbon/human/H, team_number)
|
||||
if(!team_number && isabductor(H))
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
team_number = S.team
|
||||
|
||||
var/datum/antagonist/abductor/A = H.mind.has_antag_datum(ANTAG_DATUM_ABDUCTOR)
|
||||
if(!team_number && A)
|
||||
team_number = A.team.team_number
|
||||
if(!team_number)
|
||||
team_number = 1
|
||||
|
||||
var/obj/machinery/abductor/console/console = get_team_console(team_number)
|
||||
var/obj/machinery/abductor/console/console = get_abductor_console(team_number)
|
||||
if(console)
|
||||
var/obj/item/clothing/suit/armor/abductor/vest/V = locate() in H
|
||||
if(V)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/machinery/computer/camera_advanced/abductor
|
||||
name = "Human Observation Console"
|
||||
var/team = 0
|
||||
var/team_number = 0
|
||||
networks = list("SS13","Abductor")
|
||||
var/datum/action/innate/teleport_in/tele_in_action = new
|
||||
var/datum/action/innate/teleport_out/tele_out_action = new
|
||||
@@ -9,7 +9,7 @@
|
||||
var/datum/action/innate/vest_disguise_swap/vest_disguise_action = new
|
||||
var/datum/action/innate/set_droppoint/set_droppoint_action = new
|
||||
var/obj/machinery/abductor/console/console
|
||||
z_lock = ZLEVEL_STATION_PRIMARY
|
||||
station_lock_override = TRUE
|
||||
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "camera"
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
/proc/get_abductor_console(team_number)
|
||||
for(var/obj/machinery/abductor/console/C in GLOB.machines)
|
||||
if(C.team_number == team_number)
|
||||
return C
|
||||
|
||||
//Common
|
||||
|
||||
/obj/machinery/abductor
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/team = 0
|
||||
var/team_number = 0
|
||||
|
||||
//Console
|
||||
|
||||
@@ -139,21 +144,21 @@
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/obj/machinery/abductor/console/LateInitialize()
|
||||
if(!team)
|
||||
if(!team_number)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/abductor/pad/p in GLOB.machines)
|
||||
if(p.team == team)
|
||||
if(p.team_number == team_number)
|
||||
pad = p
|
||||
break
|
||||
|
||||
for(var/obj/machinery/abductor/experiment/e in GLOB.machines)
|
||||
if(e.team == team)
|
||||
if(e.team_number == team_number)
|
||||
experiment = e
|
||||
e.console = src
|
||||
|
||||
for(var/obj/machinery/computer/camera_advanced/abductor/c in GLOB.machines)
|
||||
if(c.team == team)
|
||||
if(c.team_number == team_number)
|
||||
camera = c
|
||||
c.console = src
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
var/flash = " - || - "
|
||||
var/obj/machinery/abductor/console/console
|
||||
var/message_cooldown = 0
|
||||
var/breakout_time = 0.75
|
||||
var/breakout_time = 450
|
||||
|
||||
/obj/machinery/abductor/experiment/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !ishuman(target))
|
||||
@@ -50,9 +50,9 @@
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a metallic creaking from [src].</span>")
|
||||
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open)
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
|
||||
@@ -22,27 +22,17 @@
|
||||
var/nukes_left = 1 // Call 3714-PRAY right now and order more nukes! Limited offer!
|
||||
var/nuke_off_station = 0 //Used for tracking if the syndies actually haul the nuke to the station
|
||||
var/syndies_didnt_escape = 0 //Used for tracking if the syndies got the shuttle off of the z-level
|
||||
var/list/pre_nukeops = list()
|
||||
|
||||
/datum/game_mode/nuclear/pre_setup()
|
||||
var/n_players = num_players()
|
||||
var/n_agents = min(round(n_players / 10, 1), agents_possible)
|
||||
|
||||
if(antag_candidates.len < n_agents) //In the case of having less candidates than the selected number of agents
|
||||
n_agents = antag_candidates.len
|
||||
|
||||
while(n_agents > 0)
|
||||
var/datum/mind/new_syndicate = pick(antag_candidates)
|
||||
syndicates += new_syndicate
|
||||
antag_candidates -= new_syndicate //So it doesn't pick the same guy each time.
|
||||
n_agents--
|
||||
|
||||
for(var/datum/mind/synd_mind in syndicates)
|
||||
synd_mind.assigned_role = "Syndicate"
|
||||
synd_mind.special_role = "Syndicate"//So they actually have a special role/N
|
||||
log_game("[synd_mind.key] (ckey) has been selected as a nuclear operative")
|
||||
|
||||
return 1
|
||||
|
||||
var/n_agents = min(round(num_players() / 10), antag_candidates.len, agents_possible)
|
||||
for(var/i = 0, i < n_agents, ++i)
|
||||
var/datum/mind/new_op = pick_n_take(antag_candidates)
|
||||
pre_nukeops += new_op
|
||||
new_op.assigned_role = "Nuclear Operative"
|
||||
new_op.special_role = "Nuclear Operative"
|
||||
log_game("[new_op.key] (ckey) has been selected as a nuclear operative")
|
||||
return TRUE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -60,48 +50,36 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/datum/game_mode/nuclear/post_setup()
|
||||
|
||||
var/list/turf/synd_spawn = list()
|
||||
|
||||
for(var/obj/effect/landmark/A in GLOB.landmarks_list)
|
||||
if(A.name == "Syndicate-Spawn")
|
||||
synd_spawn += get_turf(A)
|
||||
continue
|
||||
|
||||
var/nuke_code = random_nukecode()
|
||||
var/leader_selected = 0
|
||||
var/agent_number = 1
|
||||
var/spawnpos = 1
|
||||
var/datum/mind/leader = pick(pre_nukeops)
|
||||
syndicates += pre_nukeops
|
||||
for(var/i = 1 to pre_nukeops.len)
|
||||
var/datum/mind/op = pre_nukeops[i]
|
||||
|
||||
for(var/datum/mind/synd_mind in syndicates)
|
||||
if(spawnpos > synd_spawn.len)
|
||||
spawnpos = 2
|
||||
synd_mind.current.loc = synd_spawn[spawnpos]
|
||||
|
||||
forge_syndicate_objectives(synd_mind)
|
||||
greet_syndicate(synd_mind)
|
||||
equip_syndicate(synd_mind.current)
|
||||
forge_syndicate_objectives(op)
|
||||
greet_syndicate(op)
|
||||
equip_syndicate(op.current)
|
||||
|
||||
if(nuke_code)
|
||||
synd_mind.store_memory("<B>Syndicate Nuclear Bomb Code</B>: [nuke_code]", 0, 0)
|
||||
to_chat(synd_mind.current, "The nuclear authorization code is: <B>[nuke_code]</B>")
|
||||
op.store_memory("<B>Syndicate Nuclear Bomb Code</B>: [nuke_code]", 0, 0)
|
||||
to_chat(op.current, "The nuclear authorization code is: <B>[nuke_code]</B>")
|
||||
|
||||
if(!leader_selected)
|
||||
prepare_syndicate_leader(synd_mind, nuke_code)
|
||||
leader_selected = 1
|
||||
if(op == leader)
|
||||
op.current.forceMove(pick(GLOB.nukeop_leader_start))
|
||||
prepare_syndicate_leader(op, nuke_code)
|
||||
else
|
||||
synd_mind.current.real_name = "[syndicate_name()] Operative #[agent_number]"
|
||||
agent_number++
|
||||
spawnpos++
|
||||
update_synd_icons_added(synd_mind)
|
||||
synd_mind.current.playsound_local(get_turf(synd_mind.current), 'sound/ambience/antag/ops.ogg',100,0)
|
||||
var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list
|
||||
op.current.forceMove(GLOB.nukeop_start[((i - 1) % GLOB.nukeop_start.len) + 1])
|
||||
op.current.real_name = "[syndicate_name()] Operative #[agent_number++]"
|
||||
|
||||
update_synd_icons_added(op)
|
||||
op.current.playsound_local(get_turf(op.current), 'sound/ambience/antag/ops.ogg',100,0)
|
||||
|
||||
var/obj/machinery/nuclearbomb/nuke = locate("syndienuke") in GLOB.nuke_list
|
||||
if(nuke)
|
||||
nuke.r_code = nuke_code
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/game_mode/proc/prepare_syndicate_leader(datum/mind/synd_mind, nuke_code)
|
||||
var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
|
||||
spawn(1)
|
||||
@@ -161,6 +139,12 @@
|
||||
synd_mob.equipOutfit(/datum/outfit/syndicate/no_crystals)
|
||||
return 1
|
||||
|
||||
/datum/game_mode/nuclear/OnNukeExplosion(off_station)
|
||||
..()
|
||||
nukes_left--
|
||||
var/obj/docking_port/mobile/Shuttle = SSshuttle.getShuttle("syndicate")
|
||||
syndies_didnt_escape = (Shuttle && (Shuttle.z == ZLEVEL_CENTCOM || Shuttle.z == ZLEVEL_TRANSIT)) ? 0 : 1
|
||||
nuke_off_station = off_station
|
||||
|
||||
/datum/game_mode/nuclear/check_win()
|
||||
if (nukes_left == 0)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
return
|
||||
|
||||
declaring_war = TRUE
|
||||
var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]]. Are you sure you want to alert the enemy crew? You have [-round((world.time-SSticker.round_start_time - CHALLENGE_TIME_LIMIT)/10)] seconds to decide", "Declare war?", "Yes", "No")
|
||||
var/are_you_sure = alert(user, "Consult your team carefully before you declare war on [station_name()]]. Are you sure you want to alert the enemy crew? You have [DisplayTimeText(world.time-SSticker.round_start_time - CHALLENGE_TIME_LIMIT)] to decide", "Declare war?", "Yes", "No")
|
||||
declaring_war = FALSE
|
||||
|
||||
if(!check_allowed(user))
|
||||
|
||||
@@ -81,6 +81,20 @@
|
||||
/obj/machinery/nuclearbomb/syndicate
|
||||
//ui_style = "syndicate" // actually the nuke op bomb is a stole nt bomb
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/get_cinematic_type(off_station)
|
||||
var/datum/game_mode/nuclear/NM = SSticker.mode
|
||||
switch(off_station)
|
||||
if(0)
|
||||
if(istype(NM) && NM.syndies_didnt_escape)
|
||||
return CINEMATIC_ANNIHILATION
|
||||
else
|
||||
return CINEMATIC_NUKE_WIN
|
||||
if(1)
|
||||
return CINEMATIC_NUKE_MISS
|
||||
if(2)
|
||||
return CINEMATIC_NUKE_FAR
|
||||
return CINEMATIC_NUKE_FAR
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/Initialize()
|
||||
. = ..()
|
||||
var/obj/machinery/nuclearbomb/existing = locate("syndienuke") in GLOB.nuke_list
|
||||
@@ -422,12 +436,12 @@
|
||||
update_icon()
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
if(SSticker && SSticker.mode)
|
||||
SSticker.mode.explosion_in_progress = 1
|
||||
SSticker.roundend_check_paused = TRUE
|
||||
sleep(100)
|
||||
|
||||
if(!core)
|
||||
SSticker.station_explosion_cinematic(3,"no_core",src)
|
||||
SSticker.mode.explosion_in_progress = 0
|
||||
Cinematic(CINEMATIC_NUKE_NO_CORE,world)
|
||||
SSticker.roundend_check_paused = FALSE
|
||||
return
|
||||
|
||||
GLOB.enter_allowed = 0
|
||||
@@ -437,28 +451,37 @@
|
||||
var/area/A = get_area(bomb_location)
|
||||
if(bomb_location && (bomb_location.z in GLOB.station_z_levels))
|
||||
if(istype(A, /area/space))
|
||||
off_station = NUKE_MISS_STATION
|
||||
off_station = NUKE_NEAR_MISS
|
||||
if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE)))
|
||||
off_station = NUKE_MISS_STATION
|
||||
off_station = NUKE_NEAR_MISS
|
||||
else if((istype(A, /area/syndicate_mothership) || (istype(A, /area/shuttle/syndicate)) && bomb_location.z == ZLEVEL_CENTCOM))
|
||||
off_station = NUKE_SYNDICATE_BASE
|
||||
else
|
||||
off_station = NUKE_NEAR_MISS
|
||||
off_station = NUKE_MISS_STATION
|
||||
|
||||
if(istype(SSticker.mode, /datum/game_mode/nuclear))
|
||||
var/obj/docking_port/mobile/Shuttle = SSshuttle.getShuttle("syndicate")
|
||||
var/datum/game_mode/nuclear/NM = SSticker.mode
|
||||
NM.syndies_didnt_escape = (Shuttle && (Shuttle.z == ZLEVEL_CENTCOM || Shuttle.z == ZLEVEL_TRANSIT)) ? 0 : 1
|
||||
NM.nuke_off_station = off_station
|
||||
if(off_station < 2)
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
SSshuttle.lockdown = TRUE
|
||||
|
||||
SSticker.station_explosion_cinematic(off_station,null,src)
|
||||
if(SSticker.mode)
|
||||
if(istype(SSticker.mode, /datum/game_mode/nuclear))
|
||||
var/datum/game_mode/nuclear/NM = SSticker.mode
|
||||
NM.nukes_left --
|
||||
if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
|
||||
SSticker.Reboot("Station destroyed by Nuclear Device.", "nuke - unhandled ending")
|
||||
//Cinematic
|
||||
SSticker.mode.OnNukeExplosion(off_station)
|
||||
var/bombz = z
|
||||
Cinematic(get_cinematic_type(off_station),world,CALLBACK(SSticker,/datum/controller/subsystem/ticker/proc/station_explosion_detonation,src))
|
||||
INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel,bombz)
|
||||
SSticker.roundend_check_paused = FALSE
|
||||
|
||||
/obj/machinery/nuclearbomb/proc/get_cinematic_type(off_station)
|
||||
if(off_station < 2)
|
||||
return CINEMATIC_SELFDESTRUCT
|
||||
else
|
||||
return CINEMATIC_SELFDESTRUCT_MISS
|
||||
|
||||
/proc/KillEveryoneOnZLevel(z)
|
||||
if(!z)
|
||||
return
|
||||
for(var/mob/M in GLOB.mob_list)
|
||||
if(M.stat != DEAD && M.z == z)
|
||||
M.gib()
|
||||
|
||||
/*
|
||||
This is here to make the tiles around the station mininuke change when it's armed.
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
return target
|
||||
|
||||
/datum/objective/assassinate/check_completion()
|
||||
return !target || !considered_alive(target)
|
||||
return !considered_alive(target) || considered_afk(target)
|
||||
|
||||
/datum/objective/assassinate/update_explanation_text()
|
||||
..()
|
||||
|
||||
@@ -154,8 +154,7 @@
|
||||
|
||||
|
||||
var/obj/item/device/assembly/flash/T = new(mob)
|
||||
var/obj/item/toy/crayon/spraycan/R = new(mob)
|
||||
var/obj/item/clothing/glasses/hud/security/chameleon/C = new(mob)
|
||||
var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = new(mob)
|
||||
|
||||
var/list/slots = list (
|
||||
"backpack" = slot_in_backpack,
|
||||
@@ -163,13 +162,8 @@
|
||||
"right pocket" = slot_r_store
|
||||
)
|
||||
var/where = mob.equip_in_one_of_slots(T, slots)
|
||||
var/where2 = mob.equip_in_one_of_slots(C, slots)
|
||||
mob.equip_in_one_of_slots(R,slots)
|
||||
|
||||
if (!where2)
|
||||
to_chat(mob, "The Syndicate were unfortunately unable to get you a chameleon security HUD.")
|
||||
else
|
||||
to_chat(mob, "The chameleon security HUD in your [where2] will help you keep track of who is mindshield-implanted, and unable to be recruited.")
|
||||
S.Insert(mob, special = FALSE, drop_if_replaced = FALSE)
|
||||
to_chat(mob, "Your eyes have been implanted with a cybernetic security HUD which will help you keep track of who is mindshield-implanted, and therefore unable to be recruited.")
|
||||
|
||||
if (!where)
|
||||
to_chat(mob, "The Syndicate were unfortunately unable to get you a flash.")
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
////////////////////////////Proc for moving soul in and out off stone//////////////////////////////////////
|
||||
|
||||
|
||||
/obj/item/device/soulstone/proc/transfer_soul(choice as text, target, mob/user).
|
||||
/obj/item/device/soulstone/proc/transfer_soul(choice as text, target, mob/user)
|
||||
switch(choice)
|
||||
if("FORCE")
|
||||
if(!iscarbon(target)) //TODO: Add sacrifice stoning for non-organics, just because you have no body doesnt mean you dont have a soul
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
to_chat(user, "<span class='danger'>[src] is out of foam and cannot be activated.</span>")
|
||||
return
|
||||
if(cooldown_time > world.time)
|
||||
to_chat(user, "<span class='danger'>[src] cannot be activated for another <b>[round((world.time - cooldown_time) * 0.1)]</b> second\s.</span>")
|
||||
to_chat(user, "<span class='danger'>[src] cannot be activated for <b>[DisplayTimeText(world.time - cooldown_time)]</b>.</span>")
|
||||
return
|
||||
new /obj/effect/particle_effect/foam(loc)
|
||||
uses--
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
var/initial_icon_state
|
||||
var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi', "engineer" = 'icons/mob/augmentation/augments_engineer.dmi', "security" = 'icons/mob/augmentation/augments_security.dmi', "mining" = 'icons/mob/augmentation/augments_mining.dmi')
|
||||
|
||||
/obj/machinery/aug_manipulator/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to eject the limb.</span>")
|
||||
|
||||
/obj/machinery/aug_manipulator/Initialize()
|
||||
initial_icon_state = initial(icon_state)
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
desc = "Used to access the various cameras on the station."
|
||||
icon_screen = "cameras"
|
||||
icon_keyboard = "security_key"
|
||||
var/z_lock = null // Lock use to this zlevel
|
||||
var/list/z_lock = list() // Lock use to these z levels
|
||||
var/station_lock_override = FALSE
|
||||
var/mob/camera/aiEye/remote/eyeobj
|
||||
var/mob/living/current_user = null
|
||||
var/list/networks = list("SS13")
|
||||
@@ -13,6 +14,11 @@
|
||||
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
/obj/machinery/computer/camera_advanced/Initialize()
|
||||
. = ..()
|
||||
if(station_lock_override)
|
||||
z_lock = GLOB.station_z_levels.Copy()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/syndie
|
||||
icon_keyboard = "syndie_key"
|
||||
|
||||
@@ -76,7 +82,7 @@
|
||||
if(!eyeobj.eye_initialized)
|
||||
var/camera_location
|
||||
for(var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
if(!C.can_use() || z_lock && C.z != z_lock)
|
||||
if(!C.can_use() || z_lock.len && !(C.z in z_lock))
|
||||
continue
|
||||
if(C.network & networks)
|
||||
camera_location = get_turf(C)
|
||||
@@ -201,7 +207,7 @@
|
||||
var/list/L = list()
|
||||
|
||||
for (var/obj/machinery/camera/cam in GLOB.cameranet.cameras)
|
||||
if(origin.z_lock && cam.z != origin.z_lock)
|
||||
if(origin.z_lock.len && !(cam.z in origin.z_lock))
|
||||
continue
|
||||
L.Add(cam)
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
if("working")
|
||||
temp_html += status
|
||||
temp_html += "<h1>System Busy</h1>"
|
||||
temp_html += "Working ... Please wait ([radduration] Seconds)"
|
||||
temp_html += "Working ... Please wait ([DisplayTimeText(radduration)])"
|
||||
if("buffer")
|
||||
temp_html += status
|
||||
temp_html += buttons
|
||||
|
||||
+143
-145
@@ -1,145 +1,143 @@
|
||||
/obj/machinery/computer/pod
|
||||
name = "mass driver launch control"
|
||||
desc = "A combined blastdoor and mass driver control unit."
|
||||
var/obj/machinery/mass_driver/connected = null
|
||||
var/title = "Mass Driver Controls"
|
||||
var/id = 1
|
||||
var/timing = 0
|
||||
var/time = 30
|
||||
var/range = 4
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
connected = M
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/proc/alarm()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(!connected)
|
||||
say("Cannot locate mass driver connector. Cancelling firing sequence!")
|
||||
return
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.open()
|
||||
|
||||
sleep(20)
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
|
||||
sleep(50)
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.close()
|
||||
|
||||
/obj/machinery/computer/pod/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
user.set_machine(src)
|
||||
if(connected)
|
||||
var/d2
|
||||
if(timing) //door controls do not need timers.
|
||||
d2 = "<A href='?src=\ref[src];time=0'>Stop Time Launch</A>"
|
||||
else
|
||||
d2 = "<A href='?src=\ref[src];time=1'>Initiate Time Launch</A>"
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
dat += "<HR>\nTimer System: [d2]\nTime Left: [minute ? "[minute]:" : null][second] <A href='?src=\ref[src];tp=-30'>-</A> <A href='?src=\ref[src];tp=-1'>-</A> <A href='?src=\ref[src];tp=1'>+</A> <A href='?src=\ref[src];tp=30'>+</A>"
|
||||
var/temp = ""
|
||||
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
|
||||
for(var/t in L)
|
||||
if(t == connected.power)
|
||||
temp += "[t] "
|
||||
else
|
||||
temp += "<A href = '?src=\ref[src];power=[t]'>[t]</A> "
|
||||
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=\ref[src];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=\ref[src];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
|
||||
else
|
||||
dat += "<BR>\n<A href = '?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
|
||||
dat += "<BR><BR><A href='?src=\ref[user];mach_close=computer'>Close</A>"
|
||||
add_fingerprint(usr)
|
||||
var/datum/browser/popup = new(user, "computer", title, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/process()
|
||||
if(!..())
|
||||
return
|
||||
if(timing)
|
||||
if(time > 0)
|
||||
time = round(time) - 1
|
||||
else
|
||||
alarm()
|
||||
time = 0
|
||||
timing = 0
|
||||
updateDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
usr.set_machine(src)
|
||||
if(href_list["power"])
|
||||
var/t = text2num(href_list["power"])
|
||||
t = min(max(0.25, t), 16)
|
||||
if(connected)
|
||||
connected.power = t
|
||||
if(href_list["alarm"])
|
||||
alarm()
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 120)
|
||||
if(href_list["door"])
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
if(M.density)
|
||||
M.open()
|
||||
else
|
||||
M.close()
|
||||
if(href_list["drive"])
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
updateUsrDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/old
|
||||
name = "\improper DoorMex control console"
|
||||
title = "Door Controls"
|
||||
icon_state = "oldcomp"
|
||||
icon_screen = "library"
|
||||
icon_keyboard = null
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/old/syndicate
|
||||
name = "\improper ProComp Executive IIc"
|
||||
desc = "The Syndicate operate on a tight budget. Operates external airlocks."
|
||||
title = "External Airlock Controls"
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/computer/pod/old/syndicate/attack_hand(mob/user)
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='notice'>Access denied.</span>")
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/old/swf
|
||||
name = "\improper Magix System IV"
|
||||
desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorceror's Edition"
|
||||
/obj/machinery/computer/pod
|
||||
name = "mass driver launch control"
|
||||
desc = "A combined blastdoor and mass driver control unit."
|
||||
var/obj/machinery/mass_driver/connected = null
|
||||
var/title = "Mass Driver Controls"
|
||||
var/id = 1
|
||||
var/timing = 0
|
||||
var/time = 30
|
||||
var/range = 4
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Initialize()
|
||||
. = ..()
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
connected = M
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/proc/alarm()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(!connected)
|
||||
say("Cannot locate mass driver connector. Cancelling firing sequence!")
|
||||
return
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.open()
|
||||
|
||||
sleep(20)
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
|
||||
sleep(50)
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.close()
|
||||
|
||||
/obj/machinery/computer/pod/attack_hand(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
user.set_machine(src)
|
||||
if(connected)
|
||||
var/d2
|
||||
if(timing) //door controls do not need timers.
|
||||
d2 = "<A href='?src=\ref[src];time=0'>Stop Time Launch</A>"
|
||||
else
|
||||
d2 = "<A href='?src=\ref[src];time=1'>Initiate Time Launch</A>"
|
||||
dat += "<HR>\nTimer System: [d2]\nTime Left: [DisplayTimeText(time)] <A href='?src=\ref[src];tp=-30'>-</A> <A href='?src=\ref[src];tp=-1'>-</A> <A href='?src=\ref[src];tp=1'>+</A> <A href='?src=\ref[src];tp=30'>+</A>"
|
||||
var/temp = ""
|
||||
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
|
||||
for(var/t in L)
|
||||
if(t == connected.power)
|
||||
temp += "[t] "
|
||||
else
|
||||
temp += "<A href = '?src=\ref[src];power=[t]'>[t]</A> "
|
||||
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=\ref[src];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=\ref[src];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
|
||||
else
|
||||
dat += "<BR>\n<A href = '?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
|
||||
dat += "<BR><BR><A href='?src=\ref[user];mach_close=computer'>Close</A>"
|
||||
add_fingerprint(usr)
|
||||
var/datum/browser/popup = new(user, "computer", title, 400, 500)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/process()
|
||||
if(!..())
|
||||
return
|
||||
if(timing)
|
||||
if(time > 0)
|
||||
time = round(time) - 1
|
||||
else
|
||||
alarm()
|
||||
time = 0
|
||||
timing = 0
|
||||
updateDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
usr.set_machine(src)
|
||||
if(href_list["power"])
|
||||
var/t = text2num(href_list["power"])
|
||||
t = min(max(0.25, t), 16)
|
||||
if(connected)
|
||||
connected.power = t
|
||||
if(href_list["alarm"])
|
||||
alarm()
|
||||
if(href_list["time"])
|
||||
timing = text2num(href_list["time"])
|
||||
if(href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
time += tp
|
||||
time = min(max(round(time), 0), 120)
|
||||
if(href_list["door"])
|
||||
for(var/obj/machinery/door/poddoor/M in range(range, src))
|
||||
if(M.id == id)
|
||||
if(M.density)
|
||||
M.open()
|
||||
else
|
||||
M.close()
|
||||
if(href_list["drive"])
|
||||
for(var/obj/machinery/mass_driver/M in range(range, src))
|
||||
if(M.id == id)
|
||||
M.power = connected.power
|
||||
M.drive()
|
||||
updateUsrDialog()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/old
|
||||
name = "\improper DoorMex control console"
|
||||
title = "Door Controls"
|
||||
icon_state = "oldcomp"
|
||||
icon_screen = "library"
|
||||
icon_keyboard = null
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/old/syndicate
|
||||
name = "\improper ProComp Executive IIc"
|
||||
desc = "The Syndicate operate on a tight budget. Operates external airlocks."
|
||||
title = "External Airlock Controls"
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/machinery/computer/pod/old/syndicate/attack_hand(mob/user)
|
||||
if(!allowed(user))
|
||||
to_chat(user, "<span class='notice'>Access denied.</span>")
|
||||
return
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/computer/pod/old/swf
|
||||
name = "\improper Magix System IV"
|
||||
desc = "An arcane artifact that holds much magic. Running E-Knock 2.2: Sorceror's Edition"
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
dat += "</div><br>"
|
||||
dat += "<A href='?src=\ref[src];action=select'> Select Track</A><br>"
|
||||
dat += "Track Selected: [selection.song_name]<br>"
|
||||
dat += "Track Length: [selection.song_length/10] seconds<br><br>"
|
||||
dat += "Track Length: [DisplayTimeText(selection.song_length)]<br><br>"
|
||||
dat += "<br>DJ's Soundboard:<b><br>"
|
||||
dat +="<div class='statusDisplay'><div style='text-align:center'>"
|
||||
dat += "<A href='?src=\ref[src];action=horn'>Air Horn</A> "
|
||||
@@ -122,7 +122,7 @@
|
||||
return
|
||||
if(!active)
|
||||
if(stop > world.time)
|
||||
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [round((stop-world.time)/10)] seconds.</span>")
|
||||
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
|
||||
return
|
||||
active = TRUE
|
||||
|
||||
@@ -110,13 +110,17 @@
|
||||
|
||||
/obj/item/grenade/barrier
|
||||
name = "barrier grenade"
|
||||
desc = "Instant cover. Alt+click to toggle modes."
|
||||
desc = "Instant cover."
|
||||
icon = 'icons/obj/grenade.dmi'
|
||||
icon_state = "flashbang"
|
||||
item_state = "flashbang"
|
||||
actions_types = list(/datum/action/item_action/toggle_barrier_spread)
|
||||
var/mode = SINGLE
|
||||
|
||||
/obj/item/grenade/barrier/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to toggle modes.</span>")
|
||||
|
||||
/obj/item/grenade/barrier/AltClick(mob/living/user)
|
||||
if(!istype(user) || user.incapacitated())
|
||||
return
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var/scan_level
|
||||
var/precision_coeff
|
||||
var/message_cooldown
|
||||
var/breakout_time = 2
|
||||
var/breakout_time = 1200
|
||||
|
||||
/obj/machinery/dna_scannernew/RefreshParts()
|
||||
scan_level = 0
|
||||
@@ -73,9 +73,9 @@
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a metallic creaking from [src].</span>")
|
||||
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
|
||||
return
|
||||
locked = FALSE
|
||||
|
||||
@@ -20,7 +20,7 @@ The console is located at computer/gulag_teleporter.dm
|
||||
circuit = /obj/item/circuitboard/machine/gulag_teleporter
|
||||
var/locked = FALSE
|
||||
var/message_cooldown
|
||||
var/breakout_time = 1
|
||||
var/breakout_time = 600
|
||||
var/jumpsuit_type = /obj/item/clothing/under/rank/prisoner
|
||||
var/shoes_type = /obj/item/clothing/shoes/sneakers/orange
|
||||
var/obj/machinery/gulag_item_reclaimer/linked_reclaimer
|
||||
@@ -104,9 +104,9 @@ The console is located at computer/gulag_teleporter.dm
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a metallic creaking from [src].</span>")
|
||||
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open || !locked)
|
||||
return
|
||||
locked = FALSE
|
||||
|
||||
@@ -305,7 +305,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
dat+="Creating new Feed Message..."
|
||||
dat+="<HR><B><A href='?src=\ref[src];set_channel_receiving=1'>Receiving Channel</A>:</B> [channel_name]<BR>"
|
||||
dat+="<B>Message Author:</B> <FONT COLOR='green'>[scanned_user]</FONT><BR>"
|
||||
dat+="<B><A href='?src=\ref[src];set_new_message=1'>Message Body</A>:</B> <BR><font face=\"[PEN_FONT]\">[parsepencode(msg, user, SIGNFONT)]</font><BR>"
|
||||
dat+="<B><A href='?src=\ref[src];set_new_message=1'>Message Body</A>:</B> <BR><font face=\"[PEN_FONT]\">[parsemarkdown(msg, user)]</font><BR>"
|
||||
dat+="<B><A href='?src=\ref[src];set_attachment=1'>Attach Photo</A>:</B> [(photo ? "Photo Attached" : "No Photo")]</BR>"
|
||||
dat+="<B><A href='?src=\ref[src];set_comment=1'>Comments [allow_comments ? "Enabled" : "Disabled"]</A></B><BR>"
|
||||
dat+="<BR><A href='?src=\ref[src];submit_new_message=1'>Submit</A><BR><BR><A href='?src=\ref[src];setScreen=[0]'>Cancel</A><BR>"
|
||||
@@ -555,7 +555,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
if(msg =="" || msg=="\[REDACTED\]" || scanned_user == "Unknown" || channel_name == "" )
|
||||
screen=6
|
||||
else
|
||||
GLOB.news_network.SubmitArticle("<font face=\"[PEN_FONT]\">[parsepencode(msg, usr, SIGNFONT)]</font>", scanned_user, channel_name, photo, 0, allow_comments)
|
||||
GLOB.news_network.SubmitArticle("<font face=\"[PEN_FONT]\">[parsemarkdown(msg, usr)]</font>", scanned_user, channel_name, photo, 0, allow_comments)
|
||||
SSblackbox.inc("newscaster_stories",1)
|
||||
screen=4
|
||||
msg = ""
|
||||
|
||||
@@ -213,6 +213,8 @@ GLOBAL_LIST_INIT(pipeID2State, list(
|
||||
return ..()
|
||||
if (!isturf(src.loc))
|
||||
return 1
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
fixdir()
|
||||
if(pipe_type in list(PIPE_GAS_MIXER, PIPE_GAS_FILTER))
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
return
|
||||
|
||||
if(world.time < last_teleport + teleport_cooldown)
|
||||
to_chat(user, "<span class='warning'>[src] is recharging power. Please wait [round((last_teleport + teleport_cooldown - world.time) / 10)] seconds.</span>")
|
||||
to_chat(user, "<span class='warning'>[src] is recharging power. Please wait [DisplayTimeText(last_teleport + teleport_cooldown - world.time)].</span>")
|
||||
return
|
||||
|
||||
if(teleporting)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
var/uv_super = FALSE
|
||||
var/uv_cycles = 6
|
||||
var/message_cooldown
|
||||
var/breakout_time = 0.5
|
||||
var/breakout_time = 300
|
||||
|
||||
/obj/machinery/suit_storage_unit/standard_unit
|
||||
suit_type = /obj/item/clothing/suit/space/eva
|
||||
@@ -267,9 +267,9 @@
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the doors of [src]!</span>", \
|
||||
"<span class='notice'>You start kicking against the doors... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
|
||||
"<span class='notice'>You start kicking against the doors... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a thump from [src].</span>")
|
||||
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src )
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
|
||||
@@ -1,37 +1,26 @@
|
||||
/obj/mecha/combat
|
||||
force = 30
|
||||
internal_damage_threshold = 50
|
||||
armor = list(melee = 30, bullet = 30, laser = 15, energy = 20, bomb = 20, bio = 0, rad = 0, fire = 100, acid = 100)
|
||||
|
||||
/obj/mecha/combat/CheckParts(list/parts_list)
|
||||
..()
|
||||
var/obj/item/stock_parts/capacitor/C = locate() in contents
|
||||
var/obj/item/stock_parts/scanning_module/SM = locate() in contents
|
||||
step_energy_drain = 20 - (5 * SM.rating) //10 is normal, so on lowest part its worse, on second its ok and on higher its real good up to 0 on best
|
||||
armor["energy"] += (C.rating * 10) //Each level of capacitor protects the mech against emp by 10%
|
||||
qdel(C)
|
||||
qdel(SM)
|
||||
|
||||
/obj/mecha/combat/moved_inside(mob/living/carbon/human/H)
|
||||
if(..())
|
||||
if(H.client && H.client.mouse_pointer_icon == initial(H.client.mouse_pointer_icon))
|
||||
H.client.mouse_pointer_icon = 'icons/mecha/mecha_mouse.dmi'
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/mecha/combat/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user)
|
||||
if(..())
|
||||
if(occupant.client && occupant.client.mouse_pointer_icon == initial(occupant.client.mouse_pointer_icon))
|
||||
occupant.client.mouse_pointer_icon = 'icons/mecha/mecha_mouse.dmi'
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
/obj/mecha/combat/go_out()
|
||||
if(occupant && occupant.client && occupant.client.mouse_pointer_icon == 'icons/mecha/mecha_mouse.dmi')
|
||||
occupant.client.mouse_pointer_icon = initial(occupant.client.mouse_pointer_icon)
|
||||
..()
|
||||
|
||||
|
||||
/obj/mecha/combat
|
||||
force = 30
|
||||
internal_damage_threshold = 50
|
||||
armor = list(melee = 30, bullet = 30, laser = 15, energy = 20, bomb = 20, bio = 0, rad = 0, fire = 100, acid = 100)
|
||||
|
||||
/obj/mecha/combat/moved_inside(mob/living/carbon/human/H)
|
||||
if(..())
|
||||
if(H.client && H.client.mouse_pointer_icon == initial(H.client.mouse_pointer_icon))
|
||||
H.client.mouse_pointer_icon = 'icons/mecha/mecha_mouse.dmi'
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/mecha/combat/mmi_moved_inside(obj/item/device/mmi/mmi_as_oc,mob/user)
|
||||
if(..())
|
||||
if(occupant.client && occupant.client.mouse_pointer_icon == initial(occupant.client.mouse_pointer_icon))
|
||||
occupant.client.mouse_pointer_icon = 'icons/mecha/mecha_mouse.dmi'
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
/obj/mecha/combat/go_out()
|
||||
if(occupant && occupant.client && occupant.client.mouse_pointer_icon == 'icons/mecha/mecha_mouse.dmi')
|
||||
occupant.client.mouse_pointer_icon = initial(occupant.client.mouse_pointer_icon)
|
||||
..()
|
||||
|
||||
@@ -202,6 +202,19 @@
|
||||
GLOB.mechas_list -= src //global mech list
|
||||
return ..()
|
||||
|
||||
/obj/mecha/CheckParts(list/parts_list)
|
||||
..()
|
||||
var/obj/item/C = locate(/obj/item/stock_parts/cell) in contents
|
||||
cell = C
|
||||
var/obj/item/stock_parts/scanning_module/SM = locate() in contents
|
||||
var/obj/item/stock_parts/capacitor/CP = locate() in contents
|
||||
if(SM)
|
||||
step_energy_drain = 20 - (5 * SM.rating) //10 is normal, so on lowest part its worse, on second its ok and on higher its real good up to 0 on best
|
||||
qdel(SM)
|
||||
if(CP)
|
||||
armor["energy"] += (CP.rating * 10) //Each level of capacitor protects the mech against emp by 10%
|
||||
qdel(CP)
|
||||
|
||||
////////////////////////
|
||||
////// Helpers /////////
|
||||
////////////////////////
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -157,11 +157,27 @@
|
||||
/obj/effect/landmark/start/wizard
|
||||
name = "wizard"
|
||||
|
||||
/obj/effect/landmark/start/wizard/Initialize(mapload)
|
||||
/obj/effect/landmark/start/wizard/Initialize()
|
||||
..()
|
||||
GLOB.wizardstart += loc
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/landmark/start/nukeop
|
||||
name = "nukeop"
|
||||
|
||||
/obj/effect/landmark/start/nukeop/Initialize()
|
||||
..()
|
||||
GLOB.nukeop_start += loc
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/landmark/start/nukeop_leader
|
||||
name = "nukeop leader"
|
||||
|
||||
/obj/effect/landmark/start/nukeop_leader/Initialize()
|
||||
..()
|
||||
GLOB.nukeop_leader_start += loc
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/landmark/start/new_player
|
||||
name = "New Player"
|
||||
|
||||
@@ -205,23 +221,6 @@
|
||||
/obj/effect/landmark/tripai
|
||||
name = "tripai"
|
||||
|
||||
// marauder entry (XXX WTF IS MAURADER ENTRY???)
|
||||
|
||||
/obj/effect/landmark/marauder_entry
|
||||
name = "Marauder Entry"
|
||||
|
||||
// syndicate breach area (XXX I DON'T KNOW WHAT THIS IS EITHER)
|
||||
|
||||
/obj/effect/landmark/syndicate_breach_area
|
||||
name = "Syndicate Breach Area"
|
||||
|
||||
// teleport scroll landmark, XXX DOES THIS DO ANYTHING?
|
||||
/obj/effect/landmark/teleport_scroll
|
||||
name = "Teleport-Scroll"
|
||||
|
||||
/obj/effect/landmark/syndicate_spawn
|
||||
name = "Syndicate-Spawn"
|
||||
|
||||
// xenos.
|
||||
/obj/effect/landmark/xeno_spawn
|
||||
name = "xeno_spawn"
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
if(!force_rebuild && range == current_range)
|
||||
return FALSE
|
||||
. = TRUE
|
||||
|
||||
|
||||
current_range = range
|
||||
|
||||
var/list/checkers_local = checkers
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
icon_state = "eggs"
|
||||
var/amount_grown = 0
|
||||
var/player_spiders = 0
|
||||
var/directive = "" //Message from the mother
|
||||
var/poison_type = "toxin"
|
||||
var/poison_per_bite = 5
|
||||
var/list/faction = list("spiders")
|
||||
@@ -71,6 +72,7 @@
|
||||
S.poison_type = poison_type
|
||||
S.poison_per_bite = poison_per_bite
|
||||
S.faction = faction.Copy()
|
||||
S.directive = directive
|
||||
if(player_spiders)
|
||||
S.player_spiders = 1
|
||||
qdel(src)
|
||||
@@ -87,6 +89,7 @@
|
||||
var/obj/machinery/atmospherics/components/unary/vent_pump/entry_vent
|
||||
var/travelling_in_vent = 0
|
||||
var/player_spiders = 0
|
||||
var/directive = "" //Message from the mother
|
||||
var/poison_type = "toxin"
|
||||
var/poison_per_bite = 5
|
||||
var/list/faction = list("spiders")
|
||||
@@ -192,6 +195,7 @@
|
||||
S.poison_per_bite = poison_per_bite
|
||||
S.poison_type = poison_type
|
||||
S.faction = faction.Copy()
|
||||
S.directive = directive
|
||||
if(player_spiders)
|
||||
S.playable_spider = TRUE
|
||||
notify_ghosts("Spider [S.name] can be controlled", null, enter_link="<a href=?src=\ref[S];activate=1>(Click to play)</a>", source=S, action=NOTIFY_ATTACK)
|
||||
@@ -210,12 +214,12 @@
|
||||
. = ..()
|
||||
|
||||
/obj/structure/spider/cocoon/container_resist(mob/living/user)
|
||||
var/breakout_time = 1
|
||||
var/breakout_time = 600
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
to_chat(user, "<span class='notice'>You struggle against the tight bonds... (This will take about [breakout_time] minutes.)</span>")
|
||||
to_chat(user, "<span class='notice'>You struggle against the tight bonds... (This will take about [DisplayTimeText(breakout_time)].)</span>")
|
||||
visible_message("You see something struggling and writhing in \the [src]!")
|
||||
if(do_after(user,(breakout_time*60*10), target = src))
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src)
|
||||
return
|
||||
qdel(src)
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
to_chat(user, "Your name has been sent to your employers for approval.")
|
||||
// Autoapproves after a certain time
|
||||
response_timer_id = addtimer(CALLBACK(src, .proc/rename_station, new_name, user.name, user.real_name, key_name(user)), approval_time, TIMER_STOPPABLE)
|
||||
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[ADMIN_LOOKUPFLW(user)] proposes to rename the [name_type] to [new_name] (will autoapprove in [approval_time / 10] seconds). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;[HrefToken(TRUE)];reject_custom_name=\ref[src]'>REJECT</A>) [ADMIN_CENTCOM_REPLY(user)]</span>")
|
||||
to_chat(GLOB.admins, "<span class='adminnotice'><b><font color=orange>CUSTOM STATION RENAME:</font></b>[ADMIN_LOOKUPFLW(user)] proposes to rename the [name_type] to [new_name] (will autoapprove in [DisplayTimeText(approval_time)]). [ADMIN_SMITE(user)] (<A HREF='?_src_=holder;[HrefToken(TRUE)];reject_custom_name=\ref[src]'>REJECT</A>) [ADMIN_CENTCOM_REPLY(user)]</span>")
|
||||
|
||||
/obj/item/station_charter/proc/reject_proposed(user)
|
||||
if(!user)
|
||||
|
||||
@@ -234,6 +234,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
/obj/item/clothing/mask/cigarette/attack(mob/living/carbon/M, mob/living/carbon/user)
|
||||
if(!istype(M))
|
||||
return ..()
|
||||
if(M.on_fire && !lit)
|
||||
light("<span class='notice'>[user] lights [src] with [M]'s burning body. What a cold-blooded badass.</span>")
|
||||
return
|
||||
var/obj/item/clothing/mask/cigarette/cig = help_light_cig(M)
|
||||
if(lit && cig && user.a_intent == INTENT_HELP)
|
||||
if(cig.lit)
|
||||
|
||||
@@ -26,6 +26,14 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
var/obj/item/cartridge/cartridge = null //current cartridge
|
||||
var/mode = 0 //Controls what menu the PDA will display. 0 is hub; the rest are either built in or based on cartridge.
|
||||
var/icon_alert = "pda-r" //Icon to be overlayed for message alerts. Taken from the pda icon file.
|
||||
var/font_index = 0 //This int tells DM which font is currently selected and lets DM know when the last font has been selected so that it can cycle back to the first font when "toggle font" is pressed again.
|
||||
var/font_mode = "font-family:\"VT323\", monospace;letter-spacing:1px;" //The currently selected font.
|
||||
var/background_color = "#808000" //The currently selected background color.
|
||||
|
||||
#define FONT_VT 0
|
||||
#define FONT_SHARE 1
|
||||
#define FONT_ORBITRON 2
|
||||
#define FONT_MONO 3
|
||||
|
||||
//Secondary variables
|
||||
var/scanmode = 0 //1 is medical scanner, 2 is forensics, 3 is reagent scanner.
|
||||
@@ -58,6 +66,13 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
var/obj/item/inserted_item //Used for pen, crayon, and lipstick insertion or removal. Same as above.
|
||||
var/overlays_x_offset = 0 //x offset to use for certain overlays
|
||||
|
||||
/obj/item/device/pda/examine(mob/user)
|
||||
..()
|
||||
if(!id && !inserted_item)
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>Alt-click to remove contents.</span>")
|
||||
|
||||
/obj/item/device/pda/Initialize()
|
||||
. = ..()
|
||||
if(fon)
|
||||
@@ -121,7 +136,8 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
hidden_uplink.interact(user)
|
||||
return
|
||||
|
||||
var/dat = "<html><head><title>Personal Data Assistant</title></head><body bgcolor=\"#808000\"><style>a, a:link, a:visited, a:active, a:hover { color: #000000; }img {border-style:none;}</style>"
|
||||
var/dat = "<!DOCTYPE html><html><head><title>Personal Data Assistant</title><link href=\"https://fonts.googleapis.com/css?family=Orbitron|Share+Tech+Mono|VT323\" rel=\"stylesheet\"></head><body bgcolor=\"" + background_color + "\"><style>body{" + font_mode + "}ul,ol{list-style-type: none;}a, a:link, a:visited, a:active, a:hover { color: #000000;text-decoration:none; }img {border-style:none;}</style>"
|
||||
|
||||
|
||||
dat += "<a href='byond://?src=\ref[src];choice=Refresh'><img src=pda_refresh.png> Refresh</a>"
|
||||
|
||||
@@ -130,6 +146,12 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
if (mode)
|
||||
dat += " | <a href='byond://?src=\ref[src];choice=Return'><img src=pda_menu.png> Return</a>"
|
||||
|
||||
if (mode == 0)
|
||||
dat += "<div align=\"center\">"
|
||||
dat += "<br><a href='byond://?src=\ref[src];choice=Toggle_Font'>Toggle Font</a>"
|
||||
dat += " | <a href='byond://?src=\ref[src];choice=Change_Color'>Change Color</a>"
|
||||
dat += "</div>"
|
||||
|
||||
dat += "<br>"
|
||||
|
||||
if (!owner)
|
||||
@@ -307,6 +329,24 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
//BASIC FUNCTIONS===================================
|
||||
|
||||
if("Refresh")//Refresh, goes to the end of the proc.
|
||||
|
||||
if ("Toggle_Font")
|
||||
//CODE REVISION 2
|
||||
font_index = (font_index + 1) % 4
|
||||
|
||||
switch(font_index)
|
||||
if (FONT_VT)
|
||||
font_mode = "font-family:\"VT323\", monospace;letter-spacing:1px;"
|
||||
if (FONT_SHARE)
|
||||
font_mode = "font-family:\"Share Tech Mono\", monospace;letter-spacing:0px;"
|
||||
if (FONT_ORBITRON)
|
||||
font_mode = "font-family:\"Orbitron\", monospace;letter-spacing:0px; font-size:15px"
|
||||
if (FONT_MONO)
|
||||
font_mode = "font-family:monospace;"
|
||||
if ("Change_Color")
|
||||
var/new_color = input("Please enter a color name or hex value (Default is \'#808000\').")as color
|
||||
background_color = new_color
|
||||
|
||||
if("Return")//Return
|
||||
if(mode<=9)
|
||||
mode = 0
|
||||
@@ -400,7 +440,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
if (in_range(src, U) && loc == U)
|
||||
if (mode == 1 && n)
|
||||
note = n
|
||||
notehtml = parsepencode(n, U, SIGNFONT)
|
||||
notehtml = parsemarkdown(n, U)
|
||||
notescanned = 0
|
||||
else
|
||||
U << browse(null, "window=pda")
|
||||
@@ -538,7 +578,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
P.show_recieved_message(msg,src)
|
||||
if(!multiple)
|
||||
show_to_ghosts(user,msg)
|
||||
log_talk(user,"[key_name(user)] (PDA: [name]) sent \"[message]\" to [key_name(P,null,TRUE)]",LOGPDA)
|
||||
log_talk(user,"[key_name(user)] (PDA: [initial(name)]) sent \"[message]\" to [key_name(P,null,TRUE)]",LOGPDA)
|
||||
else
|
||||
if(!multiple)
|
||||
to_chat(user, "<span class='notice'>ERROR: Server isn't responding.</span>")
|
||||
@@ -548,7 +588,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
if(multiple)
|
||||
show_to_sender(last_sucessful_msg,1)
|
||||
show_to_ghosts(user,last_sucessful_msg,1)
|
||||
log_talk(user,"[user] (PDA: [name]) sent \"[message]\" to Everyone",LOGPDA)
|
||||
log_talk(user,"[user] (PDA: [initial(name)]) sent \"[message]\" to Everyone",LOGPDA)
|
||||
|
||||
/obj/item/device/pda/proc/show_to_sender(datum/data_pda_msg/msg,multiple = 0)
|
||||
tnote += "<i><b>→ To [multiple ? "Everyone" : msg.recipient]:</b></i><br>[msg.message][msg.get_photo_ref()]<br>"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
GLOBAL_LIST_EMPTY(GPS_list)
|
||||
/obj/item/device/gps
|
||||
name = "global positioning system"
|
||||
desc = "Helping lost spacemen find their way through the planets since 2016. Alt+click to toggle power."
|
||||
desc = "Helping lost spacemen find their way through the planets since 2016."
|
||||
icon = 'icons/obj/telescience.dmi'
|
||||
icon_state = "gps-c"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
@@ -15,6 +15,9 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
|
||||
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
|
||||
|
||||
/obj/item/device/gps/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>")
|
||||
|
||||
/obj/item/device/gps/Initialize()
|
||||
. = ..()
|
||||
@@ -209,4 +212,4 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
clear()
|
||||
tagged = null
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
. = ..()
|
||||
. = ..()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/item/device/radio/headset
|
||||
name = "radio headset"
|
||||
desc = "An updated, modular intercom that fits over the head. Takes encryption keys. \nTo speak on the general radio frequency, use ; before speaking."
|
||||
desc = "An updated, modular intercom that fits over the head. Takes encryption keys."
|
||||
icon_state = "headset"
|
||||
item_state = "headset"
|
||||
materials = list(MAT_METAL=75)
|
||||
@@ -11,6 +11,12 @@
|
||||
var/obj/item/device/encryptionkey/keyslot2 = null
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/device/radio/headset/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>To speak on the general radio frequency, use ; before speaking.</span>")
|
||||
if (command)
|
||||
to_chat(user, "<span class='notice'>Alt-click to toggle the high-volume mode.</span>")
|
||||
|
||||
/obj/item/device/radio/headset/Initialize()
|
||||
. = ..()
|
||||
recalculateChannels()
|
||||
|
||||
@@ -181,7 +181,7 @@ MASS SPECTROMETER
|
||||
to_chat(user, "<span class='info'>Time of Death:</span> [M.tod]")
|
||||
var/tdelta = round(world.time - M.timeofdeath)
|
||||
if(tdelta < (DEFIB_TIME_LIMIT * 10))
|
||||
to_chat(user, "<span class='danger'>Subject died [tdelta / 10] seconds ago, defibrillation may be possible!</span>")
|
||||
to_chat(user, "<span class='danger'>Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!</span>")
|
||||
|
||||
for(var/thing in M.viruses)
|
||||
var/datum/disease/D = thing
|
||||
@@ -214,7 +214,7 @@ MASS SPECTROMETER
|
||||
|
||||
var/cyberimp_detect
|
||||
for(var/obj/item/organ/cyberimp/CI in C.internal_organs)
|
||||
if(CI.status == ORGAN_ROBOTIC)
|
||||
if(CI.status == ORGAN_ROBOTIC && !CI.syndicate_implant)
|
||||
cyberimp_detect += "[C.name] is modified with a [CI.name].<br>"
|
||||
if(cyberimp_detect)
|
||||
to_chat(user, "<span class='notice'>Detected cybernetic modifications:</span>")
|
||||
|
||||
@@ -111,7 +111,6 @@ effective or pretty fucking useless.
|
||||
/obj/item/device/healthanalyzer/rad_laser/interact(mob/user)
|
||||
user.set_machine(src)
|
||||
|
||||
var/cooldown = GetCooldown()
|
||||
var/dat = "Irradiation: <A href='?src=\ref[src];rad=1'>[irradiate ? "On" : "Off"]</A><br>"
|
||||
dat += "Stealth Mode (NOTE: Deactivates automatically while Irradiation is off): <A href='?src=\ref[src];stealthy=[TRUE]'>[stealth ? "On" : "Off"]</A><br>"
|
||||
dat += "Scan Mode: <a href='?src=\ref[src];mode=1'>"
|
||||
@@ -133,7 +132,7 @@ effective or pretty fucking useless.
|
||||
<A href='?src=\ref[src];radwav=-5'>-</A><A href='?src=\ref[src];radwav=-1'>-</A>
|
||||
[(wavelength+(intensity*4))]
|
||||
<A href='?src=\ref[src];radwav=1'>+</A><A href='?src=\ref[src];radwav=5'>+</A><BR>
|
||||
Laser Cooldown: [cooldown] Seconds<BR>
|
||||
Laser Cooldown: [DisplayTimeText(GetCooldown())]<BR>
|
||||
"}
|
||||
|
||||
var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240)
|
||||
|
||||
@@ -38,10 +38,14 @@
|
||||
|
||||
/obj/item/toy/eightball/Initialize(mapload)
|
||||
. = ..()
|
||||
if(prob(1))
|
||||
new /obj/item/toy/eightball/haunted(get_turf(src))
|
||||
if(MakeHaunted())
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/item/toy/eightball/proc/MakeHaunted()
|
||||
. = prob(1)
|
||||
if(.)
|
||||
new /obj/item/toy/eightball/haunted(loc)
|
||||
|
||||
/obj/item/toy/eightball/attack_self(mob/user)
|
||||
if(shaking)
|
||||
return
|
||||
@@ -105,6 +109,9 @@
|
||||
GLOB.poi_list -= src
|
||||
. = ..()
|
||||
|
||||
/obj/item/toy/eightball/haunted/MakeHaunted()
|
||||
return FALSE
|
||||
|
||||
/obj/item/toy/eightball/haunted/attack_ghost(mob/user)
|
||||
if(!shaking)
|
||||
to_chat(user, "<span class='warning'>[src] is not currently being shaken.</span>")
|
||||
|
||||
@@ -1,188 +1,190 @@
|
||||
/obj/item/extinguisher
|
||||
name = "fire extinguisher"
|
||||
desc = "A traditional red fire extinguisher."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "fire_extinguisher0"
|
||||
item_state = "fire_extinguisher"
|
||||
hitsound = 'sound/weapons/smash.ogg'
|
||||
flags_1 = CONDUCT_1
|
||||
throwforce = 10
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 7
|
||||
force = 10
|
||||
materials = list(MAT_METAL=90)
|
||||
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/max_water = 50
|
||||
var/last_use = 1
|
||||
var/safety = TRUE
|
||||
var/refilling = FALSE
|
||||
var/sprite_name = "fire_extinguisher"
|
||||
var/power = 5 //Maximum distance launched water will travel
|
||||
var/precision = 0 //By default, turfs picked from a spray are random, set to 1 to make it always have at least one water effect per row
|
||||
var/cooling_power = 2 //Sets the cooling_temperature of the water reagent datum inside of the extinguisher when it is refilled
|
||||
|
||||
/obj/item/extinguisher/mini
|
||||
name = "pocket fire extinguisher"
|
||||
desc = "A light and compact fibreglass-framed model fire extinguisher."
|
||||
icon_state = "miniFE0"
|
||||
item_state = "miniFE"
|
||||
hitsound = null //it is much lighter, after all.
|
||||
flags_1 = null //doesn't CONDUCT_1
|
||||
throwforce = 2
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 3
|
||||
materials = list()
|
||||
max_water = 30
|
||||
sprite_name = "miniFE"
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/extinguisher/New()
|
||||
..()
|
||||
create_reagents(max_water)
|
||||
reagents.add_reagent("water", max_water)
|
||||
|
||||
/obj/item/extinguisher/attack_self(mob/user)
|
||||
safety = !safety
|
||||
src.icon_state = "[sprite_name][!safety]"
|
||||
src.desc = "The safety is [safety ? "on" : "off"]."
|
||||
to_chat(user, "The safety is [safety ? "on" : "off"].")
|
||||
return
|
||||
|
||||
/obj/item/extinguisher/attack(mob/M, mob/user)
|
||||
if(user.a_intent == INTENT_HELP && !safety) //If we're on help intent and going to spray people, don't bash them.
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/attack_obj(obj/O, mob/living/user)
|
||||
if(AttemptRefill(O, user))
|
||||
refilling = TRUE
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/examine(mob/user)
|
||||
..()
|
||||
if(reagents.total_volume)
|
||||
to_chat(user, "It contains [round(reagents.total_volume)] units.")
|
||||
else
|
||||
to_chat(user, "It is empty.")
|
||||
|
||||
/obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user)
|
||||
if(istype(target, /obj/structure/reagent_dispensers/watertank) && target.Adjacent(user))
|
||||
var/safety_save = safety
|
||||
safety = TRUE
|
||||
if(reagents.total_volume == reagents.maximum_volume)
|
||||
to_chat(user, "<span class='warning'>\The [src] is already full!</span>")
|
||||
safety = safety_save
|
||||
return 1
|
||||
var/obj/structure/reagent_dispensers/watertank/W = target
|
||||
var/transferred = W.reagents.trans_to(src, max_water)
|
||||
if(transferred > 0)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been refilled by [transferred] units.</span>")
|
||||
playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
|
||||
for(var/datum/reagent/water/R in reagents.reagent_list)
|
||||
R.cooling_temperature = cooling_power
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [W] is empty!</span>")
|
||||
safety = safety_save
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/extinguisher/afterattack(atom/target, mob/user , flag)
|
||||
// Make it so the extinguisher doesn't spray yourself when you click your inventory items
|
||||
if (target.loc == user)
|
||||
return
|
||||
//TODO; Add support for reagents in water.
|
||||
if(refilling)
|
||||
refilling = FALSE
|
||||
return
|
||||
if (!safety)
|
||||
if (src.reagents.total_volume < 1)
|
||||
to_chat(usr, "<span class='warning'>\The [src] is empty!</span>")
|
||||
return
|
||||
|
||||
if (world.time < src.last_use + 12)
|
||||
return
|
||||
|
||||
src.last_use = world.time
|
||||
|
||||
playsound(src.loc, 'sound/effects/extinguish.ogg', 75, 1, -3)
|
||||
|
||||
var/direction = get_dir(src,target)
|
||||
|
||||
if(user.buckled && isobj(user.buckled) && !user.buckled.anchored)
|
||||
spawn(0)
|
||||
var/obj/B = user.buckled
|
||||
var/movementdirection = turn(direction,180)
|
||||
step(B, movementdirection)
|
||||
sleep(1)
|
||||
step(B, movementdirection)
|
||||
sleep(1)
|
||||
step(B, movementdirection)
|
||||
sleep(1)
|
||||
step(B, movementdirection)
|
||||
sleep(2)
|
||||
step(B, movementdirection)
|
||||
sleep(2)
|
||||
step(B, movementdirection)
|
||||
sleep(3)
|
||||
step(B, movementdirection)
|
||||
sleep(3)
|
||||
step(B, movementdirection)
|
||||
sleep(3)
|
||||
step(B, movementdirection)
|
||||
|
||||
else user.newtonian_move(turn(direction, 180))
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
var/turf/T1 = get_step(T,turn(direction, 90))
|
||||
var/turf/T2 = get_step(T,turn(direction, -90))
|
||||
var/list/the_targets = list(T,T1,T2)
|
||||
if(precision)
|
||||
var/turf/T3 = get_step(T1, turn(direction, 90))
|
||||
var/turf/T4 = get_step(T2,turn(direction, -90))
|
||||
the_targets = list(T,T1,T2,T3,T4)
|
||||
|
||||
for(var/a=0, a<5, a++)
|
||||
spawn(0)
|
||||
var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src))
|
||||
var/turf/my_target = pick(the_targets)
|
||||
if(precision)
|
||||
the_targets -= my_target
|
||||
var/datum/reagents/R = new/datum/reagents(5)
|
||||
if(!W) return
|
||||
W.reagents = R
|
||||
R.my_atom = W
|
||||
if(!W || !src) return
|
||||
src.reagents.trans_to(W,1)
|
||||
for(var/b=0, b<power, b++)
|
||||
step_towards(W,my_target)
|
||||
if(!W || !W.reagents) return
|
||||
W.reagents.reaction(get_turf(W))
|
||||
for(var/A in get_turf(W))
|
||||
if(!W) return
|
||||
W.reagents.reaction(A)
|
||||
if(W.loc == my_target) break
|
||||
sleep(2)
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/AltClick(mob/user)
|
||||
EmptyExtinguisher(user)
|
||||
|
||||
/obj/item/extinguisher/proc/EmptyExtinguisher(var/mob/user)
|
||||
if(loc == user && reagents.total_volume)
|
||||
reagents.clear_reagents()
|
||||
|
||||
var/turf/T = get_turf(loc)
|
||||
if(isopenturf(T))
|
||||
var/turf/open/theturf = T
|
||||
theturf.MakeSlippery(min_wet_time = 10, wet_time_to_add = 5)
|
||||
|
||||
user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "<span class='info'>You quietly empty out \the [src] using its release valve.</span>")
|
||||
|
||||
/obj/item/extinguisher
|
||||
name = "fire extinguisher"
|
||||
desc = "A traditional red fire extinguisher."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "fire_extinguisher0"
|
||||
item_state = "fire_extinguisher"
|
||||
hitsound = 'sound/weapons/smash.ogg'
|
||||
flags_1 = CONDUCT_1
|
||||
throwforce = 10
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
throw_speed = 2
|
||||
throw_range = 7
|
||||
force = 10
|
||||
materials = list(MAT_METAL=90)
|
||||
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/max_water = 50
|
||||
var/last_use = 1
|
||||
var/safety = TRUE
|
||||
var/refilling = FALSE
|
||||
var/sprite_name = "fire_extinguisher"
|
||||
var/power = 5 //Maximum distance launched water will travel
|
||||
var/precision = 0 //By default, turfs picked from a spray are random, set to 1 to make it always have at least one water effect per row
|
||||
var/cooling_power = 2 //Sets the cooling_temperature of the water reagent datum inside of the extinguisher when it is refilled
|
||||
|
||||
/obj/item/extinguisher/mini
|
||||
name = "pocket fire extinguisher"
|
||||
desc = "A light and compact fibreglass-framed model fire extinguisher."
|
||||
icon_state = "miniFE0"
|
||||
item_state = "miniFE"
|
||||
hitsound = null //it is much lighter, after all.
|
||||
flags_1 = null //doesn't CONDUCT_1
|
||||
throwforce = 2
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 3
|
||||
materials = list()
|
||||
max_water = 30
|
||||
sprite_name = "miniFE"
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/extinguisher/New()
|
||||
..()
|
||||
create_reagents(max_water)
|
||||
reagents.add_reagent("water", max_water)
|
||||
|
||||
/obj/item/extinguisher/attack_self(mob/user)
|
||||
safety = !safety
|
||||
src.icon_state = "[sprite_name][!safety]"
|
||||
src.desc = "The safety is [safety ? "on" : "off"]."
|
||||
to_chat(user, "The safety is [safety ? "on" : "off"].")
|
||||
return
|
||||
|
||||
/obj/item/extinguisher/attack(mob/M, mob/user)
|
||||
if(user.a_intent == INTENT_HELP && !safety) //If we're on help intent and going to spray people, don't bash them.
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/attack_obj(obj/O, mob/living/user)
|
||||
if(AttemptRefill(O, user))
|
||||
refilling = TRUE
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/examine(mob/user)
|
||||
..()
|
||||
if(reagents.total_volume)
|
||||
to_chat(user, "It contains [round(reagents.total_volume)] units.")
|
||||
to_chat(user, "<span class='notice'>Alt-click to empty it.</span>")
|
||||
else
|
||||
to_chat(user, "It is empty.")
|
||||
|
||||
/obj/item/extinguisher/proc/AttemptRefill(atom/target, mob/user)
|
||||
if(istype(target, /obj/structure/reagent_dispensers/watertank) && target.Adjacent(user))
|
||||
var/safety_save = safety
|
||||
safety = TRUE
|
||||
if(reagents.total_volume == reagents.maximum_volume)
|
||||
to_chat(user, "<span class='warning'>\The [src] is already full!</span>")
|
||||
safety = safety_save
|
||||
return 1
|
||||
var/obj/structure/reagent_dispensers/watertank/W = target
|
||||
var/transferred = W.reagents.trans_to(src, max_water)
|
||||
if(transferred > 0)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been refilled by [transferred] units.</span>")
|
||||
playsound(src.loc, 'sound/effects/refill.ogg', 50, 1, -6)
|
||||
for(var/datum/reagent/water/R in reagents.reagent_list)
|
||||
R.cooling_temperature = cooling_power
|
||||
else
|
||||
to_chat(user, "<span class='warning'>\The [W] is empty!</span>")
|
||||
safety = safety_save
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/extinguisher/afterattack(atom/target, mob/user , flag)
|
||||
// Make it so the extinguisher doesn't spray yourself when you click your inventory items
|
||||
if (target.loc == user)
|
||||
return
|
||||
//TODO; Add support for reagents in water.
|
||||
if(refilling)
|
||||
refilling = FALSE
|
||||
return
|
||||
if (!safety)
|
||||
if (src.reagents.total_volume < 1)
|
||||
to_chat(usr, "<span class='warning'>\The [src] is empty!</span>")
|
||||
return
|
||||
|
||||
if (world.time < src.last_use + 12)
|
||||
return
|
||||
|
||||
src.last_use = world.time
|
||||
|
||||
playsound(src.loc, 'sound/effects/extinguish.ogg', 75, 1, -3)
|
||||
|
||||
var/direction = get_dir(src,target)
|
||||
|
||||
if(user.buckled && isobj(user.buckled) && !user.buckled.anchored)
|
||||
spawn(0)
|
||||
var/obj/B = user.buckled
|
||||
var/movementdirection = turn(direction,180)
|
||||
step(B, movementdirection)
|
||||
sleep(1)
|
||||
step(B, movementdirection)
|
||||
sleep(1)
|
||||
step(B, movementdirection)
|
||||
sleep(1)
|
||||
step(B, movementdirection)
|
||||
sleep(2)
|
||||
step(B, movementdirection)
|
||||
sleep(2)
|
||||
step(B, movementdirection)
|
||||
sleep(3)
|
||||
step(B, movementdirection)
|
||||
sleep(3)
|
||||
step(B, movementdirection)
|
||||
sleep(3)
|
||||
step(B, movementdirection)
|
||||
|
||||
else user.newtonian_move(turn(direction, 180))
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
var/turf/T1 = get_step(T,turn(direction, 90))
|
||||
var/turf/T2 = get_step(T,turn(direction, -90))
|
||||
var/list/the_targets = list(T,T1,T2)
|
||||
if(precision)
|
||||
var/turf/T3 = get_step(T1, turn(direction, 90))
|
||||
var/turf/T4 = get_step(T2,turn(direction, -90))
|
||||
the_targets = list(T,T1,T2,T3,T4)
|
||||
|
||||
for(var/a=0, a<5, a++)
|
||||
spawn(0)
|
||||
var/obj/effect/particle_effect/water/W = new /obj/effect/particle_effect/water(get_turf(src))
|
||||
var/turf/my_target = pick(the_targets)
|
||||
if(precision)
|
||||
the_targets -= my_target
|
||||
var/datum/reagents/R = new/datum/reagents(5)
|
||||
if(!W) return
|
||||
W.reagents = R
|
||||
R.my_atom = W
|
||||
if(!W || !src) return
|
||||
src.reagents.trans_to(W,1)
|
||||
for(var/b=0, b<power, b++)
|
||||
step_towards(W,my_target)
|
||||
if(!W || !W.reagents) return
|
||||
W.reagents.reaction(get_turf(W))
|
||||
for(var/A in get_turf(W))
|
||||
if(!W) return
|
||||
W.reagents.reaction(A)
|
||||
if(W.loc == my_target) break
|
||||
sleep(2)
|
||||
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/AltClick(mob/user)
|
||||
EmptyExtinguisher(user)
|
||||
|
||||
/obj/item/extinguisher/proc/EmptyExtinguisher(var/mob/user)
|
||||
if(loc == user && reagents.total_volume)
|
||||
reagents.clear_reagents()
|
||||
|
||||
var/turf/T = get_turf(loc)
|
||||
if(isopenturf(T))
|
||||
var/turf/open/theturf = T
|
||||
theturf.MakeSlippery(min_wet_time = 10, wet_time_to_add = 5)
|
||||
|
||||
user.visible_message("[user] empties out \the [src] onto the floor using the release valve.", "<span class='info'>You quietly empty out \the [src] using its release valve.</span>")
|
||||
|
||||
@@ -26,21 +26,15 @@
|
||||
if(..())
|
||||
var/obj/machinery/abductor/console/console
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(H.dna.species.id == "abductor")
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
console = get_team_console(S.team)
|
||||
var/datum/antagonist/abductor/A = target.mind.has_antag_datum(ANTAG_DATUM_ABDUCTOR)
|
||||
if(A)
|
||||
console = get_abductor_console(A.team.team_number)
|
||||
home = console.pad
|
||||
|
||||
if(!home)
|
||||
console = get_team_console(pick(1, 2, 3, 4))
|
||||
var/list/consoles = list()
|
||||
for(var/obj/machinery/abductor/console/C in GLOB.machines)
|
||||
consoles += C
|
||||
console = pick(consoles)
|
||||
home = console.pad
|
||||
return 1
|
||||
|
||||
/obj/item/implant/abductor/proc/get_team_console(var/team)
|
||||
var/obj/machinery/abductor/console/console
|
||||
for(var/obj/machinery/abductor/console/c in GLOB.machines)
|
||||
if(c.team == team)
|
||||
console = c
|
||||
break
|
||||
return console
|
||||
return TRUE
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
var/special = FALSE
|
||||
var/special_name = "special function"
|
||||
var/message_cooldown
|
||||
var/breakout_time = 1
|
||||
var/breakout_time = 600
|
||||
|
||||
/obj/machinery/implantchair/Initialize()
|
||||
. = ..()
|
||||
@@ -124,9 +124,9 @@
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='notice'>You see [user] kicking against the door of [src]!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear a metallic creaking from [src].</span>")
|
||||
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || state_open)
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] successfully broke out of [src]!</span>", \
|
||||
|
||||
@@ -400,7 +400,6 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
|
||||
singular_name = "plastic sheet"
|
||||
icon_state = "sheet-plastic"
|
||||
throwforce = 7
|
||||
origin_tech = "materials=1"
|
||||
origin_tech = "materials=1;biotech=1"
|
||||
merge_type = /obj/item/stack/sheet/plastic
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
to_chat(user, "There are [get_amount()] in the stack.")
|
||||
else
|
||||
to_chat(user, "There is [get_amount()] in the stack.")
|
||||
to_chat(user, "<span class='notice'>Alt-click to take a custom amount.</span>")
|
||||
|
||||
/obj/item/stack/proc/get_amount()
|
||||
if(is_cyborg)
|
||||
|
||||
@@ -125,13 +125,21 @@
|
||||
icon_type = "cigarette"
|
||||
spawn_type = /obj/item/clothing/mask/cigarette/space_cigarette
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to extract contents.</span>")
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/AltClick(mob/user)
|
||||
if(user.get_active_held_item())
|
||||
if(user.stat || user.restrained())
|
||||
return
|
||||
for(var/obj/item/lighter/lighter in src)
|
||||
remove_from_storage(lighter, user.loc)
|
||||
user.put_in_active_hand(lighter)
|
||||
break
|
||||
var/obj/item/clothing/mask/cigarette/W = locate(/obj/item/clothing/mask/cigarette) in contents
|
||||
if(W && contents.len > 0)
|
||||
remove_from_storage(W, user)
|
||||
user.put_in_hands(W)
|
||||
contents -= W
|
||||
to_chat(user, "<span class='notice'>You take a [icon_type] out of the pack.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There are no [icon_type]s left in the pack.</span>")
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/update_icon()
|
||||
if(fancy_open || !contents.len)
|
||||
|
||||
@@ -123,6 +123,11 @@
|
||||
icon_broken = "medalbox+b"
|
||||
can_hold = list(/obj/item/clothing/accessory/medal)
|
||||
|
||||
/obj/item/storage/lockbox/medal/examine(mob/user)
|
||||
..()
|
||||
if(!locked)
|
||||
to_chat(user, "<span class='notice'>Alt-click to [open ? "close":"open"] it.</span>")
|
||||
|
||||
/obj/item/storage/lockbox/medal/AltClick()
|
||||
if(!locked)
|
||||
open = (open ? FALSE : TRUE)
|
||||
@@ -179,4 +184,4 @@
|
||||
|
||||
/obj/item/storage/lockbox/medal/sci/PopulateContents()
|
||||
for(var/i in 1 to 3)
|
||||
new /obj/item/clothing/accessory/medal/plasma/nobel_science(src)
|
||||
new /obj/item/clothing/accessory/medal/plasma/nobel_science(src)
|
||||
|
||||
@@ -28,31 +28,29 @@
|
||||
|
||||
/obj/item/storage/secure/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, text("The service panel is [src.open ? "open" : "closed"]."))
|
||||
to_chat(user, text("The service panel is currently <b>[open ? "unscrewed" : "screwed shut"]</b>."))
|
||||
|
||||
/obj/item/storage/secure/attackby(obj/item/W, mob/user, params)
|
||||
if(locked)
|
||||
if (istype(W, /obj/item/screwdriver))
|
||||
if (do_after(user, 20*W.toolspeed, target = src))
|
||||
src.open =! src.open
|
||||
user.show_message("<span class='notice'>You [open ? "open" : "close"] the service panel.</span>", 1)
|
||||
if (do_after(user, 20*W.toolspeed, target = user))
|
||||
open =! open
|
||||
to_chat(user, "<span class='notice'>You [open ? "open" : "close"] the service panel.</span>")
|
||||
return
|
||||
if ((istype(W, /obj/item/device/multitool)) && (src.open == 1)&& (!src.l_hacking))
|
||||
user.show_message("<span class='danger'>Now attempting to reset internal memory, please hold.</span>", 1)
|
||||
src.l_hacking = 1
|
||||
if (do_after(usr, 100*W.toolspeed, target = src))
|
||||
if (prob(33))
|
||||
src.l_setshort = 1
|
||||
if (istype(W, /obj/item/wirecutters) || istype(W, /obj/item/card/emag))
|
||||
to_chat(user, "<span class='danger'>[src] is protected from this sort of tampering, yet it appears the internal memory wires can still be <b>pulsed</b>.</span>")
|
||||
if ((istype(W, /obj/item/device/multitool)) && (!l_hacking))
|
||||
if(src.open == 1)
|
||||
to_chat(user, "<span class='danger'>Now attempting to reset internal memory, please hold.</span>")
|
||||
src.l_hacking = 1
|
||||
if (do_after(usr, 400*W.toolspeed, target = user))
|
||||
to_chat(user, "<span class='danger'>Internal memory reset - lock has been disengaged.</span>")
|
||||
src.l_set = 0
|
||||
user.show_message("<span class='danger'>Internal memory reset. Please give it a few seconds to reinitialize.</span>", 1)
|
||||
sleep(80)
|
||||
src.l_setshort = 0
|
||||
src.l_hacking = 0
|
||||
else
|
||||
user.show_message("<span class='danger'>Unable to reset internal memory.</span>", 1)
|
||||
src.l_hacking = 0
|
||||
else
|
||||
src.l_hacking = 0
|
||||
to_chat(user, "<span class='notice'>You must <b>unscrew</b> the service panel before you can pulse the wiring.</span>")
|
||||
return
|
||||
//At this point you have exhausted all the special things to do when locked
|
||||
// ... but it's still locked.
|
||||
|
||||
@@ -1,183 +1,184 @@
|
||||
/* Types of tanks!
|
||||
* Contains:
|
||||
* Oxygen
|
||||
* Anesthetic
|
||||
* Air
|
||||
* Plasma
|
||||
* Emergency Oxygen
|
||||
*/
|
||||
|
||||
/*
|
||||
* Oxygen
|
||||
*/
|
||||
/obj/item/tank/internals/oxygen
|
||||
name = "oxygen tank"
|
||||
desc = "A tank of oxygen."
|
||||
icon_state = "oxygen"
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
force = 10
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
|
||||
/obj/item/tank/internals/oxygen/New()
|
||||
..()
|
||||
air_contents.assert_gas("o2")
|
||||
air_contents.gases["o2"][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/tank/internals/oxygen/yellow
|
||||
desc = "A tank of oxygen, this one is yellow."
|
||||
icon_state = "oxygen_f"
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/tank/internals/oxygen/red
|
||||
desc = "A tank of oxygen, this one is red."
|
||||
icon_state = "oxygen_fr"
|
||||
dog_fashion = null
|
||||
|
||||
|
||||
/*
|
||||
* Anesthetic
|
||||
*/
|
||||
/obj/item/tank/internals/anesthetic
|
||||
name = "anesthetic tank"
|
||||
desc = "A tank with an N2O/O2 gas mix."
|
||||
icon_state = "anesthetic"
|
||||
item_state = "an_tank"
|
||||
force = 10
|
||||
|
||||
/obj/item/tank/internals/anesthetic/New()
|
||||
..()
|
||||
air_contents.assert_gases("o2", "n2o")
|
||||
air_contents.gases["o2"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases["n2o"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
return
|
||||
|
||||
/*
|
||||
* Air
|
||||
*/
|
||||
/obj/item/tank/internals/air
|
||||
name = "air tank"
|
||||
desc = "Mixed anyone?"
|
||||
icon_state = "oxygen"
|
||||
force = 10
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/tank/internals/air/New()
|
||||
..()
|
||||
air_contents.assert_gases("o2","n2")
|
||||
air_contents.gases["o2"][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases["n2"][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* Plasma
|
||||
*/
|
||||
/obj/item/tank/internals/plasma
|
||||
name = "plasma tank"
|
||||
desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable."
|
||||
icon_state = "plasma"
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = null //they have no straps!
|
||||
force = 8
|
||||
|
||||
|
||||
/obj/item/tank/internals/plasma/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/flamethrower))
|
||||
var/obj/item/flamethrower/F = W
|
||||
if ((!F.status)||(F.ptank))
|
||||
return
|
||||
if(!user.transferItemToLoc(src, F))
|
||||
return
|
||||
src.master = F
|
||||
F.ptank = src
|
||||
F.update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/tank/internals/plasma/full/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* Plasmaman Plasma Tank
|
||||
*/
|
||||
|
||||
/obj/item/tank/internals/plasmaman
|
||||
name = "plasma internals tank"
|
||||
desc = "A tank of plasma gas designed specifically for use as internals, particularly for plasma-based lifeforms. If you're not a Plasmaman, you probably shouldn't use this."
|
||||
icon_state = "plasmaman_tank"
|
||||
item_state = "plasmaman_tank"
|
||||
force = 10
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
|
||||
/obj/item/tank/internals/plasmaman/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/plasmaman/full/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt
|
||||
icon_state = "plasmaman_tank_belt"
|
||||
item_state = "plasmaman_tank_belt"
|
||||
slot_flags = SLOT_BELT
|
||||
force = 5
|
||||
volume = 6
|
||||
w_class = WEIGHT_CLASS_SMALL //thanks i forgot this
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt/full/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Emergency Oxygen
|
||||
*/
|
||||
/obj/item/tank/internals/emergency_oxygen
|
||||
name = "emergency oxygen tank"
|
||||
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
|
||||
icon_state = "emergency"
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 4
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
volume = 3 //Tiny. Real life equivalents only have 21 breaths of oxygen in them. They're EMERGENCY tanks anyway -errorage (dangercon 2011)
|
||||
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/New()
|
||||
..()
|
||||
air_contents.assert_gas("o2")
|
||||
air_contents.gases["o2"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/engi
|
||||
name = "extended-capacity emergency oxygen tank"
|
||||
icon_state = "emergency_engi"
|
||||
volume = 6
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/double
|
||||
name = "double emergency oxygen tank"
|
||||
icon_state = "emergency_engi"
|
||||
volume = 10
|
||||
/* Types of tanks!
|
||||
* Contains:
|
||||
* Oxygen
|
||||
* Anesthetic
|
||||
* Air
|
||||
* Plasma
|
||||
* Emergency Oxygen
|
||||
*/
|
||||
|
||||
/*
|
||||
* Oxygen
|
||||
*/
|
||||
/obj/item/tank/internals/oxygen
|
||||
name = "oxygen tank"
|
||||
desc = "A tank of oxygen."
|
||||
icon_state = "oxygen"
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
force = 10
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
|
||||
/obj/item/tank/internals/oxygen/New()
|
||||
..()
|
||||
air_contents.assert_gas("o2")
|
||||
air_contents.gases["o2"][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/tank/internals/oxygen/yellow
|
||||
desc = "A tank of oxygen, this one is yellow."
|
||||
icon_state = "oxygen_f"
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/tank/internals/oxygen/red
|
||||
desc = "A tank of oxygen, this one is red."
|
||||
icon_state = "oxygen_fr"
|
||||
dog_fashion = null
|
||||
|
||||
|
||||
/*
|
||||
* Anesthetic
|
||||
*/
|
||||
/obj/item/tank/internals/anesthetic
|
||||
name = "anesthetic tank"
|
||||
desc = "A tank with an N2O/O2 gas mix."
|
||||
icon_state = "anesthetic"
|
||||
item_state = "an_tank"
|
||||
force = 10
|
||||
|
||||
/obj/item/tank/internals/anesthetic/New()
|
||||
..()
|
||||
air_contents.assert_gases("o2", "n2o")
|
||||
air_contents.gases["o2"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases["n2o"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
return
|
||||
|
||||
/*
|
||||
* Air
|
||||
*/
|
||||
/obj/item/tank/internals/air
|
||||
name = "air tank"
|
||||
desc = "Mixed anyone?"
|
||||
icon_state = "air"
|
||||
item_state = "air"
|
||||
force = 10
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/tank/internals/air/New()
|
||||
..()
|
||||
air_contents.assert_gases("o2","n2")
|
||||
air_contents.gases["o2"][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD
|
||||
air_contents.gases["n2"][MOLES] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* Plasma
|
||||
*/
|
||||
/obj/item/tank/internals/plasma
|
||||
name = "plasma tank"
|
||||
desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable."
|
||||
icon_state = "plasma"
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = null //they have no straps!
|
||||
force = 8
|
||||
|
||||
|
||||
/obj/item/tank/internals/plasma/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/flamethrower))
|
||||
var/obj/item/flamethrower/F = W
|
||||
if ((!F.status)||(F.ptank))
|
||||
return
|
||||
if(!user.transferItemToLoc(src, F))
|
||||
return
|
||||
src.master = F
|
||||
F.ptank = src
|
||||
F.update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/tank/internals/plasma/full/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* Plasmaman Plasma Tank
|
||||
*/
|
||||
|
||||
/obj/item/tank/internals/plasmaman
|
||||
name = "plasma internals tank"
|
||||
desc = "A tank of plasma gas designed specifically for use as internals, particularly for plasma-based lifeforms. If you're not a Plasmaman, you probably shouldn't use this."
|
||||
icon_state = "plasmaman_tank"
|
||||
item_state = "plasmaman_tank"
|
||||
force = 10
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
|
||||
/obj/item/tank/internals/plasmaman/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/plasmaman/full/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt
|
||||
icon_state = "plasmaman_tank_belt"
|
||||
item_state = "plasmaman_tank_belt"
|
||||
slot_flags = SLOT_BELT
|
||||
force = 5
|
||||
volume = 6
|
||||
w_class = WEIGHT_CLASS_SMALL //thanks i forgot this
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt/full/New()
|
||||
..()
|
||||
air_contents.assert_gas("plasma")
|
||||
air_contents.gases["plasma"][MOLES] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Emergency Oxygen
|
||||
*/
|
||||
/obj/item/tank/internals/emergency_oxygen
|
||||
name = "emergency oxygen tank"
|
||||
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
|
||||
icon_state = "emergency"
|
||||
flags_1 = CONDUCT_1
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 4
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
volume = 3 //Tiny. Real life equivalents only have 21 breaths of oxygen in them. They're EMERGENCY tanks anyway -errorage (dangercon 2011)
|
||||
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/New()
|
||||
..()
|
||||
air_contents.assert_gas("o2")
|
||||
air_contents.gases["o2"][MOLES] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/engi
|
||||
name = "extended-capacity emergency oxygen tank"
|
||||
icon_state = "emergency_engi"
|
||||
volume = 6
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/double
|
||||
name = "double emergency oxygen tank"
|
||||
icon_state = "emergency_engi"
|
||||
volume = 10
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
if("pressure")
|
||||
var/pressure = params["pressure"]
|
||||
if(pressure == "reset")
|
||||
pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
pressure = initial(distribute_pressure)
|
||||
. = TRUE
|
||||
else if(pressure == "min")
|
||||
pressure = TANK_MIN_RELEASE_PRESSURE
|
||||
|
||||
@@ -104,11 +104,11 @@
|
||||
/obj/item/paper/guides/antag/supermatter_sliver
|
||||
info = "How to safely extract a supermatter sliver:<br>\
|
||||
<ul>\
|
||||
<li>Approach an active supermatter crystal with proper protective gear. DO NOT MAKE PHYSICAL CONTACT.</li>\
|
||||
<li>Approach an active supermatter crystal with radiation shielded personal protective equipment. DO NOT MAKE PHYSICAL CONTACT.</li>\
|
||||
<li>Use a supermatter scalpel (provided) to slice off a sliver of the crystal.</li>\
|
||||
<li>Use supermatter extraction tongs (also provided) to safely remove the sliver.</li>\
|
||||
<li>Use supermatter extraction tongs (also provided) to safely pick up the sliver you sliced off.</li>\
|
||||
<li>Physical contact of any object with the sliver will dust the object, as well as yourself.</li>\
|
||||
<li>Use the tongs to place the sliver into the provided container, which will take some time to seal</li>\
|
||||
<li>Use the tongs to place the sliver into the provided container, which will take some time to seal.</li>\
|
||||
<li>Get the hell out before the crystal delaminates.</li>\
|
||||
<li>???</li>\
|
||||
</ul>"
|
||||
|
||||
@@ -427,6 +427,11 @@
|
||||
var/obj/item/grenade/explosive = null
|
||||
var/war_cry = "AAAAARGH!!!"
|
||||
|
||||
/obj/item/twohanded/spear/examine(mob/user)
|
||||
..()
|
||||
if(explosive)
|
||||
to_chat(user, "<span class='notice'>Alt-click to set your war cry.</span>")
|
||||
|
||||
/obj/item/twohanded/spear/update_icon()
|
||||
if(explosive)
|
||||
icon_state = "spearbomb[wielded]"
|
||||
@@ -475,7 +480,7 @@
|
||||
if(G)
|
||||
explosive = G
|
||||
name = "explosive lance"
|
||||
desc = "A makeshift spear with [G] attached to it. Alt+click on the spear to set your war cry!"
|
||||
desc = "A makeshift spear with [G] attached to it."
|
||||
update_icon()
|
||||
|
||||
// CHAINSAW
|
||||
|
||||
@@ -45,14 +45,13 @@
|
||||
switch(state)
|
||||
if(EMPTY_CORE)
|
||||
if(istype(P, /obj/item/circuitboard/aicore))
|
||||
if(!user.drop_item())
|
||||
if(!user.transferItemToLoc(P, src))
|
||||
return
|
||||
playsound(loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>You place the circuit board inside the frame.</span>")
|
||||
update_icon()
|
||||
state = CIRCUIT_CORE
|
||||
circuit = P
|
||||
P.forceMove(src)
|
||||
return
|
||||
if(CIRCUIT_CORE)
|
||||
if(istype(P, /obj/item/screwdriver))
|
||||
@@ -143,10 +142,9 @@
|
||||
to_chat(user, "<span class='warning'>This [M.name] is mindless!</span>")
|
||||
return
|
||||
|
||||
if(!user.drop_item())
|
||||
if(!user.transferItemToLoc(M,src))
|
||||
return
|
||||
|
||||
M.forceMove(src)
|
||||
brain = M
|
||||
to_chat(user, "<span class='notice'>You add [M.name] to the frame.</span>")
|
||||
update_icon()
|
||||
@@ -176,7 +174,14 @@
|
||||
SSticker.mode.remove_antag_for_borging(brain.brainmob.mind)
|
||||
if(!istype(brain.laws, /datum/ai_laws/ratvar))
|
||||
remove_servant_of_ratvar(brain.brainmob, TRUE)
|
||||
var/mob/living/silicon/ai/A = new /mob/living/silicon/ai(loc, laws, brain.brainmob)
|
||||
|
||||
var/mob/living/silicon/ai/A = null
|
||||
|
||||
if (brain.overrides_aicore_laws)
|
||||
A = new /mob/living/silicon/ai(loc, brain.laws, brain.brainmob)
|
||||
else
|
||||
A = new /mob/living/silicon/ai(loc, laws, brain.brainmob)
|
||||
|
||||
if(brain.force_replace_ai_name)
|
||||
A.fully_replace_character_name(A.name, brain.replacement_ai_name())
|
||||
SSblackbox.inc("cyborg_ais_created",1)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
max_integrity = 200
|
||||
integrity_failure = 50
|
||||
armor = list(melee = 20, bullet = 10, laser = 10, energy = 0, bomb = 10, bio = 0, rad = 0, fire = 70, acid = 60)
|
||||
var/breakout_time = 2
|
||||
var/breakout_time = 1200
|
||||
var/message_cooldown
|
||||
var/can_weld_shut = TRUE
|
||||
var/horizontal = FALSE
|
||||
@@ -366,9 +366,9 @@
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
user.visible_message("<span class='warning'>[src] begins to shake violently!</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [(breakout_time<1) ? "[breakout_time*60] seconds" : "[breakout_time] minute\s"].)</span>", \
|
||||
"<span class='notice'>You lean on the back of [src] and start pushing the door open... (this will take about [DisplayTimeText(breakout_time)].)</span>", \
|
||||
"<span class='italics'>You hear banging from [src].</span>")
|
||||
if(do_after(user,(breakout_time*60*10), target = src)) //minutes * 60seconds * 10deciseconds
|
||||
if(do_after(user,(breakout_time), target = src))
|
||||
if(!user || user.stat != CONSCIOUS || user.loc != src || opened || (!locked && !welded) )
|
||||
return
|
||||
//we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user