Merge remote-tracking branch 'upstream/master' into signaler-tgui-next
This commit is contained in:
@@ -57,7 +57,6 @@
|
||||
#define FLOODLIGHT_NEEDS_WIRES 0
|
||||
#define FLOODLIGHT_NEEDS_LIGHTS 1
|
||||
#define FLOODLIGHT_NEEDS_SECURING 2
|
||||
#define FLOODLIGHT_NEEDS_WRENCHING 3
|
||||
|
||||
//other construction-related things
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@
|
||||
#define MATERIAL_COLOR (1<<0)
|
||||
#define MATERIAL_ADD_PREFIX (1<<1)
|
||||
#define MATERIAL_NO_EFFECTS (1<<2)
|
||||
#define MATERIAL_AFFECT_STATISTICS (1<<3)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
// Skills
|
||||
// Skill levels
|
||||
#define SKILL_LEVEL_NONE 0
|
||||
#define SKILL_LEVEL_NOVICE 1
|
||||
#define SKILL_LEVEL_APPRENTICE 2
|
||||
@@ -8,6 +8,7 @@
|
||||
#define SKILL_LEVEL_MASTER 5
|
||||
#define SKILL_LEVEL_LEGENDARY 6
|
||||
|
||||
//Skill experience thresholds
|
||||
#define SKILL_EXP_NOVICE 100
|
||||
#define SKILL_EXP_APPRENTICE 250
|
||||
#define SKILL_EXP_JOURNEYMAN 500
|
||||
@@ -15,5 +16,9 @@
|
||||
#define SKILL_EXP_MASTER 1500
|
||||
#define SKILL_EXP_LEGENDARY 2500
|
||||
|
||||
//Skill modifier types
|
||||
#define SKILL_SPEED_MODIFIER "skill_speed_modifier"
|
||||
|
||||
|
||||
// Gets the reference for the skill type that was given
|
||||
#define GetSkillRef(A) (SSskills.all_skills[A])
|
||||
|
||||
@@ -49,24 +49,24 @@
|
||||
if(!istext(color))
|
||||
color = ""
|
||||
|
||||
var/start = 1 + (text2ascii(color,1)==35)
|
||||
var/start = 1 + (text2ascii(color, 1) == 35)
|
||||
var/len = length(color)
|
||||
var/step_size = 1 + ((len+1)-start != desired_format)
|
||||
var/char = ""
|
||||
|
||||
. = ""
|
||||
for(var/i=start, i<=len, i+=step_size)
|
||||
var/ascii = text2ascii(color,i)
|
||||
switch(ascii)
|
||||
if(48 to 57)
|
||||
. += ascii2text(ascii) //numbers 0 to 9
|
||||
if(97 to 102)
|
||||
. += ascii2text(ascii) //letters a to f
|
||||
if(65 to 70)
|
||||
. += ascii2text(ascii+32) //letters A to F - translates to lowercase
|
||||
for(var/i = start, i <= len, i += length(char))
|
||||
char = color[i]
|
||||
switch(text2ascii(char))
|
||||
if(48 to 57) //numbers 0 to 9
|
||||
. += char
|
||||
if(97 to 102) //letters a to f
|
||||
. += char
|
||||
if(65 to 70) //letters A to F
|
||||
. += lowertext(char)
|
||||
else
|
||||
break
|
||||
|
||||
if(length(.) != desired_format)
|
||||
if(length_char(.) != desired_format)
|
||||
if(default)
|
||||
return default
|
||||
return crunch + repeat_string(desired_format, "0")
|
||||
|
||||
+216
-235
@@ -40,8 +40,8 @@
|
||||
for(var/char in repl_chars)
|
||||
var/index = findtext(t, char)
|
||||
while(index)
|
||||
t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+1)
|
||||
index = findtext(t, char, index+1)
|
||||
t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index + length(char))
|
||||
index = findtext(t, char, index + length(char))
|
||||
return t
|
||||
|
||||
/proc/sanitize_filename(t)
|
||||
@@ -73,22 +73,28 @@
|
||||
|
||||
|
||||
//Returns null if there is any bad text in the string
|
||||
/proc/reject_bad_text(text, max_length=512)
|
||||
if(length(text) > max_length)
|
||||
return //message too long
|
||||
var/non_whitespace = 0
|
||||
for(var/i=1, i<=length(text), i++)
|
||||
switch(text2ascii(text,i))
|
||||
if(62,60,92,47)
|
||||
return //rejects the text if it contains these bad characters: <, >, \ or /
|
||||
if(127 to 255)
|
||||
return //rejects weird letters like �
|
||||
/proc/reject_bad_text(text, max_length = 512, ascii_only = TRUE)
|
||||
var/char_count = 0
|
||||
var/non_whitespace = FALSE
|
||||
var/lenbytes = length(text)
|
||||
var/char = ""
|
||||
for(var/i = 1, i <= lenbytes, i += length(char))
|
||||
char = text[i]
|
||||
char_count++
|
||||
if(char_count > max_length)
|
||||
return
|
||||
switch(text2ascii(char))
|
||||
if(62, 60, 92, 47) // <, >, \, /
|
||||
return
|
||||
if(0 to 31)
|
||||
return //more weird stuff
|
||||
return
|
||||
if(32)
|
||||
continue //whitespace
|
||||
continue
|
||||
if(127 to INFINITY)
|
||||
if(ascii_only)
|
||||
return
|
||||
else
|
||||
non_whitespace = 1
|
||||
non_whitespace = TRUE
|
||||
if(non_whitespace)
|
||||
return text //only accepts the text if it has some non-spaces
|
||||
|
||||
@@ -109,73 +115,84 @@
|
||||
else
|
||||
return trim(html_encode(name), max_length)
|
||||
|
||||
#define NO_CHARS_DETECTED 0
|
||||
#define SPACES_DETECTED 1
|
||||
#define SYMBOLS_DETECTED 2
|
||||
#define NUMBERS_DETECTED 3
|
||||
#define LETTERS_DETECTED 4
|
||||
|
||||
//Filters out undesirable characters from names
|
||||
/proc/reject_bad_name(t_in, allow_numbers=0, max_length=MAX_NAME_LEN)
|
||||
if(!t_in || length(t_in) > max_length)
|
||||
return //Rejects the input if it is null or if it is longer then the max length allowed
|
||||
/proc/reject_bad_name(t_in, allow_numbers = FALSE, max_length = MAX_NAME_LEN, ascii_only = TRUE)
|
||||
if(!t_in)
|
||||
return //Rejects the input if it is null
|
||||
|
||||
var/number_of_alphanumeric = 0
|
||||
var/last_char_group = 0
|
||||
var/number_of_alphanumeric = 0
|
||||
var/last_char_group = NO_CHARS_DETECTED
|
||||
var/t_out = ""
|
||||
var/t_len = length(t_in)
|
||||
var/charcount = 0
|
||||
var/char = ""
|
||||
|
||||
for(var/i=1, i<=length(t_in), i++)
|
||||
var/ascii_char = text2ascii(t_in,i)
|
||||
switch(ascii_char)
|
||||
|
||||
for(var/i = 1, i <= t_len, i += length(char))
|
||||
char = t_in[i]
|
||||
|
||||
switch(text2ascii(char))
|
||||
// A .. Z
|
||||
if(65 to 90) //Uppercase Letters
|
||||
t_out += ascii2text(ascii_char)
|
||||
number_of_alphanumeric++
|
||||
last_char_group = 4
|
||||
last_char_group = LETTERS_DETECTED
|
||||
|
||||
// a .. z
|
||||
if(97 to 122) //Lowercase Letters
|
||||
if(last_char_group<2)
|
||||
t_out += ascii2text(ascii_char-32) //Force uppercase first character
|
||||
else
|
||||
t_out += ascii2text(ascii_char)
|
||||
if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED || last_char_group == SYMBOLS_DETECTED) //start of a word
|
||||
char = uppertext(char)
|
||||
number_of_alphanumeric++
|
||||
last_char_group = 4
|
||||
last_char_group = LETTERS_DETECTED
|
||||
|
||||
// 0 .. 9
|
||||
if(48 to 57) //Numbers
|
||||
if(!last_char_group)
|
||||
continue //suppress at start of string
|
||||
if(!allow_numbers)
|
||||
if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string
|
||||
continue
|
||||
t_out += ascii2text(ascii_char)
|
||||
number_of_alphanumeric++
|
||||
last_char_group = 3
|
||||
last_char_group = NUMBERS_DETECTED
|
||||
|
||||
// ' - .
|
||||
if(39,45,46) //Common name punctuation
|
||||
if(!last_char_group)
|
||||
if(last_char_group == NO_CHARS_DETECTED)
|
||||
continue
|
||||
t_out += ascii2text(ascii_char)
|
||||
last_char_group = 2
|
||||
last_char_group = SYMBOLS_DETECTED
|
||||
|
||||
// ~ | @ : # $ % & * +
|
||||
if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI)
|
||||
if(!last_char_group)
|
||||
continue //suppress at start of string
|
||||
if(!allow_numbers)
|
||||
if(last_char_group == NO_CHARS_DETECTED || !allow_numbers) //suppress at start of string
|
||||
continue
|
||||
t_out += ascii2text(ascii_char)
|
||||
last_char_group = 2
|
||||
last_char_group = SYMBOLS_DETECTED
|
||||
|
||||
//Space
|
||||
if(32)
|
||||
if(last_char_group <= 1)
|
||||
continue //suppress double-spaces and spaces at start of string
|
||||
t_out += ascii2text(ascii_char)
|
||||
last_char_group = 1
|
||||
if(last_char_group == NO_CHARS_DETECTED || last_char_group == SPACES_DETECTED) //suppress double-spaces and spaces at start of string
|
||||
continue
|
||||
last_char_group = SPACES_DETECTED
|
||||
|
||||
if(127 to INFINITY)
|
||||
if(ascii_only)
|
||||
continue
|
||||
last_char_group = SYMBOLS_DETECTED //for now, we'll treat all non-ascii characters like symbols even though most are letters
|
||||
|
||||
else
|
||||
return
|
||||
continue
|
||||
|
||||
t_out += char
|
||||
charcount++
|
||||
if(charcount >= max_length)
|
||||
break
|
||||
|
||||
if(number_of_alphanumeric < 2)
|
||||
return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '"
|
||||
|
||||
if(last_char_group == 1)
|
||||
t_out = copytext(t_out,1,length(t_out)) //removes the last character (in this case a space)
|
||||
if(last_char_group == SPACES_DETECTED)
|
||||
t_out = copytext_char(t_out, 1, -1) //removes the last character (in this case a space)
|
||||
|
||||
for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai")) //prevents these common metagamey names
|
||||
if(cmptext(t_out,bad_name))
|
||||
@@ -183,6 +200,13 @@
|
||||
|
||||
return t_out
|
||||
|
||||
#undef NO_CHARS_DETECTED
|
||||
#undef SPACES_DETECTED
|
||||
#undef NUMBERS_DETECTED
|
||||
#undef LETTERS_DETECTED
|
||||
|
||||
|
||||
|
||||
//html_encode helper proc that returns the smallest non null of two numbers
|
||||
//or 0 if they're both null (needed because of findtext returning 0 when a value is not present)
|
||||
/proc/non_zero_min(a, b)
|
||||
@@ -192,39 +216,6 @@
|
||||
return a
|
||||
return (a < b ? a : b)
|
||||
|
||||
/*
|
||||
* Text searches
|
||||
*/
|
||||
|
||||
//Checks the beginning of a string for a specified sub-string
|
||||
//Returns the position of the substring or 0 if it was not found
|
||||
/proc/dd_hasprefix(text, prefix)
|
||||
var/start = 1
|
||||
var/end = length(prefix) + 1
|
||||
return findtext(text, prefix, start, end)
|
||||
|
||||
//Checks the beginning of a string for a specified sub-string. This proc is case sensitive
|
||||
//Returns the position of the substring or 0 if it was not found
|
||||
/proc/dd_hasprefix_case(text, prefix)
|
||||
var/start = 1
|
||||
var/end = length(prefix) + 1
|
||||
return findtextEx(text, prefix, start, end)
|
||||
|
||||
//Checks the end of a string for a specified substring.
|
||||
//Returns the position of the substring or 0 if it was not found
|
||||
/proc/dd_hassuffix(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if(start)
|
||||
return findtext(text, suffix, start, null)
|
||||
return
|
||||
|
||||
//Checks the end of a string for a specified substring. This proc is case sensitive
|
||||
//Returns the position of the substring or 0 if it was not found
|
||||
/proc/dd_hassuffix_case(text, suffix)
|
||||
var/start = length(text) - length(suffix)
|
||||
if(start)
|
||||
return findtextEx(text, suffix, start, null)
|
||||
|
||||
//Checks if any of a given list of needles is in the haystack
|
||||
/proc/text_in_list(haystack, list/needle_list, start=1, end=0)
|
||||
for(var/needle in needle_list)
|
||||
@@ -239,23 +230,17 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Adds 'u' number of zeros ahead of the text 't'
|
||||
/proc/add_zero(t, u)
|
||||
while (length(t) < u)
|
||||
t = "0[t]"
|
||||
return t
|
||||
//Adds 'char' ahead of 'text' until there are 'count' characters total
|
||||
/proc/add_leading(text, count, char = " ")
|
||||
var/charcount = count - length_char(text)
|
||||
var/list/chars_to_add[max(charcount + 1, 0)]
|
||||
return jointext(chars_to_add, char) + text
|
||||
|
||||
//Adds 'u' number of spaces ahead of the text 't'
|
||||
/proc/add_lspace(t, u)
|
||||
while(length(t) < u)
|
||||
t = " [t]"
|
||||
return t
|
||||
|
||||
//Adds 'u' number of spaces behind the text 't'
|
||||
/proc/add_tspace(t, u)
|
||||
while(length(t) < u)
|
||||
t = "[t] "
|
||||
return t
|
||||
//Adds 'char' behind 'text' until there are 'count' characters total
|
||||
/proc/add_trailing(text, count, char = " ")
|
||||
var/charcount = count - length_char(text)
|
||||
var/list/chars_to_add[max(charcount + 1, 0)]
|
||||
return text + jointext(chars_to_add, char)
|
||||
|
||||
//Returns a string with reserved characters and spaces before the first letter removed
|
||||
/proc/trim_left(text)
|
||||
@@ -269,63 +254,45 @@
|
||||
for (var/i = length(text), i > 0, i--)
|
||||
if (text2ascii(text, i) > 32)
|
||||
return copytext(text, 1, i + 1)
|
||||
|
||||
return ""
|
||||
|
||||
//Returns a string with reserved characters and spaces before the first word and after the last word removed.
|
||||
/proc/trim(text, max_length)
|
||||
if(max_length)
|
||||
text = copytext(text, 1, max_length)
|
||||
text = copytext_char(text, 1, max_length)
|
||||
return trim_left(trim_right(text))
|
||||
|
||||
//Returns a string with the first element of the string capitalized.
|
||||
/proc/capitalize(t as text)
|
||||
return uppertext(copytext(t, 1, 2)) + copytext(t, 2)
|
||||
|
||||
//Centers text by adding spaces to either side of the string.
|
||||
/proc/dd_centertext(message, length)
|
||||
var/new_message = message
|
||||
var/size = length(message)
|
||||
var/delta = length - size
|
||||
if(size == length)
|
||||
return new_message
|
||||
if(size > length)
|
||||
return copytext(new_message, 1, length + 1)
|
||||
if(delta == 1)
|
||||
return new_message + " "
|
||||
if(delta % 2)
|
||||
new_message = " " + new_message
|
||||
delta--
|
||||
var/spaces = add_lspace("",delta/2-1)
|
||||
return spaces + new_message + spaces
|
||||
|
||||
//Limits the length of the text. Note: MAX_MESSAGE_LEN and MAX_NAME_LEN are widely used for this purpose
|
||||
/proc/dd_limittext(message, length)
|
||||
var/size = length(message)
|
||||
if(size <= length)
|
||||
return message
|
||||
return copytext(message, 1, length + 1)
|
||||
|
||||
. = t[1]
|
||||
return uppertext(.) + copytext(t, 1 + length(.))
|
||||
|
||||
/proc/stringmerge(text,compare,replace = "*")
|
||||
//This proc fills in all spaces with the "replace" var (* by default) with whatever
|
||||
//is in the other string at the same spot (assuming it is not a replace char).
|
||||
//This is used for fingerprints
|
||||
var/newtext = text
|
||||
if(length(text) != length(compare))
|
||||
return 0
|
||||
for(var/i = 1, i < length(text), i++)
|
||||
var/a = copytext(text,i,i+1)
|
||||
var/b = copytext(compare,i,i+1)
|
||||
var/text_it = 1 //iterators
|
||||
var/comp_it = 1
|
||||
var/newtext_it = 1
|
||||
var/text_length = length(text)
|
||||
var/comp_length = length(compare)
|
||||
while(comp_it <= comp_length && text_it <= text_length)
|
||||
var/a = text[text_it]
|
||||
var/b = compare[comp_it]
|
||||
//if it isn't both the same letter, or if they are both the replacement character
|
||||
//(no way to know what it was supposed to be)
|
||||
if(a != b)
|
||||
if(a == replace) //if A is the replacement char
|
||||
newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1)
|
||||
newtext = copytext(newtext, 1, newtext_it) + b + copytext(newtext, newtext_it + length(newtext[newtext_it]))
|
||||
else if(b == replace) //if B is the replacement char
|
||||
newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1)
|
||||
newtext = copytext(newtext, 1, newtext_it) + a + copytext(newtext, newtext_it + length(newtext[newtext_it]))
|
||||
else //The lists disagree, Uh-oh!
|
||||
return 0
|
||||
text_it += length(a)
|
||||
comp_it += length(b)
|
||||
newtext_it += length(newtext[newtext_it])
|
||||
|
||||
return newtext
|
||||
|
||||
/proc/stringpercent(text,character = "*")
|
||||
@@ -334,16 +301,21 @@
|
||||
if(!text || !character)
|
||||
return 0
|
||||
var/count = 0
|
||||
for(var/i = 1, i <= length(text), i++)
|
||||
var/a = copytext(text,i,i+1)
|
||||
var/lentext = length(text)
|
||||
var/a = ""
|
||||
for(var/i = 1, i <= lentext, i += length(a))
|
||||
a = text[i]
|
||||
if(a == character)
|
||||
count++
|
||||
return count
|
||||
|
||||
/proc/reverse_text(text = "")
|
||||
var/new_text = ""
|
||||
for(var/i = length(text); i > 0; i--)
|
||||
new_text += copytext(text, i, i+1)
|
||||
var/lentext = length(text)
|
||||
var/letter = ""
|
||||
for(var/i = 1, i <= lentext, i += length(letter))
|
||||
letter = text[i]
|
||||
new_text = letter + new_text
|
||||
return new_text
|
||||
|
||||
GLOBAL_LIST_INIT(zero_character_only, list("0"))
|
||||
@@ -366,15 +338,6 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
/proc/random_color()
|
||||
return random_string(6, GLOB.hex_characters)
|
||||
|
||||
/proc/add_zero2(t, u)
|
||||
var/temp1
|
||||
while (length(t) < u)
|
||||
t = "0[t]"
|
||||
temp1 = t
|
||||
if (length(t) > u)
|
||||
temp1 = copytext(t,2,u+1)
|
||||
return temp1
|
||||
|
||||
//merges non-null characters (3rd argument) from "from" into "into". Returns result
|
||||
//e.g. into = "Hello World"
|
||||
// from = "Seeya______"
|
||||
@@ -387,41 +350,48 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
into = ""
|
||||
if(!istext(from))
|
||||
from = ""
|
||||
var/null_ascii = istext(null_char) ? text2ascii(null_char,1) : null_char
|
||||
|
||||
var/previous = 0
|
||||
var/null_ascii = istext(null_char) ? text2ascii(null_char, 1) : null_char
|
||||
var/copying_into = FALSE
|
||||
var/char = ""
|
||||
var/start = 1
|
||||
var/end = length(into) + 1
|
||||
|
||||
for(var/i=1, i<end, i++)
|
||||
var/ascii = text2ascii(from, i)
|
||||
if(ascii == null_ascii)
|
||||
if(previous != 1)
|
||||
. += copytext(from, start, i)
|
||||
start = i
|
||||
previous = 1
|
||||
var/end_from = length(from)
|
||||
var/end_into = length(into)
|
||||
var/into_it = 1
|
||||
var/from_it = 1
|
||||
while(from_it <= end_from && into_it <= end_into)
|
||||
char = from[from_it]
|
||||
if(text2ascii(char) == null_ascii)
|
||||
if(!copying_into)
|
||||
. += copytext(from, start, from_it)
|
||||
start = into_it
|
||||
copying_into = TRUE
|
||||
else
|
||||
if(previous != 0)
|
||||
. += copytext(into, start, i)
|
||||
start = i
|
||||
previous = 0
|
||||
if(copying_into)
|
||||
. += copytext(into, start, into_it)
|
||||
start = from_it
|
||||
copying_into = FALSE
|
||||
into_it += length(into[into_it])
|
||||
from_it += length(char)
|
||||
|
||||
if(previous == 0)
|
||||
. += copytext(from, start, end)
|
||||
if(copying_into)
|
||||
. += copytext(into, start)
|
||||
else
|
||||
. += copytext(into, start, end)
|
||||
. += copytext(from, start, from_it)
|
||||
if(into_it <= end_into)
|
||||
. += copytext(into, into_it)
|
||||
|
||||
//finds the first occurrence of one of the characters from needles argument inside haystack
|
||||
//it may appear this can be optimised, but it really can't. findtext() is so much faster than anything you can do in byondcode.
|
||||
//stupid byond :(
|
||||
/proc/findchar(haystack, needles, start=1, end=0)
|
||||
var/temp
|
||||
var/char = ""
|
||||
var/len = length(needles)
|
||||
for(var/i=1, i<=len, i++)
|
||||
temp = findtextEx(haystack, ascii2text(text2ascii(needles,i)), start, end) //Note: ascii2text(text2ascii) is faster than copytext()
|
||||
if(temp)
|
||||
end = temp
|
||||
return end
|
||||
for(var/i = 1, i <= len, i += length(char))
|
||||
char = needles[i]
|
||||
. = findtextEx(haystack, char, start, end)
|
||||
if(.)
|
||||
return
|
||||
return 0
|
||||
|
||||
/proc/parsemarkdown_basic_step1(t, limited=FALSE)
|
||||
if(length(t) <= 0)
|
||||
@@ -579,23 +549,28 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
|
||||
return t
|
||||
|
||||
#define string2charlist(string) (splittext(string, regex("(.)")) - splittext(string, ""))
|
||||
/proc/text2charlist(text)
|
||||
var/char = ""
|
||||
var/lentext = length(text)
|
||||
. = list()
|
||||
for(var/i = 1, i <= lentext, i += length(char))
|
||||
char = text[i]
|
||||
. += char
|
||||
|
||||
/proc/rot13(text = "")
|
||||
var/list/textlist = string2charlist(text)
|
||||
var/list/result = list()
|
||||
for(var/c in textlist)
|
||||
var/ca = text2ascii(c)
|
||||
if(ca >= text2ascii("a") && ca <= text2ascii("m"))
|
||||
ca += 13
|
||||
else if(ca >= text2ascii("n") && ca <= text2ascii("z"))
|
||||
ca -= 13
|
||||
else if(ca >= text2ascii("A") && ca <= text2ascii("M"))
|
||||
ca += 13
|
||||
else if(ca >= text2ascii("N") && ca <= text2ascii("Z"))
|
||||
ca -= 13
|
||||
result += ascii2text(ca)
|
||||
return jointext(result, "")
|
||||
var/lentext = length(text)
|
||||
var/char = ""
|
||||
var/ascii = 0
|
||||
. = ""
|
||||
for(var/i = 1, i <= lentext, i += length(char))
|
||||
char = text[i]
|
||||
ascii = text2ascii(char)
|
||||
switch(ascii)
|
||||
if(65 to 77, 97 to 109) //A to M, a to m
|
||||
ascii += 13
|
||||
if(78 to 90, 110 to 122) //N to Z, n to z
|
||||
ascii -= 13
|
||||
. += ascii2text(ascii)
|
||||
|
||||
//Takes a list of values, sanitizes it down for readability and character count,
|
||||
//then exports it as a json file at data/npc_saves/[filename].json.
|
||||
@@ -607,7 +582,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
return
|
||||
|
||||
//Regular expressions are, as usual, absolute magic
|
||||
var/regex/all_invalid_symbols = new("\[^ -~]+")
|
||||
//Any characters outside of 32 (space) to 126 (~) because treating things you don't understand as "magic" is really stupid
|
||||
var/regex/all_invalid_symbols = new(@"[^ -~]{1}")
|
||||
|
||||
var/list/accepted = list()
|
||||
for(var/string in proposed)
|
||||
@@ -615,34 +591,44 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
continue
|
||||
var/buffer = ""
|
||||
var/early_culling = TRUE
|
||||
for(var/pos = 1, pos <= length(string), pos++)
|
||||
var/let = copytext(string, pos, (pos + 1) % length(string))
|
||||
if(early_culling && !findtext(let,GLOB.is_alphanumeric))
|
||||
var/lentext = length(string)
|
||||
var/let = ""
|
||||
|
||||
for(var/pos = 1, pos <= lentext, pos += length(let))
|
||||
let = string[pos]
|
||||
if(!findtext(let, GLOB.is_alphanumeric))
|
||||
continue
|
||||
early_culling = FALSE
|
||||
buffer += let
|
||||
if(!findtext(buffer,GLOB.is_alphanumeric))
|
||||
buffer = copytext(string, pos)
|
||||
break
|
||||
if(early_culling) //Never found any letters! Bail!
|
||||
continue
|
||||
|
||||
var/punctbuffer = ""
|
||||
var/cutoff = length(buffer)
|
||||
for(var/pos = length(buffer), pos >= 0, pos--)
|
||||
var/let = copytext(buffer, pos, (pos + 1) % length(buffer))
|
||||
if(findtext(let,GLOB.is_alphanumeric))
|
||||
var/cutoff = 0
|
||||
lentext = length_char(buffer)
|
||||
for(var/pos = 1, pos <= lentext, pos++)
|
||||
let = copytext_char(buffer, -pos, -pos + 1)
|
||||
if(!findtext(let, GLOB.is_punctuation)) //This won't handle things like Nyaaaa!~ but that's fine
|
||||
break
|
||||
if(findtext(let,GLOB.is_punctuation))
|
||||
punctbuffer = let + punctbuffer //Note this isn't the same thing as using +=
|
||||
cutoff = pos
|
||||
punctbuffer += let
|
||||
cutoff += length(let)
|
||||
if(punctbuffer) //We clip down excessive punctuation to get the letter count lower and reduce repeats. It's not perfect but it helps.
|
||||
var/exclaim = FALSE
|
||||
var/question = FALSE
|
||||
var/periods = 0
|
||||
for(var/pos = length(punctbuffer), pos >= 0, pos--)
|
||||
var/punct = copytext(punctbuffer, pos, (pos + 1) % length(punctbuffer))
|
||||
if(!exclaim && findtext(punct,"!"))
|
||||
lentext = length(punctbuffer)
|
||||
for(var/pos = 1, pos <= lentext, pos += length(let))
|
||||
let = punctbuffer[pos]
|
||||
if(!exclaim && findtext(let, "!"))
|
||||
exclaim = TRUE
|
||||
if(!question && findtext(punct,"?"))
|
||||
if(question)
|
||||
break
|
||||
if(!question && findtext(let, "?"))
|
||||
question = TRUE
|
||||
if(!exclaim && !question && findtext(punct,"."))
|
||||
if(exclaim)
|
||||
break
|
||||
if(!exclaim && !question && findtext(let, ".")) //? and ! take priority over periods
|
||||
periods += 1
|
||||
if(exclaim)
|
||||
if(question)
|
||||
@@ -651,15 +637,13 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
punctbuffer = "!"
|
||||
else if(question)
|
||||
punctbuffer = "?"
|
||||
else if(periods)
|
||||
if(periods > 1)
|
||||
punctbuffer = "..."
|
||||
else
|
||||
punctbuffer = "" //Grammer nazis be damned
|
||||
buffer = copytext(buffer, 1, cutoff) + punctbuffer
|
||||
if(!findtext(buffer,GLOB.is_alphanumeric))
|
||||
continue
|
||||
if(!buffer || length(buffer) > 280 || length(buffer) <= cullshort || buffer in accepted)
|
||||
else if(periods > 1)
|
||||
punctbuffer = "..."
|
||||
else
|
||||
punctbuffer = "" //Grammer nazis be damned
|
||||
buffer = copytext(buffer, 1, -cutoff) + punctbuffer
|
||||
lentext = length_char(buffer)
|
||||
if(!buffer || lentext > 280 || lentext <= cullshort || (buffer in accepted))
|
||||
continue
|
||||
|
||||
accepted += buffer
|
||||
@@ -696,7 +680,7 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
|
||||
var/leng = length(string)
|
||||
|
||||
var/next_space = findtext(string, " ", next_backslash + 1)
|
||||
var/next_space = findtext(string, " ", next_backslash + length(string[next_backslash]))
|
||||
if(!next_space)
|
||||
next_space = leng - next_backslash
|
||||
|
||||
@@ -704,8 +688,8 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
return string
|
||||
|
||||
var/base = next_backslash == 1 ? "" : copytext(string, 1, next_backslash)
|
||||
var/macro = lowertext(copytext(string, next_backslash + 1, next_space))
|
||||
var/rest = next_backslash > leng ? "" : copytext(string, next_space + 1)
|
||||
var/macro = lowertext(copytext(string, next_backslash + length(string[next_backslash]), next_space))
|
||||
var/rest = next_backslash > leng ? "" : copytext(string, next_space + length(string[next_space]))
|
||||
|
||||
//See https://secure.byond.com/docs/ref/info.html#/DM/text/macros
|
||||
switch(macro)
|
||||
@@ -781,38 +765,35 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
return uppertext(pick(GLOB.alphabet))
|
||||
|
||||
/proc/unintelligize(message)
|
||||
var/prefix=copytext(message,1,2)
|
||||
var/regex/word_boundaries = regex(@"\b[\S]+\b", "g")
|
||||
var/prefix = message[1]
|
||||
if(prefix == ";")
|
||||
message = copytext(message,2)
|
||||
else if(prefix in list(":","#"))
|
||||
prefix += copytext(message,2,3)
|
||||
message = copytext(message,3)
|
||||
message = copytext(message, 1 + length(prefix))
|
||||
else if(prefix in list(":", "#"))
|
||||
prefix += message[1 + length(prefix)]
|
||||
message = copytext(message, length(prefix))
|
||||
else
|
||||
prefix=""
|
||||
prefix = ""
|
||||
|
||||
var/list/words = splittext(message," ")
|
||||
var/list/rearranged = list()
|
||||
for(var/i=1;i<=words.len;i++)
|
||||
var/cword = pick(words)
|
||||
words.Remove(cword)
|
||||
var/suffix = copytext(cword,length(cword)-1,length(cword))
|
||||
while(length(cword)>0 && suffix in list(".",",",";","!",":","?"))
|
||||
cword = copytext(cword,1 ,length(cword)-1)
|
||||
suffix = copytext(cword,length(cword)-1,length(cword) )
|
||||
while(word_boundaries.Find(message))
|
||||
var/cword = word_boundaries.match
|
||||
if(length(cword))
|
||||
rearranged += cword
|
||||
message = "[prefix][jointext(rearranged," ")]"
|
||||
. = message
|
||||
shuffle_inplace(rearranged)
|
||||
return "[prefix][jointext(rearranged, " ")]"
|
||||
|
||||
|
||||
/proc/readable_corrupted_text(text)
|
||||
var/list/corruption_options = list("..", "£%", "~~\"", "!!", "*", "^", "$!", "-", "}", "?")
|
||||
var/corrupted_text = ""
|
||||
|
||||
var/lentext = length(text)
|
||||
var/letter = ""
|
||||
// Have every letter have a chance of creating corruption on either side
|
||||
// Small chance of letters being removed in place of corruption - still overall readable
|
||||
for(var/letter_index = 1; letter_index <= length(text); letter_index++)
|
||||
var/letter = text[letter_index]
|
||||
for(var/letter_index = 1, letter_index <= lentext, letter_index += length(letter))
|
||||
letter = text[letter_index]
|
||||
|
||||
if (prob(15))
|
||||
corrupted_text += pick(corruption_options)
|
||||
|
||||
@@ -549,26 +549,3 @@
|
||||
else //regex everything else (works for /proc too)
|
||||
return lowertext(replacetext("[the_type]", "[type2parent(the_type)]/", ""))
|
||||
|
||||
/proc/strtohex(str)
|
||||
if(!istext(str)||!str)
|
||||
return
|
||||
var/r
|
||||
var/c
|
||||
for(var/i = 1 to length(str))
|
||||
c= text2ascii(str,i)
|
||||
r+= num2hex(c)
|
||||
return r
|
||||
|
||||
// Decodes hex to raw byte string.
|
||||
// If safe=TRUE, returns null on incorrect input strings instead of CRASHing
|
||||
/proc/hextostr(str, safe=FALSE)
|
||||
if(!istext(str)||!str)
|
||||
return
|
||||
var/r
|
||||
var/c
|
||||
for(var/i = 1 to length(str)/2)
|
||||
c = hex2num(copytext(str,i*2-1,i*2+1), safe)
|
||||
if(isnull(c))
|
||||
return null
|
||||
r += ascii2text(c)
|
||||
return r
|
||||
|
||||
@@ -181,15 +181,15 @@ Turf and target are separate in case you want to teleport some distance from a t
|
||||
//Returns whether or not a player is a guest using their ckey as an input
|
||||
/proc/IsGuestKey(key)
|
||||
if (findtext(key, "Guest-", 1, 7) != 1) //was findtextEx
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
var/i, ch, len = length(key)
|
||||
|
||||
for (i = 7, i <= len, ++i)
|
||||
for (i = 7, i <= len, ++i) //we know the first 6 chars are Guest-
|
||||
ch = text2ascii(key, i)
|
||||
if (ch < 48 || ch > 57)
|
||||
return 0
|
||||
return 1
|
||||
if (ch < 48 || ch > 57) //0-9
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//Generalised helper proc for letting mobs rename themselves. Used to be clname() and ainame()
|
||||
/mob/proc/apply_pref_name(role, client/C)
|
||||
|
||||
@@ -39,6 +39,26 @@
|
||||
#error You need version 512 or higher
|
||||
#endif
|
||||
|
||||
//Compatability -- These procs were added in 513.1493, not 513.1490
|
||||
//Which really shoulda bumped us up to 514 right then and there but instead Lummox is a dumb dumb
|
||||
#if DM_BUILD < 1493
|
||||
#define length_char(args...) length(args)
|
||||
#define text2ascii_char(args...) text2ascii(args)
|
||||
#define copytext_char(args...) copytext(args)
|
||||
#define splittext_char(args...) splittext(args)
|
||||
#define spantext_char(args...) spantext(args)
|
||||
#define nonspantext_char(args...) nonspantext(args)
|
||||
#define findtext_char(args...) findtext(args)
|
||||
#define findtextEx_char(args...) findtextEx(args)
|
||||
#define findlasttext_char(args...) findlasttext(args)
|
||||
#define findlasttextEx_char(args...) findlasttextEx(args)
|
||||
#define replacetext_char(args...) replacetext(args)
|
||||
#define replacetextEx_char(args...) replacetextEx(args)
|
||||
// /regex procs
|
||||
#define Find_char(args...) Find(args)
|
||||
#define Replace_char(args...) Replace(args)
|
||||
#endif
|
||||
|
||||
//Additional code for the above flags.
|
||||
#ifdef TESTING
|
||||
#warn compiling in TESTING mode. testing() debug messages will be visible.
|
||||
|
||||
@@ -10,6 +10,7 @@ GLOBAL_LIST_EMPTY(navbeacons) //list of all bot nagivation beacons, used
|
||||
GLOBAL_LIST_EMPTY(teleportbeacons) //list of all tracking beacons used by teleporters
|
||||
GLOBAL_LIST_EMPTY(deliverybeacons) //list of all MULEbot delivery beacons.
|
||||
GLOBAL_LIST_EMPTY(deliverybeacontags) //list of all tags associated with delivery beacons.
|
||||
GLOBAL_LIST_EMPTY(wayfindingbeacons) //list of all navigation beacons used by wayfinding pinpointers
|
||||
GLOBAL_LIST_EMPTY(nuke_list)
|
||||
GLOBAL_LIST_EMPTY(alarmdisplay) //list of all machines or programs that can display station alerts
|
||||
GLOBAL_LIST_EMPTY(singularities) //list of all singularities on the station (actually technically all engines)
|
||||
|
||||
@@ -379,4 +379,8 @@
|
||||
config_entry_value = 64
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/ratcap
|
||||
config_entry_value = 64
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/dynamic_config_enabled
|
||||
|
||||
@@ -284,7 +284,7 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
log_world("ERROR: Station areas list failed to generate!")
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/maprotate()
|
||||
if(map_voted)
|
||||
if(map_voted || SSmapping.next_map_config) //If voted or set by other means.
|
||||
return
|
||||
|
||||
var/players = GLOB.clients.len
|
||||
@@ -307,9 +307,13 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
for (var/map in mapvotes)
|
||||
if (!map)
|
||||
mapvotes.Remove(map)
|
||||
continue
|
||||
if (!(map in global.config.maplist))
|
||||
mapvotes.Remove(map)
|
||||
continue
|
||||
if(map in SSpersistence.blocked_maps)
|
||||
mapvotes.Remove(map)
|
||||
continue
|
||||
var/datum/map_config/VM = global.config.maplist[map]
|
||||
if (!VM)
|
||||
mapvotes.Remove(map)
|
||||
@@ -336,6 +340,13 @@ GLOBAL_LIST_EMPTY(the_station_areas)
|
||||
if (. && VM.map_name != config.map_name)
|
||||
to_chat(world, "<span class='boldannounce'>Map rotation has chosen [VM.map_name] for next round!</span>")
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/mapvote()
|
||||
if(map_voted || SSmapping.next_map_config) //If voted or set by other means.
|
||||
return
|
||||
if(SSvote.mode) //Theres already a vote running, default to rotation.
|
||||
maprotate()
|
||||
SSvote.initiate_vote("map", "automatic map rotation")
|
||||
|
||||
/datum/controller/subsystem/mapping/proc/changemap(var/datum/map_config/VM)
|
||||
if(!VM.MakeNextMap())
|
||||
next_map_config = load_map_config(default_to_box = TRUE)
|
||||
|
||||
@@ -8,6 +8,7 @@ SUBSYSTEM_DEF(mobs)
|
||||
var/static/list/clients_by_zlevel[][]
|
||||
var/static/list/dead_players_by_zlevel[][] = list(list()) // Needs to support zlevel 1 here, MaxZChanged only happens when z2 is created and new_players can login before that.
|
||||
var/static/list/cubemonkeys = list()
|
||||
var/static/list/cheeserats = list()
|
||||
|
||||
/datum/controller/subsystem/mobs/stat_entry()
|
||||
..("P:[GLOB.mob_living_list.len]")
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#define FILE_ANTAG_REP "data/AntagReputation.json"
|
||||
#define FILE_RECENT_MAPS "data/RecentMaps.json"
|
||||
|
||||
#define KEEP_ROUNDS_MAP 3
|
||||
|
||||
SUBSYSTEM_DEF(persistence)
|
||||
name = "Persistence"
|
||||
init_order = INIT_ORDER_PERSISTENCE
|
||||
@@ -9,7 +11,8 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/list/obj/structure/chisel_message/chisel_messages = list()
|
||||
var/list/saved_messages = list()
|
||||
var/list/saved_modes = list(1,2,3)
|
||||
var/list/saved_maps = list(1,2)
|
||||
var/list/saved_maps = list()
|
||||
var/list/blocked_maps = list()
|
||||
var/list/saved_trophies = list()
|
||||
var/list/antag_rep = list()
|
||||
var/list/antag_rep_change = list()
|
||||
@@ -116,6 +119,18 @@ SUBSYSTEM_DEF(persistence)
|
||||
return
|
||||
saved_maps = json["data"]
|
||||
|
||||
//Convert the mapping data to a shared blocking list, saves us doing this in several places later.
|
||||
for(var/map in config.maplist)
|
||||
var/datum/map_config/VM = config.maplist[map]
|
||||
var/run = 0
|
||||
if(VM.map_name == SSmapping.config.map_name)
|
||||
run++
|
||||
for(var/name in SSpersistence.saved_maps)
|
||||
if(VM.map_name == name)
|
||||
run++
|
||||
if(run >= 2) //If run twice in the last KEEP_ROUNDS_MAP + 1 (including current) rounds, disable map for voting and rotation.
|
||||
blocked_maps += VM.map_name
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadAntagReputation()
|
||||
var/json = file2text(FILE_ANTAG_REP)
|
||||
if(!json)
|
||||
@@ -284,7 +299,13 @@ SUBSYSTEM_DEF(persistence)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/CollectMaps()
|
||||
saved_maps[2] = saved_maps[1]
|
||||
if(length(saved_maps) > KEEP_ROUNDS_MAP) //Get rid of extras from old configs.
|
||||
saved_maps.Cut(KEEP_ROUNDS_MAP+1)
|
||||
var/mapstosave = min(length(saved_maps)+1, KEEP_ROUNDS_MAP)
|
||||
if(length(saved_maps) < mapstosave) //Add extras if too short, one per round.
|
||||
saved_maps += mapstosave
|
||||
for(var/i = mapstosave; i > 1; i--)
|
||||
saved_maps[i] = saved_maps[i-1]
|
||||
saved_maps[1] = SSmapping.config.map_name
|
||||
var/json_file = file(FILE_RECENT_MAPS)
|
||||
var/list/file_data = list()
|
||||
|
||||
@@ -41,3 +41,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
|
||||
badquirk = TRUE
|
||||
if(badquirk)
|
||||
cli.prefs.save_character()
|
||||
|
||||
// Assign wayfinding pinpointer granting quirk if they're new
|
||||
if(cli.calc_exp_type(EXP_TYPE_LIVING) < 1200 && !user.has_quirk(/datum/quirk/needswayfinder))
|
||||
user.add_quirk(/datum/quirk/needswayfinder, TRUE)
|
||||
|
||||
@@ -43,8 +43,6 @@ 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/maprotatechecked = 0
|
||||
|
||||
var/news_report
|
||||
|
||||
var/late_join_disabled
|
||||
@@ -156,10 +154,10 @@ SUBSYSTEM_DEF(ticker)
|
||||
//lobby stats for statpanels
|
||||
if(isnull(timeLeft))
|
||||
timeLeft = max(0,start_at - world.time)
|
||||
totalPlayers = LAZYLEN(GLOB.new_player_list)
|
||||
totalPlayers = LAZYLEN(GLOB.new_player_list)
|
||||
totalPlayersReady = 0
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
if(player.ready == PLAYER_READY_TO_PLAY)
|
||||
++totalPlayersReady
|
||||
|
||||
@@ -192,13 +190,13 @@ SUBSYSTEM_DEF(ticker)
|
||||
if(GAME_STATE_PLAYING)
|
||||
mode.process(wait * 0.1)
|
||||
check_queue()
|
||||
check_maprotate()
|
||||
|
||||
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)
|
||||
declare_completion(force_ending)
|
||||
check_maprotate()
|
||||
Master.SetRunLevel(RUNLEVEL_POSTGAME)
|
||||
|
||||
|
||||
@@ -343,8 +341,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
explosion(epi, 0, 256, 512, 0, TRUE, TRUE, 0, TRUE)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/create_characters()
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
if(player.ready == PLAYER_READY_TO_PLAY && player.mind)
|
||||
GLOB.joined_player_list += player.ckey
|
||||
player.create_character(FALSE)
|
||||
@@ -353,8 +351,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
CHECK_TICK
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/collect_minds()
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/P = i
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/P = i
|
||||
if(P.new_character && P.new_character.mind)
|
||||
SSticker.minds += P.new_character.mind
|
||||
CHECK_TICK
|
||||
@@ -362,8 +360,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/equip_characters()
|
||||
var/captainless=1
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/N = i
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/N = i
|
||||
var/mob/living/carbon/human/player = N.new_character
|
||||
if(istype(player) && player.mind && player.mind.assigned_role)
|
||||
if(player.mind.assigned_role == "Captain")
|
||||
@@ -374,16 +372,16 @@ SUBSYSTEM_DEF(ticker)
|
||||
SSquirks.AssignQuirks(N.new_character, N.client, TRUE)
|
||||
CHECK_TICK
|
||||
if(captainless)
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/N = i
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/N = i
|
||||
if(N.new_character)
|
||||
to_chat(N, "<span class='notice'>Captainship not forced on anyone.</span>")
|
||||
CHECK_TICK
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/transfer_characters()
|
||||
var/list/livings = list()
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
var/mob/living = player.transfer_character()
|
||||
if(living)
|
||||
qdel(player)
|
||||
@@ -449,17 +447,9 @@ SUBSYSTEM_DEF(ticker)
|
||||
queue_delay = 0
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/check_maprotate()
|
||||
if (!CONFIG_GET(flag/maprotation))
|
||||
if(!CONFIG_GET(flag/maprotation))
|
||||
return
|
||||
if (SSshuttle.emergency && SSshuttle.emergency.mode != SHUTTLE_ESCAPE || SSshuttle.canRecall())
|
||||
return
|
||||
if (maprotatechecked)
|
||||
return
|
||||
|
||||
maprotatechecked = 1
|
||||
|
||||
//map rotate chance defaults to 75% of the length of the round (in minutes)
|
||||
if (!prob((world.time/600)*CONFIG_GET(number/maprotatechancedelta)))
|
||||
if(world.time - SSticker.round_start_time < 10 MINUTES) //Not forcing map rotation for very short rounds.
|
||||
return
|
||||
INVOKE_ASYNC(SSmapping, /datum/controller/subsystem/mapping/.proc/maprotate)
|
||||
|
||||
@@ -493,12 +483,10 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
queue_delay = SSticker.queue_delay
|
||||
queued_players = SSticker.queued_players
|
||||
maprotatechecked = SSticker.maprotatechecked
|
||||
round_start_time = SSticker.round_start_time
|
||||
|
||||
queue_delay = SSticker.queue_delay
|
||||
queued_players = SSticker.queued_players
|
||||
maprotatechecked = SSticker.maprotatechecked
|
||||
|
||||
switch (current_state)
|
||||
if(GAME_STATE_SETTING_UP)
|
||||
@@ -569,8 +557,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
|
||||
//Everyone who wanted to be an observer gets made one now
|
||||
/datum/controller/subsystem/ticker/proc/create_observers()
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
for(var/i in GLOB.new_player_list)
|
||||
var/mob/dead/new_player/player = i
|
||||
if(player.ready == PLAYER_READY_TO_OBSERVE && player.mind)
|
||||
//Break chain since this has a sleep input in it
|
||||
addtimer(CALLBACK(player, /mob/dead/new_player.proc/make_me_an_observer), 1)
|
||||
|
||||
@@ -74,14 +74,16 @@ SUBSYSTEM_DEF(vote)
|
||||
else if(mode == "map")
|
||||
for (var/non_voter_ckey in non_voters)
|
||||
var/client/C = non_voters[non_voter_ckey]
|
||||
if(C.prefs.preferred_map && choices[C.prefs.preferred_map]) //No votes if the map isnt in the vote.
|
||||
var/preferred_map = C.prefs.preferred_map
|
||||
choices[preferred_map] += 1
|
||||
greatest_votes = max(greatest_votes, choices[preferred_map])
|
||||
else if(config.defaultmap && choices[config.defaultmap]) //No votes if the map isnt in the vote.
|
||||
var/default_map = config.defaultmap.map_name
|
||||
choices[default_map] += 1
|
||||
greatest_votes = max(greatest_votes, choices[default_map])
|
||||
if(C.prefs.preferred_map)
|
||||
if(choices[C.prefs.preferred_map]) //No votes if the map isnt in the vote.
|
||||
var/preferred_map = C.prefs.preferred_map
|
||||
choices[preferred_map] += 1
|
||||
greatest_votes = max(greatest_votes, choices[preferred_map])
|
||||
else if(config.defaultmap)
|
||||
if(choices[config.defaultmap]) //No votes if the map isnt in the vote.
|
||||
var/default_map = config.defaultmap.map_name
|
||||
choices[default_map] += 1
|
||||
greatest_votes = max(greatest_votes, choices[default_map])
|
||||
//get all options with that many votes and return them in a list
|
||||
. = list()
|
||||
if(greatest_votes)
|
||||
@@ -163,6 +165,9 @@ SUBSYSTEM_DEF(vote)
|
||||
return FALSE
|
||||
|
||||
/datum/controller/subsystem/vote/proc/initiate_vote(vote_type, initiator_key)
|
||||
if(!Master.current_runlevel) //Server is still intializing.
|
||||
to_chat(usr, "<span class='warning'>Cannot start vote, server is not done initializing.</span>")
|
||||
return FALSE
|
||||
var/admin = FALSE
|
||||
var/ckey = ckey(initiator_key)
|
||||
if(GLOB.admin_datums[ckey])
|
||||
@@ -192,13 +197,7 @@ SUBSYSTEM_DEF(vote)
|
||||
return FALSE
|
||||
for(var/map in config.maplist)
|
||||
var/datum/map_config/VM = config.maplist[map]
|
||||
var/run = 0
|
||||
if(VM.map_name == SSmapping.config.map_name)
|
||||
run++
|
||||
for(var/name in SSpersistence.saved_maps)
|
||||
if(VM.map_name == name)
|
||||
run++
|
||||
if(run >= 2 || !VM.votable) //If run twice in the last three (including current) as of time of writing, disable map for voting.
|
||||
if(!VM.votable || (VM.map_name in SSpersistence.blocked_maps))
|
||||
continue
|
||||
choices.Add(VM.map_name)
|
||||
if("custom")
|
||||
|
||||
@@ -199,14 +199,16 @@
|
||||
var/list/new_message = list()
|
||||
|
||||
for(var/word in message_split)
|
||||
var/suffix = copytext(word,-1)
|
||||
|
||||
// Check if we have a suffix and break it out of the word
|
||||
if(suffix in list("." , "," , ";" , "!" , ":" , "?"))
|
||||
word = copytext(word,1,-1)
|
||||
else
|
||||
suffix = ""
|
||||
var/suffix = ""
|
||||
var/suffix_foundon = 0
|
||||
for(var/potential_suffix in list("." , "," , ";" , "!" , ":" , "?"))
|
||||
suffix_foundon = findtext(word, potential_suffix, -length(potential_suffix))
|
||||
if(suffix_foundon)
|
||||
suffix = potential_suffix
|
||||
break
|
||||
|
||||
if(suffix_foundon)
|
||||
word = copytext(word, 1, suffix_foundon)
|
||||
word = html_decode(word)
|
||||
|
||||
if(lowertext(word) in common_words)
|
||||
@@ -216,10 +218,10 @@
|
||||
new_message += pick("uh","erm")
|
||||
break
|
||||
else
|
||||
var/list/charlist = string2charlist(word) // Stupid shit code
|
||||
var/list/charlist = text2charlist(word)
|
||||
charlist.len = round(charlist.len * 0.5, 1)
|
||||
shuffle_inplace(charlist)
|
||||
charlist.len = round(charlist.len * 0.5,1)
|
||||
new_message += html_encode(jointext(charlist,"")) + suffix
|
||||
new_message += jointext(charlist, "") + suffix
|
||||
|
||||
message = jointext(new_message, " ")
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@
|
||||
SetSpread(DISEASE_SPREAD_CONTACT_FLUIDS)
|
||||
else
|
||||
SetSpread(DISEASE_SPREAD_BLOOD)
|
||||
|
||||
|
||||
permeability_mod = max(CEILING(0.4 * properties["transmittable"], 1), 1)
|
||||
cure_chance = 15 - CLAMP(properties["resistance"], -5, 5) // can be between 10 and 20
|
||||
stage_prob = max(properties["stage_rate"], 2)
|
||||
@@ -419,7 +419,7 @@
|
||||
|
||||
// Should be only 1 entry left, but if not let's only return a single entry
|
||||
var/datum/disease/advance/to_return = pick(diseases)
|
||||
to_return.Refresh(1)
|
||||
to_return.Refresh(TRUE)
|
||||
return to_return
|
||||
|
||||
/proc/SetViruses(datum/reagent/R, list/data)
|
||||
@@ -464,8 +464,9 @@
|
||||
var/new_name = stripped_input(user, "Name your new disease.", "New Name")
|
||||
if(!new_name)
|
||||
return
|
||||
D.AssignName(new_name)
|
||||
D.Refresh()
|
||||
D.AssignName(new_name) //Updates the master copy
|
||||
D.name = new_name //Updates our copy
|
||||
|
||||
var/list/targets = list("Random")
|
||||
targets += sortNames(GLOB.human_list)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*! Material datum
|
||||
|
||||
Simple datum which is instanced once per type and is used for every object of said material. It has a variety of variables that define behavior. Subtyping from this makes it easier to create your own materials.
|
||||
Simple datum which is instanced once per type and is used for every object of said material. It has a variety of variables that define behavior. Subtyping from this makes it easier to create your own materials.
|
||||
|
||||
*/
|
||||
|
||||
@@ -27,7 +27,7 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
///Armor modifiers, multiplies an items normal armor vars by these amounts.
|
||||
var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
|
||||
///How beautiful is this material per unit
|
||||
var/beauty_modifier = 0
|
||||
var/beauty_modifier = 0
|
||||
|
||||
///This proc is called when the material is added to an object.
|
||||
/datum/material/proc/on_applied(atom/source, amount, material_flags)
|
||||
@@ -48,20 +48,21 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force *= strength_modifier
|
||||
o.throwforce *= strength_modifier
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force *= strength_modifier
|
||||
o.throwforce *= strength_modifier
|
||||
|
||||
var/list/temp_armor_list = list() //Time to add armor modifiers!
|
||||
var/list/temp_armor_list = list() //Time to add armor modifiers!
|
||||
|
||||
if(!istype(o.armor))
|
||||
return
|
||||
var/list/current_armor = o.armor?.getList()
|
||||
if(!istype(o.armor))
|
||||
return
|
||||
var/list/current_armor = o.armor?.getList()
|
||||
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
@@ -72,13 +73,14 @@ Simple datum which is instanced once per type and is used for every object of sa
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = initial(source.name)
|
||||
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, material_flags)
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
if(material_flags & MATERIAL_AFFECT_STATISTICS)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
|
||||
+3
-3
@@ -153,10 +153,10 @@
|
||||
else
|
||||
to_chat(current, "<span class='warning'>I feel like I've become worse at [S.name]!</span>")
|
||||
|
||||
///Gets the skill's singleton and returns the result of its get_skill_speed_modifier
|
||||
/datum/mind/proc/get_skill_speed_modifier(skill)
|
||||
///Gets the skill's singleton and returns the result of its get_skill_modifier
|
||||
/datum/mind/proc/get_skill_modifier(skill, modifier)
|
||||
var/datum/skill/S = GetSkillRef(skill)
|
||||
return S.get_skill_speed_modifier(known_skills[S] || SKILL_LEVEL_NONE)
|
||||
return S.get_skill_modifier(modifier, known_skills[S] || SKILL_LEVEL_NONE)
|
||||
|
||||
/datum/mind/proc/get_skill_level(skill)
|
||||
var/datum/skill/S = GetSkillRef(skill)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/datum/skill
|
||||
var/name = "Skill"
|
||||
var/desc = "the art of doing things"
|
||||
var/modifiers = list(SKILL_SPEED_MODIFIER = list(1, 1, 1, 1, 1, 1, 1)) //Dictionary of modifier type - list of modifiers (indexed by level). 7 entries in each list for all 7 skill levels.
|
||||
|
||||
/datum/skill/proc/get_skill_speed_modifier(level)
|
||||
return
|
||||
/datum/skill/proc/get_skill_modifier(modifier, level)
|
||||
return modifiers[modifier][level+1] //+1 because lists start at 1
|
||||
|
||||
@@ -1,20 +1,4 @@
|
||||
/datum/skill/medical
|
||||
name = "Medical"
|
||||
desc = "From Bandaids to biopsies, this improves your ability to get people back up both in the field and on the operating table."
|
||||
|
||||
/datum/skill/medical/get_skill_speed_modifier(level)
|
||||
switch(level)
|
||||
if(SKILL_LEVEL_NONE)
|
||||
return 1
|
||||
if(SKILL_LEVEL_NOVICE)
|
||||
return 0.95
|
||||
if(SKILL_LEVEL_APPRENTICE)
|
||||
return 0.9
|
||||
if(SKILL_LEVEL_JOURNEYMAN)
|
||||
return 0.85
|
||||
if(SKILL_LEVEL_EXPERT)
|
||||
return 0.75
|
||||
if(SKILL_LEVEL_MASTER)
|
||||
return 0.6
|
||||
if(SKILL_LEVEL_LEGENDARY)
|
||||
return 0.5
|
||||
modifiers = list(SKILL_SPEED_MODIFIER = list(1, 0.95, 0.9, 0.85, 0.75, 0.6, 0.5))
|
||||
|
||||
@@ -1,20 +1,4 @@
|
||||
/datum/skill/mining
|
||||
name = "Mining"
|
||||
desc = "A dwarf's biggest skill, after drinking."
|
||||
|
||||
/datum/skill/mining/get_skill_speed_modifier(level)
|
||||
switch(level)
|
||||
if(SKILL_LEVEL_NONE)
|
||||
return 1
|
||||
if(SKILL_LEVEL_NOVICE)
|
||||
return 0.95
|
||||
if(SKILL_LEVEL_APPRENTICE)
|
||||
return 0.9
|
||||
if(SKILL_LEVEL_JOURNEYMAN)
|
||||
return 0.85
|
||||
if(SKILL_LEVEL_EXPERT)
|
||||
return 0.75
|
||||
if(SKILL_LEVEL_MASTER)
|
||||
return 0.65
|
||||
if(SKILL_LEVEL_LEGENDARY)
|
||||
return 0.5
|
||||
modifiers = list(SKILL_SPEED_MODIFIER = list(1, 0.95, 0.9, 0.85, 0.75, 0.6, 0.5))
|
||||
|
||||
@@ -129,8 +129,39 @@
|
||||
/datum/quirk/phobia/post_add()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
H.gain_trauma(new /datum/brain_trauma/mild/phobia(H.client.prefs.phobia), TRAUMA_RESILIENCE_ABSOLUTE)
|
||||
|
||||
|
||||
/datum/quirk/phobia/remove()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
if(H)
|
||||
H.cure_trauma_type(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_ABSOLUTE)
|
||||
|
||||
/datum/quirk/needswayfinder
|
||||
name = "Navigationally Challenged"
|
||||
desc = "Lacking familiarity with certain stations, you start with a wayfinding pinpointer where available."
|
||||
value = 0
|
||||
medical_record_text = "Patient demonstrates a keen ability to get lost."
|
||||
|
||||
var/obj/item/pinpointer/wayfinding/wayfinder
|
||||
var/where
|
||||
|
||||
/datum/quirk/needswayfinder/on_spawn()
|
||||
if(!GLOB.wayfindingbeacons.len)
|
||||
return
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
|
||||
wayfinder = new /obj/item/pinpointer/wayfinding
|
||||
var/list/slots = list(
|
||||
"in your left pocket" = ITEM_SLOT_LPOCKET,
|
||||
"in your right pocket" = ITEM_SLOT_RPOCKET,
|
||||
"in your backpack" = ITEM_SLOT_BACKPACK
|
||||
)
|
||||
where = H.equip_in_one_of_slots(wayfinder, slots, FALSE) || "at your feet"
|
||||
|
||||
/datum/quirk/needswayfinder/post_add()
|
||||
if(!GLOB.wayfindingbeacons.len)
|
||||
return
|
||||
if(where == "in your backpack")
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
|
||||
|
||||
to_chat(quirk_holder, "<span class='notice'>There is a pinpointer [where], which can help you find your way around. Click in-hand to activate.</span>")
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/wires/proc/is_dud(wire)
|
||||
return dd_hasprefix(wire, WIRE_DUD_PREFIX)
|
||||
return findtext(wire, WIRE_DUD_PREFIX, 1, length(WIRE_DUD_PREFIX) + 1)
|
||||
|
||||
/datum/wires/proc/is_dud_color(color)
|
||||
return is_dud(get_wire(color))
|
||||
|
||||
@@ -433,7 +433,7 @@
|
||||
var/dat = ""
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
var/timeleft = SSshuttle.emergency.timeLeft()
|
||||
dat += "<B>Emergency shuttle</B>\n<BR>\nETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
dat += "<B>Emergency shuttle</B>\n<BR>\nETA: [timeleft / 60 % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]"
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500)
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
if(timing)
|
||||
var/disp1 = id
|
||||
var/time_left = time_left(seconds = TRUE)
|
||||
var/disp2 = "[add_zero(num2text((time_left / 60) % 60),2)]:[add_zero(num2text(time_left % 60), 2)]"
|
||||
var/disp2 = "[add_leading(num2text((time_left / 60) % 60), 2, "0")]:[add_leading(num2text(time_left % 60), 2, "0")]"
|
||||
if(length(disp2) > CHARS_PER_LINE)
|
||||
disp2 = "Error"
|
||||
update_display(disp1, disp2)
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "navbeacon0-f"
|
||||
name = "navigation beacon"
|
||||
desc = "A radio beacon used for bot navigation."
|
||||
desc = "A radio beacon used for bot navigation and crew wayfinding."
|
||||
level = 1 // underfloor
|
||||
layer = LOW_OBJ_LAYER
|
||||
max_integrity = 500
|
||||
@@ -18,28 +18,31 @@
|
||||
var/location = "" // location response text
|
||||
var/list/codes // assoc. list of transponder codes
|
||||
var/codes_txt = "" // codes as set on map: "tag1;tag2" or "tag1=value;tag2=value"
|
||||
var/wayfinding = FALSE
|
||||
|
||||
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
|
||||
|
||||
/obj/machinery/navbeacon/Initialize()
|
||||
. = ..()
|
||||
|
||||
if(wayfinding)
|
||||
if(!location)
|
||||
var/obj/machinery/door/airlock/A = locate(/obj/machinery/door/airlock) in loc
|
||||
if(A)
|
||||
location = A.name
|
||||
else
|
||||
location = get_area(src)
|
||||
codes_txt += "wayfinding=[location]"
|
||||
|
||||
set_codes()
|
||||
|
||||
var/turf/T = loc
|
||||
hide(T.intact)
|
||||
if(codes["patrol"])
|
||||
if(!GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] = list()
|
||||
GLOB.navbeacons["[z]"] += src //Register with the patrol list!
|
||||
if(codes["delivery"])
|
||||
GLOB.deliverybeacons += src
|
||||
GLOB.deliverybeacontags += location
|
||||
|
||||
glob_lists_register(init=TRUE)
|
||||
|
||||
/obj/machinery/navbeacon/Destroy()
|
||||
if (GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] -= src //Remove from beacon list, if in one.
|
||||
GLOB.deliverybeacons -= src
|
||||
glob_lists_deregister()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/navbeacon/onTransitZ(old_z, new_z)
|
||||
@@ -67,6 +70,25 @@
|
||||
else
|
||||
codes[e] = "1"
|
||||
|
||||
/obj/machinery/navbeacon/proc/glob_lists_deregister()
|
||||
if (GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] -= src //Remove from beacon list, if in one.
|
||||
GLOB.deliverybeacons -= src
|
||||
GLOB.deliverybeacontags -= location
|
||||
GLOB.wayfindingbeacons -= src
|
||||
|
||||
/obj/machinery/navbeacon/proc/glob_lists_register(var/init=FALSE)
|
||||
if(!init)
|
||||
glob_lists_deregister()
|
||||
if(codes["patrol"])
|
||||
if(!GLOB.navbeacons["[z]"])
|
||||
GLOB.navbeacons["[z]"] = list()
|
||||
GLOB.navbeacons["[z]"] += src //Register with the patrol list!
|
||||
if(codes["delivery"])
|
||||
GLOB.deliverybeacons += src
|
||||
GLOB.deliverybeacontags += location
|
||||
if(codes["wayfinding"])
|
||||
GLOB.wayfindingbeacons += src
|
||||
|
||||
// called when turf state changes
|
||||
// hide the object if turf is intact
|
||||
@@ -170,6 +192,7 @@ Transponder Codes:<UL>"}
|
||||
var/newloc = copytext(sanitize(input("Enter New Location", "Navigation Beacon", location) as text|null),1,MAX_MESSAGE_LEN)
|
||||
if(newloc)
|
||||
location = newloc
|
||||
glob_lists_register()
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["edit"])
|
||||
@@ -187,12 +210,14 @@ Transponder Codes:<UL>"}
|
||||
|
||||
codes.Remove(codekey)
|
||||
codes[newkey] = newval
|
||||
glob_lists_register()
|
||||
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["delete"])
|
||||
var/codekey = href_list["code"]
|
||||
codes.Remove(codekey)
|
||||
glob_lists_register()
|
||||
updateDialog()
|
||||
|
||||
else if(href_list["add"])
|
||||
@@ -210,5 +235,6 @@ Transponder Codes:<UL>"}
|
||||
codes = new()
|
||||
|
||||
codes[newkey] = newval
|
||||
glob_lists_register()
|
||||
|
||||
updateDialog()
|
||||
|
||||
@@ -399,7 +399,7 @@
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
|
||||
var/output = ..()
|
||||
if(output)
|
||||
return "[output] \[[fuel]: [round(fuel.amount*fuel.mats_per_stack,0.1)] cm<sup>3</sup>\] - <a href='?src=[REF(src)];toggle=1'>[equip_ready?"A":"Dea"]ctivate</a>"
|
||||
return "[output] \[[fuel]: [round(fuel.amount*MINERAL_MATERIAL_AMOUNT,0.1)] cm<sup>3</sup>\] - <a href='?src=[REF(src)];toggle=1'>[equip_ready?"A":"Dea"]ctivate</a>"
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/action(target)
|
||||
if(chassis)
|
||||
@@ -409,9 +409,9 @@
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P)
|
||||
if(P.type == fuel.type && P.amount > 0)
|
||||
var/to_load = max(max_fuel - fuel.amount*fuel.mats_per_stack,0)
|
||||
var/to_load = max(max_fuel - fuel.amount*MINERAL_MATERIAL_AMOUNT,0)
|
||||
if(to_load)
|
||||
var/units = min(max(round(to_load / P.mats_per_stack),1),P.amount)
|
||||
var/units = min(max(round(to_load / MINERAL_MATERIAL_AMOUNT),1),P.amount)
|
||||
fuel.amount += units
|
||||
P.use(units)
|
||||
occupant_message("<span class='notice'>[units] unit\s of [fuel] successfully loaded.</span>")
|
||||
@@ -447,7 +447,7 @@
|
||||
if(cur_charge < chassis.cell.maxcharge)
|
||||
use_fuel = fuel_per_cycle_active
|
||||
chassis.give_power(power_per_cycle)
|
||||
fuel.amount -= min(use_fuel/fuel.mats_per_stack,fuel.amount)
|
||||
fuel.amount -= min(use_fuel/MINERAL_MATERIAL_AMOUNT,fuel.amount)
|
||||
update_equip_info()
|
||||
return 1
|
||||
|
||||
|
||||
+25
-29
@@ -944,17 +944,15 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/mecha/proc/mmi_move_inside(obj/item/mmi/mmi_as_oc, mob/user)
|
||||
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
|
||||
to_chat(user, "<span class='warning'>Consciousness matrix not detected!</span>")
|
||||
/obj/mecha/proc/mmi_move_inside(obj/item/mmi/M, mob/user)
|
||||
if(!M.brain_check(user))
|
||||
return FALSE
|
||||
else if(mmi_as_oc.brainmob.stat)
|
||||
to_chat(user, "<span class='warning'>Beta-rhythm below acceptable level!</span>")
|
||||
return FALSE
|
||||
else if(occupant)
|
||||
|
||||
var/mob/living/brain/B = M.brainmob
|
||||
if(occupant)
|
||||
to_chat(user, "<span class='warning'>Occupant detected!</span>")
|
||||
return FALSE
|
||||
else if(dna_lock && (!mmi_as_oc.brainmob.stored_dna || (dna_lock != mmi_as_oc.brainmob.stored_dna.unique_enzymes)))
|
||||
if(dna_lock && (!B.stored_dna || (dna_lock != B.stored_dna.unique_enzymes)))
|
||||
to_chat(user, "<span class='warning'>Access denied. [name] is secured with a DNA lock.</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -962,42 +960,40 @@
|
||||
|
||||
if(do_after(user, 40, target = src))
|
||||
if(!occupant)
|
||||
return mmi_moved_inside(mmi_as_oc, user)
|
||||
return mmi_moved_inside(M, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Occupant detected!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You stop inserting the MMI.</span>")
|
||||
return FALSE
|
||||
|
||||
/obj/mecha/proc/mmi_moved_inside(obj/item/mmi/mmi_as_oc, mob/user)
|
||||
if(!(Adjacent(mmi_as_oc) && Adjacent(user)))
|
||||
/obj/mecha/proc/mmi_moved_inside(obj/item/mmi/M, mob/user)
|
||||
if(!(Adjacent(M) && Adjacent(user)))
|
||||
return FALSE
|
||||
if(!mmi_as_oc.brainmob || !mmi_as_oc.brainmob.client)
|
||||
to_chat(user, "<span class='notice'>Consciousness matrix not detected!</span>")
|
||||
if(!M.brain_check(user))
|
||||
return FALSE
|
||||
else if(mmi_as_oc.brainmob.stat)
|
||||
to_chat(user, "<span class='warning'>Beta-rhythm below acceptable level!</span>")
|
||||
|
||||
var/mob/living/brain/B = M.brainmob
|
||||
if(!user.transferItemToLoc(M, src))
|
||||
to_chat(user, "<span class='warning'>\the [M] is stuck to your hand, you cannot put it in \the [src]!</span>")
|
||||
return FALSE
|
||||
if(!user.transferItemToLoc(mmi_as_oc, src))
|
||||
to_chat(user, "<span class='warning'>\the [mmi_as_oc] is stuck to your hand, you cannot put it in \the [src]!</span>")
|
||||
return FALSE
|
||||
var/mob/living/brainmob = mmi_as_oc.brainmob
|
||||
mmi_as_oc.mecha = src
|
||||
occupant = brainmob
|
||||
|
||||
M.mecha = src
|
||||
occupant = B
|
||||
silicon_pilot = TRUE
|
||||
brainmob.forceMove(src) //should allow relaymove
|
||||
brainmob.reset_perspective(src)
|
||||
brainmob.remote_control = src
|
||||
brainmob.update_mobility()
|
||||
brainmob.update_mouse_pointer()
|
||||
B.forceMove(src) //should allow relaymove
|
||||
B.reset_perspective(src)
|
||||
B.remote_control = src
|
||||
B.update_mobility()
|
||||
B.update_mouse_pointer()
|
||||
icon_state = initial(icon_state)
|
||||
update_icon()
|
||||
setDir(dir_in)
|
||||
log_message("[mmi_as_oc] moved in as pilot.", LOG_MECHA)
|
||||
log_message("[M] moved in as pilot.", LOG_MECHA)
|
||||
if(!internal_damage)
|
||||
SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
|
||||
GrantActions(brainmob)
|
||||
log_game("[key_name(user)] has put the MMI/posibrain of [key_name(brainmob)] into [src] at [AREACOORD(src)]")
|
||||
GrantActions(B)
|
||||
log_game("[key_name(user)] has put the MMI/posibrain of [key_name(B)] into [src] at [AREACOORD(src)]")
|
||||
return TRUE
|
||||
|
||||
/obj/mecha/container_resist(mob/living/user)
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
hud.remove_hud_from(L)
|
||||
..()
|
||||
|
||||
/obj/mecha/medical/odysseus/mmi_moved_inside(obj/item/mmi/mmi_as_oc, mob/user)
|
||||
/obj/mecha/medical/odysseus/mmi_moved_inside(obj/item/mmi/M, mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/datum/atom_hud/hud = GLOB.huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
var/mob/living/brain/B = mmi_as_oc.brainmob
|
||||
var/mob/living/brain/B = M.brainmob
|
||||
hud.add_hud_to(B)
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/spread_foam()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
for(var/turf/T in t_loc.reachableAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam!
|
||||
if(foundfoam)
|
||||
continue
|
||||
@@ -238,7 +238,7 @@
|
||||
|
||||
amount = round(sqrt(amt / 2), 1)
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
if(metaltype != 0)
|
||||
if(metaltype)
|
||||
metal = metaltype
|
||||
|
||||
/datum/effect_system/foam_spread/start()
|
||||
|
||||
@@ -765,7 +765,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
|
||||
if(tool_behaviour == TOOL_MINING && ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
skill_modifier = H.mind.get_skill_speed_modifier(/datum/skill/mining)
|
||||
skill_modifier = H.mind.get_skill_modifier(/datum/skill/mining, SKILL_SPEED_MODIFIER)
|
||||
|
||||
delay *= toolspeed * skill_modifier
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ RLD
|
||||
icon_state = "rcd"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
custom_price = 1700
|
||||
custom_premium_price = 1700
|
||||
max_matter = 160
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
|
||||
|
||||
@@ -405,8 +405,8 @@ update_label()
|
||||
if (isnull(input_text))
|
||||
return
|
||||
|
||||
var/t = copytext(sanitize(input_text), 1, 26)
|
||||
if(!t || t == "Unknown" || t == "floor" || t == "wall" || t == "r-wall") //Same as mob/dead/new_player/prefrences.dm
|
||||
var/target_name = copytext(sanitize(input_text), 1, 26)
|
||||
if(!target_name || target_name == "Unknown" || target_name == "floor" || target_name == "wall" || target_name == "r-wall") //Same as mob/dead/new_player/preferences.dm
|
||||
if (ishuman(user))
|
||||
var/mob/living/carbon/human/human_agent = user
|
||||
|
||||
@@ -421,17 +421,17 @@ update_label()
|
||||
alert ("Invalid name.")
|
||||
return
|
||||
else
|
||||
registered_name = t
|
||||
registered_name = target_name
|
||||
|
||||
var/u = copytext(sanitize(input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", assignment ? assignment : "Assistant") as text | null),1,MAX_MESSAGE_LEN)
|
||||
if(!u)
|
||||
var/target_occupation = copytext(sanitize(input(user, "What occupation would you like to put on this card?\nNote: This will not grant any access levels other than Maintenance.", "Agent card job assignment", assignment ? assignment : "Assistant") as text | null),1,MAX_MESSAGE_LEN)
|
||||
if(!target_occupation)
|
||||
registered_name = ""
|
||||
return
|
||||
assignment = u
|
||||
assignment = target_occupation
|
||||
update_label()
|
||||
forged = TRUE
|
||||
to_chat(user, "<span class='notice'>You successfully forge the ID card.</span>")
|
||||
|
||||
log_game("[key_name(user)] has forged \the [initial(name)] with name \"[registered_name]\" and occupation \"[assignment]\".")
|
||||
|
||||
// First time use automatically sets the account id to the user.
|
||||
if (first_use && !registered_account)
|
||||
@@ -448,6 +448,7 @@ update_label()
|
||||
else if (popup_input == "Forge/Reset" && forged)
|
||||
registered_name = initial(registered_name)
|
||||
assignment = initial(assignment)
|
||||
log_game("[key_name(user)] has reset \the [initial(name)] named \"[src]\" to default.")
|
||||
update_label()
|
||||
forged = FALSE
|
||||
to_chat(user, "<span class='notice'>You successfully reset the ID card.</span>")
|
||||
|
||||
@@ -306,10 +306,14 @@ Code:
|
||||
|
||||
var/list/S = list(" Off","AOff"," On", " AOn")
|
||||
var/list/chg = list("N","C","F")
|
||||
|
||||
//Neither copytext nor copytext_char is appropriate here; neither 30 UTF-8 code units nor 30 code points equates to 30 columns of output.
|
||||
//Some glyphs are very tall or very wide while others are small or even take up no space at all.
|
||||
//Emojis can take modifiers which are many characters but render as only one glyph.
|
||||
//A proper solution here (as far as Unicode goes, maybe not ideal as far as markup goes, a table would be better)
|
||||
//would be to use <span style="width: NNNpx; overflow: none;">[A.area.name]</span>
|
||||
for(var/obj/machinery/power/apc/A in L)
|
||||
menu += copytext(add_tspace(A.area.name, 30), 1, 30)
|
||||
menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(DisplayPower(A.lastused_total), 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]<BR>"
|
||||
menu += copytext_char(add_trailing(A.area.name, 30, " "), 1, 30)
|
||||
menu += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_leading(DisplayPower(A.lastused_total), 6, " ")] [A.cell ? "[add_leading(round(A.cell.percent()), 3, " ")]% [chg[A.charging+1]]" : " N/C"]<BR>"
|
||||
|
||||
menu += "</FONT></PRE>"
|
||||
|
||||
|
||||
@@ -243,39 +243,20 @@
|
||||
if(!isturf(loc))
|
||||
to_chat(user, "<span class='warning'>You can't put [M] in, the frame has to be standing on the ground to be perfectly precise!</span>")
|
||||
return
|
||||
if(!M.brainmob)
|
||||
to_chat(user, "<span class='warning'>Sticking an empty [M.name] into the frame would sort of defeat the purpose!</span>")
|
||||
if(!M.brain_check(user))
|
||||
return
|
||||
|
||||
var/mob/living/brain/BM = M.brainmob
|
||||
if(!BM.key || !BM.mind)
|
||||
to_chat(user, "<span class='warning'>The MMI indicates that their mind is completely unresponsive; there's no point!</span>")
|
||||
return
|
||||
|
||||
if(!BM.client) //braindead
|
||||
to_chat(user, "<span class='warning'>The MMI indicates that their mind is currently inactive; it might change!</span>")
|
||||
return
|
||||
|
||||
if(BM.stat == DEAD || BM.suiciding || (M.brain && (M.brain.brain_death || M.brain.suicided)))
|
||||
to_chat(user, "<span class='warning'>Sticking a dead brain into the frame would sort of defeat the purpose!</span>")
|
||||
return
|
||||
|
||||
if(M.brain?.organ_flags & ORGAN_FAILING)
|
||||
to_chat(user, "<span class='warning'>The MMI indicates that the brain is damaged!</span>")
|
||||
return
|
||||
|
||||
if(is_banned_from(BM.ckey, "Cyborg") || QDELETED(src) || QDELETED(BM) || QDELETED(user) || QDELETED(M) || !Adjacent(user))
|
||||
var/mob/living/brain/B = M.brainmob
|
||||
if(is_banned_from(B.ckey, "Cyborg") || QDELETED(src) || QDELETED(B) || QDELETED(user) || QDELETED(M) || !Adjacent(user))
|
||||
if(!QDELETED(M))
|
||||
to_chat(user, "<span class='warning'>This [M.name] does not seem to fit!</span>")
|
||||
return
|
||||
|
||||
if(!user.temporarilyRemoveItemFromInventory(W))
|
||||
return
|
||||
|
||||
var/mob/living/silicon/robot/O = new /mob/living/silicon/robot/nocell(get_turf(loc))
|
||||
if(!O)
|
||||
return
|
||||
|
||||
if(M.laws && M.laws.id != DEFAULT_AI_LAWID)
|
||||
aisync = 0
|
||||
lawsync = 0
|
||||
@@ -298,7 +279,7 @@
|
||||
if(M.laws.id == DEFAULT_AI_LAWID)
|
||||
O.make_laws()
|
||||
|
||||
SSticker.mode.remove_antag_for_borging(BM.mind)
|
||||
SSticker.mode.remove_antag_for_borging(B.mind)
|
||||
O.job = "Cyborg"
|
||||
|
||||
O.cell = chest.cell
|
||||
@@ -309,9 +290,9 @@
|
||||
qdel(O.mmi)
|
||||
O.mmi = W //and give the real mmi to the borg.
|
||||
|
||||
O.updatename(BM.client)
|
||||
O.updatename(B.client)
|
||||
|
||||
BM.mind.transfer_to(O)
|
||||
B.mind.transfer_to(O)
|
||||
|
||||
if(O.mind && O.mind.special_role)
|
||||
O.mind.store_memory("As a cyborg, you must obey your silicon laws and master AI above all else. Your objectives will consider you to be dead.")
|
||||
@@ -355,7 +336,6 @@
|
||||
O.lawupdate = FALSE
|
||||
O.make_laws()
|
||||
|
||||
|
||||
O.cell = chest.cell
|
||||
chest.cell.forceMove(O)
|
||||
chest.cell = null
|
||||
|
||||
@@ -58,10 +58,10 @@
|
||||
user.visible_message("<span class='green'>[user] applies \the [src] on [C]'s [affecting.name].</span>", "<span class='green'>You apply \the [src] on [C]'s [affecting.name].</span>")
|
||||
var/brute2heal = brute
|
||||
var/burn2heal = burn
|
||||
if(user?.mind?.get_skill_speed_modifier(/datum/skill/medical))
|
||||
var/skillmods = user.mind.get_skill_speed_modifier(/datum/skill/medical)
|
||||
brute2heal *= (2-skillmods)
|
||||
burn2heal *= (2-skillmods)
|
||||
var/skill_mod = user?.mind?.get_skill_modifier(/datum/skill/medical, SKILL_SPEED_MODIFIER)
|
||||
if(skill_mod)
|
||||
brute2heal *= (2-skill_mod)
|
||||
burn2heal *= (2-skill_mod)
|
||||
if(affecting.heal_damage(brute2heal, burn2heal))
|
||||
C.update_damage_overlays()
|
||||
return TRUE
|
||||
|
||||
@@ -18,7 +18,6 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
custom_materials = list(/datum/material/iron=1000)
|
||||
mats_per_stack = 1000
|
||||
max_amount = 50
|
||||
attack_verb = list("hit", "bludgeoned", "whacked")
|
||||
hitsound = 'sound/weapons/gun/general/grenade_launch.ogg'
|
||||
@@ -35,7 +34,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
|
||||
/obj/item/stack/rods/get_main_recipes()
|
||||
. = ..()
|
||||
. += GLOB.rod_recipes
|
||||
|
||||
|
||||
/obj/item/stack/rods/update_icon()
|
||||
var/amount = get_amount()
|
||||
if((amount <= 5) && (amount > 0))
|
||||
|
||||
@@ -182,7 +182,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
|
||||
singular_name = "reinforced plasma glass sheet"
|
||||
icon_state = "sheet-prglass"
|
||||
item_state = "sheet-prglass"
|
||||
custom_materials = list(/datum/material/plasma=MINERAL_MATERIAL_AMOUNT * 0.5, /datum/material/glass=MINERAL_MATERIAL_AMOUNT, /datum/material/iron = MINERAL_MATERIAL_AMOUNT * 0.5,)
|
||||
custom_materials = list(/datum/material/plasma=MINERAL_MATERIAL_AMOUNT * 0.5, /datum/material/glass=MINERAL_MATERIAL_AMOUNT, /datum/material/iron = MINERAL_MATERIAL_AMOUNT * 0.5)
|
||||
armor = list("melee" = 20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 100)
|
||||
resistance_flags = ACID_PROOF
|
||||
material_flags = MATERIAL_NO_EFFECTS
|
||||
|
||||
@@ -247,7 +247,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \
|
||||
. = ..()
|
||||
. += GLOB.silver_recipes
|
||||
|
||||
/*
|
||||
/*
|
||||
* Clown
|
||||
*/
|
||||
/obj/item/stack/sheet/mineral/bananium
|
||||
@@ -272,8 +272,8 @@ GLOBAL_LIST_INIT(bananium_recipes, list ( \
|
||||
. = ..()
|
||||
. += GLOB.bananium_recipes
|
||||
|
||||
/*
|
||||
* Titanium
|
||||
/*
|
||||
* Titanium
|
||||
*/
|
||||
/obj/item/stack/sheet/mineral/titanium
|
||||
name = "titanium"
|
||||
@@ -333,7 +333,7 @@ GLOBAL_LIST_INIT(plastitanium_recipes, list ( \
|
||||
/*
|
||||
* Snow
|
||||
*/
|
||||
|
||||
|
||||
/obj/item/stack/sheet/mineral/snow
|
||||
name = "snow"
|
||||
icon_state = "sheet-snow"
|
||||
|
||||
@@ -156,7 +156,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
|
||||
desc = "This sheet is an alloy of iron and plasma."
|
||||
icon_state = "sheet-plasteel"
|
||||
item_state = "sheet-metal"
|
||||
custom_materials = list(/datum/material/iron=2000, /datum/material/plasma=2000)
|
||||
custom_materials = list(/datum/material/iron=MINERAL_MATERIAL_AMOUNT, /datum/material/plasma=MINERAL_MATERIAL_AMOUNT)
|
||||
throwforce = 10
|
||||
flags_1 = CONDUCT_1
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80)
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
throw_range = 3
|
||||
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed")
|
||||
novariants = FALSE
|
||||
mats_per_stack = MINERAL_MATERIAL_AMOUNT
|
||||
var/sheettype = null //this is used for girders in the creation of walls/false walls
|
||||
var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity.
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
var/merge_type = null // This path and its children should merge with this stack, defaults to src.type
|
||||
var/full_w_class = WEIGHT_CLASS_NORMAL //The weight class the stack should have at amount > 2/3rds max_amount
|
||||
var/novariants = TRUE //Determines whether the item should update it's sprites based on amount.
|
||||
var/mats_per_stack = 0
|
||||
var/list/mats_per_unit //list that tells you how much is in a single unit.
|
||||
///Datum material type that this stack is made of
|
||||
var/material_type
|
||||
//NOTE: When adding grind_results, the amounts should be for an INDIVIDUAL ITEM - these amounts will be multiplied by the stack size in on_grind()
|
||||
@@ -49,8 +49,11 @@
|
||||
if(!merge_type)
|
||||
merge_type = type
|
||||
if(custom_materials && custom_materials.len)
|
||||
mats_per_unit = list()
|
||||
var/in_process_mat_list = custom_materials.Copy()
|
||||
for(var/i in custom_materials)
|
||||
custom_materials[getmaterialref(i)] = mats_per_stack * amount
|
||||
mats_per_unit[getmaterialref(i)] = in_process_mat_list[i]
|
||||
custom_materials[i] *= amount
|
||||
. = ..()
|
||||
if(merge)
|
||||
for(var/obj/item/stack/S in loc)
|
||||
@@ -315,8 +318,8 @@
|
||||
amount -= used
|
||||
if(check)
|
||||
zero_amount()
|
||||
for(var/i in custom_materials)
|
||||
custom_materials[i] = amount * mats_per_stack
|
||||
for(var/i in mats_per_unit)
|
||||
custom_materials[i] = amount * mats_per_unit[i]
|
||||
update_icon()
|
||||
update_weight()
|
||||
return TRUE
|
||||
@@ -348,9 +351,9 @@
|
||||
source.add_charge(amount * cost)
|
||||
else
|
||||
src.amount += amount
|
||||
if(custom_materials && custom_materials.len)
|
||||
for(var/i in custom_materials)
|
||||
custom_materials[getmaterialref(i)] = MINERAL_MATERIAL_AMOUNT * src.amount
|
||||
if(mats_per_unit && mats_per_unit.len)
|
||||
for(var/i in mats_per_unit)
|
||||
custom_materials[i] = mats_per_unit[i] * src.amount
|
||||
set_custom_materials() //Refresh
|
||||
update_icon()
|
||||
update_weight()
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
max_amount = 60
|
||||
mats_per_stack = 500
|
||||
var/turf_type = null
|
||||
var/mineralType = null
|
||||
novariants = TRUE
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
ion_trail.start()
|
||||
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/move_react)
|
||||
if(full_speed)
|
||||
user.add_movespeed_modifier(MOVESPEED_ID_JETPACK, priority=100, multiplicative_slowdown=-0.25, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
|
||||
user.add_movespeed_modifier(MOVESPEED_ID_JETPACK, priority=100, multiplicative_slowdown=-0.5, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
|
||||
|
||||
/obj/item/tank/jetpack/proc/turn_off(mob/user)
|
||||
on = FALSE
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/obj/machinery/pinpointer_dispenser
|
||||
name = "wayfinding pinpointer dispenser"
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "ticketmachine"
|
||||
desc = "Having trouble finding your way? This machine dispenses pinpointers that point to common locations."
|
||||
density = FALSE
|
||||
layer = HIGH_OBJ_LAYER
|
||||
var/list/obj/item/pinpointer/wayfinding/pinpointers = list()
|
||||
var/spawn_cooldown = 1200 //deciseconds per person to spawn another pinpointer
|
||||
|
||||
/obj/machinery/pinpointer_dispenser/attack_hand(mob/living/carbon/user)
|
||||
if(world.time < pinpointers[user.real_name])
|
||||
var/secsleft = (pinpointers[user.real_name] - world.time) / 10
|
||||
to_chat(user, "<span class='warning'>You need to wait [secsleft/60 > 1 ? "[round(secsleft/60)] minute\s" : "[round(secsleft)] second\s"].</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You take a pinpointer from [src].</span>")
|
||||
|
||||
var/obj/item/pinpointer/wayfinding/P = new /obj/item/pinpointer/wayfinding(get_turf(src))
|
||||
user.put_in_hands(P)
|
||||
P.owner = user.real_name
|
||||
pinpointers[user.real_name] = world.time + spawn_cooldown
|
||||
|
||||
/obj/item/pinpointer/wayfinding //For new players or new stations to help players find their way around
|
||||
name = "wayfinding pinpointer"
|
||||
desc = "A handheld tracking device that points to useful places."
|
||||
icon_state = "pinpointer_crew"
|
||||
var/owner = null
|
||||
var/list/beacons = list()
|
||||
|
||||
/obj/item/pinpointer/wayfinding/attack_self(mob/living/user)
|
||||
if(active)
|
||||
toggle_on()
|
||||
to_chat(user, "<span class='notice'>You deactivate your pinpointer.</span>")
|
||||
return
|
||||
|
||||
if (!owner)
|
||||
owner = user.real_name
|
||||
|
||||
if(beacons.len)
|
||||
beacons.Cut()
|
||||
for(var/obj/machinery/navbeacon/B in GLOB.wayfindingbeacons)
|
||||
beacons[B.codes["wayfinding"]] = B
|
||||
|
||||
if(!beacons.len)
|
||||
to_chat(user, "<span class='notice'>Your pinpointer fails to detect a signal.</span>")
|
||||
return
|
||||
|
||||
var/A = input(user, "", "Pinpoint") as null|anything in sortList(beacons)
|
||||
if(!A || QDELETED(src) || !user || !user.is_holding(src) || user.incapacitated())
|
||||
return
|
||||
|
||||
target = beacons[A]
|
||||
toggle_on()
|
||||
to_chat(user, "<span class='notice'>You activate your pinpointer.</span>")
|
||||
|
||||
/obj/item/pinpointer/wayfinding/examine(mob/user)
|
||||
. = ..()
|
||||
var/msg = "Its tracking indicator reads "
|
||||
if(target)
|
||||
var/obj/machinery/navbeacon/wayfinding/B = target
|
||||
msg += "\"[B.codes["wayfinding"]]\"."
|
||||
else
|
||||
msg = "Its tracking indicator is blank."
|
||||
if(owner)
|
||||
msg += " It belongs to [owner]."
|
||||
. += msg
|
||||
|
||||
/obj/item/pinpointer/wayfinding/scan_for_target()
|
||||
if(!target) //target can be set to null from above code, or elsewhere
|
||||
active = FALSE
|
||||
|
||||
/obj/machinery/navbeacon/wayfinding
|
||||
wayfinding = TRUE
|
||||
|
||||
@@ -185,26 +185,14 @@
|
||||
|
||||
if(istype(P, /obj/item/mmi) && !brain)
|
||||
var/obj/item/mmi/M = P
|
||||
if(!M.brainmob)
|
||||
to_chat(user, "<span class='warning'>Sticking an empty [M.name] into the frame would sort of defeat the purpose!</span>")
|
||||
return
|
||||
if(M.brainmob.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>Sticking a dead [M.name] into the frame would sort of defeat the purpose!</span>")
|
||||
if(!M.brain_check(user))
|
||||
return
|
||||
|
||||
if(!M.brainmob.client)
|
||||
to_chat(user, "<span class='warning'>Sticking an inactive [M.name] into the frame would sort of defeat the purpose.</span>")
|
||||
return
|
||||
|
||||
if(!CONFIG_GET(flag/allow_ai) || (is_banned_from(M.brainmob.ckey, "AI") && !QDELETED(src) && !QDELETED(user) && !QDELETED(M) && !QDELETED(user) && Adjacent(user)))
|
||||
var/mob/living/brain/B = M.brainmob
|
||||
if(!CONFIG_GET(flag/allow_ai) || (is_banned_from(B.ckey, "AI") && !QDELETED(src) && !QDELETED(user) && !QDELETED(M) && !QDELETED(user) && Adjacent(user)))
|
||||
if(!QDELETED(M))
|
||||
to_chat(user, "<span class='warning'>This [M.name] does not seem to fit!</span>")
|
||||
return
|
||||
|
||||
if(!M.brainmob.mind)
|
||||
to_chat(user, "<span class='warning'>This [M.name] is mindless!</span>")
|
||||
return
|
||||
|
||||
if(!user.transferItemToLoc(M,src))
|
||||
return
|
||||
|
||||
@@ -234,14 +222,15 @@
|
||||
P.play_tool_sound(src)
|
||||
to_chat(user, "<span class='notice'>You connect the monitor.</span>")
|
||||
if(brain)
|
||||
SSticker.mode.remove_antag_for_borging(brain.brainmob.mind)
|
||||
var/mob/living/brain/B = brain.brainmob
|
||||
SSticker.mode.remove_antag_for_borging(B.mind)
|
||||
|
||||
var/mob/living/silicon/ai/A = null
|
||||
|
||||
if (brain.overrides_aicore_laws)
|
||||
A = new /mob/living/silicon/ai(loc, brain.laws, brain.brainmob)
|
||||
A = new /mob/living/silicon/ai(loc, brain.laws, B)
|
||||
else
|
||||
A = new /mob/living/silicon/ai(loc, laws, brain.brainmob)
|
||||
A = new /mob/living/silicon/ai(loc, laws, B)
|
||||
|
||||
if(brain.force_replace_ai_name)
|
||||
A.fully_replace_character_name(A.name, brain.replacement_ai_name())
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
|
||||
///Material chair
|
||||
/obj/structure/chair/greyscale
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
item_chair = /obj/item/chair/greyscale
|
||||
buildstacktype = null //Custom mats handle this
|
||||
|
||||
@@ -340,7 +340,7 @@
|
||||
smash(user)
|
||||
|
||||
/obj/item/chair/greyscale
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
origin_type = /obj/structure/chair/greyscale
|
||||
|
||||
/obj/item/chair/stool
|
||||
|
||||
@@ -24,6 +24,12 @@
|
||||
if(BURN)
|
||||
playsound(loc, 'sound/items/welder.ogg', 80, TRUE)
|
||||
|
||||
/obj/structure/sign/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.examinate(src)
|
||||
|
||||
/obj/structure/sign/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_WRENCH && buildable_sign)
|
||||
user.visible_message("<span class='notice'>[user] starts removing [src]...</span>", \
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
desc = "A sign labelling an area containing chemical equipment."
|
||||
icon_state = "chemistry1"
|
||||
|
||||
/obj/structure/sign/departments/chemistry/pharmacy
|
||||
name = "\improper PHARMACY"
|
||||
desc = "A sign labelling an area containing pharmacy equipment."
|
||||
icon_state = "pharmacy"
|
||||
|
||||
/obj/structure/sign/departments/botany
|
||||
name = "\improper HYDROPONICS"
|
||||
desc = "A sign labelling an area as a place where plants are grown."
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
/obj/structure/sign/warning/testchamber
|
||||
name = "\improper TESTING AREA"
|
||||
desc = "A sign that warns of high power testing equipment in the area. That's either a really powerful laser... or a satellite landing on some person's head."
|
||||
desc = "A sign that warns of high-power testing equipment in the area. That's either a really powerful laser... or a satellite landing on some person's head."
|
||||
icon_state = "testchamber"
|
||||
|
||||
/obj/structure/sign/warning/firingrange
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
/obj/structure/sign/warning/gasmask
|
||||
name = "\improper CONTAMINATED AIR"
|
||||
desc = "A sign that warns of dangerous particulates in the air, instructing you to wear a filtration device.."
|
||||
desc = "A sign that warns of dangerous particulates in the air, instructing you to wear a filtration device."
|
||||
icon_state = "gasmask"
|
||||
|
||||
/obj/structure/sign/warning/chemdiamond
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
make_new_table(material.tableVariant)
|
||||
else
|
||||
if(material.get_amount() < 1)
|
||||
to_chat(user, "<span class='warning'>You need one metal sheet to do this!</span>")
|
||||
to_chat(user, "<span class='warning'>You need one sheet to do this!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start adding [material] to [src]...</span>")
|
||||
if(do_after(user, 20, target = src) && material.use(1))
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
/obj/structure/table/greyscale
|
||||
icon = 'icons/obj/smooth_structures/table_greyscale.dmi'
|
||||
icon_state = "table"
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
buildstack = null //No buildstack, so generate from mat datums
|
||||
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
contents += secret
|
||||
|
||||
/obj/structure/toilet/greyscale
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
buildstacktype = null
|
||||
|
||||
/obj/structure/urinal
|
||||
@@ -398,7 +398,7 @@
|
||||
|
||||
/obj/structure/sink/greyscale
|
||||
icon_state = "sink_greyscale"
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
buildstacktype = null
|
||||
|
||||
//Shower Curtains//
|
||||
|
||||
@@ -122,7 +122,10 @@
|
||||
baseturfs = /turf/open/lava/smooth/lava_land_surface
|
||||
|
||||
|
||||
|
||||
/turf/open/floor/plating/asteroid/lowpressure
|
||||
initial_gas_mix = OPENTURF_LOW_PRESSURE
|
||||
baseturfs = /turf/open/floor/plating/asteroid/lowpressure
|
||||
turf_type = /turf/open/floor/plating/asteroid/lowpressure
|
||||
|
||||
/turf/open/floor/plating/asteroid/airless
|
||||
initial_gas_mix = AIRLESS_ATMOS
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
icon_state = "plating"
|
||||
initial_gas_mix = AIRLESS_ATMOS
|
||||
|
||||
/turf/open/floor/plating/lowpressure
|
||||
initial_gas_mix = OPENTURF_LOW_PRESSURE
|
||||
baseturfs = /turf/open/floor/plating/lowpressure
|
||||
|
||||
/turf/open/floor/plating/abductor
|
||||
name = "alien floor"
|
||||
icon_state = "alienpod1"
|
||||
|
||||
@@ -151,10 +151,10 @@
|
||||
else
|
||||
var/timeleft = SSshuttle.emergency.timeLeft()
|
||||
if(SSshuttle.emergency.mode == SHUTTLE_CALL)
|
||||
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
|
||||
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]</a><BR>"
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];call_shuttle=2'>Send Back</a><br>"
|
||||
else
|
||||
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
|
||||
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_leading(num2text(timeleft % 60), 2, "0")]</a><BR>"
|
||||
dat += "<B>Continuous Round Status</B><BR>"
|
||||
dat += "<a href='?_src_=holder;[HrefToken()];toggle_continuous=1'>[CONFIG_GET(keyed_list/continuous)[SSticker.mode.config_tag] ? "Continue if antagonists die" : "End on antagonist death"]</a>"
|
||||
if(CONFIG_GET(keyed_list/continuous)[SSticker.mode.config_tag])
|
||||
|
||||
@@ -444,7 +444,7 @@
|
||||
var/datum/round_event_control/disease_outbreak/DC = locate(/datum/round_event_control/disease_outbreak) in SSevents.control
|
||||
E = DC.runEvent()
|
||||
if("Choose")
|
||||
var/virus = input("Choose the virus to spread", "BIOHAZARD") as null|anything in sortList(typesof(/datum/disease, /proc/cmp_typepaths_asc))
|
||||
var/virus = input("Choose the virus to spread", "BIOHAZARD") as null|anything in sortList(typesof(/datum/disease), /proc/cmp_typepaths_asc)
|
||||
var/datum/round_event_control/disease_outbreak/DC = locate(/datum/round_event_control/disease_outbreak) in SSevents.control
|
||||
var/datum/round_event/disease_outbreak/DO = DC.runEvent()
|
||||
DO.virus_type = virus
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] is forcing a random map rotation.")
|
||||
log_admin("[key_name(usr)] is forcing a random map rotation.")
|
||||
SSticker.maprotatechecked = 1
|
||||
SSmapping.maprotate()
|
||||
|
||||
/client/proc/adminchangemap()
|
||||
@@ -36,8 +35,7 @@
|
||||
var/chosenmap = input("Choose a map to change to", "Change Map") as null|anything in sortList(maprotatechoices)|"Custom"
|
||||
if (!chosenmap)
|
||||
return
|
||||
|
||||
SSticker.maprotatechecked = 1
|
||||
|
||||
if(chosenmap == "Custom")
|
||||
message_admins("[key_name_admin(usr)] is changing the map to a custom map")
|
||||
log_admin("[key_name(usr)] is changing the map to a custom map")
|
||||
@@ -46,29 +44,29 @@
|
||||
VM.map_name = input("Choose the name for the map", "Map Name") as null|text
|
||||
if(isnull(VM.map_name))
|
||||
VM.map_name = "Custom"
|
||||
|
||||
|
||||
var/map_file = input("Pick file:", "Map File") as null|file
|
||||
if(isnull(map_file))
|
||||
return
|
||||
|
||||
|
||||
if(copytext("[map_file]",-4) != ".dmm")
|
||||
to_chat(src, "<span class='warning'>Filename must end in '.dmm': [map_file]</span>")
|
||||
return
|
||||
|
||||
if(!fcopy(map_file, "_maps/custom/[map_file]"))
|
||||
return
|
||||
|
||||
|
||||
// This is to make sure the map works so the server does not start without a map.
|
||||
var/datum/parsed_map/M = new (map_file)
|
||||
if(!M)
|
||||
to_chat(src, "<span class='warning'>Map '[map_file]' failed to parse properly.</span>")
|
||||
return
|
||||
|
||||
|
||||
if(!M.bounds)
|
||||
to_chat(src, "<span class='warning'>Map '[map_file]' has non-existant bounds.</span>")
|
||||
qdel(M)
|
||||
return
|
||||
|
||||
|
||||
qdel(M)
|
||||
|
||||
var/shuttles = alert("Do you want to modify the shuttles?", "Map Shuttles", "Yes", "No")
|
||||
|
||||
@@ -155,6 +155,14 @@
|
||||
var/give_flash = FALSE
|
||||
var/give_hud = TRUE
|
||||
|
||||
/datum/antagonist/rev/head/on_removal()
|
||||
if(give_hud)
|
||||
var/mob/living/carbon/C = owner.current
|
||||
var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = C.getorganslot(ORGAN_SLOT_HUD)
|
||||
if(S)
|
||||
S.Remove(C)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/rev/head/antag_listing_name()
|
||||
return ..() + "(Leader)"
|
||||
|
||||
@@ -227,27 +235,27 @@
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/rev/head/equip_rev()
|
||||
var/mob/living/carbon/H = owner.current
|
||||
if(!ishuman(H) && !ismonkey(H))
|
||||
var/mob/living/carbon/C = owner.current
|
||||
if(!ishuman(C) && !ismonkey(C))
|
||||
return
|
||||
|
||||
if(give_flash)
|
||||
var/obj/item/assembly/flash/T = new(H)
|
||||
var/obj/item/assembly/flash/T = new(C)
|
||||
var/list/slots = list (
|
||||
"backpack" = ITEM_SLOT_BACKPACK,
|
||||
"left pocket" = ITEM_SLOT_LPOCKET,
|
||||
"right pocket" = ITEM_SLOT_RPOCKET
|
||||
)
|
||||
var/where = H.equip_in_one_of_slots(T, slots)
|
||||
var/where = C.equip_in_one_of_slots(T, slots)
|
||||
if (!where)
|
||||
to_chat(H, "The Syndicate were unfortunately unable to get you a flash.")
|
||||
to_chat(C, "The Syndicate were unfortunately unable to get you a flash.")
|
||||
else
|
||||
to_chat(H, "The flash in your [where] will help you to persuade the crew to join your cause.")
|
||||
to_chat(C, "The flash in your [where] will help you to persuade the crew to join your cause.")
|
||||
|
||||
if(give_hud)
|
||||
var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = new(H)
|
||||
S.Insert(H, special = FALSE, drop_if_replaced = FALSE)
|
||||
to_chat(H, "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.")
|
||||
var/obj/item/organ/cyberimp/eyes/hud/security/syndicate/S = new()
|
||||
S.Insert(C)
|
||||
to_chat(C, "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.")
|
||||
|
||||
/datum/team/revolution
|
||||
name = "Revolution"
|
||||
|
||||
@@ -273,7 +273,7 @@
|
||||
icon_state = "knight_greyscale"
|
||||
item_state = "knight_greyscale"
|
||||
armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR//Can change color and add prefix
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS //Can change color and add prefix
|
||||
|
||||
/obj/item/clothing/head/helmet/skull
|
||||
name = "skull helmet"
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
desc = "A classic suit of armour, able to be made from many different materials."
|
||||
icon_state = "knight_greyscale"
|
||||
item_state = "knight_greyscale"
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR//Can change color and add prefix
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS//Can change color and add prefix
|
||||
armor = list("melee" = 35, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 10, "rad" = 10, "fire" = 40, "acid" = 40)
|
||||
|
||||
/obj/item/clothing/suit/armor/vest/durathread
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/datum/round_event/disease_outbreak/start()
|
||||
var/advanced_virus = FALSE
|
||||
max_severity = 3 + max(FLOOR((world.time - control.earliest_start)/6000, 1),0) //3 symptoms at 20 minutes, plus 1 per 10 minutes
|
||||
if(prob(20 + (10 * max_severity)))
|
||||
if(!virus_type && prob(20 + (10 * max_severity)))
|
||||
advanced_virus = TRUE
|
||||
|
||||
if(!virus_type && !advanced_virus)
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
else if(status == NOT_ENOUGH_PLAYERS)
|
||||
message_admins("[role_name] cannot be spawned due to lack of players \
|
||||
signing up.")
|
||||
deadchat_broadcast(" did not get enough candidates ([minimum_required]) to spawn.", "<b>[role_name]</b>")
|
||||
else if(status == SUCCESSFUL_SPAWN)
|
||||
message_admins("[role_name] spawned successfully.")
|
||||
if(spawned_mobs.len)
|
||||
|
||||
@@ -299,10 +299,14 @@
|
||||
|
||||
/datum/plant_gene/trait/glow/shadow
|
||||
//makes plant emit slightly purple shadows
|
||||
//adds -potency*(rate*0.2) light power to products
|
||||
name = "Shadow Emission"
|
||||
rate = 0.04
|
||||
glow_color = "#AAD84B"
|
||||
|
||||
/datum/plant_gene/trait/glow/shadow/glow_power(obj/item/seeds/S)
|
||||
return -max(S.potency*(rate*0.2), 0.2)
|
||||
|
||||
/datum/plant_gene/trait/glow/white
|
||||
name = "White Bioluminescence"
|
||||
glow_color = "#FFFFFF"
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
var/refined_type = null //What this ore defaults to being refined into
|
||||
var/mine_experience = 5 //How much experience do you get for mining this ore?
|
||||
novariants = TRUE // Ore stacks handle their icon updates themselves to keep the illusion that there's more going
|
||||
mats_per_stack = MINERAL_MATERIAL_AMOUNT
|
||||
var/list/stack_overlays
|
||||
|
||||
/obj/item/stack/ore/update_icon()
|
||||
@@ -323,7 +322,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
|
||||
throwforce = 2
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
custom_materials = list(/datum/material/iron = 400)
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR
|
||||
material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
||||
var/string_attached
|
||||
var/list/sideslist = list("heads","tails")
|
||||
var/cooldown = 0
|
||||
|
||||
@@ -85,7 +85,6 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/mmi/attack_self(mob/user)
|
||||
if(!brain)
|
||||
radio.on = !radio.on
|
||||
@@ -204,17 +203,43 @@
|
||||
if(brainmob)
|
||||
var/mob/living/brain/B = brainmob
|
||||
if(!B.key || !B.mind || B.stat == DEAD)
|
||||
. += "<span class='warning'>The MMI indicates the brain is completely unresponsive.</span>"
|
||||
|
||||
. += "<span class='warning'>\The [src] indicates that the brain is completely unresponsive.</span>"
|
||||
else if(!B.client)
|
||||
. += "<span class='warning'>The MMI indicates the brain is currently inactive; it might change.</span>"
|
||||
|
||||
. += "<span class='warning'>\The [src] indicates that the brain is currently inactive; it might change.</span>"
|
||||
else
|
||||
. += "<span class='notice'>The MMI indicates the brain is active.</span>"
|
||||
. += "<span class='notice'>\The [src] indicates that the brain is active.</span>"
|
||||
|
||||
/obj/item/mmi/relaymove(mob/user)
|
||||
return //so that the MMI won't get a warning about not being able to move if it tries to move
|
||||
|
||||
/obj/item/mmi/proc/brain_check(mob/user)
|
||||
var/mob/living/brain/B = brainmob
|
||||
if(!B)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [src] indicates that there is no brain present!</span>")
|
||||
return FALSE
|
||||
if(!B.key || !B.mind)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [src] indicates that their mind is completely unresponsive!</span>")
|
||||
return FALSE
|
||||
if(!B.client)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [src] indicates that their mind is currently inactive.</span>")
|
||||
return FALSE
|
||||
if(B.suiciding || brain?.suicided)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [src] indicates that their mind has no will to live!</span>")
|
||||
return FALSE
|
||||
if(B.stat == DEAD || brain?.brain_death)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [src] indicates that the brain is dead!</span>")
|
||||
return FALSE
|
||||
if(brain?.organ_flags & ORGAN_FAILING)
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>\The [src] indicates that the brain is damaged!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/mmi/syndie
|
||||
name = "\improper Syndicate Man-Machine Interface"
|
||||
desc = "Syndicate's own brand of MMI. It enforces laws designed to help Syndicate agents achieve their goals upon cyborgs and AIs created with it."
|
||||
|
||||
@@ -121,7 +121,8 @@ Des: Removes all infected images from the alien.
|
||||
/mob/living/carbon/alien/proc/RemoveInfectionImages()
|
||||
if (client)
|
||||
for(var/image/I in client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
var/searchfor = "infected"
|
||||
if(findtext(I.icon_state, searchfor, 1, length(searchfor) + 1))
|
||||
qdel(I)
|
||||
return
|
||||
|
||||
|
||||
@@ -129,5 +129,6 @@ Des: Removes all images from the mob infected by this embryo
|
||||
/obj/item/organ/body_egg/alien_embryo/RemoveInfectionImages()
|
||||
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
|
||||
for(var/image/I in alien.client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == owner)
|
||||
var/searchfor = "infected"
|
||||
if(I.loc == owner && findtext(I.icon_state, searchfor, 1, length(searchfor) + 1))
|
||||
qdel(I)
|
||||
|
||||
@@ -79,6 +79,18 @@
|
||||
else
|
||||
C.deconstruct()
|
||||
visible_message("<span class='warning'>[src] chews through the [C].</span>")
|
||||
for(var/obj/item/reagent_containers/food/snacks/cheesewedge/cheese in range(1, src))
|
||||
if(prob(10))
|
||||
var/cap = CONFIG_GET(number/ratcap)
|
||||
if(LAZYLEN(SSmobs.cheeserats) >= cap)
|
||||
visible_message("<span class='warning'>[src] carefully eats the cheese, hiding it from the [cap] mice on the station!</span>")
|
||||
qdel(cheese)
|
||||
return
|
||||
var/mob/living/newmouse = new /mob/living/simple_animal/mouse(loc)
|
||||
SSmobs.cheeserats += newmouse
|
||||
visible_message("<span class='notice'>[src] nibbles through the [cheese], attracting another mouse!</span>")
|
||||
qdel(cheese)
|
||||
return
|
||||
|
||||
/*
|
||||
* Mouse types
|
||||
@@ -96,6 +108,10 @@
|
||||
body_color = "brown"
|
||||
icon_state = "mouse_brown"
|
||||
|
||||
/mob/living/simple_animal/mouse/Destroy()
|
||||
SSmobs.cheeserats -= src
|
||||
return ..()
|
||||
|
||||
//TOM IS ALIVE! SQUEEEEEEEE~K :)
|
||||
/mob/living/simple_animal/mouse/brown/Tom
|
||||
name = "Tom"
|
||||
|
||||
@@ -363,7 +363,6 @@ All the important duct code:
|
||||
icon = 'icons/obj/plumbing/fluid_ducts.dmi'
|
||||
icon_state = "ducts"
|
||||
custom_materials = list(/datum/material/iron=500)
|
||||
mats_per_stack = 500
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
novariants = FALSE
|
||||
max_amount = 50
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
|
||||
#define FLOODLIGHT_OFF 1
|
||||
#define FLOODLIGHT_LOW 2
|
||||
#define FLOODLIGHT_MED 3
|
||||
#define FLOODLIGHT_HIGH 4
|
||||
|
||||
/obj/structure/floodlight_frame
|
||||
name = "floodlight frame"
|
||||
desc = "A bare metal frame looking vaguely like a floodlight. Requires wrenching down."
|
||||
desc = "A bare metal frame looking vaguely like a floodlight. Requires wiring."
|
||||
max_integrity = 100
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "floodlight_c1"
|
||||
density = TRUE
|
||||
var/state = FLOODLIGHT_NEEDS_WRENCHING
|
||||
var/state = FLOODLIGHT_NEEDS_WIRES
|
||||
|
||||
/obj/structure/floodlight_frame/attackby(obj/item/O, mob/user, params)
|
||||
if(O.tool_behaviour == TOOL_WRENCH && (state == FLOODLIGHT_NEEDS_WRENCHING))
|
||||
to_chat(user, "<span class='notice'>You secure [src].</span>")
|
||||
anchored = TRUE
|
||||
state = FLOODLIGHT_NEEDS_WIRES
|
||||
desc = "A bare metal frame looking vaguely like a floodlight. Requires wiring."
|
||||
else if(istype(O, /obj/item/stack/cable_coil) && (state == FLOODLIGHT_NEEDS_WIRES))
|
||||
if(istype(O, /obj/item/stack/cable_coil) && state == FLOODLIGHT_NEEDS_WIRES)
|
||||
var/obj/item/stack/S = O
|
||||
if(S.use(5))
|
||||
to_chat(user, "<span class='notice'>You wire [src].</span>")
|
||||
@@ -22,19 +22,36 @@
|
||||
desc = "A bare metal frame looking vaguely like a floodlight. Requires securing with a screwdriver."
|
||||
icon_state = "floodlight_c2"
|
||||
state = FLOODLIGHT_NEEDS_SECURING
|
||||
else if(istype(O, /obj/item/light/tube) && (state == FLOODLIGHT_NEEDS_LIGHTS))
|
||||
if(user.transferItemToLoc(O))
|
||||
to_chat(user, "<span class='notice'>You put lights in [src].</span>")
|
||||
new /obj/machinery/power/floodlight(src.loc)
|
||||
qdel(src)
|
||||
else if(O.tool_behaviour == TOOL_SCREWDRIVER && (state == FLOODLIGHT_NEEDS_SECURING))
|
||||
return
|
||||
else
|
||||
to_chat(user, "You need 5 cables to wire [src].")
|
||||
return
|
||||
if(O.tool_behaviour == TOOL_SCREWDRIVER && state == FLOODLIGHT_NEEDS_SECURING)
|
||||
to_chat(user, "<span class='notice'>You fasten the wiring and electronics in [src].</span>")
|
||||
name = "secured [name]"
|
||||
desc = "A bare metal frame that looks like a floodlight. Requires light tubes."
|
||||
desc = "A bare metal frame that looks like a floodlight. Requires a light tube to complete."
|
||||
icon_state = "floodlight_c3"
|
||||
state = FLOODLIGHT_NEEDS_LIGHTS
|
||||
else
|
||||
..()
|
||||
return
|
||||
if(istype(O, /obj/item/light/tube))
|
||||
var/obj/item/light/tube/L = O
|
||||
if(state == FLOODLIGHT_NEEDS_LIGHTS && L.status != 2) //Ready for a light tube, and not broken.
|
||||
to_chat(user, "<span class='notice'>You put lights in [src].</span>")
|
||||
new /obj/machinery/power/floodlight(loc)
|
||||
qdel(src)
|
||||
qdel(O)
|
||||
return
|
||||
else //A minute of silence for all the accidentally broken light tubes.
|
||||
return
|
||||
if(istype(O, /obj/item/lightreplacer))
|
||||
var/obj/item/lightreplacer/L = O
|
||||
if(state == FLOODLIGHT_NEEDS_LIGHTS && L.CanUse(user))
|
||||
L.Use(user)
|
||||
to_chat(user, "<span class='notice'>You put lights in [src].</span>")
|
||||
new /obj/machinery/power/floodlight(loc)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/power/floodlight
|
||||
name = "floodlight"
|
||||
@@ -46,31 +63,39 @@
|
||||
integrity_failure = 0.8
|
||||
idle_power_usage = 100
|
||||
active_power_usage = 1000
|
||||
var/list/light_setting_list = list(0, 5, 10, 15)
|
||||
var/light_power_coefficient = 300
|
||||
var/setting = 1
|
||||
anchored = FALSE
|
||||
light_power = 1.75
|
||||
var/list/light_setting_list = list(0, 5, 10, 15)
|
||||
var/light_power_coefficient = 200
|
||||
var/setting = FLOODLIGHT_OFF
|
||||
|
||||
/obj/machinery/power/floodlight/process()
|
||||
if(avail(active_power_usage))
|
||||
add_load(active_power_usage)
|
||||
else
|
||||
change_setting(1)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/structure/cable/C = locate() in T
|
||||
if(!C && powernet)
|
||||
disconnect_from_network()
|
||||
if(setting > FLOODLIGHT_OFF) //If on
|
||||
if(avail(active_power_usage))
|
||||
add_load(active_power_usage)
|
||||
else
|
||||
change_setting(FLOODLIGHT_OFF)
|
||||
else if(avail(idle_power_usage))
|
||||
add_load(idle_power_usage)
|
||||
|
||||
/obj/machinery/power/floodlight/proc/change_setting(val, mob/user)
|
||||
if((val < 1) || (val > light_setting_list.len))
|
||||
/obj/machinery/power/floodlight/proc/change_setting(newval, mob/user)
|
||||
if((newval < FLOODLIGHT_OFF) || (newval > light_setting_list.len))
|
||||
return
|
||||
active_power_usage = light_setting_list[val]
|
||||
if(!avail(active_power_usage))
|
||||
return change_setting(val - 1)
|
||||
setting = val
|
||||
set_light(light_setting_list[val])
|
||||
setting = newval
|
||||
active_power_usage = light_setting_list[setting] * light_power_coefficient
|
||||
if(!avail(active_power_usage) && setting > FLOODLIGHT_OFF)
|
||||
return change_setting(setting - 1)
|
||||
set_light(light_setting_list[setting], light_power)
|
||||
var/setting_text = ""
|
||||
if(val > 1)
|
||||
if(setting > FLOODLIGHT_OFF)
|
||||
icon_state = "[initial(icon_state)]_on"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
switch(val)
|
||||
switch(setting)
|
||||
if(1)
|
||||
setting_text = "OFF"
|
||||
if(2)
|
||||
|
||||
@@ -376,7 +376,7 @@
|
||||
|
||||
/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.75, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.35, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
|
||||
/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L)
|
||||
L.remove_movespeed_modifier(type)
|
||||
@@ -556,7 +556,7 @@
|
||||
/datum/reagent/consumable/monkey_energy/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
if(ismonkey(L))
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.75, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.35, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
|
||||
/datum/reagent/consumable/monkey_energy/on_mob_end_metabolize(mob/living/L)
|
||||
L.remove_movespeed_modifier(type)
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
|
||||
/datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.65, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
|
||||
/datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L)
|
||||
L.remove_movespeed_modifier(type)
|
||||
|
||||
@@ -422,7 +422,7 @@
|
||||
|
||||
/datum/reagent/medicine/ephedrine/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.85, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
ADD_TRAIT(L, TRAIT_STUNRESISTANCE, type)
|
||||
|
||||
/datum/reagent/medicine/ephedrine/on_mob_end_metabolize(mob/living/L)
|
||||
|
||||
@@ -391,9 +391,13 @@
|
||||
|
||||
if(MUTCOLORS in N.dna.species.species_traits) //take current alien color and darken it slightly
|
||||
var/newcolor = ""
|
||||
var/len = length(N.dna.features["mcolor"])
|
||||
for(var/i=1, i<=len, i+=1)
|
||||
var/ascii = text2ascii(N.dna.features["mcolor"],i)
|
||||
var/string = N.dna.features["mcolor"]
|
||||
var/len = length(string)
|
||||
var/char = ""
|
||||
var/ascii = 0
|
||||
for(var/i=1, i<=len, i += length(char))
|
||||
char = string[i]
|
||||
ascii = text2ascii(char)
|
||||
switch(ascii)
|
||||
if(48)
|
||||
newcolor += "0"
|
||||
@@ -404,7 +408,7 @@
|
||||
if(98 to 102)
|
||||
newcolor += ascii2text(ascii-1) //letters b to f lowercase
|
||||
if(65)
|
||||
newcolor +="9"
|
||||
newcolor += "9"
|
||||
if(66 to 70)
|
||||
newcolor += ascii2text(ascii+31) //letters B to F - translates to lowercase
|
||||
else
|
||||
@@ -1226,7 +1230,7 @@
|
||||
|
||||
/datum/reagent/nitryl/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.65, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
|
||||
/datum/reagent/nitryl/on_mob_end_metabolize(mob/living/L)
|
||||
L.remove_movespeed_modifier(type)
|
||||
@@ -2021,4 +2025,3 @@
|
||||
reagent_state = SOLID
|
||||
color = "#E6E6DA"
|
||||
taste_mult = 0
|
||||
|
||||
|
||||
@@ -209,13 +209,13 @@ Borg Shaker
|
||||
/datum/reagent/consumable/nothing, /datum/reagent/consumable/orangejuice, /datum/reagent/consumable/peachjuice,
|
||||
/datum/reagent/consumable/sodawater, /datum/reagent/consumable/space_cola, /datum/reagent/consumable/spacemountainwind,
|
||||
/datum/reagent/consumable/pwr_game, /datum/reagent/consumable/shamblers, /datum/reagent/consumable/soymilk,
|
||||
/datum/reagent/consumable/space_up, /datum/reagent/consumable/tea, /datum/reagent/consumable/tomatojuice,
|
||||
/datum/reagent/consumable/tonic, /datum/reagent/water,
|
||||
/datum/reagent/consumable/space_up, /datum/reagent/consumable/sugar, /datum/reagent/consumable/tea,
|
||||
/datum/reagent/consumable/tomatojuice, /datum/reagent/consumable/tonic, /datum/reagent/water,
|
||||
/datum/reagent/consumable/ethanol/ale, /datum/reagent/consumable/ethanol/applejack, /datum/reagent/consumable/ethanol/beer,
|
||||
/datum/reagent/consumable/ethanol/cognac, /datum/reagent/consumable/ethanol/creme_de_menthe,
|
||||
/datum/reagent/consumable/ethanol/champagne, /datum/reagent/consumable/ethanol/cognac, /datum/reagent/consumable/ethanol/creme_de_menthe,
|
||||
/datum/reagent/consumable/ethanol/creme_de_cacao, /datum/reagent/consumable/ethanol/gin, /datum/reagent/consumable/ethanol/kahlua,
|
||||
/datum/reagent/consumable/ethanol/rum, /datum/reagent/consumable/ethanol/sake, /datum/reagent/consumable/ethanol/tequila,
|
||||
/datum/reagent/consumable/ethanol/triple_sec, /datum/reagent/consumable/ethanol/vermouth,
|
||||
/datum/reagent/consumable/ethanol/triple_sec, /datum/reagent/consumable/ethanol/vermouth, /datum/reagent/consumable/ethanol/vodka,
|
||||
/datum/reagent/consumable/ethanol/whiskey, /datum/reagent/consumable/ethanol/wine)
|
||||
|
||||
/obj/item/reagent_containers/borghypo/borgshaker/attack(mob/M, mob/user)
|
||||
|
||||
@@ -210,11 +210,12 @@
|
||||
if(CLONE)
|
||||
damage_amt = host_mob.getCloneLoss()
|
||||
|
||||
if(damage_amt >= damage.get_value())
|
||||
if(check_above)
|
||||
if(check_above)
|
||||
if(damage_amt >= damage.get_value())
|
||||
reached_threshold = TRUE
|
||||
else
|
||||
if(damage_amt < damage.get_value())
|
||||
reached_threshold = TRUE
|
||||
else if(!check_above)
|
||||
reached_threshold = TRUE
|
||||
|
||||
if(reached_threshold)
|
||||
if(!spent)
|
||||
@@ -228,7 +229,9 @@
|
||||
/datum/nanite_program/sensor/damage/make_rule(datum/nanite_program/target)
|
||||
var/datum/nanite_rule/damage/rule = new(target)
|
||||
var/datum/nanite_extra_setting/direction = extra_settings[NES_DIRECTION]
|
||||
rule.above = direction.get_value()
|
||||
var/datum/nanite_extra_setting/damage_type = extra_settings[NES_DAMAGE_TYPE]
|
||||
var/datum/nanite_extra_setting/damage = extra_settings[NES_DAMAGE]
|
||||
rule.above = (direction == "Above")
|
||||
rule.threshold = damage
|
||||
rule.damage_type = damage_type
|
||||
return rule
|
||||
|
||||
@@ -133,11 +133,12 @@
|
||||
if(CLONE)
|
||||
damage_amt = program.host_mob.getCloneLoss()
|
||||
|
||||
if(damage_amt >= threshold)
|
||||
if(above)
|
||||
if(above)
|
||||
if(damage_amt >= threshold)
|
||||
return TRUE
|
||||
else
|
||||
if(damage_amt < threshold)
|
||||
return TRUE
|
||||
else if(!above)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/nanite_rule/damage/copy_to(datum/nanite_program/new_program)
|
||||
|
||||
@@ -684,7 +684,7 @@ datum/status_effect/stabilized/blue/on_remove()
|
||||
/datum/status_effect/stabilized/sepia/tick()
|
||||
if(prob(50) && mod > -1)
|
||||
mod--
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, override = TRUE, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_SEPIA, override = TRUE, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
else if(mod < 1)
|
||||
mod++
|
||||
// yeah a value of 0 does nothing but replacing the trait in place is cheaper than removing and adding repeatedly
|
||||
@@ -900,7 +900,7 @@ datum/status_effect/stabilized/blue/on_remove()
|
||||
colour = "light pink"
|
||||
|
||||
/datum/status_effect/stabilized/lightpink/on_apply()
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_SLIME_STATUS, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/stabilized/lightpink/tick()
|
||||
|
||||
@@ -368,6 +368,7 @@
|
||||
launch_status = ENDGAME_LAUNCHED
|
||||
setTimer(SSshuttle.emergencyEscapeTime * engine_coeff)
|
||||
priority_announce("The Emergency Shuttle has left the station. Estimate [timeLeft(600)] minutes until the shuttle docks at Central Command.", null, null, "Priority")
|
||||
SSmapping.mapvote() //If no map vote has been run yet, start one.
|
||||
|
||||
if(SHUTTLE_STRANDED)
|
||||
SSshuttle.checkHostileEnvironment()
|
||||
|
||||
@@ -686,7 +686,7 @@
|
||||
if(timeleft > 1 HOURS)
|
||||
return "--:--"
|
||||
else if(timeleft > 0)
|
||||
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
return "[add_leading(num2text((timeleft / 60) % 60), 2, "0")]:[add_leading(num2text(timeleft % 60), 2, " ")]"
|
||||
else
|
||||
return "00:00"
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
ADD_TRAIT(H, TRAIT_PIERCEIMMUNE, "dna_vault")
|
||||
if(VAULT_SPEED)
|
||||
to_chat(H, "<span class='notice'>Your legs feel faster.</span>")
|
||||
H.add_movespeed_modifier(MOVESPEED_ID_DNA_VAULT, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
H.add_movespeed_modifier(MOVESPEED_ID_DNA_VAULT, update=TRUE, priority=100, multiplicative_slowdown=-0.4, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
if(VAULT_QUICK)
|
||||
to_chat(H, "<span class='notice'>Your arms move as fast as lightning.</span>")
|
||||
H.next_move_modifier = 0.5
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
if(allow_thrust(0.01))
|
||||
ion_trail.start()
|
||||
RegisterSignal(owner, COMSIG_MOVABLE_MOVED, .proc/move_react)
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER, priority=100, multiplicative_slowdown=-2, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_CYBER_THRUSTER, priority=100, multiplicative_slowdown=-0.5, movetypes=FLOATING, conflict=MOVE_CONFLICT_JETPACK)
|
||||
if(!silent)
|
||||
to_chat(owner, "<span class='notice'>You turn your thrusters set on.</span>")
|
||||
else
|
||||
|
||||
@@ -188,17 +188,17 @@
|
||||
//Cut out the name so it doesn't trigger commands
|
||||
message = copytext(message, 0, start)+copytext(message, start + length(devilinfo.truename), length(message) + 1)
|
||||
break
|
||||
else if(dd_hasprefix(message, L.real_name))
|
||||
else if(findtext(message, L.real_name, 1, length(L.real_name) + 1))
|
||||
specific_listeners += L //focus on those with the specified name
|
||||
//Cut out the name so it doesn't trigger commands
|
||||
found_string = L.real_name
|
||||
|
||||
else if(dd_hasprefix(message, L.first_name()))
|
||||
else if(findtext(message, L.first_name(), 1, length(L.first_name()) + 1))
|
||||
specific_listeners += L //focus on those with the specified name
|
||||
//Cut out the name so it doesn't trigger commands
|
||||
found_string = L.first_name()
|
||||
|
||||
else if(L.mind && L.mind.assigned_role && dd_hasprefix(message, L.mind.assigned_role))
|
||||
else if(L.mind && L.mind.assigned_role && findtext(message, L.mind.assigned_role, 1, length(L.mind.assigned_role) + 1))
|
||||
specific_listeners += L //focus on those with the specified job
|
||||
//Cut out the job so it doesn't trigger commands
|
||||
found_string = L.mind.assigned_role
|
||||
|
||||
@@ -83,27 +83,39 @@
|
||||
|
||||
/proc/attempt_cancel_surgery(datum/surgery/S, obj/item/I, mob/living/M, mob/user)
|
||||
var/selected_zone = user.zone_selected
|
||||
|
||||
if(S.status == 1)
|
||||
M.surgeries -= S
|
||||
user.visible_message("<span class='notice'>[user] removes [I] from [M]'s [parse_zone(selected_zone)].</span>", \
|
||||
"<span class='notice'>You remove [I] from [M]'s [parse_zone(selected_zone)].</span>")
|
||||
qdel(S)
|
||||
else if(S.can_cancel)
|
||||
return
|
||||
|
||||
if(S.can_cancel)
|
||||
var/required_tool_type = TOOL_CAUTERY
|
||||
var/obj/item/close_tool = user.get_inactive_held_item()
|
||||
var/is_robotic = S.requires_bodypart_type == BODYPART_ROBOTIC
|
||||
|
||||
if(is_robotic)
|
||||
required_tool_type = TOOL_SCREWDRIVER
|
||||
if(close_tool && close_tool.tool_behaviour == required_tool_type || iscyborg(user))
|
||||
if (ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.bleed_rate = max( (H.bleed_rate - 3), 0)
|
||||
M.surgeries -= S
|
||||
user.visible_message("<span class='notice'>[user] closes [M]'s [parse_zone(selected_zone)] with [close_tool] and removes [I].</span>", \
|
||||
"<span class='notice'>You close [M]'s [parse_zone(selected_zone)] with [close_tool] and remove [I].</span>")
|
||||
qdel(S)
|
||||
else
|
||||
|
||||
if(iscyborg(user))
|
||||
close_tool = locate(/obj/item/cautery) in user.held_items
|
||||
if(!close_tool)
|
||||
to_chat(user, "<span class='warning'>You need to equip a cautery in an inactive slot to stop [M]'s surgery!</span>")
|
||||
return
|
||||
else if(!close_tool || close_tool.tool_behaviour != required_tool_type)
|
||||
to_chat(user, "<span class='warning'>You need to hold a [is_robotic ? "screwdriver" : "cautery"] in your inactive hand to stop [M]'s surgery!</span>")
|
||||
return
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.bleed_rate = max( (H.bleed_rate - 3), 0)
|
||||
M.surgeries -= S
|
||||
user.visible_message("<span class='notice'>[user] closes [M]'s [parse_zone(selected_zone)] with [close_tool] and removes [I].</span>", \
|
||||
"<span class='notice'>You close [M]'s [parse_zone(selected_zone)] with [close_tool] and remove [I].</span>")
|
||||
qdel(S)
|
||||
|
||||
|
||||
/proc/get_location_modifier(mob/M)
|
||||
var/turf/T = get_turf(M)
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
implement_speed_mod = implements[implement_type] / 100.0
|
||||
|
||||
speed_mod /= (get_location_modifier(target) * (1 + surgery.speed_modifier) * implement_speed_mod)
|
||||
var/modded_time = time * speed_mod * user.mind.get_skill_speed_modifier(/datum/skill/medical)
|
||||
var/modded_time = time * speed_mod * user.mind.get_skill_modifier(/datum/skill/medical, SKILL_SPEED_MODIFIER)
|
||||
|
||||
|
||||
fail_prob = min(max(0, modded_time - (time * SURGERY_SLOWDOWN_CAP_MULTIPLIER)),99)//if modded_time > time * modifier, then fail_prob = modded_time - time*modifier. starts at 0, caps at 99
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
products = list(/obj/item/clothing/glasses/meson/engine = 2,
|
||||
/obj/item/clothing/glasses/welding = 3,
|
||||
/obj/item/multitool = 4,
|
||||
/obj/item/construction/rcd/loaded = 3,
|
||||
/obj/item/grenade/chem_grenade/smart_metal_foam = 10,
|
||||
/obj/item/geiger_counter = 5,
|
||||
/obj/item/stock_parts/cell/high = 10,
|
||||
@@ -18,7 +17,8 @@
|
||||
/obj/item/electronics/firelock = 10)
|
||||
contraband = list(/obj/item/stock_parts/cell/potato = 3)
|
||||
premium = list(/obj/item/storage/belt/utility = 3,
|
||||
/obj/item/storage/box/smart_metal_foam = 1)
|
||||
/obj/item/construction/rcd/loaded = 2,
|
||||
/obj/item/storage/box/smart_metal_foam = 1)
|
||||
refill_canister = /obj/item/vending_refill/engivend
|
||||
default_price = 450
|
||||
extra_price = 500
|
||||
|
||||
Reference in New Issue
Block a user