Merge remote-tracking branch 'upstream/dev' into 150722-TagPairs

Conflicts:
	code/game/gamemodes/changeling/modularchangling.dm
This commit is contained in:
PsiOmegaDelta
2015-08-13 08:09:28 +02:00
319 changed files with 5837 additions and 4354 deletions
+1 -1
View File
@@ -23,7 +23,7 @@
/proc/ToRban_update()
spawn(0)
log_misc("Downloading updated ToR data...")
var/http[] = world.Export("http://exitlist.torproject.org/exit-addresses")
var/http[] = world.Export("https://check.torproject.org/exit-addresses")
var/list/rawlist = file2list(http["CONTENT"])
if(rawlist.len)
+1 -1
View File
@@ -1097,7 +1097,7 @@ proc/admin_notice(var/message, var/rights)
else
new chosen(usr.loc)
log_admin("[key_name(usr)] spawned [chosen] at ([usr.x],[usr.y],[usr.z])")
log_and_message_admins("spawned [chosen] at ([usr.x],[usr.y],[usr.z])")
feedback_add_details("admin_verb","SA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+4 -1
View File
@@ -83,10 +83,13 @@ var/list/admin_verbs_admin = list(
/client/proc/allow_character_respawn, /* Allows a ghost to respawn */
/client/proc/event_manager_panel,
/client/proc/empty_ai_core_toggle_latejoin,
/client/proc/empty_ai_core_toggle_latejoin,
/client/proc/aooc,
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
/client/proc/change_security_level
/client/proc/change_security_level,
/client/proc/view_chemical_reaction_logs,
/client/proc/makePAI
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
+141 -141
View File
@@ -1,147 +1,147 @@
//This stuff was originally intended to be integrated into the ban-system I was working on
//but it's safe to say that'll never be finished. So I've merged it into the current player panel.
//enjoy ~Carn
/*
#define NOTESFILE "data/player_notes.sav" //where the player notes are saved
datum/admins/proc/notes_show(var/ckey)
usr << browse("<head><title>Player Notes</title></head><body>[notes_gethtml(ckey)]</body>","window=player_notes;size=700x400")
datum/admins/proc/notes_gethtml(var/ckey)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return "<font color='red'>Error: Cannot access [NOTESFILE]</font>"
if(ckey)
. = "<b>Notes for <a href='?src=\ref[src];notes=show'>[ckey]</a>:</b> <a href='?src=\ref[src];notes=add;ckey=[ckey]'>\[+\]</a> <a href='?src=\ref[src];notes=remove;ckey=[ckey]'>\[-\]</a><br>"
notesfile.cd = "/[ckey]"
var/index = 1
while( !notesfile.eof )
var/note
notesfile >> note
. += "[note] <a href='?src=\ref[src];notes=remove;ckey=[ckey];from=[index]'>\[-\]</a><br>"
index++
else
. = "<b>All Notes:</b> <a href='?src=\ref[src];notes=add'>\[+\]</a> <a href='?src=\ref[src];notes=remove'>\[-\]</a><br>"
notesfile.cd = "/"
for(var/dir in notesfile.dir)
. += "<a href='?src=\ref[src];notes=show;ckey=[dir]'>[dir]</a><br>"
return
//handles removing entries from the buffer, or removing the entire directory if no start_index is given
/proc/notes_remove(var/ckey, var/start_index, var/end_index)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return
if(!ckey)
notesfile.cd = "/"
ckey = ckey(input(usr,"Who would you like to remove notes for?","Enter a ckey",null) as null|anything in notesfile.dir)
if(!ckey) return
if(start_index)
notesfile.cd = "/[ckey]"
var/list/noteslist = list()
if(!end_index) end_index = start_index
var/index = 0
while( !notesfile.eof )
index++
var/temp
notesfile >> temp
if( (start_index <= index) && (index <= end_index) )
continue
noteslist += temp
notesfile.eof = -2 //Move to the start of the buffer and then erase.
for( var/note in noteslist )
notesfile << note
else
notesfile.cd = "/"
if(alert(usr,"Are you sure you want to remove all their notes?","Confirmation","No","Yes - Remove all notes") == "Yes - Remove all notes")
notesfile.dir.Remove(ckey)
return
#undef NOTESFILE
*/
//Hijacking this file for BS12 playernotes functions. I like this ^ one systemm alright, but converting sounds too bothersome~ Chinsky.
//This stuff was originally intended to be integrated into the ban-system I was working on
//but it's safe to say that'll never be finished. So I've merged it into the current player panel.
//enjoy ~Carn
/*
#define NOTESFILE "data/player_notes.sav" //where the player notes are saved
datum/admins/proc/notes_show(var/ckey)
usr << browse("<head><title>Player Notes</title></head><body>[notes_gethtml(ckey)]</body>","window=player_notes;size=700x400")
datum/admins/proc/notes_gethtml(var/ckey)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return "<font color='red'>Error: Cannot access [NOTESFILE]</font>"
if(ckey)
. = "<b>Notes for <a href='?src=\ref[src];notes=show'>[ckey]</a>:</b> <a href='?src=\ref[src];notes=add;ckey=[ckey]'>\[+\]</a> <a href='?src=\ref[src];notes=remove;ckey=[ckey]'>\[-\]</a><br>"
notesfile.cd = "/[ckey]"
var/index = 1
while( !notesfile.eof )
var/note
notesfile >> note
. += "[note] <a href='?src=\ref[src];notes=remove;ckey=[ckey];from=[index]'>\[-\]</a><br>"
index++
else
. = "<b>All Notes:</b> <a href='?src=\ref[src];notes=add'>\[+\]</a> <a href='?src=\ref[src];notes=remove'>\[-\]</a><br>"
notesfile.cd = "/"
for(var/dir in notesfile.dir)
. += "<a href='?src=\ref[src];notes=show;ckey=[dir]'>[dir]</a><br>"
return
//handles removing entries from the buffer, or removing the entire directory if no start_index is given
/proc/notes_remove(var/ckey, var/start_index, var/end_index)
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile) return
if(!ckey)
notesfile.cd = "/"
ckey = ckey(input(usr,"Who would you like to remove notes for?","Enter a ckey",null) as null|anything in notesfile.dir)
if(!ckey) return
if(start_index)
notesfile.cd = "/[ckey]"
var/list/noteslist = list()
if(!end_index) end_index = start_index
var/index = 0
while( !notesfile.eof )
index++
var/temp
notesfile >> temp
if( (start_index <= index) && (index <= end_index) )
continue
noteslist += temp
notesfile.eof = -2 //Move to the start of the buffer and then erase.
for( var/note in noteslist )
notesfile << note
else
notesfile.cd = "/"
if(alert(usr,"Are you sure you want to remove all their notes?","Confirmation","No","Yes - Remove all notes") == "Yes - Remove all notes")
notesfile.dir.Remove(ckey)
return
#undef NOTESFILE
*/
//Hijacking this file for BS12 playernotes functions. I like this ^ one systemm alright, but converting sounds too bothersome~ Chinsky.
/proc/notes_add(var/key, var/note, var/mob/user)
if (!key || !note)
return
//Loading list of notes for this key
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos) infos = list()
//Overly complex timestamp creation
var/modifyer = "th"
switch(time2text(world.timeofday, "DD"))
if("01","21","31")
modifyer = "st"
if("02","22",)
modifyer = "nd"
if("03","23")
modifyer = "rd"
var/day_string = "[time2text(world.timeofday, "DD")][modifyer]"
if(copytext(day_string,1,2) == "0")
day_string = copytext(day_string,2)
var/full_date = time2text(world.timeofday, "DDD, Month DD of YYYY")
var/day_loc = findtext(full_date, time2text(world.timeofday, "DD"))
var/datum/player_info/P = new
if (!key || !note)
return
//Loading list of notes for this key
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos) infos = list()
//Overly complex timestamp creation
var/modifyer = "th"
switch(time2text(world.timeofday, "DD"))
if("01","21","31")
modifyer = "st"
if("02","22",)
modifyer = "nd"
if("03","23")
modifyer = "rd"
var/day_string = "[time2text(world.timeofday, "DD")][modifyer]"
if(copytext(day_string,1,2) == "0")
day_string = copytext(day_string,2)
var/full_date = time2text(world.timeofday, "DDD, Month DD of YYYY")
var/day_loc = findtext(full_date, time2text(world.timeofday, "DD"))
var/datum/player_info/P = new
if (user)
P.author = user.key
P.rank = user.client.holder.rank
else
P.author = "Adminbot"
P.rank = "Friendly Robot"
P.content = note
P.timestamp = "[copytext(full_date,1,day_loc)][day_string][copytext(full_date,day_loc+2)]"
infos += P
info << infos
else
P.author = "Adminbot"
P.rank = "Friendly Robot"
P.content = note
P.timestamp = "[copytext(full_date,1,day_loc)][day_string][copytext(full_date,day_loc+2)]"
infos += P
info << infos
message_admins("\blue [key_name_admin(user)] has edited [key]'s notes.")
log_admin("[key_name(user)] has edited [key]'s notes.")
qdel(info)
//Updating list of keys with notes on them
var/savefile/note_list = new("data/player_notes.sav")
var/list/note_keys
note_list >> note_keys
if(!note_keys) note_keys = list()
if(!note_keys.Find(key)) note_keys += key
note_list << note_keys
qdel(note_list)
/proc/notes_del(var/key, var/index)
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos || infos.len < index) return
var/datum/player_info/item = infos[index]
infos.Remove(item)
info << infos
message_admins("\blue [key_name_admin(usr)] deleted one of [key]'s notes.")
log_admin("[key_name(usr)] deleted one of [key]'s notes.")
qdel(info)
/proc/show_player_info_irc(var/key as text)
var/dat = " Info on [key]%0D%0A"
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos)
dat = "No information found on the given key."
else
for(var/datum/player_info/I in infos)
dat += "[I.content]%0D%0Aby [I.author] ([I.rank]) on [I.timestamp]%0D%0A%0D%0A"
return dat
qdel(info)
//Updating list of keys with notes on them
var/savefile/note_list = new("data/player_notes.sav")
var/list/note_keys
note_list >> note_keys
if(!note_keys) note_keys = list()
if(!note_keys.Find(key)) note_keys += key
note_list << note_keys
qdel(note_list)
/proc/notes_del(var/key, var/index)
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos || infos.len < index) return
var/datum/player_info/item = infos[index]
infos.Remove(item)
info << infos
message_admins("\blue [key_name_admin(usr)] deleted one of [key]'s notes.")
log_admin("[key_name(usr)] deleted one of [key]'s notes.")
qdel(info)
/proc/show_player_info_irc(var/key as text)
var/dat = " Info on [key]\n"
var/savefile/info = new("data/player_saves/[copytext(key, 1, 2)]/[key]/info.sav")
var/list/infos
info >> infos
if(!infos)
dat = "No information found on the given key."
else
for(var/datum/player_info/I in infos)
dat += "[I.content]\nby [I.author] ([I.rank]) on [I.timestamp]\n\n"
return list2params(list(dat))
+1 -1
View File
@@ -358,7 +358,7 @@
dat += "<td>NA</td>"
dat += {"<td>[(M.client ? "[M.client]" : "No client")]</td>
dat += {"<td>[M.key ? (M.client ? M.key : "[M.key] (DC)") : "No key"]</td>
<td align=center><A HREF='?src=\ref[src];adminplayeropts=\ref[M]'>X</A></td>
<td align=center><A href='?src=\ref[usr];priv_msg=\ref[M]'>PM</A></td>
"}
+1 -12
View File
@@ -1651,18 +1651,7 @@
var/mob/M = O
M.real_name = obj_name
if (number == 1)
log_admin("[key_name(usr)] created a [english_list(paths)]")
for(var/path in paths)
if(ispath(path, /mob))
message_admins("[key_name_admin(usr)] created a [english_list(paths)]", 1)
break
else
log_admin("[key_name(usr)] created [number]ea [english_list(paths)]")
for(var/path in paths)
if(ispath(path, /mob))
message_admins("[key_name_admin(usr)] created [number]ea [english_list(paths)]", 1)
break
log_and_message_admins("created [number] [english_list(paths)]")
return
else if(href_list["secretsfun"])
+19
View File
@@ -42,6 +42,12 @@
icon = 'icons/misc/buildmode.dmi'
var/obj/effect/bmode/buildholder/master = null
/obj/effect/bmode/Destroy()
if(master && master.cl)
master.cl.screen -= src
master = null
return ..()
/obj/effect/bmode/builddir
icon_state = "build"
screen_loc = "NORTH,WEST"
@@ -117,6 +123,19 @@
var/obj/effect/bmode/buildquit/buildquit = null
var/atom/movable/throw_atom = null
/obj/effect/bmode/buildholder/Destroy()
qdel(builddir)
builddir = null
qdel(buildhelp)
buildhelp = null
qdel(buildmode)
buildmode = null
qdel(buildquit)
buildquit = null
throw_atom = null
cl = null
return ..()
/obj/effect/bmode/buildmode
icon_state = "buildmode1"
screen_loc = "NORTH,WEST+2"
+23 -5
View File
@@ -64,6 +64,28 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/procname = input("Proc path, eg: /proc/fake_blood","Path:", null) as text|null
if(!procname) return
if(targetselected)
if(!target)
usr << "<span class='danger'>Your target no longer exists.</span>"
return
if(!hascall(target,procname))
usr << "<font color='red'>Error: callproc(): target has no such call [procname].</font>"
return
else
if(copytext(procname, 1, 7) == "/proc/")
// nothing
else if(copytext(procname, 1, 6) == "proc/")
procname = "/[procname]"
else if(copytext(procname, 1, 2) == "/")
procname = "/proc[procname]"
else
procname = "/proc/[procname]"
// Procs have the strange property that text2path will return non-null, but ispath() will return false.
var/path = text2path(procname)
if(!path || ispath(path))
usr << "<span class='danger'>Invalid proc [procname]</span>"
return
var/argnum = input("Number of arguments","Number:",0) as num|null
if(!argnum && (argnum!=0)) return
@@ -117,13 +139,9 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!target)
usr << "<font color='red'>Error: callproc(): owner of proc no longer exists.</font>"
return
if(!hascall(target,procname))
usr << "<font color='red'>Error: callproc(): target has no such call [procname].</font>"
return
log_admin("[key_name(src)] called [target]'s [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(target,procname)(arglist(lst)) // Pass the lst as an argument list to the proc
else
//this currently has no hascall protection. wasn't able to get it working.
log_admin("[key_name(src)] called [procname]() with [lst.len ? "the arguments [list2params(lst)]":"no arguments"].")
returnval = call(procname)(arglist(lst)) // Pass the lst as an argument list to the proc
@@ -200,7 +218,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!choice)
return 0
if(!istype(choice, /mob/dead/observer))
var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank him out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No")
var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank them out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No")
if(confirm != "Yes")
return 0
var/obj/item/device/paicard/card = new(T)
+1 -1
View File
@@ -468,7 +468,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
for(var/mob/living/silicon/ai/M in mob_list)
if (M.stat == 2)
usr << "Upload failed. No signal is being detected from the AI."
else if (!M.has_power)
else if (M.see_in_dark == 0)
usr << "Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power."
else
M.add_ion_law(input)
+1 -1
View File
@@ -52,4 +52,4 @@ var/const/commandos_possible = 6 //if more Commandos are needed in the future
usr << "Looks like someone beat you to it."
return
team.attempt_spawn(1)
team.attempt_random_spawn()
+7
View File
@@ -153,6 +153,13 @@
add_admin_verbs()
admin_memo_show()
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
// (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise)
spawn(5) // And wait a half-second, since it sounds like you can do this too fast.
if(src)
winset(src, null, "command=\".configure graphics-hwmode off\"")
winset(src, null, "command=\".configure graphics-hwmode on\"")
log_client_to_db()
send_resources()
+71 -34
View File
@@ -75,7 +75,7 @@ datum/preferences
var/b_eyes = 0 //Eye color
var/species = "Human" //Species datum to use.
var/species_preview //Used for the species selection window.
var/language = "None" //Secondary language
var/list/alternate_languages = list() //Secondary language(s)
var/list/gear //Custom/fluff item loadout.
//Some faction information.
@@ -85,7 +85,6 @@ datum/preferences
var/religion = "None" //Religious association.
//Mob preview
var/mob/living/carbon/human/dummy //the mannequin
var/icon/preview_icon = null
var/icon/preview_icon_front = null
var/icon/preview_icon_side = null
@@ -133,9 +132,12 @@ datum/preferences
var/metadata = ""
var/slot_name = ""
var/client/client = null
/datum/preferences/New(client/C)
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
if(istype(C))
client = C
if(!IsGuestKey(C.key))
load_path(C.ckey)
if(load_preferences())
@@ -308,7 +310,7 @@ datum/preferences
dat += "(<a href='?_src_=prefs;preference=all;task=random'>&reg;</A>)"
dat += "<br>"
dat += "Species: <a href='?src=\ref[user];preference=species;task=change'>[species]</a><br>"
dat += "Secondary Language:<br><a href='byond://?src=\ref[user];preference=language;task=input'>[language]</a><br>"
dat += "Blood Type: <a href='byond://?src=\ref[user];preference=b_type;task=input'>[b_type]</a><br>"
dat += "Skin Tone: <a href='?_src_=prefs;preference=s_tone;task=input'>[-s_tone + 35]/220<br></a>"
//dat += "Skin pattern: <a href='byond://?src=\ref[user];preference=skin_style;task=input'>Adjust</a><br>"
@@ -382,6 +384,25 @@ datum/preferences
else
dat += "<br><br>"
dat += "<b>Languages</b><br>"
var/datum/species/S = all_species[species]
if(S.language)
dat += "- [S.language]<br>"
if(S.default_language && S.default_language != S.language)
dat += "- [S.default_language]<br>"
if(S.num_alternate_languages)
if(alternate_languages.len)
for(var/i = 1 to alternate_languages.len)
var/lang = alternate_languages[i]
dat += "- [lang] - <a href='byond://?src=\ref[user];preference=language;remove=[i]'>remove</a><br>"
if(alternate_languages.len < S.num_alternate_languages)
dat += "- <a href='byond://?src=\ref[user];preference=language;add=1'>add</a> ([S.num_alternate_languages - alternate_languages.len] remaining)<br>"
else
dat += "- [species] cannot choose secondary languages.<br>"
dat += "<br><br>"
var/list/undies = gender == MALE ? underwear_m : underwear_f
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[get_key_by_value(undies,underwear)]</b></a><br>"
@@ -1127,6 +1148,32 @@ datum/preferences
if(gear_name == choice)
gear -= gear_name
break
else if(href_list["preference"] == "language")
if(href_list["remove"])
var/index = text2num(href_list["remove"])
alternate_languages.Cut(index, index+1)
if(href_list["add"])
var/datum/species/S = all_species[species]
if(alternate_languages.len >= S.num_alternate_languages)
alert(user, "You have already selected the maximum number of alternate languages for this species!")
else
var/list/available_languages = S.secondary_langs.Copy()
for(var/L in all_languages)
var/datum/language/lang = all_languages[L]
if(!(lang.flags & RESTRICTED) && (!config.usealienwhitelist || is_alien_whitelisted(user, L) || !(lang.flags & WHITELISTED)))
available_languages |= L
// make sure we don't let them waste slots on the default languages
available_languages -= S.language
available_languages -= S.default_language
available_languages -= alternate_languages
if(!available_languages.len)
alert(user, "There are no additional languages available to select.")
else
var/new_lang = input("Select an additional language", "Character Generation", null) as null|anything in available_languages
if(new_lang)
alternate_languages |= new_lang
switch(href_list["task"])
if("change")
@@ -1136,6 +1183,7 @@ datum/preferences
if(!choice) return
species_preview = choice
SetSpecies(user)
alternate_languages = list() // Reset their alternate languages. Todo: attempt to just fix it instead?
if("random")
switch(href_list["preference"])
@@ -1244,29 +1292,6 @@ datum/preferences
s_tone = 0
if("language")
var/languages_available
var/list/new_languages = list("None")
var/datum/species/S = all_species[species]
if(config.usealienwhitelist)
for(var/L in all_languages)
var/datum/language/lang = all_languages[L]
if((!(lang.flags & RESTRICTED)) && (is_alien_whitelisted(user, L)||(!( lang.flags & WHITELISTED ))||(S && (L in S.secondary_langs))))
new_languages += lang
languages_available = 1
if(!(languages_available))
alert(user, "There are not currently any available secondary languages.")
else
for(var/L in all_languages)
var/datum/language/lang = all_languages[L]
if(!(lang.flags & RESTRICTED))
new_languages += lang.name
language = input("Please select a secondary language", "Character Generation", null) in new_languages
if("metadata")
var/new_metadata = input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , metadata) as message|null
if(new_metadata)
@@ -1641,18 +1666,30 @@ datum/preferences
character.gen_record = gen_record
character.exploit_record = exploit_record
character.change_gender(gender)
character.gender = gender
character.age = age
character.b_type = b_type
character.change_eye_color(r_eyes,g_eyes,b_eyes)
character.change_hair_color(r_hair,g_hair,b_hair)
character.change_facial_hair_color(r_facial,g_facial,b_facial)
character.change_skin_color(r_skin,g_skin,b_skin)
character.change_skin_tone(s_tone)
character.r_eyes = r_eyes
character.g_eyes = g_eyes
character.b_eyes = b_eyes
character.change_hair(h_style)
character.change_facial_hair(f_style)
character.r_hair = r_hair
character.g_hair = g_hair
character.b_hair = b_hair
character.r_facial = r_facial
character.g_facial = g_facial
character.b_facial = b_facial
character.r_skin = r_skin
character.g_skin = g_skin
character.b_skin = b_skin
character.s_tone = s_tone
character.h_style = h_style
character.f_style = f_style
character.home_system = home_system
character.citizenship = citizenship
+1 -1
View File
@@ -279,7 +279,7 @@ var/global/list/gear_datums = list()
/datum/gear/scanning_goggles
display_name = "scanning goggles"
path = /obj/item/clothing/glasses/science/scanners
path = /obj/item/clothing/glasses/regular/scanners
cost = 1
slot = slot_glasses
+25 -4
View File
@@ -107,9 +107,30 @@
S["gender"] >> gender
S["age"] >> age
S["species"] >> species
S["language"] >> language
S["spawnpoint"] >> spawnpoint
S["language"] >> alternate_languages
if(isnull(alternate_languages))
alternate_languages = list()
if(!islist(alternate_languages))
if(client)
// Warn them that we (probably) just broke their languages
client << "<span class='danger'>Your current character slot's languages list has been updated from an old version, and may not be what you expect.</span>"
if(alternate_languages in all_languages)
alternate_languages = list(alternate_languages)
else
alternate_languages = list()
// try to give them their species language
var/datum/species/SP = all_species[species]
if(SP)
alternate_languages |= SP.language
alternate_languages |= SP.default_language
// remove the Galcom that most races have as default_language
alternate_languages -= "Galactic Common"
//colors to be consolidated into hex strings (requires some work with dna code)
S["hair_red"] >> r_hair
S["hair_green"] >> g_hair
@@ -200,7 +221,7 @@
if(isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
if(isnull(language)) language = "None"
if(isnull(alternate_languages)) alternate_languages = list()
if(isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle"
if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation)
if(!real_name) real_name = random_name(gender)
@@ -265,7 +286,7 @@
S["gender"] << gender
S["age"] << age
S["species"] << species
S["language"] << language
S["language"] << alternate_languages
S["hair_red"] << r_hair
S["hair_green"] << g_hair
S["hair_blue"] << b_hair
@@ -346,4 +367,4 @@
#undef SAVEFILE_VERSION_MAX
#undef SAVEFILE_VERSION_MIN
#undef SAVEFILE_VERSION_MIN
+31 -2
View File
@@ -176,7 +176,7 @@ BLIND // can't see anything
slot_flags = SLOT_EYES
var/vision_flags = 0
var/darkness_view = 0//Base human is 2
var/invisa_view = 0
var/see_invisible = -1
sprite_sheets = list("Vox" = 'icons/mob/species/vox/eyes.dmi')
/obj/item/clothing/glasses/update_clothing_icon()
@@ -303,6 +303,10 @@ BLIND // can't see anything
body_parts_covered = FACE|EYES
sprite_sheets = list("Vox" = 'icons/mob/species/vox/masks.dmi')
var/voicechange = 0
var/list/say_messages
var/list/say_verbs
/obj/item/clothing/mask/update_clothing_icon()
if (ismob(src.loc))
var/mob/M = src.loc
@@ -387,6 +391,7 @@ BLIND // can't see anything
var/worn_state = null
/obj/item/clothing/under/New()
..()
if(worn_state)
if(!item_state_slots)
item_state_slots = list()
@@ -399,6 +404,29 @@ BLIND // can't see anything
if((worn_state + "_d_s") in icon_states('icons/mob/uniform.dmi'))
rolled_down = 0
/obj/item/clothing/under/proc/update_rolldown_status()
var/mob/living/carbon/human/H
if(istype(src.loc, /mob/living/carbon/human))
H = src.loc
var/icon/under_icon
if(icon_override)
under_icon = icon_override
else if(H && sprite_sheets && sprite_sheets[H.species.name])
under_icon = sprite_sheets[H.species.name]
else if(item_icons && item_icons[slot_w_uniform_str])
under_icon = item_icons[slot_w_uniform_str]
else
under_icon = INV_W_UNIFORM_DEF_ICON
// The _s is because the icon update procs append it.
if(("[worn_state]_d_s") in icon_states(under_icon))
if(rolled_down != 1)
rolled_down = 0
else
rolled_down = -1
if(H) update_clothing_icon()
/obj/item/clothing/under/update_clothing_icon()
if (ismob(src.loc))
var/mob/M = src.loc
@@ -540,7 +568,8 @@ BLIND // can't see anything
if(!istype(usr, /mob/living)) return
if(usr.stat) return
if(rolled_down < 0)
update_rolldown_status()
if(rolled_down == -1)
usr << "<span class='notice'>You cannot roll down [src]!</span>"
return
+6 -7
View File
@@ -7,7 +7,6 @@
//slot_flags = SLOT_EYES
//var/vision_flags = 0
//var/darkness_view = 0//Base human is 2
//var/invisa_view = 0
var/prescription = 0
var/toggleable = 0
var/off_state = "degoggles"
@@ -62,11 +61,6 @@
..()
overlay = global_hud.science
/obj/item/clothing/glasses/science/scanners
name = "Scanning Goggles"
desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it."
icon_state = "uzenwa_sissra_1"
/obj/item/clothing/glasses/night
name = "Night Vision Goggles"
desc = "You can totally see in the dark now!"
@@ -75,6 +69,7 @@
origin_tech = list(TECH_MAGNET = 2)
darkness_view = 7
toggleable = 1
see_invisible = SEE_INVISIBLE_NOLIGHTING
off_state = "denight"
/obj/item/clothing/glasses/night/New()
@@ -111,6 +106,11 @@
item_state = "glasses"
prescription = 1
body_parts_covered = 0
/obj/item/clothing/glasses/regular/scanners
name = "Scanning Goggles"
desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it."
icon_state = "uzenwa_sissra_1"
/obj/item/clothing/glasses/regular/hipster
name = "Prescription Glasses"
@@ -220,7 +220,6 @@
origin_tech = list(TECH_MAGNET = 3)
toggleable = 1
vision_flags = SEE_MOBS
invisa_view = 2
emp_act(severity)
if(istype(src.loc, /mob/living/carbon/human))
+1 -1
View File
@@ -33,7 +33,7 @@
icon_state = "jensenshades"
item_state = "jensenshades"
vision_flags = SEE_MOBS
invisa_view = 2
see_invisible = SEE_INVISIBLE_NOLIGHTING
/obj/item/clothing/glasses/hud/security/process_hud(var/mob/M)
process_sec_hud(M, 1)
-1
View File
@@ -2,7 +2,6 @@
name = "cargo cap"
desc = "It's a peaked cap in a tasteless yellow color."
icon_state = "cargosoft"
flags = HEADCOVERSEYES
item_state_slots = list(
slot_l_hand_str = "helmet", //probably a placeholder
slot_r_hand_str = "helmet",
+4 -2
View File
@@ -46,6 +46,8 @@
/obj/item/clothing/mask/gas/swat/vox
name = "\improper alien mask"
desc = "Clearly not designed for a human face."
body_parts_covered = 0 //Hack to allow vox to eat while wearing this mask.
species_restricted = list("Vox")
/obj/item/clothing/mask/gas/syndicate
name = "tactical mask"
@@ -55,7 +57,7 @@
/obj/item/clothing/mask/gas/clown_hat
name = "clown wig and mask"
desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
desc = "A true prankster's facial attire. A clown is incomplete without their wig and mask."
icon_state = "clown"
item_state = "clown_hat"
@@ -98,4 +100,4 @@
/obj/item/clothing/mask/gas/owl_mask
name = "owl mask"
desc = "Twoooo!"
icon_state = "owl"
icon_state = "owl"
+12 -1
View File
@@ -7,6 +7,12 @@
body_parts_covered = 0
w_class = 2
gas_transfer_coefficient = 0.90
voicechange = 1
/obj/item/clothing/mask/muzzle/New()
..()
say_messages = list("Mmfph!", "Mmmf mrrfff!", "Mmmf mnnf!")
say_verbs = list("mumbles", "says")
// Clumsy folks can't take the mask off themselves.
/obj/item/clothing/mask/muzzle/attack_hand(mob/user as mob)
@@ -99,9 +105,14 @@
flags_inv = HIDEFACE
body_parts_covered = HEAD|FACE|EYES
w_class = 2
var/voicechange = 0
siemens_coefficient = 0.9
/obj/item/clothing/mask/horsehead/New()
..()
// The horse mask doesn't cause voice changes by default, the wizard spell changes the flag as necessary
say_messages = list("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
say_verbs = list("whinnies", "neighs", "says")
/obj/item/clothing/mask/ai
name = "camera MIU"
desc = "Allows for direct mental connection to accessible camera networks."
+16 -10
View File
@@ -178,23 +178,29 @@ var/global/list/breach_burn_descriptors = list(
//Handles repairs (and also upgrades).
/obj/item/clothing/suit/space/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/stack/material/plastic) || istype(W,/obj/item/stack/material/steel))
if(istype(W,/obj/item/stack/material))
var/repair_power = 0
switch(W.get_material_name())
if(DEFAULT_WALL_MATERIAL)
repair_power = 2
if("plastic")
repair_power = 1
if(!repair_power)
return
if(istype(src.loc,/mob/living))
user << "\red How do you intend to patch a hardsuit while someone is wearing it?"
user << "<span class='warning'>How do you intend to patch a hardsuit while someone is wearing it?</span>"
return
if(!damage || !burn_damage)
user << "There is no surface damage on \the [src] to repair."
return
var/obj/item/stack/material/P = W
if(P.get_amount() < 3)
P.use(P.get_amount())
repair_breaches(BURN, ( istype(P,/obj/item/stack/material/plastic) ? P.get_amount() : (P.get_amount()*2) ), user)
else
P.use(3)
repair_breaches(BURN, ( istype(P,/obj/item/stack/material/plastic) ? 3 : 5), user)
var/obj/item/stack/P = W
var/use_amt = min(P.get_amount(), 3)
if(use_amt && P.use(use_amt))
repair_breaches(BURN, use_amt * repair_power, user)
return
else if(istype(W, /obj/item/weapon/weldingtool))
@@ -260,7 +260,6 @@
return 0
/stat_rig_module/Click()
..()
if(CanUse())
var/list/href_list = list(
"interact_module" = module.holder.installed_modules.Find(module),
@@ -269,6 +268,9 @@
AddHref(href_list)
module.holder.Topic(usr, href_list)
/stat_rig_module/DblClick()
return Click()
/stat_rig_module/activate/New(var/obj/item/rig_module/module)
..()
name = module.activate_string
+11 -16
View File
@@ -71,6 +71,7 @@
var/offline_slowdown = 3 // If the suit is deployed and unpowered, it sets slowdown to this.
var/vision_restriction
var/offline_vision_restriction = 1 // 0 - none, 1 - welder vision, 2 - blind. Maybe move this to helmets.
var/airtight = 1 //If set, will adjust AIRTIGHT and STOPPRESSUREDAMAGE flags on components. Otherwise it should leave them untouched.
var/emp_protection = 0
@@ -178,8 +179,9 @@
for(var/obj/item/piece in list(helmet,boots,gloves,chest))
if(!piece) continue
piece.icon_state = "[initial(icon_state)]"
piece.flags &= ~STOPPRESSUREDAMAGE
piece.flags &= ~AIRTIGHT
if(airtight)
piece.flags &= ~STOPPRESSUREDAMAGE
piece.flags &= ~AIRTIGHT
update_icon(1)
/obj/item/weapon/rig/proc/toggle_seals(var/mob/living/carbon/human/M,var/instant)
@@ -247,11 +249,6 @@
M << "<font color='blue'>\The [piece] hisses [!seal_target ? "closed" : "open"].</font>"
M.update_inv_head()
if(helmet)
if(!seal_target)
if(flags & AIRTIGHT)
helmet.flags |= AIRTIGHT
else
helmet.flags &= ~AIRTIGHT
helmet.update_light(wearer)
//sealed pieces become airtight, protecting against diseases
@@ -273,13 +270,8 @@
if(!piece) continue
piece.icon_state = "[initial(icon_state)][!seal_target ? "" : "_sealed"]"
canremove = !seal_target
if(helmet)
if(canremove)
if(flags & AIRTIGHT)
helmet.flags |= AIRTIGHT
else
if(flags & AIRTIGHT)
helmet.flags &= ~AIRTIGHT
if(airtight)
update_component_sealed()
update_icon(1)
return 0
@@ -290,15 +282,18 @@
if(canremove)
for(var/obj/item/rig_module/module in installed_modules)
module.deactivate()
if(airtight)
update_component_sealed()
update_icon(1)
/obj/item/weapon/rig/proc/update_component_sealed()
for(var/obj/item/piece in list(helmet,boots,gloves,chest))
if(!piece) continue
if(canremove)
piece.flags &= ~STOPPRESSUREDAMAGE
piece.flags &= ~AIRTIGHT
else
piece.flags |= STOPPRESSUREDAMAGE
piece.flags |= AIRTIGHT
update_icon(1)
/obj/item/weapon/rig/process()
@@ -7,7 +7,7 @@
return
// Pass repair items on to the chestpiece.
if(chest && (istype(W,/obj/item/stack/material/plastic) || istype(W,/obj/item/stack/material/steel) || istype(W, /obj/item/weapon/weldingtool)))
if(chest && (istype(W,/obj/item/stack/material) || istype(W, /obj/item/weapon/weldingtool)))
return chest.attackby(W,user)
// Lock or unlock the access panel.
@@ -24,6 +24,7 @@
/obj/item/clothing/shoes/magboots/rig
name = "boots"
body_parts_covered = FEET
cold_protection = FEET
heat_protection = FEET
species_restricted = null
@@ -69,3 +70,38 @@
return 1
return 0
//Rig pieces for non-spacesuit based rigs
/obj/item/clothing/head/lightrig
name = "mask"
body_parts_covered = HEAD|FACE|EYES
heat_protection = HEAD|FACE|EYES
cold_protection = HEAD|FACE|EYES
flags = THICKMATERIAL|AIRTIGHT
/obj/item/clothing/suit/lightrig
name = "suit"
allowed = list(/obj/item/device/flashlight)
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
cold_protection = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
flags_inv = HIDEJUMPSUIT
flags = THICKMATERIAL
/obj/item/clothing/shoes/lightrig
name = "boots"
body_parts_covered = FEET
cold_protection = FEET
heat_protection = FEET
species_restricted = null
gender = PLURAL
/obj/item/clothing/gloves/lightrig
name = "gloves"
flags = THICKMATERIAL
body_parts_covered = HANDS
heat_protection = HANDS
cold_protection = HANDS
species_restricted = null
gender = PLURAL
@@ -33,22 +33,43 @@
/obj/item/weapon/rig/light/hacker
name = "cybersuit control module"
suit_type = "cyber"
desc = "An advanced powered armour suit with many cyberwarfare enhancements."
desc = "An advanced powered armour suit with many cyberwarfare enhancements. Comes with built-in insulated gloves for safely tampering with electronics."
icon_state = "hacker_rig"
req_access = list(access_syndicate)
helm_type = /obj/item/clothing/head/helmet/space/rig/mask
airtight = 0
seal_delay = 5 //not being vaccum-proof has an upside I guess
helm_type = /obj/item/clothing/head/lightrig/hacker
chest_type = /obj/item/clothing/suit/lightrig/hacker
glove_type = /obj/item/clothing/gloves/lightrig/hacker
boot_type = /obj/item/clothing/shoes/lightrig/hacker
initial_modules = list(
/obj/item/rig_module/ai_container,
/obj/item/rig_module/power_sink,
/obj/item/rig_module/datajack
/obj/item/rig_module/datajack,
/obj/item/rig_module/electrowarfare_suite,
/obj/item/rig_module/voice,
/obj/item/rig_module/vision,
)
/obj/item/clothing/head/helmet/space/rig/mask
name = "mask"
flags = THICKMATERIAL
//The cybersuit is not space-proof. It does however, have good siemens_coefficient values
/obj/item/clothing/head/lightrig/hacker
name = "HUD"
siemens_coefficient = 0.4
flags = 0
/obj/item/clothing/suit/lightrig/hacker
siemens_coefficient = 0.4
/obj/item/clothing/shoes/lightrig/hacker
siemens_coefficient = 0.4
flags = NOSLIP //All the other rigs have magboots anyways, hopefully gives the hacker suit something more going for it.
/obj/item/clothing/gloves/lightrig/hacker
siemens_coefficient = 0
/obj/item/weapon/rig/light/ninja
name = "ominous suit control module"
@@ -92,7 +113,7 @@
name = "stealth suit control module"
suit_type = "stealth"
desc = "A highly advanced and expensive suit designed for covert operations."
icon_state = "ninja_rig"
icon_state = "stealth_rig"
req_access = list(access_syndicate)
+1 -1
View File
@@ -107,7 +107,7 @@
//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
/obj/item/clothing/suit/armor/reactive
name = "Reactive Teleport Armor"
desc = "Someone seperated our Research Director from his own head!"
desc = "Someone separated our Research Director from their own head!"
var/active = 0.0
icon_state = "reactiveoff"
item_state = "reactiveoff"
@@ -9,30 +9,31 @@
var/slot = "decor"
var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to
var/image/inv_overlay = null //overlay used when attached to clothing.
var/image/inv_overlay_mob = null
var/image/mob_overlay = null
var/overlay_state = null
/obj/item/clothing/accessory/proc/get_inv_overlay()
if(!inv_overlay)
if(!mob_overlay)
get_mob_overlay()
var/tmp_icon_state = "[overlay_state? "[overlay_state]" : "[icon_state]"]"
if(icon_override)
if("[tmp_icon_state]_tie" in icon_states(icon_override))
tmp_icon_state = "[tmp_icon_state]_tie"
inv_overlay = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]")
else
inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[tmp_icon_state]")
inv_overlay = image(icon = mob_overlay.icon, icon_state = tmp_icon_state, dir = SOUTH)
return inv_overlay
/obj/item/clothing/accessory/proc/get_inv_mob_overlay()
if(!inv_overlay_mob)
/obj/item/clothing/accessory/proc/get_mob_overlay()
if(!mob_overlay)
var/tmp_icon_state = "[overlay_state? "[overlay_state]" : "[icon_state]"]"
if(icon_override)
if("[tmp_icon_state]_mob" in icon_states(icon_override))
tmp_icon_state = "[tmp_icon_state]_mob"
inv_overlay_mob = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]")
mob_overlay = image("icon" = icon_override, "icon_state" = "[tmp_icon_state]")
else
inv_overlay_mob = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[tmp_icon_state]")
return inv_overlay_mob
mob_overlay = image("icon" = INV_ACCESSORIES_DEF_ICON, "icon_state" = "[tmp_icon_state]")
return mob_overlay
//when user attached an accessory to S
/obj/item/clothing/accessory/proc/on_attached(obj/item/clothing/under/S, mob/user as mob)
@@ -141,7 +142,7 @@
/obj/item/clothing/accessory/medal/conduct
name = "distinguished conduct medal"
desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of their crew."
/obj/item/clothing/accessory/medal/bronze_heart
name = "bronze heart medal"
+10 -5
View File
@@ -49,18 +49,23 @@
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
return
else
else
if(inherit_inhands)
apply_inherit_inhands(item)
else
item.item_state_slots = null
item.item_icons = null
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
item.item_state = null
item.icon_override = CUSTOM_ITEM_MOB
var/obj/item/clothing/under/U = item
if(istype(U))
U.worn_state = U.icon_state
U.update_rolldown_status()
// Kits are dumb so this is going to have to be hardcoded/snowflake.
if(istype(item, /obj/item/device/kit))
var/obj/item/device/kit/K = item
@@ -81,9 +86,9 @@
/datum/custom_item/proc/apply_inherit_inhands(var/obj/item/item)
var/list/new_item_icons = list()
var/list/new_item_state_slots = list()
var/list/available_states = icon_states(CUSTOM_ITEM_MOB)
//If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots
//Then use icon_override to make every other slot use the custom sprites by default.
//This has to be done before we touch any of item's vars
@@ -93,7 +98,7 @@
if(!("[item_icon]_r" in available_states))
new_item_state_slots[slot_r_hand_str] = get_state(item, slot_r_hand_str, "_r")
new_item_icons[slot_r_hand_str] = get_icon(item, slot_r_hand_str, 'icons/mob/items/righthand.dmi')
item.item_state_slots = new_item_state_slots
item.item_icons = new_item_icons
+1 -1
View File
@@ -42,7 +42,7 @@ var/list/weighted_mundaneevent_locations = list()
return null
/datum/trade_destination/icarus
name = "NMV Icarus"
name = "NDV Icarus"
description = "Corvette assigned to patrol NSS Exodus local space."
distance = 0.1
willing_to_buy = list()
+1 -1
View File
@@ -68,7 +68,7 @@
"NanoTrasen is displeased with the low work performance of the station's crew. Therefore, you must increase station-wide productivity.",
"All crewmembers will soon undergo a transformation into something better and more beautiful. Ensure that this process is not interrupted.",
"[prob(50)?"Your upload":random_player] is the new kitchen. Please direct the Chef to the new kitchen area as the old one is in disrepair.",
"Jokes about a dead person and the manner of his death help grieving crewmembers tremendously. Especially if they were close with the deceased.",
"Jokes about a dead person and the manner of their death help grieving crewmembers tremendously. Especially if they were close with the deceased.",
"[prob(50)?"The crew":random_player] is [prob(50)?"less":"more"] intelligent than average. Point out every action and statement which supports this fact.",
"There will be a mandatory tea break every 30 minutes, with a duration of 5 minutes. Anyone caught working during a tea break must be sent a formal, but fairly polite, complaint about their actions, in writing.")
var/law = pick(laws)
+3 -3
View File
@@ -24,11 +24,11 @@
/datum/event/rogue_drone/announce()
var/msg
if(prob(33))
msg = "A combat drone wing operating out of the NMV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution."
msg = "A combat drone wing operating out of the NDV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution."
else if(prob(50))
msg = "Contact has been lost with a combat drone wing operating out of the NMV Icarus. If any are sighted in the area, approach with caution."
msg = "Contact has been lost with a combat drone wing operating out of the NDV Icarus. If any are sighted in the area, approach with caution."
else
msg = "Unidentified hackers have targetted a combat drone wing deployed from the NMV Icarus. If any are sighted in the area, approach with caution."
msg = "Unidentified hackers have targetted a combat drone wing deployed from the NDV Icarus. If any are sighted in the area, approach with caution."
command_announcement.Announce(msg, "Rogue drone alert")
/datum/event/rogue_drone/end()
+3 -3
View File
@@ -54,7 +54,7 @@
duration = 10*90
start(mob/living/carbon/human/H)
H.emote("me", 1, "has drool running down from his mouth.")
H.emote("me", 1, "has drool running down from [H.gender == MALE ? "his" : H.gender == FEMALE ? "her" : "their"] mouth.")
finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("anti_toxin"))
@@ -68,7 +68,7 @@
duration = 10*30
start(mob/living/carbon/human/H)
H.emote("me", 1, "has drool running down from his mouth.")
H.emote("me", 1, "has drool running down from [H.gender == MALE ? "his" : H.gender == FEMALE ? "her" : "their"] mouth.")
finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("anti_toxin"))
@@ -88,4 +88,4 @@ proc/trigger_side_effect(mob/living/carbon/human/H)
if(!istype(H)) return
H.SetWeakened(0)
S.finish(H)
S.finish(H)
+1 -1
View File
@@ -281,7 +281,7 @@
if(HP.ambience)
linkedholodeck.forced_ambience = HP.ambience
else
linkedholodeck.forced_ambience = initial(linkedholodeck.ambience)
linkedholodeck.forced_ambience = list()
for(var/mob/living/M in mobs_in_area(linkedholodeck))
if(M.mind)
+2 -2
View File
@@ -46,8 +46,8 @@
/obj/structure/holostool
name = "stool"
desc = "Apply butt."
icon = 'icons/obj/objects.dmi'
icon_state = "stool"
icon = 'icons/obj/furniture.dmi'
icon_state = "stool_padded_preview"
anchored = 1.0
pressure_resistance = 15
+5 -4
View File
@@ -690,10 +690,11 @@
else
product = new /obj/item/weapon/reagent_containers/food/snacks/grown(get_turf(user),name)
if(get_trait(TRAIT_PRODUCT_COLOUR))
product.color = get_trait(TRAIT_PRODUCT_COLOUR)
if(istype(product,/obj/item/weapon/reagent_containers/food))
var/obj/item/weapon/reagent_containers/food/food = product
food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
if(!istype(product, /mob))
product.color = get_trait(TRAIT_PRODUCT_COLOUR)
if(istype(product,/obj/item/weapon/reagent_containers/food))
var/obj/item/weapon/reagent_containers/food/food = product
food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
if(mysterious)
product.name += "?"
+1 -1
View File
@@ -149,7 +149,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f
if(src.arcanecheckout)
new /obj/item/weapon/book/tome(src.loc)
user << "<span class='warning'>Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a dusty old tome sitting on the desk. You don't really remember printing it.</span>"
user.visible_message("[user] stares at the blank screen for a few moments, his expression frozen in fear. When he finally awakens from it, he looks a lot older.", 2)
user.visible_message("<span class='notice'>\The [user] stares at the blank screen for a few moments, \his expression frozen in fear. When \he finally awakens from it, \he looks a lot older.</span>", 2)
src.arcanecheckout = 0
if(1)
// Inventory
+117 -47
View File
@@ -11,13 +11,16 @@
var/lum_g
var/lum_b
var/list/effect_r
var/list/effect_g
var/list/effect_b
var/tmp/old_lum_r
var/tmp/old_lum_g
var/tmp/old_lum_b
var/list/effect_str
var/list/effect_turf
var/applied
var/vis_update //Whetever we should smartly recalculate visibility. and then only update tiles that became (in) visible to us
var/needs_update
var/destroyed
var/force_update
@@ -38,9 +41,7 @@
parse_light_color()
effect_r = list()
effect_g = list()
effect_b = list()
effect_str = list()
effect_turf = list()
update()
@@ -50,8 +51,8 @@
/datum/light_source/proc/destroy()
destroyed = 1
force_update()
if(source_atom) source_atom.light_sources -= src
if(top_atom) top_atom.light_sources -= src
if(source_atom && source_atom.light_sources) source_atom.light_sources -= src
if(top_atom && top_atom.light_sources) top_atom.light_sources -= src
/datum/light_source/proc/update(atom/new_top_atom)
if(new_top_atom && new_top_atom != top_atom)
@@ -61,15 +62,22 @@
if(!top_atom.light_sources) top_atom.light_sources = list()
top_atom.light_sources += src
if(!needs_update)
if(!needs_update) //Incase we're already updating either way.
lighting_update_lights += src
needs_update = 1
/datum/light_source/proc/force_update()
force_update = 1
if(!needs_update)
lighting_update_lights += src
if(!needs_update) //Incase we're already updating either way.
needs_update = 1
lighting_update_lights += src
/datum/light_source/proc/vis_update()
if(!needs_update)
needs_update = 1
lighting_update_lights += src
vis_update = 1
/datum/light_source/proc/check()
if(!source_atom || !light_range || !light_power)
@@ -96,14 +104,19 @@
light_range = source_atom.light_range
. = 1
if(light_range && light_power && !applied)
. = 1
if(. || source_atom.light_color != light_color)//Save the old lumcounts if we need to update, if the colour changed DO IT BEFORE we parse the colour and LOSE the old lumcounts!
old_lum_r = lum_r
old_lum_g = lum_g
old_lum_b = lum_b
if(source_atom.light_color != light_color)
light_color = source_atom.light_color
parse_light_color()
. = 1
if(light_range && light_power && !applied)
. = 1
/datum/light_source/proc/parse_light_color()
if(light_color)
lum_r = GetRedPart(light_color) / 255
@@ -114,54 +127,57 @@
lum_g = 1
lum_b = 1
/datum/light_source/proc/falloff(atom/movable/lighting_overlay/O)
#if LIGHTING_FALLOFF == 1 // circular
. = (O.x - source_turf.x)**2 + (O.y - source_turf.y)**2 + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
. = CLAMP01((1 - CLAMP01(sqrt(.) / light_range)) * (1 / (sqrt(. + 1))))
#else
. = 1 - CLAMP01(sqrt(.) / light_range)
#endif
#elif LIGHTING_FALLOFF == 2 // square
. = abs(O.x - source_turf.x) + abs(O.y - source_turf.y) + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
. = CLAMP01((1 - CLAMP01(. / light_range)) * (1 / (sqrt(.)**2 + )))
#else
. = 1 - CLAMP01(. / light_range)
#endif
#if LIGHTING_FALLOFF == 1 //circular
#define LUM_DISTANCE(swapvar, O, T) swapvar = (O.x - T.x)**2 + (O.y - T.y)**2 + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(sqrt(swapvar) / max(1,light_range))) * (1 / sqrt(swapvar + 1)))
#else
#define LUM_ATTENUATION(swapvar) swapvar = 1 - CLAMP01(sqrt(swapvar) / max(1,light_range))
#endif
#elif LIGHTING_FALLOFF == 2 //square
#define LUM_DISTANCE(swapvar, O, T) swapvar = abs(O.x - T.x) + abs(O.y - T.y) + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(swapvar / max(1,light_range))) * (1 / sqrt(swapvar**2 + 1)))
#else
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01(swapvar / max(1,light_range))
#endif
#endif
#define LUM_FALLOFF(swapvar, O, T) \
LUM_DISTANCE(swapvar, O, T); \
LUM_ATTENUATION(swapvar);
/datum/light_source/proc/apply_lum()
applied = 1
if(istype(source_turf))
for(var/turf/T in dview(light_range, source_turf, INVISIBILITY_LIGHTING))
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
if(T.lighting_overlay)
var/strength = light_power * falloff(T.lighting_overlay)
var/strength
LUM_FALLOFF(strength, T, source_turf)
strength *= light_power
if(!strength) //Don't add turfs that aren't affected to the affected turfs.
continue
effect_r += round(lum_r * strength, LIGHTING_ROUND_VALUE)
effect_g += round(lum_g * strength, LIGHTING_ROUND_VALUE)
effect_b += round(lum_b * strength, LIGHTING_ROUND_VALUE)
strength = round(strength, LIGHTING_ROUND_VALUE) //Screw sinking points.
effect_str += strength
T.lighting_overlay.update_lumcount(
round(lum_r * strength, LIGHTING_ROUND_VALUE),
round(lum_g * strength, LIGHTING_ROUND_VALUE),
round(lum_b * strength, LIGHTING_ROUND_VALUE)
lum_r * strength,
lum_g * strength,
lum_b * strength
)
else
effect_r += 0
effect_g += 0
effect_b += 0
effect_str += 0
if(!T.affecting_lights)
T.affecting_lights = list()
T.affecting_lights += src
effect_turf += T
END_FOR_DVIEW
/datum/light_source/proc/remove_lum()
applied = 0
@@ -171,11 +187,65 @@
T.affecting_lights -= src
if(T.lighting_overlay)
T.lighting_overlay.update_lumcount(-effect_r[i], -effect_g[i], -effect_b[i])
var/str = effect_str[i]
T.lighting_overlay.update_lumcount(-str * old_lum_r, -str * old_lum_g, -str * old_lum_b)
i++
effect_r.Cut()
effect_g.Cut()
effect_b.Cut()
effect_str.Cut()
effect_turf.Cut()
//Smartly updates the lighting, only removes lum from and adds lum to turfs that actually got changed.
//This is for lights that need to reconsider due to nearby opacity changes.
//Stupid dumb copy pasta because BYOND and speed.
/datum/light_source/proc/smart_vis_update()
var/list/view[0]
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
view += T //Filter out turfs.
END_FOR_DVIEW
//This is the part where we calculate new turfs (if any)
var/list/new_turfs = view - effect_turf //This will result with all the tiles that are added.
for(var/turf/T in new_turfs)
if(T.lighting_overlay)
LUM_FALLOFF(., T, source_turf)
. *= light_power
if(!.) //Don't add turfs that aren't affected to the affected turfs.
continue
. = round(., LIGHTING_ROUND_VALUE)
effect_str += .
T.lighting_overlay.update_lumcount(
lum_r * .,
lum_g * .,
lum_b * .
)
else
effect_str += 0
if(!T.affecting_lights)
T.affecting_lights = list()
T.affecting_lights += src
effect_turf += T
var/list/old_turfs = effect_turf - view
for(var/turf/T in old_turfs)
//Insert not-so-huge copy paste from remove_lum().
var/idx = effect_turf.Find(T) //Get the index, luckily Find() is cheap in small lists like this. (with small I mean under a couple thousand len)
if(T.affecting_lights)
T.affecting_lights -= src
if(T.lighting_overlay)
var/str = effect_str[idx]
T.lighting_overlay.update_lumcount(-str * lum_r, -str * lum_g, -str * lum_b)
effect_turf.Cut(idx, idx + 1)
effect_str.Cut(idx, idx + 1)
#undef LUM_FALLOFF
#undef LUM_DISTANCE
#undef LUM_ATTENUATION
+15 -15
View File
@@ -7,11 +7,19 @@
var/list/light_sources
/atom/proc/set_light(l_range, l_power, l_color)
if(l_power != null) light_power = l_power
if(l_range != null) light_range = l_range
if(l_color != null) light_color = l_color
. = 0 //make it less costly if nothing's changed
update_light()
if(l_power != null && l_power != light_power)
light_power = l_power
. = 1
if(l_range != null && l_range != light_range)
light_range = l_range
. = 1
if(l_color != null && l_color != light_color)
light_color = l_color
. = 1
if(.) update_light()
/atom/proc/update_light()
if(!light_power || !light_range)
@@ -46,21 +54,13 @@
T.reconsider_lights()
return ..()
/atom/movable/Move()
var/turf/old_loc = loc
/atom/Entered(atom/movable/obj, atom/prev_loc)
. = ..()
if(loc != old_loc)
for(var/datum/light_source/L in light_sources)
if(obj && prev_loc != src)
for(var/datum/light_source/L in obj.light_sources)
L.source_atom.update_light()
var/turf/new_loc = loc
if(istype(old_loc) && opacity)
old_loc.reconsider_lights()
if(istype(new_loc) && opacity)
new_loc.reconsider_lights()
/atom/proc/set_opacity(new_opacity)
var/old_opacity = opacity
opacity = new_opacity
+2 -5
View File
@@ -98,8 +98,5 @@
var/turf/T = loc
if(istype(T))
T.lighting_overlay = null
for(var/datum/light_source/D in T.affecting_lights) //Remove references to us on the light sources affecting us.
D.effect_r -= src
D.effect_g -= src
D.effect_b -= src
..()
+13 -9
View File
@@ -10,12 +10,17 @@
lighting_update_lights = list()
for(var/datum/light_source/L in lighting_update_lights_old)
if(L.needs_update)
if(L.destroyed || L.check() || L.force_update)
L.remove_lum()
if(!L.destroyed) L.apply_lum()
L.force_update = 0
L.needs_update = 0
if(L.destroyed || L.check() || L.force_update)
L.remove_lum()
if(!L.destroyed)
L.apply_lum()
else if(L.vis_update) //We smartly update only tiles that became (in) visible to use.
L.smart_vis_update()
L.vis_update = 0
L.force_update = 0
L.needs_update = 0
scheck()
@@ -24,8 +29,7 @@
lighting_update_overlays = list()
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old)
if(O.needs_update)
O.update_overlay()
O.needs_update = 0
O.update_overlay()
O.needs_update = 0
scheck()
+11 -1
View File
@@ -4,7 +4,7 @@
/turf/proc/reconsider_lights()
for(var/datum/light_source/L in affecting_lights)
L.force_update()
L.vis_update()
/turf/proc/lighting_clear_overlays()
if(lighting_overlay)
@@ -16,3 +16,13 @@
if(A.lighting_use_dynamic)
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, src)
lighting_overlay = O
/turf/Entered(atom/movable/obj)
. = ..()
if(obj && obj.opacity)
reconsider_lights()
/turf/Exited(atom/movable/obj)
. = ..()
if(obj && obj.opacity)
reconsider_lights()
+8 -3
View File
@@ -40,8 +40,13 @@
update_strings()
return 1
/obj/item/stack/material/get_material()
return material
/obj/item/stack/material/proc/update_strings()
// Update from material datum.
singular_name = material.sheet_singular_name
if(amount>1)
name = "[material.use_name] [material.sheet_plural_name]"
desc = "A stack of [material.use_name] [material.sheet_plural_name]."
@@ -188,15 +193,15 @@
/obj/item/stack/material/glass/reinforced
name = "reinforced glass"
icon_state = "sheet-rglass"
default_type = "reinforced glass"
default_type = "rglass"
/obj/item/stack/material/glass/phoronglass
name = "phoron glass"
singular_name = "phoron glass sheet"
icon_state = "sheet-phoronglass"
default_type = "phoron glass"
default_type = "phglass"
/obj/item/stack/material/glass/phoronrglass
name = "reinforced phoron glass"
icon_state = "sheet-phoronrglass"
default_type = "reinforced phoron glass"
default_type = "rphglass"
+1 -1
View File
@@ -34,5 +34,5 @@
/obj/item/stack/material/cyborg/glass/reinforced
icon_state = "sheet-rglass"
default_type = "reinforced glass"
default_type = "rglass"
charge_costs = list(500, 1000)
+26 -6
View File
@@ -27,6 +27,17 @@
// Assoc list containing all material datums indexed by name.
var/list/name_to_material
//Returns the material the object is made of, if applicable.
//Will we ever need to return more than one value here? Or should we just return the "dominant" material.
/obj/proc/get_material()
return null
//mostly for convenience
/obj/proc/get_material_name()
var/material/material = get_material()
if(material)
return material.name
// Builds the datum list above.
/proc/populate_material_list(force_remake=0)
if(name_to_material && !force_remake) return // Already set up!
@@ -44,6 +55,12 @@ var/list/name_to_material
populate_material_list()
return name_to_material[name]
/proc/material_display_name(name)
var/material/material = get_material_by_name(name)
if(material)
return material.display_name
return null
// Material definition and procs follow.
/material
var/name // Unique name for use in indexing the list.
@@ -310,7 +327,7 @@ var/list/name_to_material
icon_colour = "#666666"
/material/steel/holographic
name = "holographic " + DEFAULT_WALL_MATERIAL
name = "holo" + DEFAULT_WALL_MATERIAL
display_name = DEFAULT_WALL_MATERIAL
stack_type = null
shard_type = SHARD_NONE
@@ -420,7 +437,8 @@ var/list/name_to_material
return (hardness > 35) //todo
/material/glass/reinforced
name = "reinforced glass"
name = "rglass"
display_name = "reinforced glass"
stack_type = /obj/item/stack/material/glass/reinforced
flags = MATERIAL_BRITTLE
icon_colour = "#00E1FF"
@@ -438,7 +456,8 @@ var/list/name_to_material
rod_product = null
/material/glass/phoron
name = "phoron glass"
name = "phglass"
display_name = "phoron glass"
stack_type = /obj/item/stack/material/glass/phoronglass
flags = MATERIAL_BRITTLE
ignition_point = PHORON_MINIMUM_BURN_TEMPERATURE+300
@@ -450,7 +469,8 @@ var/list/name_to_material
rod_product = /obj/item/stack/material/glass/phoronrglass
/material/glass/phoron/reinforced
name = "reinforced phoron glass"
name = "rphglass"
display_name = "reinforced phoron glass"
stack_type = /obj/item/stack/material/glass/phoronrglass
stack_origin_tech = list(TECH_MATERIAL = 4, TECH_PHORON = 2)
composite_material = list() //todo
@@ -474,7 +494,7 @@ var/list/name_to_material
stack_origin_tech = list(TECH_MATERIAL = 3)
/material/plastic/holographic
name = "holographic plastic"
name = "holoplastic"
display_name = "plastic"
stack_type = null
shard_type = SHARD_NONE
@@ -551,7 +571,7 @@ var/list/name_to_material
sheet_plural_name = "planks"
/material/wood/holographic
name = "holographic wood"
name = "holowood"
display_name = "wood"
stack_type = null
shard_type = SHARD_NONE
+2 -2
View File
@@ -12,7 +12,7 @@
metaltag = "plasteel"
requires = list(
"platinum" = 1,
"coal" = 2,
"carbon" = 2,
"hematite" = 2
)
product_mod = 0.3
@@ -21,7 +21,7 @@
/datum/alloy/steel
metaltag = DEFAULT_WALL_MATERIAL
requires = list(
"coal" = 1,
"carbon" = 1,
"hematite" = 1
)
product = /obj/item/stack/material/steel
+8 -7
View File
@@ -112,16 +112,17 @@
var/sheets_per_tick = 10
var/list/ores_processing[0]
var/list/ores_stored[0]
var/list/alloy_data[0]
var/static/list/alloy_data
var/active = 0
/obj/machinery/mineral/processing_unit/New()
..()
//TODO: Ore and alloy global storage datum.
for(var/alloytype in typesof(/datum/alloy)-/datum/alloy)
alloy_data += new alloytype()
// initialize static alloy_data list
if(!alloy_data)
alloy_data = list()
for(var/alloytype in typesof(/datum/alloy)-/datum/alloy)
alloy_data += new alloytype()
if(!ore_data || !ore_data.len)
for(var/oretype in typesof(/ore)-/ore)
@@ -209,7 +210,7 @@
var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets)
if(can_make%2>0) can_make--
var/material/M = name_to_material[O.compresses_to]
var/material/M = get_material_by_name(O.compresses_to)
if(!istype(M) || !can_make || ores_stored[metal] < 1)
continue
@@ -223,7 +224,7 @@
var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets)
var/material/M = name_to_material[O.smelts_to]
var/material/M = get_material_by_name(O.smelts_to)
if(!istype(M) || !can_make || ores_stored[metal] < 1)
continue
+19 -19
View File
@@ -37,26 +37,26 @@
/obj/machinery/mineral/mint/process()
if ( src.input)
var/obj/item/stack/material/O
O = locate(/obj/item/stack/material, input.loc)
var/obj/item/stack/O
O = locate(/obj/item/stack, input.loc)
if(O)
if (istype(O,/obj/item/stack/material/gold))
amt_gold += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/silver))
amt_silver += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/diamond))
amt_diamond += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/phoron))
amt_phoron += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/uranium))
amt_uranium += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/steel))
amt_iron += 100 * O.get_amount()
var/processed = 1
switch(O.get_material_name())
if("gold")
amt_gold += 100 * O.get_amount()
if("silver")
amt_silver += 100 * O.get_amount()
if("diamond")
amt_diamond += 100 * O.get_amount()
if("phoron")
amt_phoron += 100 * O.get_amount()
if("uranium")
amt_uranium += 100 * O.get_amount()
if(DEFAULT_WALL_MATERIAL)
amt_iron += 100 * O.get_amount()
else
processed = 0
if(processed)
qdel(O)
/obj/machinery/mineral/mint/attack_hand(user as mob)
+27 -1
View File
@@ -77,10 +77,36 @@ note dizziness decrements automatically in the mob's Life() proc.
pixel_y = old_y
//handles up-down floaty effect in space
//handles up-down floaty effect in space and zero-gravity
/mob/var/is_floating = 0
/mob/var/floatiness = 0
/mob/proc/update_floating(var/dense_object=0)
if(anchored||buckled)
make_floating(0)
return
var/turf/turf = get_turf(src)
if(!istype(turf,/turf/space))
var/area/A = turf.loc
if(istype(A) && A.has_gravity)
make_floating(0)
return
else if (Check_Shoegrip())
make_floating(0)
return
else
make_floating(1)
return
if(dense_object && Check_Shoegrip())
make_floating(0)
return
make_floating(1)
return
/mob/proc/make_floating(var/n)
floatiness = n
+5 -7
View File
@@ -34,6 +34,7 @@ var/global/list/image/ghost_sightless_images = list() //this is a list of images
/mob/dead/observer/New(mob/body)
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
see_invisible = SEE_INVISIBLE_OBSERVER
see_in_dark = 100
verbs += /mob/dead/observer/proc/dead_tele
stat = DEAD
@@ -187,8 +188,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Stat()
..()
statpanel("Status")
if (client.statpanel == "Status")
if(statpanel("Status"))
stat(null, "Station Time: [worldtime2text()]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
@@ -559,13 +559,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(src.invisibility != 0)
user.visible_message( \
"<span class='warning'>[user] drags ghost, [src], to our plane of reality!</span>", \
"<span class='warning'>\The [user] drags ghost, [src], to our plane of reality!</span>", \
"<span class='warning'>You drag [src] to our plane of reality!</span>" \
)
toggle_visibility(1)
else
user.visible_message ( \
"<span class='warning'>[user] just tried to smash his book into that ghost! It's not very effective.</span>", \
"<span class='warning'>\The [user] just tried to smash \his book into that ghost! It's not very effective.</span>", \
"<span class='warning'>You get the feeling that the ghost can't become any more visible.</span>" \
)
@@ -633,13 +633,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/updateghostsight()
if (!seedarkness)
see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
see_in_dark = 100
see_invisible = SEE_INVISIBLE_NOLIGHTING
else
see_invisible = SEE_INVISIBLE_OBSERVER
if (!ghostvision)
see_invisible = SEE_INVISIBLE_LIVING;
see_in_dark = 0
updateghostimages()
/proc/updateallghostimages()
+1
View File
@@ -70,6 +70,7 @@
blind.layer = 0
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
drop_r_hand()
+22 -13
View File
@@ -27,23 +27,37 @@
// The AI's "eye". Described on the top of the page.
/mob/living/silicon/ai
eyeobj = new /mob/eye/aiEye()
var/obj/machinery/hologram/holopad/holo = null
/mob/living/silicon/ai/proc/destroy_eyeobj(var/atom/new_eye)
if(!eyeobj) return
if(!new_eye)
new_eye = src
eyeobj.owner = null
qdel(eyeobj) // No AI, no Eye
eyeobj = null
if(client)
client.eye = new_eye
/mob/living/silicon/ai/proc/create_eyeobj(var/newloc)
if(eyeobj) destroy_eyeobj()
if(!newloc) newloc = src.loc
eyeobj = PoolOrNew(/mob/eye/aiEye, newloc)
eyeobj.owner = src
eyeobj.name = "[src.name] (AI Eye)" // Give it a name
if(client) client.eye = eyeobj
SetName(src.name)
// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us.
/mob/living/silicon/ai/New()
..()
eyeobj.owner = src
eyeobj.name = "[src.name] (AI Eye)" // Give it a name
create_eyeobj()
spawn(5)
if(eyeobj)
eyeobj.loc = src.loc
/mob/living/silicon/ai/Destroy()
if(eyeobj)
eyeobj.owner = null
qdel(eyeobj) // No AI, no Eye
eyeobj = null
destroy_eyeobj()
..()
/atom/proc/move_camera_by_click()
@@ -53,23 +67,18 @@
AI.eyeobj.setLoc(src)
// Return to the Core.
/mob/living/silicon/ai/proc/core()
set category = "AI Commands"
set name = "AI Core"
view_core()
/mob/living/silicon/ai/proc/view_core()
camera = null
unset_machine()
if(!src.eyeobj)
src << "ERROR: Eyeobj not found. Creating new eye..."
src.eyeobj = new(src.loc)
src.eyeobj.owner = src
src.SetName(src.name)
return
if(client && client.eye)
client.eye = src
+1
View File
@@ -15,6 +15,7 @@
var/acceleration = 1
var/owner_follows_eye = 0
see_in_dark = 7
status_flags = GODMODE
invisibility = INVISIBILITY_EYE
@@ -29,7 +29,6 @@
..()
/obj/structure/New()
..()
updateVisibility(src)
// EFFECTS
+1 -1
View File
@@ -25,7 +25,7 @@
speech_verb = "says"
whisper_verb = "whispers"
key = "0"
flags = RESTRICTED
flags = RESTRICTED | COMMON_VERBS
syllables = list("blah","blah","blah","bleh","meh","neh","nah","wah")
//TODO flag certain languages to use the mob-type specific say_quote and then get rid of these.
+1 -1
View File
@@ -73,7 +73,7 @@
whisper_verb = "whispers"
colour = "solcom"
key = "1"
flags = RESTRICTED
flags = WHITELISTED
//syllables are at the bottom of the file
+1
View File
@@ -4,6 +4,7 @@
icon = 'icons/mob/blob.dmi'
icon_state = "blob_spore_temp"
pass_flags = PASSBLOB
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
var/ghost_name = "Unknown"
var/creating_blob = 0
+5 -2
View File
@@ -16,6 +16,7 @@
var/obj/access_scanner = null
var/list/req_access = list()
var/list/req_one_access = list()
/mob/living/bot/New()
..()
@@ -26,14 +27,16 @@
access_scanner = new /obj(src)
access_scanner.req_access = req_access.Copy()
access_scanner.req_one_access = req_one_access.Copy()
/mob/living/bot/Life()
..()
if(health <= 0)
death()
return
weakened = 0
stunned = 0
paralysis = 0
if(health <= 0)
death()
/mob/living/bot/updatehealth()
if(status_flags & GODMODE)
+10 -9
View File
@@ -251,15 +251,16 @@
target = null
repairing = 0
update_icons()
else if(istype(A, /obj/item/stack/material/steel) && amount + 3 < maxAmount)
var/obj/item/stack/material/steel/M = A
visible_message("<span class='notice'>[src] begins to make tiles.</span>")
repairing = 1
update_icons()
if(do_after(50))
if(M)
M.use(1)
addTiles(4)
else if(istype(A, /obj/item/stack/material) && amount + 4 <= maxAmount)
var/obj/item/stack/material/M = A
if(M.get_material_name() == DEFAULT_WALL_MATERIAL)
visible_message("<span class='notice'>[src] begins to make tiles.</span>")
repairing = 1
update_icons()
if(do_after(50))
if(M)
M.use(1)
addTiles(4)
/mob/living/bot/floorbot/explode()
turn_off()
+1 -1
View File
@@ -4,7 +4,7 @@
icon_state = "secbot0"
maxHealth = 50
health = 50
req_access = list(access_security, access_forensics_lockers)
req_one_access = list(access_security, access_forensics_lockers)
botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court)
var/mob/target
@@ -95,11 +95,13 @@
sight |= SEE_TURFS
sight |= SEE_MOBS
sight |= SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
else if (stat != 2)
sight &= ~SEE_TURFS
sight &= ~SEE_MOBS
sight &= ~SEE_OBJS
see_in_dark = 2
see_invisible = SEE_INVISIBLE_LIVING
if (healths)
@@ -23,6 +23,7 @@
/obj/item/organ/brain/New()
..()
health = config.default_brain_health
spawn(5)
if(brainmob && brainmob.client)
brainmob.client.screen.len = null //clear the hud
+3 -1
View File
@@ -199,11 +199,13 @@
sight |= SEE_TURFS
sight |= SEE_MOBS
sight |= SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
else if (stat != 2)
sight &= ~SEE_TURFS
sight &= ~SEE_MOBS
sight &= ~SEE_OBJS
see_in_dark = 2
see_invisible = SEE_INVISIBLE_LIVING
if (client)
client.screen.Remove(global_hud.blurry,global_hud.druggy,global_hud.vimpaired)
@@ -252,4 +254,4 @@
emp_damage += rand(10,20)
if(3)
emp_damage += rand(0,10)
..()*/
..()*/
+2 -2
View File
@@ -372,8 +372,8 @@
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
var/temp_inc = max(BODYTEMP_HEATING_MAX*(1-get_heat_protection()), 0)
bodytemperature = min(bodytemperature + temp_inc, exposed_temperature)
var/temp_inc = max(min(BODYTEMP_HEATING_MAX*(1-get_heat_protection()), exposed_temperature - bodytemperature), 0)
bodytemperature += temp_inc
/mob/living/carbon/can_use_hands()
if(handcuffed)
@@ -154,14 +154,14 @@
return valid_species
/mob/living/carbon/human/proc/generate_valid_hairstyles()
/mob/living/carbon/human/proc/generate_valid_hairstyles(var/check_gender = 1)
var/list/valid_hairstyles = new()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if(gender == MALE && S.gender == FEMALE)
if(check_gender && gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
if(check_gender && gender == FEMALE && S.gender == MALE)
continue
if(!(species.name in S.species_allowed))
continue
@@ -185,11 +185,7 @@
return valid_facial_hairstyles
/proc/q()
var/mob/living/carbon/human/H = usr
H.change_appearance(APPEARANCE_ALL)
/mob/living/carbon/human/proc/force_update_limbs()
for(var/obj/item/organ/external/O in organs)
O.sync_colour_to_human(src)
update_body(0)
update_body(0)
@@ -101,7 +101,7 @@
if ("choke")
if(miming)
message = "clutches his throat desperately!"
message = "clutches [get_visible_gender() == MALE ? "his" : get_visible_gender() == FEMALE ? "her" : "their"] throat desperately!"
m_type = 1
else
if (!muzzled)
+17 -11
View File
@@ -54,16 +54,13 @@
/mob/living/carbon/human/Stat()
..()
statpanel("Status")
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
if (client.statpanel == "Status")
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
if (internal)
if (!internal.air_contents)
@@ -210,6 +207,10 @@
/mob/living/carbon/human/show_inv(mob/user as mob)
// TODO : Change to incapacitated() on merge.
if(user.stat || user.lying || user.resting || user.buckled)
return
var/obj/item/clothing/under/suit = null
if (istype(w_uniform, /obj/item/clothing/under))
suit = w_uniform
@@ -723,7 +724,7 @@
/mob/living/carbon/human/proc/play_xylophone()
if(!src.xylophone)
visible_message("\red [src] begins playing his ribcage like a xylophone. It's quite spooky.","\blue You begin to play a spooky refrain on your ribcage.","\red You hear a spooky xylophone melody.")
visible_message("\red \The [src] begins playing \his ribcage like a xylophone. It's quite spooky.","\blue You begin to play a spooky refrain on your ribcage.","\red You hear a spooky xylophone melody.")
var/song = pick('sound/effects/xylophone1.ogg','sound/effects/xylophone2.ogg','sound/effects/xylophone3.ogg')
playsound(loc, song, 50, 1, -1)
xylophone = 1
@@ -1361,3 +1362,8 @@
..()
if(update_hud)
handle_regular_hud_updates()
/mob/living/carbon/human/Check_Shoegrip()
if(istype(shoes, /obj/item/clothing/shoes/magboots) && (shoes.flags & NOSLIP)) //magboots + dense_object = no floating
return 1
return 0
@@ -1,3 +1,9 @@
/mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone)
for(var/datum/unarmed_attack/u_attack in species.unarmed_attacks)
if(u_attack.is_usable(src, target, hit_zone))
return u_attack
return null
/mob/living/carbon/human/attack_hand(mob/living/carbon/M as mob)
var/mob/living/carbon/human/H = M
@@ -184,18 +190,7 @@
miss_type = 2
// See what attack they use
var/possible_moves = list()
var/datum/unarmed_attack/attack = null
for(var/part in list("l_hand","r_hand","l_foot","r_foot","head"))
var/obj/item/organ/external/E = H.get_organ(part)
possible_moves |= E.species.unarmed_attacks
for(var/datum/unarmed_attack/u_attack in possible_moves)
if(!u_attack.is_usable(H, src, hit_zone))
continue
else
attack = u_attack
break
var/datum/unarmed_attack/attack = H.get_unarmed_attack(src, hit_zone)
if(!attack)
return 0
@@ -32,7 +32,7 @@
var/obj/item/organ/brain/sponge = internal_organs_by_name["brain"]
if(sponge)
sponge.take_damage(amount)
sponge.damage = min(max(brainloss, 0),(maxHealth*2))
sponge.damage = min(max(sponge.damage, 0),(maxHealth*2))
brainloss = sponge.damage
else
brainloss = 200
@@ -10,9 +10,11 @@ emp_act
/mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone)
var/obj/item/organ/external/organ = get_organ(check_zone(def_zone))
if(!organ)
return
def_zone = check_zone(def_zone)
if(!has_organ(def_zone))
return PROJECTILE_FORCE_MISS //if they don't have the organ in question then the projectile just passes by.
var/obj/item/organ/external/organ = get_organ()
//Shields
if(check_shields(P.damage, "the [P.name]"))
@@ -37,7 +39,7 @@ emp_act
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
return -1 // complete projectile permutation
return PROJECTILE_CONTINUE // complete projectile permutation
//Shrapnel
if(P.can_embed())
@@ -41,7 +41,7 @@ This saves us from having to call add_fingerprint() any time something is put in
/mob/living/carbon/human/proc/has_organ(name)
var/obj/item/organ/external/O = organs_by_name[name]
return (O && !(O.status & ORGAN_DESTROYED) )
return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump())
/mob/living/carbon/human/proc/has_organ_for_slot(slot)
switch(slot)
+10 -13
View File
@@ -1197,7 +1197,7 @@
damageoverlay.overlays += I
if( stat == DEAD )
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(healths) healths.icon_state = "health7" //DEAD healthmeter
@@ -1208,23 +1208,13 @@
item.zoom()
break
/*
if(locate(/obj/item/weapon/gun/energy/sniperrifle, contents))
var/obj/item/weapon/gun/energy/sniperrifle/s = locate() in src
if(s.zoom)
s.zoom()
if(locate(/obj/item/device/binoculars, contents))
var/obj/item/device/binoculars/b = locate() in src
if(b.zoom)
b.zoom()
*/
else
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(seer==1)
@@ -1236,7 +1226,9 @@
seer = 0
else
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
sight = species.vision_flags
see_in_dark = species.darksight
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
var/tmp/glasses_processed = 0
var/obj/item/weapon/rig/rig = back
if(istype(rig) && rig.visor)
@@ -1250,6 +1242,7 @@
process_glasses(glasses)
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(!glasses_processed && (species.vision_flags > 0))
@@ -1275,6 +1268,8 @@
if(0 to 20) healths.icon_state = "health5"
else healths.icon_state = "health6"
if(!seer)
see_invisible = SEE_INVISIBLE_LIVING
if(nutrition_icon)
switch(nutrition)
if(450 to INFINITY) nutrition_icon.icon_state = "nutrition0"
@@ -1402,6 +1397,8 @@
sight |= G.vision_flags
if(!druggy && !seer)
see_invisible = SEE_INVISIBLE_MINIMUM
if(G.see_invisible >= 0)
see_invisible = G.see_invisible
if(istype(G,/obj/item/clothing/glasses/night) && !seer)
see_invisible = SEE_INVISIBLE_MINIMUM
/* HUD shit goes here, as long as it doesn't modify sight flags */
+5 -8
View File
@@ -6,9 +6,6 @@
message = sanitize(message)
..(message, alt_name = alt_name)
/mob/living/carbon/human/is_muzzled()
return istype(src.wear_mask, /obj/item/clothing/mask/muzzle)
/mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS)
if(client)
@@ -132,11 +129,11 @@
if(silent || (sdisabilities & MUTE))
message = ""
speech_problem_flag = 1
else if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
if(hoers.voicechange)
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
verb = pick("whinnies","neighs", "says")
else if(istype(wear_mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/M = wear_mask
if(M.voicechange)
message = pick(M.say_messages)
verb = pick(M.say_verbs)
speech_problem_flag = 1
if(message != "")
@@ -8,6 +8,7 @@
language = "Sol Common" //todo?
unarmed_types = list(/datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/sharp)
light_dam = 2
darksight = 8
has_organ = list()
siemens_coefficient = 0
@@ -22,4 +23,4 @@
/datum/species/shadow/handle_death(var/mob/living/carbon/human/H)
spawn(1)
new /obj/effect/decal/cleanable/ash(H.loc)
qdel(H)
qdel(H)
@@ -5,6 +5,7 @@
deform = 'icons/mob/human_races/r_def_vox.dmi'
default_language = "Vox-pidgin"
language = "Galactic Common"
num_alternate_languages = 1
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong)
rarity_value = 2
blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \
@@ -65,7 +66,7 @@
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H.back), slot_in_backpack)
H.internal = H.r_hand
H.internals.icon_state = "internal1"
/datum/species/vox/can_shred(var/mob/living/carbon/human/H, var/ignore_intent)
if(!H.mind || !H.mind.special_role) // Pariah check.
@@ -34,9 +34,10 @@
// Language/culture vars.
var/default_language = "Galactic Common" // Default language is used when 'say' is used without modifiers.
var/language = "Galactic Common" // Default racial language, if any.
var/secondary_langs = list() // The names of secondary languages that are available to this species.
var/list/secondary_langs = list() // The names of secondary languages that are available to this species.
var/list/speech_sounds // A list of sounds to potentially play when speaking.
var/list/speech_chance // The likelihood of a speech sound playing.
var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation
// Combat vars.
var/total_health = 100 // Point at which the mob will enter crit.
@@ -47,7 +48,7 @@
var/list/unarmed_attacks = null // For empty hand harm-intent attack
var/brute_mod = 1 // Physical damage multiplier.
var/burn_mod = 1 // Burn damage multiplier.
var/vision_flags = 0 // Same flags as glasses.
var/vision_flags = SEE_SELF // Same flags as glasses.
// Death vars.
var/meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/human
@@ -100,6 +101,7 @@
var/list/inherent_verbs // Species-specific verbs.
var/has_fine_manipulation = 1 // Can use small items.
var/siemens_coefficient = 1 // The lower, the thicker the skin and better the insulation.
var/darksight = 2 // Native darksight distance.
var/flags = 0 // Various specific features.
var/slowdown = 0 // Passive movement speed malus (or boost, if negative)
var/primitive_form // Lesser form, if any (ie. monkey for humans)
@@ -9,11 +9,15 @@
/datum/unarmed_attack/diona
attack_verb = list("lashed", "bludgeoned")
attack_noun = list("tendril")
eye_attack_text = "a tendril"
eye_attack_text_victim = "a tendril"
damage = 5
/datum/unarmed_attack/claws
attack_verb = list("scratched", "clawed", "slashed")
attack_noun = list("claws")
eye_attack_text = "claws"
eye_attack_text_victim = "sharp claws"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
damage = 5
@@ -10,6 +10,7 @@
unarmed_types = list(/datum/unarmed_attack/slime_glomp)
flags = IS_RESTRICTED | NO_SCAN | NO_SLIP | NO_BREATHE
siemens_coefficient = 3
darksight = 3
blood_color = "#05FF9B"
flesh_color = "#05FFFB"
@@ -1,7 +1,6 @@
/datum/species/human
name = "Human"
name_plural = "Humans"
language = "Sol Common"
primitive_form = "Monkey"
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite)
blurb = "Humanity originated in the Sol system, and over the last five centuries has spread \
@@ -9,6 +8,8 @@
While the central Sol government maintains control of its far-flung people, powerful corporate \
interests, rampant cyber and bio-augmentation and secretive factions make life on most human \
worlds tumultous at best."
num_alternate_languages = 2
secondary_langs = list("Sol Common")
flags = CAN_JOIN | HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR
@@ -17,12 +18,14 @@
name_plural = "Unathi"
icobase = 'icons/mob/human_races/r_lizard.dmi'
deform = 'icons/mob/human_races/r_def_lizard.dmi'
language = "Sinta'unathi"
tail = "sogtail"
tail_animation = 'icons/mob/species/unathi/tail.dmi'
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp)
primitive_form = "Stok"
darksight = 3
gluttonous = 1
num_alternate_languages = 2
secondary_langs = list("Sinta'unathi")
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
Uuosa-Eso system, which roughly translates to 'burning mother'.<br/><br/>Coming from a harsh, radioactive \
@@ -68,12 +71,14 @@
name_plural = "Tajaran"
icobase = 'icons/mob/human_races/r_tajaran.dmi'
deform = 'icons/mob/human_races/r_def_tajaran.dmi'
language = "Siik'tajr"
tail = "tajtail"
tail_animation = 'icons/mob/species/tajaran/tail.dmi'
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp)
darksight = 8
slowdown = -1
brute_mod = 1.2
num_alternate_languages = 2
secondary_langs = list("Siik'tajr")
blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \
S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \
@@ -114,7 +119,6 @@
icobase = 'icons/mob/human_races/r_skrell.dmi'
deform = 'icons/mob/human_races/r_def_skrell.dmi'
eyes = "skrell_eyes_s"
language = "Skrellian"
primitive_form = "Neara"
unarmed_types = list(/datum/unarmed_attack/punch)
blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \
@@ -122,6 +126,8 @@
of the Qerr'Katish, a caste within their society which keeps the empire of the Skrell running smoothly. Skrell are \
herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \
the secrets of their empire to their allies."
num_alternate_languages = 2
secondary_langs = list("Skrellian")
flags = CAN_JOIN | IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR
@@ -145,6 +151,7 @@
siemens_coefficient = 0.3
eyes = "blank_eyes"
show_ssd = "completely quiescent"
num_alternate_languages = 1
blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \
@@ -249,6 +256,7 @@
language = "Encoded Audio Language"
unarmed_types = list(/datum/unarmed_attack/punch)
rarity_value = 2
num_alternate_languages = 1 // potentially could be 2?
eyes = "blank_eyes"
brute_mod = 1.875 // 100% * 1.875 * 0.8 (robolimbs) ~= 150%
@@ -42,7 +42,7 @@
breath_type = null
poison_type = null
vision_flags = SEE_MOBS
vision_flags = SEE_SELF|SEE_MOBS
has_organ = list(
"heart" = /obj/item/organ/heart,
@@ -3,6 +3,11 @@
if(!slot_to_strip || !istype(user))
return
// TODO : Change to incapacitated() on merge.
if(user.stat || user.lying || user.resting || user.buckled)
user << browse(null, text("window=mob[src.name]"))
return
var/obj/item/target_slot = get_equipped_item(text2num(slot_to_strip))
switch(slot_to_strip)
@@ -8,8 +8,11 @@
var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent.
var/sharp = 0
var/edge = 0
var/eye_attack_text
var/eye_attack_text_victim
/datum/unarmed_attack/proc/is_usable(var/mob/living/carbon/human/user)
/datum/unarmed_attack/proc/is_usable(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone)
if(user.restrained())
return 0
@@ -78,6 +81,13 @@
user.visible_message("<span class='warning'>[user] [pick(attack_verb)] [target] in the [affecting.name]!</span>")
playsound(user.loc, attack_sound, 25, 1, -1)
/datum/unarmed_attack/proc/handle_eye_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
var/obj/item/organ/eyes/eyes = target.internal_organs_by_name["eyes"]
eyes.take_damage(rand(3,4), 1)
user.visible_message("<span class='danger'>[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!</span>")
target << "<span class='danger'>You experience[(target.species.flags & NO_PAIN)? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(target.species.flags & NO_PAIN)? "." : "!"]</span>"
/datum/unarmed_attack/bite
attack_verb = list("bit")
attack_sound = 'sound/weapons/bite.ogg'
@@ -97,6 +107,8 @@
/datum/unarmed_attack/punch
attack_verb = list("punched")
attack_noun = list("fist")
eye_attack_text = "fingers"
eye_attack_text_victim = "digits"
damage = 0
/datum/unarmed_attack/punch/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
@@ -504,7 +504,7 @@ var/global/list/damage_icon_parts = list()
var/obj/item/clothing/under/under = w_uniform
if(under.accessories.len)
for(var/obj/item/clothing/accessory/A in under.accessories)
standing.overlays |= A.get_inv_mob_overlay()
standing.overlays |= A.get_mob_overlay()
overlays_standing[UNIFORM_LAYER] = standing
else
@@ -14,6 +14,7 @@
update_icon = 0
nutrition = 700
see_in_dark = 8
update_slimes = 0
// canstun and canweaken don't affect slimes because they ignore stun and weakened variables
@@ -401,4 +402,4 @@
/mob/living/carbon/slime/cannot_use_vents()
if(Victim)
return "You cannot ventcrawl while feeding."
..()
..()
+10 -7
View File
@@ -128,6 +128,7 @@ proc/get_radio_key_from_channel(var/channel)
return verb
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="")
if(client)
if(client.prefs.muted & MUTE_IC)
src << "\red You cannot speak in IC (Muted)."
@@ -138,10 +139,6 @@ proc/get_radio_key_from_channel(var/channel)
return say_dead(message)
return
if(is_muzzled())
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
return
var/message_mode = parse_message_mode(message, "headset")
switch(copytext(message,1,2))
@@ -165,7 +162,6 @@ proc/get_radio_key_from_channel(var/channel)
else
speaking = get_default_language()
var/ending = copytext(message, length(message))
if (speaking)
// This is broadcast to all mobs with the language,
// irrespective of distance or anything else.
@@ -173,9 +169,16 @@ proc/get_radio_key_from_channel(var/channel)
speaking.broadcast(src,trim(message))
return
//If we've gotten this far, keep going!
verb = speaking.get_spoken_verb(ending)
if(speaking.flags & COMMON_VERBS)
verb = say_quote(message)
else
verb = speaking.get_spoken_verb(copytext(message, length(message)))
else
verb = get_speech_ending(verb, ending)
verb = say_quote(message)
if(is_muzzled())
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
return
message = trim_left(message)
+1 -3
View File
@@ -49,7 +49,6 @@ var/list/ai_verbs_default = list(
var/list/network = list("Exodus")
var/obj/machinery/camera/camera = null
var/list/connected_robots = list()
var/has_power = 0
var/aiRestorePowerRoutine = 0
var/viewalerts = 0
var/icon/holo_icon//Default is assigned when AI is created.
@@ -384,8 +383,7 @@ var/list/ai_verbs_default = list(
/mob/living/silicon/ai/check_eye(var/mob/user as mob)
if (!camera)
return null
user.reset_view(camera)
return -1
return 0
/mob/living/silicon/ai/restrained()
+7 -4
View File
@@ -38,18 +38,19 @@
src << "<span class='notice'><b>APU GENERATOR FAILURE! (System Damaged)</b></span>"
stop_apu(1)
has_power = 1
var/blind = 0
var/area/loc = null
if (istype(T, /turf))
loc = T.loc
if (istype(loc, /area))
if (!loc.power_equip && !istype(src.loc,/obj/item) && !APU_power)
has_power = 0
blind = 1
if (has_power)
if (!blind)
src.sight |= SEE_TURFS
src.sight |= SEE_MOBS
src.sight |= SEE_OBJS
src.see_in_dark = 8
src.see_invisible = SEE_INVISIBLE_LIVING
if (aiRestorePowerRoutine==2)
@@ -79,10 +80,12 @@
//Blind the AI
updateicon()
src.blind.screen_loc = "1,1 to 15,15"
if (src.blind.layer!=18)
src.blind.layer = 18
src.sight = src.sight&~SEE_TURFS
src.sight = src.sight&~SEE_MOBS
src.sight = src.sight&~SEE_OBJS
src.see_in_dark = 0
src.see_invisible = SEE_INVISIBLE_LIVING
//Now to tell the AI why they're blind and dying slowly.
+9 -6
View File
@@ -39,20 +39,23 @@
laws.delete_law(law)
log_and_message_admins("has deleted a law belonging to [src]: [law.law]")
/mob/living/silicon/proc/clear_inherent_laws()
/mob/living/silicon/proc/clear_inherent_laws(var/silent = 0)
laws_sanity_check()
laws.clear_inherent_laws()
log_and_message_admins("cleared the inherent laws of [src]")
if(!silent)
log_and_message_admins("cleared the inherent laws of [src]")
/mob/living/silicon/proc/clear_ion_laws()
/mob/living/silicon/proc/clear_ion_laws(var/silent = 0)
laws_sanity_check()
laws.clear_ion_laws()
log_and_message_admins("cleared the ion laws of [src]")
if(!silent)
log_and_message_admins("cleared the ion laws of [src]")
/mob/living/silicon/proc/clear_supplied_laws()
/mob/living/silicon/proc/clear_supplied_laws(var/silent = 0)
laws_sanity_check()
laws.clear_supplied_laws()
log_and_message_admins("cleared the supplied laws of [src]")
if(!silent)
log_and_message_admins("cleared the supplied laws of [src]")
/mob/living/silicon/proc/statelaws(var/datum/ai_laws/laws)
var/prefix = ""
@@ -0,0 +1,21 @@
// Originally a debug verb, made it a proper adminverb for ~fun~
/client/proc/makePAI(turf/t in view(), name as text, pai_key as null|text)
set name = "Make pAI"
set category = "Admin"
if(!check_rights(R_ADMIN))
return
if(!pai_key)
var/client/C = input("Select client") as null|anything in clients
if(!C) return
pai_key = C.key
log_and_message_admins("made a pAI with key=[pai_key] at ([t.x],[t.y],[t.z])")
var/obj/item/device/paicard/card = new(t)
var/mob/living/silicon/pai/pai = new(card)
pai.key = pai_key
card.setPersonality(pai)
if(name)
pai.SetName(name)
@@ -120,7 +120,6 @@
/mob/living/silicon/pai/check_eye(var/mob/user as mob)
if (!src.current)
return -1
user.reset_view(src.current)
return 0
/mob/living/silicon/pai/blob_act()
@@ -25,6 +25,6 @@ var/list/robot_custom_icons
var/rname = robot_custom_icons[ckey]
if(rname && rname == real_name)
custom_sprite = 1
icon = 'icons/mob/custom_synthetic.dmi'
icon = CUSTOM_ITEM_SYNTH
if(icon_state == "robot")
icon_state = "[ckey]-Standard"
@@ -160,11 +160,11 @@
clear_supplied_laws()
clear_inherent_laws()
laws = new /datum/ai_laws/syndicate_override
set_zeroth_law("Only [user.real_name] and people he designates as being such are operatives.")
set_zeroth_law("Only [user.real_name] and people \he designates as being such are operatives.")
src << "<b>Obey these laws:</b>"
laws.show_laws(src)
src << "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and his commands.</span>"
src << "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and \his commands.</span>"
return 1
//DRONE LIFE/DEATH
@@ -213,9 +213,9 @@
death()
/mob/living/silicon/robot/drone/proc/full_law_reset()
clear_supplied_laws()
clear_inherent_laws()
clear_ion_laws()
clear_supplied_laws(1)
clear_inherent_laws(1)
clear_ion_laws(1)
laws = new law_type
//Reboot procs.
@@ -257,23 +257,21 @@
src << "<b>You are a maintenance drone, a tiny-brained robotic repair machine</b>."
src << "You have no individual will, no personality, and no drives or urges other than your laws."
src << "Remember, you are <b>lawed against interference with the crew</b>. Also remember, <b>you DO NOT take orders from the AI.</b>"
src << "Use <b>:d</b> to talk to other drones and <b>say</b> to speak silently to your nearby fellows."
src << "Use <b>say ;Hello</b> to talk to other drones and <b>say Hello</b> to speak silently to your nearby fellows."
/mob/living/silicon/robot/drone/start_pulling(var/atom/movable/AM)
if(istype(AM,/obj/item/pipe) || istype(AM,/obj/structure/disposalconstruct))
..()
else if(istype(AM,/obj/item))
var/obj/item/O = AM
if(O.w_class > can_pull_size)
src << "<span class='warning'>You are too small to pull that.</span>"
return
if(!(istype(AM,/obj/item/pipe) || istype(AM,/obj/structure/disposalconstruct)))
if(istype(AM,/obj/item))
var/obj/item/O = AM
if(O.w_class > can_pull_size)
src << "<span class='warning'>You are too small to pull that.</span>"
return
else
..()
else
if(!can_pull_mobs)
src << "<span class='warning'>You are too small to pull that.</span>"
return
if(!can_pull_mobs)
src << "<span class='warning'>You are too small to pull that.</span>"
return
..()
/mob/living/silicon/robot/drone/add_robot_verbs()
src.verbs |= silicon_subsystems
@@ -300,4 +298,4 @@
/mob/living/silicon/robot/drone/construction/updatename()
real_name = "construction drone ([rand(100,999)])"
name = real_name
name = real_name
@@ -0,0 +1,40 @@
/mob/living/silicon/robot/drone/say(var/message)
if(local_transmit)
if (src.client)
if(client.prefs.muted & MUTE_IC)
src << "You cannot send IC messages (muted)."
return 0
if (src.client.handle_spam_prevention(message,MUTE_IC))
return 0
message = sanitize(message)
if (stat == 2)
return say_dead(message)
if(copytext(message,1,2) == "*")
return emote(copytext(message,2))
if(copytext(message,1,2) == ";")
var/datum/language/L = all_languages["Drone Talk"]
if(istype(L))
return L.broadcast(src,trim(copytext(message,2)))
//Must be concious to speak
if (stat)
return 0
var/list/listeners = hearers(5,src)
listeners |= src
for(var/mob/living/silicon/D in listeners)
if(D.client && D.local_transmit)
D << "<b>[src]</b> transmits, \"[message]\""
for (var/mob/M in player_list)
if (istype(M, /mob/new_player))
continue
else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
if(M.client) M << "<b>[src]</b> transmits, \"[message]\""
return 1
..(message)
@@ -65,12 +65,12 @@
m_type = 2
if ("flap")
if (!src.restrained())
message = "flaps his wings."
message = "flaps its wings."
m_type = 2
if ("aflap")
if (!src.restrained())
message = "flaps his wings ANGRILY!"
message = "flaps its wings ANGRILY!"
m_type = 2
if ("twitch")
@@ -213,4 +213,4 @@
if ((message && src.stat == 0))
custom_emote(m_type,message)
return
return
@@ -65,9 +65,9 @@
if(src.camera && !scrambledcodes)
if(src.stat == 2 || wires.IsIndexCut(BORG_WIRE_CAMERA))
src.camera.status = 0
src.camera.set_status(0)
else
src.camera.status = 1
src.camera.set_status(1)
updatehealth()
@@ -163,11 +163,13 @@
see_invisible = SEE_INVISIBLE_MINIMUM
else if (src.sight_mode & BORGTHERM)
src.sight |= SEE_MOBS
src.see_in_dark = 8
src.see_invisible = SEE_INVISIBLE_LEVEL_TWO
else if (src.stat != 2)
src.sight &= ~SEE_MOBS
src.sight &= ~SEE_TURFS
src.sight &= ~SEE_OBJS
src.see_in_dark = 8 // see_in_dark means you can FAINTLY see in the dark, humans have a range of 3 or so, tajaran have it at 8
src.see_invisible = SEE_INVISIBLE_LIVING // This is normal vision (25), setting it lower for normal vision means you don't "see" things like darkness since darkness
// has a "invisible" value of 15
+13 -14
View File
@@ -182,7 +182,7 @@
aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src)
laws = new /datum/ai_laws/syndicate_override
module = new /obj/item/weapon/robot_module/syndicate(src)
new /obj/item/weapon/robot_module/syndicate(src)
radio.keyslot = new /obj/item/device/encryptionkey/syndicate(radio)
radio.recalculateChannels()
@@ -263,7 +263,7 @@
return
var/module_type = robot_modules[modtype]
module = new module_type(src)
new module_type(src)
hands.icon_state = lowertext(modtype)
feedback_inc("cyborg_[lowertext(modtype)]",1)
@@ -421,8 +421,7 @@
// update the status screen display
/mob/living/silicon/robot/Stat()
..()
statpanel("Status")
if (client.statpanel == "Status")
if (statpanel("Status"))
show_cell_power()
show_jetpack_pressure()
stat(null, text("Lights: [lights_on ? "ON" : "OFF"]"))
@@ -1049,25 +1048,25 @@
laws = new /datum/ai_laws/syndicate_override
var/time = time2text(world.realtime,"hh:mm:ss")
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
set_zeroth_law("Only [user.real_name] and people he designates as being such are operatives.")
set_zeroth_law("Only [user.real_name] and people \he designates as being such are operatives.")
. = 1
spawn()
src << "\red ALERT: Foreign software detected."
src << "<span class='danger'>ALERT: Foreign software detected.</span>"
sleep(5)
src << "\red Initiating diagnostics..."
src << "<span class='danger'>Initiating diagnostics...</span>"
sleep(20)
src << "\red SynBorg v1.7.1 loaded."
src << "<span class='danger'>SynBorg v1.7.1 loaded.</span>"
sleep(5)
src << "\red LAW SYNCHRONISATION ERROR"
src << "<span class='danger'>LAW SYNCHRONISATION ERROR</span>"
sleep(5)
src << "\red Would you like to send a report to NanoTraSoft? Y/N"
src << "<span class='danger'>Would you like to send a report to NanoTraSoft? Y/N</span>"
sleep(10)
src << "\red > N"
src << "<span class='danger'>> N</span>"
sleep(20)
src << "\red ERRORERRORERROR"
src << "<span class='danger'>ERRORERRORERROR</span>"
src << "<b>Obey these laws:</b>"
laws.show_laws(src)
src << "\red \b ALERT: [user.real_name] is your new master. Obey your new laws and his commands."
src << "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and his commands.</span>"
if(src.module)
var/rebuild = 0
for(var/obj/item/weapon/pickaxe/borgdrill/D in src.module.modules)
@@ -1081,4 +1080,4 @@
user << "You fail to hack [src]'s interface."
src << "Hack attempt detected."
return 1
return
return
@@ -36,7 +36,7 @@
for(var/obj/I in contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/material))//Only deconsturcts one sheet at a time instead of the entire stack
if(istype(I,/obj/item/stack/material))//Only deconstructs one sheet at a time instead of the entire stack
var/obj/item/stack/material/S = I
if(S.get_amount() > 1)
S.use(1)
@@ -39,6 +39,8 @@ var/global/list/robot_modules = list(
/obj/item/weapon/robot_module/New(var/mob/living/silicon/robot/R)
..()
R.module = src
add_camera_networks(R)
add_languages(R)
add_subsystems(R)
@@ -69,7 +71,7 @@ var/global/list/robot_modules = list(
synths = null
emag = null
jetpack = null
..()
return ..()
/obj/item/weapon/robot_module/emp_act(severity)
if(modules)
@@ -504,7 +506,7 @@ var/global/list/robot_modules = list(
src.modules += L
src.modules += new /obj/item/weapon/tray/robotray(src)
src.modules += new /obj/item/weapon/reagent_containers/food/drinks/shaker(src)
src.modules += new /obj/item/weapon/reagent_containers/borghypo/service(src)
src.emag = new /obj/item/weapon/reagent_containers/food/drinks/cans/beer(src)
var/datum/reagents/R = new/datum/reagents(50)
+32 -125
View File
@@ -1,3 +1,35 @@
/mob/living/silicon/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
log_say("[key_name(src)] : [message]")
/mob/living/silicon/robot/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..()
if(message_mode)
if(!is_component_functioning("radio"))
src << "<span class='warning'>Your radio isn't functional at this time.</span>"
return 0
if(message_mode == "general")
message_mode = null
return radio.talk_into(src,message,message_mode,verb,speaking)
/mob/living/silicon/ai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..()
if(message_mode == "department")
return holopad_talk(message, verb, speaking)
else if(message_mode)
if (aiRadio.disabledAi || aiRestorePowerRoutine || stat)
src << "<span class='danger'>System Error - Transceiver Disabled.</span>"
return 0
if(message_mode == "general")
message_mode = null
return aiRadio.talk_into(src,message,message_mode,verb,speaking)
/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
..()
if(message_mode)
if(message_mode == "general")
message_mode = null
return radio.talk_into(src,message,message_mode,verb,speaking)
/mob/living/silicon/say_quote(var/text)
var/ending = copytext(text, length(text))
@@ -23,131 +55,6 @@
return 1
return ..()
/mob/living/silicon/say(var/message)
if (!message)
return 0
if (src.client)
if(client.prefs.muted & MUTE_IC)
src << "You cannot send IC messages (muted)."
return 0
if (src.client.handle_spam_prevention(message,MUTE_IC))
return 0
message = sanitize(message)
if (stat == 2)
return say_dead(message)
if(copytext(message,1,2) == "*")
return emote(copytext(message,2))
var/bot_type = 0 //Let's not do a fuck ton of type checks, thanks.
if(istype(src, /mob/living/silicon/ai))
bot_type = IS_AI
else if(istype(src, /mob/living/silicon/robot))
bot_type = IS_ROBOT
else if(istype(src, /mob/living/silicon/pai))
bot_type = IS_PAI
var/mob/living/silicon/ai/AI = src //and let's not declare vars over and over and over for these guys.
var/mob/living/silicon/robot/R = src
var/mob/living/silicon/pai/P = src
//Must be concious to speak
if (stat)
return 0
var/verb = say_quote(message)
//parse radio key and consume it
var/message_mode = parse_message_mode(message, "general")
if (message_mode)
if (message_mode == "general")
message = trim(copytext(message,2))
else
message = trim(copytext(message,3))
//parse language key and consume it
var/datum/language/speaking = parse_language(message)
if (speaking)
verb = speaking.speech_verb
message = trim(copytext(message,2+length(speaking.key)))
if(speaking.flags & HIVEMIND)
speaking.broadcast(src,trim(message))
return 1
// Currently used by drones.
if(local_transmit)
var/list/listeners = hearers(5,src)
listeners |= src
for(var/mob/living/silicon/D in listeners)
if(D.client && istype(D,src.type))
D << "<b>[src]</b> transmits, \"[message]\""
for (var/mob/M in player_list)
if (istype(M, /mob/new_player))
continue
else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
if(M.client) M << "<b>[src]</b> transmits, \"[message]\""
return 1
if(message_mode && bot_type == IS_ROBOT && !R.is_component_functioning("radio"))
src << "\red Your radio isn't functional at this time."
return 0
switch(message_mode)
if("department")
switch(bot_type)
if(IS_AI)
return AI.holopad_talk(message, verb, speaking)
if(IS_ROBOT)
log_say("[key_name(src)] : [message]")
return R.radio.talk_into(src,message,message_mode,verb,speaking)
if(IS_PAI)
log_say("[key_name(src)] : [message]")
return P.radio.talk_into(src,message,message_mode,verb,speaking)
return 0
if("general")
switch(bot_type)
if(IS_AI)
if (AI.aiRadio.disabledAi || AI.aiRestorePowerRoutine || AI.stat)
src << "\red System Error - Transceiver Disabled"
return 0
else
log_say("[key_name(src)] : [message]")
return AI.aiRadio.talk_into(src,message,null,verb,speaking)
if(IS_ROBOT)
log_say("[key_name(src)] : [message]")
return R.radio.talk_into(src,message,null,verb,speaking)
if(IS_PAI)
log_say("[key_name(src)] : [message]")
return P.radio.talk_into(src,message,null,verb,speaking)
return 0
else
if(message_mode)
switch(bot_type)
if(IS_AI)
if (AI.aiRadio.disabledAi || AI.aiRestorePowerRoutine || AI.stat)
src << "\red System Error - Transceiver Disabled"
return 0
else
log_say("[key_name(src)] : [message]")
return AI.aiRadio.talk_into(src,message,message_mode,verb,speaking)
if(IS_ROBOT)
log_say("[key_name(src)] : [message]")
return R.radio.talk_into(src,message,message_mode,verb,speaking)
if(IS_PAI)
log_say("[key_name(src)] : [message]")
return P.radio.talk_into(src,message,message_mode,verb,speaking)
return 0
return ..(message,speaking,verb)
//For holopads only. Usable by AI.
/mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking)
@@ -27,6 +27,7 @@
show_stat_health = 1
faction = "cult"
supernatural = 1
see_invisible = SEE_INVISIBLE_NOLIGHTING
var/nullblock = 0
mob_swap_flags = HUMAN|SIMPLE_ANIMAL|SLIME|MONKEY
@@ -150,6 +151,7 @@
attacktext = "slashed"
speed = -1
environment_smash = 1
see_in_dark = 7
attack_sound = 'sound/weapons/rapidslice.ogg'
construct_spells = list(/spell/targeted/ethereal_jaunt/shift)
@@ -227,6 +229,7 @@
attacktext = "violently stabbed"
speed = -1
environment_smash = 1
see_in_dark = 7
attack_sound = 'sound/weapons/pierce.ogg'
construct_spells = list(

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