Merge remote-tracking branch 'upstream/dev' into 150702-MoneyMoneyMoney

Conflicts:
	code/__defines/mobs.dm
	code/game/jobs/job/civilian.dm
	code/game/jobs/job_controller.dm
This commit is contained in:
PsiOmegaDelta
2015-08-13 08:06:11 +02:00
426 changed files with 10672 additions and 9746 deletions

View File

@@ -302,7 +302,11 @@ datum/admins/proc/DB_ban_unban_by_id(var/id)
output += "<option value='[j]'>[j]</option>"
for(var/j in nonhuman_positions)
output += "<option value='[j]'>[j]</option>"
for(var/j in list("traitor","changeling","operative","revolutionary","cultist","wizard"))
var/list/bantypes = list("traitor","changeling","operative","revolutionary","cultist","wizard") //For legacy bans.
for(var/antag_type in all_antag_types) // Grab other bans.
var/datum/antagonist/antag = all_antag_types[antag_type]
bantypes |= antag.bantype
for(var/j in bantypes)
output += "<option value='[j]'>[j]</option>"
output += "</select></td></tr></table>"
output += "<b>Reason:<br></b><textarea name='dbbanreason' cols='50'></textarea><br>"

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)

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!

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,

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

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

View File

@@ -574,7 +574,13 @@
//JOBBAN'S INNARDS
else if(href_list["jobban3"])
if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN)) return
if(!check_rights(R_MOD,0) && !check_rights(R_ADMIN,0))
usr << "<span class='warning'>You do not have the appropriate permissions to add job bans!</span>"
return
if(check_rights(R_MOD,0) && !check_rights(R_ADMIN,0) && !config.mods_can_job_tempban) // If mod and tempban disabled
usr << "<span class='warning'>Mod jobbanning is disabled!</span>"
return
var/mob/M = locate(href_list["jobban4"])
if(!ismob(M))
@@ -649,13 +655,18 @@
if(notbannedlist.len) //at least 1 unbanned job exists in joblist so we have stuff to ban.
switch(alert("Temporary Ban?",,"Yes","No", "Cancel"))
if("Yes")
if(!check_rights(R_MOD,0) && !check_rights(R_BAN)) return
if(!check_rights(R_MOD,0) && !check_rights(R_BAN, 0))
usr << "<span class='warning'> You Cannot issue temporary job-bans!</span>"
return
if(config.ban_legacy_system)
usr << "\red Your server is using the legacy banning system, which does not support temporary job bans. Consider upgrading. Aborting ban."
return
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null
if(!mins)
return
if(check_rights(R_MOD, 0) && !check_rights(R_BAN, 0) && mins > config.mod_job_tempban_max)
usr << "<span class='warning'> Moderators can only job tempban up to [config.mod_job_tempban_max] minutes!</span>"
return
var/reason = sanitize(input(usr,"Reason?","Please State Reason","") as text|null)
if(!reason)
return
@@ -764,7 +775,13 @@
DB_ban_unban(ckey(key), BANTYPE_JOB_PERMA, job)
else if(href_list["newban"])
if(!check_rights(R_MOD,0) && !check_rights(R_BAN)) return
if(!check_rights(R_MOD,0) && !check_rights(R_BAN, 0))
usr << "<span class='warning'>You do not have the appropriate permissions to add bans!</span>"
return
if(check_rights(R_MOD,0) && !check_rights(R_ADMIN, 0) && !config.mods_can_job_tempban) // If mod and tempban disabled
usr << "<span class='warning'>Mod jobbanning is disabled!</span>"
return
var/mob/M = locate(href_list["newban"])
if(!ismob(M)) return
@@ -776,6 +793,9 @@
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null
if(!mins)
return
if(check_rights(R_MOD, 0) && !check_rights(R_BAN, 0) && mins > config.mod_tempban_max)
usr << "<span class='warning'>Moderators can only job tempban up to [config.mod_tempban_max] minutes!</span>"
return
if(mins >= 525600) mins = 525599
var/reason = sanitize(input(usr,"Reason?","reason","Griefer") as text|null)
if(!reason)
@@ -1314,7 +1334,7 @@
src.owner << "You sent [input] to [L] via a secure channel."
log_admin("[src.owner] replied to [key_name(L)]'s Centcomm message with the message [input].")
message_admins("[src.owner] replied to [key_name(L)]'s Centcom message with: \"[input]\"")
if(!L.isAI())
if(!L.isMobAI())
L << "<span class='info'>You hear something crackle in your headset for a moment before a voice speaks.</span>"
L << "<span class='info'>Please stand by for a message from Central Command.</span>"
L << "<span class='info'>Message as follows.</span>"
@@ -1344,7 +1364,7 @@
var/obj/item/fax = locate(href_list["AdminFaxView"])
if (istype(fax, /obj/item/weapon/paper))
var/obj/item/weapon/paper/P = fax
P.show_content(usr)
P.show_content(usr,1)
else if (istype(fax, /obj/item/weapon/photo))
var/obj/item/weapon/photo/H = fax
H.show(usr)
@@ -1631,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"])

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"

View File

@@ -21,7 +21,7 @@
var/stafftype = uppertext(holder.rank)
msg = sanitize(msg)
log_admin("[key_name(src)] : [msg]")
log_admin("DSAY: [key_name(src)] : [msg]")
if (!msg)
return

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)

View File

@@ -441,7 +441,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
//Announces the character on all the systems, based on the record.
if(!issilicon(new_character))//If they are not a cyborg/AI.
if(!record_found&&new_character.mind.assigned_role!="MODE")//If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway.
if(!record_found && !player_is_antag(new_character.mind, only_offstation_roles = 1)) //If there are no records for them. If they have a record, this info is already in there. MODE people are not announced anyway.
//Power to the user!
if(alert(new_character,"Warning: No data core entry detected. Would you like to announce the arrival of this character by adding them to various databases, such as medical records?",,"No","Yes")=="Yes")
data_core.manifest_inject(new_character)

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

View File

@@ -33,7 +33,7 @@
if( findtext(href,"<script",1,0) )
world.log << "Attempted use of scripts within a topic call, by [src]"
message_admins("Attempted use of scripts within a topic call, by [src]")
//qdel(usr)
//del(usr)
return
//Admin PM
@@ -112,7 +112,7 @@
if(!config.guests_allowed && IsGuestKey(key))
alert(src,"This server doesn't allow guest accounts to play. Please go to http://www.byond.com/ and register for a key.","Guest","OK")
qdel(src)
del(src)
return
// Change the way they should download resources.
@@ -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()

View File

@@ -4,6 +4,7 @@ var/list/preferences_datums = list()
var/global/list/special_roles = list( //keep synced with the defines BE_* in setup.dm --rastaf
//some autodetection here.
// TODO: Update to new antagonist system.
"traitor" = IS_MODE_COMPILED("traitor"), // 0
"operative" = IS_MODE_COMPILED("nuclear"), // 1
"changeling" = IS_MODE_COMPILED("changeling"), // 2
@@ -74,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.
@@ -84,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
@@ -132,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())
@@ -307,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>"
@@ -381,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>"
@@ -1126,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")
@@ -1135,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"])
@@ -1243,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)
@@ -1640,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

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

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

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

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

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)

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

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"

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

View File

@@ -66,7 +66,6 @@
icon_state = "vox-carapace"
item_state = "vox-carapace"
desc = "A glowing visor, perhaps stolen from a depressed Cylon."
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
/obj/item/clothing/suit/space/vox/carapace
name = "alien carapace armour"

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

View File

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

View File

@@ -115,6 +115,13 @@
H << "<span class='warning'>You cannot teleport into solid walls.</span>"
return 0
if(T.z in config.admin_levels)
H << "<span class='warning'>You cannot use your teleporter on this Z-level.</span>"
return 0
if(T.contains_dense_objects())
H << "<span class='warning'>You cannot teleport to a location with solid objects.</span>"
phase_out(H,get_turf(H))
H.loc = T
phase_in(H,get_turf(H))

View File

@@ -213,9 +213,9 @@
else if(charge.charges < chems_to_use)
chems_to_use = charge.charges
var/mob/living/target_mob
var/mob/living/carbon/target_mob
if(target)
if(istype(target,/mob/living))
if(istype(target,/mob/living/carbon))
target_mob = target
else
return 0
@@ -439,4 +439,4 @@
else if(device == deniedstamp)
device = iastamp
holder.wearer << "<span class='notice'>Switched to internal affairs stamp.</span>"
return 1
return 1

View File

@@ -64,13 +64,14 @@
var/malfunction_delay = 0
var/electrified = 0
var/locked_down = 0
var/locked_dna = null
var/seal_delay = SEAL_DELAY
var/sealing // Keeps track of seal status independantly of canremove.
var/offline = 1 // Should we be applying suit maluses?
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)
@@ -205,7 +207,7 @@
if(!instant)
M.visible_message("<font color='blue'>[M]'s suit emits a quiet hum as it begins to adjust its seals.</font>","<font color='blue'>With a quiet hum, the suit begins running checks and adjusting components.</font>")
if(!do_after(M,SEAL_DELAY))
if(seal_delay && !do_after(M,seal_delay))
if(M) M << "<span class='warning'>You must remain still while the suit is adjusting the components.</span>"
failed_to_seal = 1
@@ -229,9 +231,8 @@
if(!failed_to_seal && M.back == src && piece == compare_piece)
if(!instant)
if(!do_after(M,SEAL_DELAY,needhand=0))
failed_to_seal = 1
if(seal_delay && !instant && !do_after(M,seal_delay,needhand=0))
failed_to_seal = 1
piece.icon_state = "[initial(icon_state)][!seal_target ? "_sealed" : ""]"
switch(msg_type)
@@ -248,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
@@ -274,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
@@ -291,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()
@@ -500,10 +494,6 @@
return 0
if(user.back != src)
return 0
if(locked_dna)
if(!user.dna || user.dna.unique_enzymes != locked_dna)
user << "<span class='danger'>DNA scan mismatch. Access denied.</span>"
return 0
else if(!src.allowed(user))
user << "<span class='danger'>Unauthorized user. Access denied.</span>"
return 0
@@ -563,10 +553,9 @@
/obj/item/weapon/rig/equipped(mob/living/carbon/human/M)
..()
if(istype(M) && M.back == src)
if(seal_delay > 0 && istype(M) && M.back == src)
M.visible_message("<font color='blue'>[M] starts putting on \the [src]...</font>", "<font color='blue'>You start putting on \the [src]...</font>")
if(!do_after(M,SEAL_DELAY))
if(!do_after(M,seal_delay))
if(M && M.back == src)
M.back = null
M.drop_from_inventory(src)

View File

@@ -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.
@@ -188,7 +188,6 @@
/obj/item/weapon/rig/emag_act(var/remaining_charges, var/mob/user)
if(!subverted)
locked_dna = null
req_access.Cut()
req_one_access.Cut()
locked = 0

View File

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

View File

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

View File

@@ -145,9 +145,14 @@
/obj/item/rig_module/vision/meson
)
chest_type = /obj/item/clothing/suit/space/rig/ce
boot_type = null
glove_type = null
/obj/item/clothing/suit/space/rig/ce
heat_protection = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
/obj/item/weapon/rig/hazmat
name = "AMI control module"

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"

View File

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

View File

@@ -20,6 +20,7 @@
/datum/custom_item
var/assoc_key
var/character_name
var/inherit_inhands = 1 //if unset, and inhands are not provided, then the inhand overlays will be invisible.
var/item_icon
var/item_desc
var/name
@@ -44,11 +45,27 @@
if(item_desc)
item.desc = item_desc
if(item_icon)
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
if(istype(item, /obj/item))
if(!istype(item))
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
return
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
@@ -66,6 +83,48 @@
return item
/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
if(!("[item_icon]_l" in available_states))
new_item_state_slots[slot_l_hand_str] = get_state(item, slot_l_hand_str, "_l")
new_item_icons[slot_l_hand_str] = get_icon(item, slot_l_hand_str, 'icons/mob/items/lefthand.dmi')
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
//this has to mirror the way update_inv_*_hand() selects the state
/datum/custom_item/proc/get_state(var/obj/item/item, var/slot_str, var/hand_str)
var/t_state
if(item.item_state_slots && item.item_state_slots[slot_str])
t_state = item.item_state_slots[slot_str]
else if(item.item_state)
t_state = item.item_state
else
t_state = item.icon_state
if(item.icon_override)
t_state += hand_str
return t_state
//this has to mirror the way update_inv_*_hand() selects the icon
/datum/custom_item/proc/get_icon(var/obj/item/item, var/slot_str, var/icon/hand_icon)
var/icon/t_icon
if(item.icon_override)
t_icon = item.icon_override
else if(item.item_icons && (slot_str in item.item_icons))
t_icon = item.item_icons[slot_str]
else
t_icon = hand_icon
return t_icon
// Parses the config file into the custom_items list.
/hook/startup/proc/load_custom_items()
@@ -107,6 +166,8 @@
current_data.name = field_data
if("item_icon")
current_data.item_icon = field_data
if("inherit_inhands")
current_data.inherit_inhands = text2num(field_data)
if("item_desc")
current_data.item_desc = field_data
if("req_access")
@@ -174,16 +235,8 @@
if(M.equip_to_appropriate_slot(newitem))
return newitem
if(istype(M.back,/obj/item/weapon/storage))
var/obj/item/weapon/storage/backpack = M.back
if(backpack.contents.len < backpack.storage_slots)
newitem.loc = M.back
return newitem
if(M.equip_to_storage(newitem))
return newitem
// Try to place it in any item that can store stuff, on the mob.
for(var/obj/item/weapon/storage/S in M.contents)
if (S.contents.len < S.storage_slots)
newitem.loc = S
return newitem
newitem.loc = get_turf(M.loc)
return newitem

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

View File

@@ -8,7 +8,7 @@
endWhen = rand(500, 1500)
// command_alert("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert")
for (var/mob/living/carbon/human/player in player_list)
if( !player.mind || player.mind.assigned_role == "MODE" || player.client.inactivity > MinutesToTicks(10))
if( !player.mind || player_is_antag(player.mind, only_offstation_roles = 1) || player.client.inactivity > MinutesToTicks(10))
continue
players += player.real_name
@@ -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)

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

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)

View File

@@ -107,7 +107,7 @@ proc/populate_ghost_traps()
ghost_trap_role = "Plant"
/datum/ghosttrap/plant/welcome_candidate(var/mob/target)
target << "<span class='alium><B>You awaken slowly, stirring into sluggish motion as the air caresses you.</B></span>"
target << "<span class='alium'><B>You awaken slowly, stirring into sluggish motion as the air caresses you.</B></span>"
// This is a hack, replace with some kind of species blurb proc.
if(istype(target,/mob/living/carbon/alien/diona))
target << "<B>You are \a [target], one of a race of drifting interstellar plantlike creatures that sometimes share their seeds with human traders.</B>"

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)

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

View File

@@ -160,7 +160,7 @@
//Splatter a turf.
/datum/seed/proc/splatter(var/turf/T,var/obj/item/thrown)
if(splat_type)
if(splat_type && !(locate(/obj/effect/plant) in T))
var/obj/effect/plant/splat = new splat_type(T, src)
if(!istype(splat)) // Plants handle their own stuff.
splat.name = "[thrown.name] [pick("smear","smudge","splatter")]"
@@ -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 += "?"

View File

@@ -58,10 +58,10 @@
var/growth_threshold = 0
var/growth_type = 0
var/max_growth = 0
var/sampled
var/list/neighbors = list()
var/obj/effect/plant/parent
var/datum/seed/seed
var/sampled = 0
var/floor = 0
var/spread_chance = 40
var/spread_distance = 3
@@ -237,8 +237,14 @@
plant_controller.add_plant(src)
if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel))
if(sampled)
user << "<span class='warning'>\The [src] has already been sampled recently.</span>"
return
if(!is_mature())
user << "<span class='warning'>\The [src] is not mature enough to yield a sample yet.</span>"
return
if(!seed)
user << "<span class='danger'>There is nothing to take a sample from.</span>"
user << "<span class='warning'>There is nothing to take a sample from.</span>"
return
if(sampled)
user << "<span class='danger'>You cannot take another sample from \the [src].</span>"
@@ -246,7 +252,8 @@
if(prob(70))
sampled = 1
seed.harvest(user,0,1)
health -= (rand(3,5)*10)
health -= (rand(3,5)*5)
sampled = 1
else
..()
if(W.force)

View File

@@ -69,6 +69,12 @@
last_tick = world.time
update_neighbors()
if(sampled)
//Should be between 2-7 for given the default range of values for TRAIT_PRODUCTION
var/chance = max(1, round(30/seed.get_trait(TRAIT_PRODUCTION)))
if(prob(chance))
sampled = 0
if(is_mature() && neighbors.len && prob(spread_chance))
//spread to 1-3 adjacent turfs depending on yield trait.
var/max_spread = between(1, round(seed.get_trait(TRAIT_YIELD)*3/14), 3)

View File

@@ -275,7 +275,6 @@
seed.harvest(user,yield_mod)
else
seed.harvest(get_turf(src),yield_mod)
// Reset values.
harvest = 0
lastproduce = age
@@ -307,6 +306,7 @@
mutation_mod = 0
user << "You remove the dead plant."
lastproduce = 0
check_health()
return
@@ -476,6 +476,7 @@
return
user << "You plant the [S.seed.seed_name] [S.seed.seed_noun]."
lastproduce = 0
seed = S.seed //Grab the seed datum.
dead = 0
age = 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

View File

@@ -3,8 +3,7 @@
#define LIGHTING_FALLOFF 1 // type of falloff to use for lighting; 1 for circular, 2 for square
#define LIGHTING_LAMBERTIAN 1 // use lambertian shading for light sources
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
#define LIGHTING_TRANSITIONS 1 // smooth, animated transitions, similar to /tg/station
#define LIGHTING_ROUND_VALUE (1 / 128) //Value used to round lumcounts, values smaller than 1/255 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
#define LIGHTING_RESOLUTION 1 // resolution of the lighting overlays, powers of 2 only, max of 32
#define LIGHTING_LAYER 10 // drawing layer for lighting overlays
#define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects

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)
@@ -60,13 +61,23 @@
if(top_atom != source_atom)
if(!top_atom.light_sources) top_atom.light_sources = list()
top_atom.light_sources += src
lighting_update_lights += src
needs_update = 1
if(!needs_update) //Incase we're already updating either way.
lighting_update_lights += src
needs_update = 1
/datum/light_source/proc/force_update()
needs_update = 1
force_update = 1
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)
@@ -93,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
@@ -111,59 +127,125 @@
lum_g = 1
lum_b = 1
/datum/light_source/proc/falloff(atom/movable/lighting_overlay/O)
#if LIGHTING_FALLOFF == 1 // circular
#if LIGHTING_RESOLUTION == 1
. = (O.x - source_turf.x)**2 + (O.y - source_turf.y)**2 + LIGHTING_HEIGHT
#else
. = (O.x - source_turf.x + O.xoffset)**2 + (O.y - source_turf.y + O.yoffset)**2 + LIGHTING_HEIGHT
#endif
#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
#if LIGHTING_RESOLUTION == 1
. = abs(O.x - source_turf.x) + abs(O.y - source_turf.y) + LIGHTING_HEIGHT
#else
. = abs(O.x - source_turf.x + O.xoffset) + abs(O.y - source_turf.y + O.yoffset) + LIGHTING_HEIGHT
#endif
#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/atom/movable/lighting_overlay/O in view(light_range, source_turf))
var/strength = light_power * falloff(O)
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
if(T.lighting_overlay)
var/strength
LUM_FALLOFF(strength, T, source_turf)
strength *= light_power
effect_r[O] = lum_r * strength
effect_g[O] = lum_g * strength
effect_b[O] = lum_b * strength
if(!strength) //Don't add turfs that aren't affected to the affected turfs.
continue
strength = round(strength, LIGHTING_ROUND_VALUE) //Screw sinking points.
effect_str += strength
T.lighting_overlay.update_lumcount(
lum_r * strength,
lum_g * strength,
lum_b * strength
)
else
effect_str += 0
if(!T.affecting_lights)
T.affecting_lights = list()
O.update_lumcount(lum_r * strength, lum_g * strength, lum_b * strength)
for(var/turf/T in view(light_range, source_turf))
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
for(var/atom/movable/lighting_overlay/O in effect_r)
O.update_lumcount(-effect_r[O], -effect_g[O], -effect_b[O])
var/i = 1
for(var/turf/T in effect_turf)
if(T.affecting_lights) T.affecting_lights -= src
if(T.affecting_lights)
T.affecting_lights -= src
effect_r.Cut()
effect_g.Cut()
effect_b.Cut()
if(T.lighting_overlay)
var/str = effect_str[i]
T.lighting_overlay.update_lumcount(-str * old_lum_r, -str * old_lum_g, -str * old_lum_b)
i++
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

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

View File

@@ -5,44 +5,98 @@
anchored = 1
icon = LIGHTING_ICON
icon_state = "light1"
layer = LIGHTING_LAYER
invisibility = INVISIBILITY_LIGHTING
blend_mode = BLEND_MULTIPLY
color = "#000000"
var/lum_r
var/lum_g
var/lum_b
#if LIGHTING_RESOLUTION != 1
var/xoffset
var/yoffset
#endif
var/needs_update
/atom/movable/lighting_overlay/New()
. = ..()
verbs.Cut()
var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays in things that aren't turfs.
T.luminosity = 0
/atom/movable/lighting_overlay/proc/update_lumcount(delta_r, delta_g, delta_b)
if(!delta_r && !delta_g && !delta_b) //Nothing is being changed all together.
return
var/should_update = 0
if(!needs_update) //If this isn't true, we're already updating anyways.
if(max(lum_r, lum_g, lum_b) < 1) //Any change that could happen WILL change appearance.
should_update = 1
else if(max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b) < 1) //The change would bring us under 1 max lum, again, guaranteed to change appearance.
should_update = 1
else //We need to make sure that the colour ratios won't change in this code block.
var/mx1 = max(lum_r, lum_g, lum_b)
var/mx2 = max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b)
if(lum_r / mx1 != (lum_r + delta_r) / mx2 || lum_g / mx1 != (lum_g + delta_g) / mx2 || lum_b / mx1 != (lum_b + delta_b) / mx2) //Stuff would change.
should_update = 1
lum_r += delta_r
lum_g += delta_g
lum_b += delta_b
needs_update = 1
lighting_update_overlays += src
if(!needs_update && should_update)
needs_update = 1
lighting_update_overlays += src
/atom/movable/lighting_overlay/proc/update_overlay()
var/mx = max(lum_r, lum_g, lum_b)
. = 1 // factor
if(mx > 1)
. = 1/mx
#if LIGHTING_TRANSITIONS == 1
animate(src,
color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .),
LIGHTING_INTERVAL - 1
)
#else
color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .)
#endif
var/turf/T = loc
if(istype(T)) //Incase we're not on a turf, pool ourselves, something happened.
if(lum_r == lum_g && lum_r == lum_b) //greyscale
blend_mode = BLEND_OVERLAY
if(lum_r <= 0)
T.luminosity = 0
color = "#000000"
alpha = 255
else
T.luminosity = 1
color = "#000000"
alpha = (1 - min(lum_r, 1)) * 255
else
alpha = 255
var/mx = max(lum_r, lum_g, lum_b)
. = 1 // factor
if(mx > 1)
. = 1/mx
blend_mode = BLEND_MULTIPLY
color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .)
if(color != "#000000")
T.luminosity = 1
else //No light, set the turf's luminosity to 0 to remove it from view()
T.luminosity = 0
else
warning("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : ""]) in update_overlay() and got pooled!")
qdel(src)
/atom/movable/lighting_overlay/ResetVars()
loc = null
lum_r = 0
lum_g = 0
lum_b = 0
color = "#000000"
needs_update = 0
/atom/movable/lighting_overlay/Destroy()
lighting_update_overlays -= src
var/turf/T = loc
if(istype(T))
T.lighting_overlay = null
..()

View File

@@ -1,27 +1,35 @@
/datum/controller/process/lighting/setup()
name = "lighting"
schedule_interval = LIGHTING_INTERVAL
create_lighting_overlays()
/datum/controller/process/lighting/doWork()
for(var/datum/light_source/L in lighting_update_lights)
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
scheck()
lighting_update_lights.Cut()
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays)
if(O.needs_update)
O.update_overlay()
O.needs_update = 0
scheck()
lighting_update_overlays.Cut()
/datum/controller/process/lighting/setup()
name = "lighting"
schedule_interval = LIGHTING_INTERVAL
create_lighting_overlays()
/datum/controller/process/lighting/doWork()
var/list/lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from scheck() don't cause things to be cut from the list without being updated.
lighting_update_lights = null //Nulling it first because of http://www.byond.com/forum/?post=1854520
lighting_update_lights = list()
for(var/datum/light_source/L in lighting_update_lights_old)
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()
var/list/lighting_update_overlays_old = lighting_update_overlays //Same as above.
lighting_update_overlays = null //Same as above
lighting_update_overlays = list()
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old)
O.update_overlay()
O.needs_update = 0
scheck()

View File

@@ -5,26 +5,15 @@
// duplicates lots of code, but this proc needs to be as fast as possible.
/proc/create_lighting_overlays(zlevel = 0)
var/state = "light[LIGHTING_RESOLUTION]"
var/area/A
if(zlevel == 0) // populate all zlevels
for(var/turf/T in world)
if(T.dynamic_lighting)
A = T.loc
if(A.lighting_use_dynamic)
#if LIGHTING_RESOLUTION == 1
var/atom/movable/lighting_overlay/O = new(T)
O.icon_state = state
#else
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
var/atom/movable/lighting_overlay/O = new(T)
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
O.icon_state = state
#endif
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T)
T.lighting_overlay = O
else
for(var/x = 1; x <= world.maxx; x++)
for(var/y = 1; y <= world.maxy; y++)
@@ -32,16 +21,5 @@
if(T.dynamic_lighting)
A = T.loc
if(A.lighting_use_dynamic)
#if LIGHTING_RESOLUTION == 1
var/atom/movable/lighting_overlay/O = new(T)
O.icon_state = state
#else
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
var/atom/movable/lighting_overlay/O = new(T)
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
O.icon_state = state
#endif
var/atom/movable/lighting_overlay/O = PoolOrNew(/atom/movable/lighting_overlay, T)
T.lighting_overlay = O

View File

@@ -1,29 +1,28 @@
/turf
var/list/affecting_lights
var/atom/movable/lighting_overlay/lighting_overlay
/turf/proc/reconsider_lights()
for(var/datum/light_source/L in affecting_lights)
L.force_update()
L.vis_update()
/turf/proc/lighting_clear_overlays()
for(var/atom/movable/lighting_overlay/L in src)
L.loc = null
if(lighting_overlay)
qdel(lighting_overlay)
/turf/proc/lighting_build_overlays()
if(!locate(/atom/movable/lighting_overlay) in src)
var/state = "light[LIGHTING_RESOLUTION]"
if(!lighting_overlay)
var/area/A = loc
if(A.lighting_use_dynamic)
#if LIGHTING_RESOLUTION == 1
var/atom/movable/lighting_overlay/O = new(src)
O.icon_state = state
#else
for(var/i = 0; i < LIGHTING_RESOLUTION; i++)
for(var/j = 0; j < LIGHTING_RESOLUTION; j++)
var/atom/movable/lighting_overlay/O = new(src)
O.pixel_x = i * (32 / LIGHTING_RESOLUTION)
O.pixel_y = j * (32 / LIGHTING_RESOLUTION)
O.xoffset = (((2*i + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
O.yoffset = (((2*j + 1) / (LIGHTING_RESOLUTION * 2)) - 0.5)
O.icon_state = state
#endif
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()

View File

@@ -3,7 +3,6 @@
#undef LIGHTING_FALLOFF
#undef LIGHTING_LAMBERTIAN
#undef LIGHTING_HEIGHT
#undef LIGHTING_TRANSITIONS
#undef LIGHTING_RESOLUTION
#undef LIGHTING_LAYER

View File

@@ -82,7 +82,7 @@
..()
recipes += new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1)
recipes += new/datum/stack_recipe("Metal crate", /obj/structure/closet/crate, 10, time = 50, one_per_turf = 1)
recipes += new/datum/stack_recipe("knife grip", /obj/item/weapon/material/butterflyhandle, 4, time = 20, one_per_turf = 0, on_floor = 1)
recipes += new/datum/stack_recipe("knife grip", /obj/item/weapon/material/butterflyhandle, 4, time = 20, one_per_turf = 0, on_floor = 1, supplied_material = "[name]")
/material/sandstone/generate_recipes()
..()

View File

@@ -24,9 +24,6 @@
qdel(src)
return 0
// Update from material datum.
name = "[material.display_name] sheets"
desc = "A stack of sheets of [material.display_name]."
recipes = material.get_recipes()
stacktype = material.stack_type
if(islist(material.stack_origin_tech))
@@ -40,13 +37,37 @@
flags |= CONDUCT
matter = material.get_matter()
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]."
gender = PLURAL
else
name = "[material.use_name] [material.sheet_singular_name]"
desc = "A [material.sheet_singular_name] of [material.use_name]."
gender = NEUTER
/obj/item/stack/material/use(var/used)
. = ..()
update_strings()
return
/obj/item/stack/material/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified)
var/obj/item/stack/material/M = S
if(!istype(M) || material.name != M.material.name)
return 0
..(S,tamount,1)
if(src) update_strings()
if(M) M.update_strings()
/obj/item/stack/material/attack_self(var/mob/user)
if(!material.build_windows(user, src))
@@ -69,10 +90,14 @@
/obj/item/stack/material/sandstone
name = "sandstone brick"
singular_name = "sandstone brick"
icon_state = "sheet-sandstone"
default_type = "sandstone"
/obj/item/stack/material/marble
name = "marble brick"
icon_state = "sheet-marble"
default_type = "marble"
/obj/item/stack/material/diamond
name = "diamond"
icon_state = "sheet-diamond"
@@ -130,62 +155,53 @@
/obj/item/stack/material/steel
name = DEFAULT_WALL_MATERIAL
singular_name = "steel sheet"
icon_state = "sheet-metal"
default_type = DEFAULT_WALL_MATERIAL
/obj/item/stack/material/plasteel
name = "plasteel"
singular_name = "plasteel sheet"
icon_state = "sheet-plasteel"
item_state = "sheet-metal"
default_type = "plasteel"
/obj/item/stack/material/wood
name = "wooden plank"
singular_name = "wood plank"
icon_state = "sheet-wood"
default_type = "wood"
/obj/item/stack/material/cloth
name = "cloth"
singular_name = "cloth roll"
icon_state = "sheet-cloth"
default_type = "cloth"
/obj/item/stack/material/cardboard
name = "cardboard"
singular_name = "cardboard sheet"
icon_state = "sheet-card"
default_type = "cardboard"
/obj/item/stack/material/leather
name = "leather"
desc = "The by-product of mob grinding."
singular_name = "leather piece"
icon_state = "sheet-leather"
default_type = "leather"
/obj/item/stack/material/glass
name = "glass"
singular_name = "glass sheet"
icon_state = "sheet-glass"
default_type = "glass"
/obj/item/stack/material/glass/reinforced
name = "reinforced glass"
singular_name = "reinforced glass sheet"
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"
singular_name = "reinforced phoron glass sheet"
icon_state = "sheet-phoronrglass"
default_type = "reinforced phoron glass"
default_type = "rphglass"

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)

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,12 +55,20 @@ 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.
var/display_name // Prettier name for display.
var/use_name
var/flags = 0 // Various status modifiers.
var/sheet_singular_name = "sheet"
var/sheet_plural_name = "sheets"
// Shards/tables/structures
var/shard_type = SHARD_SHRAPNEL // Path of debris object.
@@ -231,6 +250,8 @@ var/list/name_to_material
weight = 24
hardness = 40
stack_origin_tech = list(TECH_MATERIAL = 4)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
/material/gold/bronze //placeholder for ashtrays
name = "bronze"
@@ -243,6 +264,8 @@ var/list/name_to_material
weight = 22
hardness = 50
stack_origin_tech = list(TECH_MATERIAL = 3)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
/material/phoron
name = "phoron"
@@ -254,6 +277,8 @@ var/list/name_to_material
hardness = 30
stack_origin_tech = list(TECH_MATERIAL = 2, TECH_PHORON = 2)
door_icon_base = "stone"
sheet_singular_name = "crystal"
sheet_plural_name = "crystals"
/*
// Commenting this out while fires are so spectacularly lethal, as I can't seem to get this balanced appropriately.
@@ -282,6 +307,8 @@ var/list/name_to_material
weight = 22
hardness = 55
door_icon_base = "stone"
sheet_singular_name = "brick"
sheet_plural_name = "bricks"
/material/stone/marble
name = "marble"
@@ -289,6 +316,7 @@ var/list/name_to_material
weight = 26
hardness = 100
integrity = 201 //hack to stop kitchen benches being flippable, todo: refactor into weight system
stack_type = /obj/item/stack/material/marble
/material/steel
name = DEFAULT_WALL_MATERIAL
@@ -299,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
@@ -409,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"
@@ -427,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
@@ -439,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
@@ -463,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
@@ -473,12 +504,16 @@ var/list/name_to_material
stack_type = /obj/item/stack/material/osmium
icon_colour = "#9999FF"
stack_origin_tech = list(TECH_MATERIAL = 5)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
/material/tritium
name = "tritium"
stack_type = /obj/item/stack/material/tritium
icon_colour = "#777777"
stack_origin_tech = list(TECH_MATERIAL = 5)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
/material/mhydrogen
name = "mhydrogen"
@@ -492,12 +527,16 @@ var/list/name_to_material
icon_colour = "#9999FF"
weight = 27
stack_origin_tech = list(TECH_MATERIAL = 2)
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
/material/iron
name = "iron"
stack_type = /obj/item/stack/material/iron
icon_colour = "#5C5454"
weight = 22
sheet_singular_name = "ingot"
sheet_plural_name = "ingots"
// Adminspawn only, do not let anyone get this.
/material/voxalloy
@@ -528,9 +567,11 @@ var/list/name_to_material
dooropen_noise = 'sound/effects/doorcreaky.ogg'
door_icon_base = "wood"
destruction_desc = "splinters"
sheet_singular_name = "plank"
sheet_plural_name = "planks"
/material/wood/holographic
name = "holographic wood"
name = "holowood"
display_name = "wood"
stack_type = null
shard_type = SHARD_NONE
@@ -566,6 +607,8 @@ var/list/name_to_material
icon_colour = "#402821"
icon_reinf = "reinf_cult"
shard_type = SHARD_STONE_PIECE
sheet_singular_name = "brick"
sheet_plural_name = "bricks"
/material/cult/place_dismantled_girder(var/turf/target)
new /obj/structure/girder/cult(target)
@@ -586,6 +629,8 @@ var/list/name_to_material
dooropen_noise = 'sound/effects/attackblob.ogg'
door_icon_base = "resin"
melting_point = T0C+300
sheet_singular_name = "blob"
sheet_plural_name = "blobs"
/material/resin/can_open_material_door(var/mob/living/user)
var/mob/living/carbon/M = user
@@ -610,6 +655,8 @@ var/list/name_to_material
flags = MATERIAL_PADDING
ignition_point = T0C+232
melting_point = T0C+300
sheet_singular_name = "tile"
sheet_plural_name = "tiles"
/material/cotton
name = "cotton"

View File

@@ -4,8 +4,8 @@
icon_state = "securecrate"
icon_opened = "securecrateopen"
icon_closed = "securecrate"
var/code = null
var/lastattempt = null
var/list/code = list()
var/list/lastattempt = list()
var/attempts = 10
var/codelen = 4
locked = 1
@@ -14,12 +14,12 @@
..()
var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
code = ""
for(var/i = 0, i < codelen, i++)
var/dig = pick(digits)
code += dig
digits -= dig // Player can enter codes with matching digits, but there are never matching digits in the answer
for(var/i in 1 to codelen)
code += pick(digits)
generate_loot()
/obj/structure/closet/crate/secure/loot/proc/generate_loot()
var/loot = rand(1, 100)
switch(loot)
if(1 to 5) // Common things go, 5%
@@ -145,60 +145,65 @@
new/obj/item/clothing/head/bearpelt(src)
/obj/structure/closet/crate/secure/loot/togglelock(mob/user as mob)
if(locked)
user << "<span class='notice'>The crate is locked with a Deca-code lock.</span>"
var/input = input(usr, "Enter [codelen] digits.", "Deca-Code Lock", "") as text
if(in_range(src, user))
if (input == code)
user << "<span class='notice'>The crate unlocks!</span>"
locked = 0
overlays.Cut()
overlays += greenlight
else if (input == null || length(input) != codelen)
user << "<span class='notice'>You leave the crate alone.</span>"
else
user << "<span class='warning'>A red light flashes.</span>"
lastattempt = input
attempts--
if (attempts == 0)
user << "<span class='danger'>The crate's anti-tamper system activates!</span>"
var/turf/T = get_turf(src.loc)
explosion(T, 0, 0, 0, 1)
qdel(src)
return
else
user << "<span class='notice'>You attempt to interact with the device using a hand gesture, but it appears this crate is from before the DECANECT came out.</span>"
return
if(!locked)
return
user << "<span class='notice'>The crate is locked with a Deca-code lock.</span>"
var/input = input(user, "Enter [codelen] digits.", "Deca-Code Lock", "") as text
if(!Adjacent(user))
return
if(input == null || length(input) != codelen)
user << "<span class='notice'>You leave the crate alone.</span>"
else if(check_input(input))
user << "<span class='notice'>The crate unlocks!</span>"
playsound(user, 'sound/machines/lockreset.ogg', 50, 1)
set_locked(0)
else
return ..()
visible_message("<span class='warning'>A red light on \the [src]'s control panel flashes briefly.</span>")
attempts--
if (attempts == 0)
user << "<span class='danger'>The crate's anti-tamper system activates!</span>"
var/turf/T = get_turf(src.loc)
explosion(T, 0, 0, 1, 2)
del(src)
/obj/structure/closet/crate/secure/loot/emag_act(var/remaining_charges, var/mob/user)
if (locked)
user << "<span class='notice'>The crate unlocks!</span>"
locked = 0
/obj/structure/closet/crate/secure/loot/proc/check_input(var/input)
if(length(input) != codelen)
return 0
. = 1
lastattempt.Cut()
for(var/i in 1 to codelen)
var/guesschar = copytext(input, i, i+1)
lastattempt += guesschar
if(guesschar != code[i])
. = 0
/obj/structure/closet/crate/secure/loot/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(locked)
if (istype(W, /obj/item/device/multitool)) // Greetings Urist McProfessor, how about a nice game of cows and bulls?
user << "<span class='notice'>DECA-CODE LOCK REPORT:</span>"
user << "<span class='notice'>DECA-CODE LOCK ANALYSIS:</span>"
if (attempts == 1)
user << "<span class='warning'>* Anti-Tamper Bomb will activate on next failed access attempt.</span>"
user << "<span class='warning'>* Anti-Tamper system will activate on the next failed access attempt.</span>"
else
user << "<span class='notice'>* Anti-Tamper Bomb will activate after [src.attempts] failed access attempts.</span>"
if (lastattempt != null)
var/list/guess = list()
user << "<span class='notice'>* Anti-Tamper system will activate after [src.attempts] failed access attempts.</span>"
if(lastattempt.len)
var/bulls = 0
var/cows = 0
for(var/i = 1, i < codelen + 1, i++)
var/a = copytext(lastattempt, i, i+1) // Stuff the code into the list
guess += a
guess[a] = i
for(var/i in guess) // Go through list and count matches
var/a = findtext(code, i)
if(a == guess[i])
var/list/code_contents = code.Copy()
for(var/i in 1 to codelen)
if(lastattempt[i] == code[i])
++bulls
else if(a)
else if(lastattempt[i] in code_contents)
++cows
code_contents -= lastattempt[i]
user << "<span class='notice'>Last code attempt had [bulls] correct digits at correct positions and [cows] correct digits at incorrect positions.</span>"
else ..()
else ..()
return
..()

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

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

View File

@@ -340,8 +340,8 @@
R.amount = rand(5,25)
if(2)
var/obj/item/stack/tile/R = new(src)
R.amount = rand(1,5)
var/obj/item/stack/material/plasteel/R = new(src)
R.amount = rand(5,25)
if(3)
var/obj/item/stack/material/steel/R = new(src)

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)

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

View File

@@ -141,17 +141,6 @@ Works together with spawning an observer, noted above.
var/client/C = U.client
for(var/mob/living/carbon/human/target in target_list)
C.images += target.hud_list[SPECIALROLE_HUD]
/*
else//If the silicon mob has no law datum, no inherent laws, or a law zero, add them to the hud.
var/mob/living/silicon/silicon_target = target
if(!silicon_target.laws||(silicon_target.laws&&(silicon_target.laws.zeroth||!silicon_target.laws.inherent.len))||silicon_target.mind.special_role=="traitor")
if(isrobot(silicon_target))//Different icons for robutts and AI.
U.client.images += image(tempHud,silicon_target,"hudmalborg")
else
U.client.images += image(tempHud,silicon_target,"hudmalai")
*/
return 1
/mob/proc/ghostize(var/can_reenter_corpse = 1)
@@ -199,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()
@@ -571,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>" \
)
@@ -645,7 +633,7 @@ 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_invisible = SEE_INVISIBLE_NOLIGHTING
else
see_invisible = SEE_INVISIBLE_OBSERVER
if (!ghostvision)

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

View File

@@ -29,7 +29,6 @@
..()
/obj/structure/New()
..()
updateVisibility(src)
// EFFECTS

View File

@@ -73,6 +73,21 @@ var/list/slot_equipment_priority = list( \
return 0
/mob/proc/equip_to_storage(obj/item/newitem)
// Try put it in their backpack
if(istype(src.back,/obj/item/weapon/storage))
var/obj/item/weapon/storage/backpack = src.back
if(backpack.contents.len < backpack.storage_slots)
newitem.loc = src.back
return 1
// Try to place it in any item that can store stuff, on the mob.
for(var/obj/item/weapon/storage/S in src.contents)
if (S.contents.len < S.storage_slots)
newitem.loc = S
return 1
return 0
//These procs handle putting s tuff in your hand. It's probably best to use these rather than setting l_hand = ...etc
//as they handle all relevant stuff like adding it to the player's screen and updating their overlays.

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.

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

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)

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

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
@@ -342,7 +342,7 @@
if(emagged)
return 10
return M.assess_perp(access_scanner, idcheck, check_records, check_arrest)
return M.assess_perp(access_scanner, 0, idcheck, check_records, check_arrest)
/mob/living/bot/secbot/proc/patrol_step()
if(loc == patrol_target)

View File

@@ -48,5 +48,5 @@
/mob/living/carbon/alien/show_inv(mob/user as mob)
return //Consider adding cuffs and hats to this, for the sake of fun.
/mob/living/carbon/alien/can_use_vents()
/mob/living/carbon/alien/cannot_use_vents()
return

View File

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

View File

@@ -195,6 +195,18 @@
else
healths.icon_state = "health7"
if (stat == 2 || (XRAY in src.mutations))
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)
@@ -242,4 +254,4 @@
emp_damage += rand(10,20)
if(3)
emp_damage += rand(0,10)
..()*/
..()*/

View File

@@ -23,6 +23,12 @@
qdel(food)
return ..()
/mob/living/carbon/rejuvenate()
bloodstr.clear_reagents()
ingested.clear_reagents()
touching.clear_reagents()
..()
/mob/living/carbon/Move(NewLoc, direct)
. = ..()
if(.)
@@ -261,8 +267,9 @@
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [t_him] up!</span>", \
"<span class='notice'>You shake [src] trying to wake [t_him] up!</span>")
else
if(istype(H))
H.species.hug(H,src)
var/mob/living/carbon/human/hugger = M
if(istype(hugger))
hugger.species.hug(hugger,src)
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [t_him] feel better!</span>", \
"<span class='notice'>You hug [src] to make [t_him] feel better!</span>")
@@ -309,22 +316,6 @@
//Throwing stuff
/mob/living/carbon/proc/toggle_throw_mode()
if (src.in_throw_mode)
throw_mode_off()
else
throw_mode_on()
/mob/living/carbon/proc/throw_mode_off()
src.in_throw_mode = 0
if(src.throw_icon) //in case we don't have the HUD and we use the hotkey
src.throw_icon.icon_state = "act_throw_off"
/mob/living/carbon/proc/throw_mode_on()
src.in_throw_mode = 1
if(src.throw_icon)
src.throw_icon.icon_state = "act_throw_on"
/mob/proc/throw_item(atom/target)
return
@@ -381,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)
@@ -452,7 +443,7 @@
if(istype(AM, /mob/living/carbon) && prob(10))
src.spread_disease_to(AM, "Contact")
/mob/living/carbon/can_use_vents()
/mob/living/carbon/cannot_use_vents()
return
/mob/living/carbon/slip(var/slipped_on,stun_duration=8)

View File

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

View File

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

View File

@@ -25,32 +25,45 @@
skipface |= wear_mask.flags_inv & HIDEFACE
// crappy hacks because you can't do \his[src] etc. I'm sorry this proc is so unreadable, blame the text macros :<
var/t_He = "It" //capitalised for use at the start of each line.
var/t_his = "its"
var/t_him = "it"
var/t_has = "has"
var/t_is = "is"
var/t_He = "They" //capitalised for use at the start of each line.
var/t_he = "they"
var/t_his = "their"
var/t_him = "them"
var/t_has = "have"
var/t_is = "are"
var/t_does = "do"
var/msg = "<span class='info'>*---------*\nThis is "
if( skipjumpsuit && skipface ) //big suits/masks/helmets make it hard to tell their gender
t_He = "They"
t_his = "their"
t_him = "them"
t_has = "have"
t_is = "are"
else
//big suits/masks/helmets make it hard to tell their gender
if(!skipjumpsuit || !skipface)
if(icon)
msg += "\icon[icon] " //fucking BYOND: this should stop dreamseeker crashing if we -somehow- examine somebody before their icon is generated
switch(gender)
if(MALE)
t_He = "He"
t_he = "he"
t_his = "his"
t_him = "him"
t_has = "has"
t_is = "is"
t_does = "does"
if(FEMALE)
t_He = "She"
t_he = "she"
t_his = "her"
t_him = "her"
t_has = "has"
t_is = "is"
t_does = "does"
if(NEUTER)
t_He = "It"
t_he = "it"
t_his = "its"
t_him = "it"
t_has = "has"
t_is = "is"
t_does = "does"
msg += "<EM>[src.name]</EM>"
if(species.name != "Human")
@@ -214,15 +227,15 @@
if (src.stat)
msg += "<span class='warning'>[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.</span>\n"
if((stat == 2 || src.losebreath) && distance <= 3)
msg += "<span class='warning'>[t_He] does not appear to be breathing.</span>\n"
msg += "<span class='warning'>[t_He] [t_does] not appear to be breathing.</span>\n"
if(istype(usr, /mob/living/carbon/human) && !usr.stat && Adjacent(usr))
usr.visible_message("<b>[usr]</b> checks [src]'s pulse.", "You check [src]'s pulse.")
spawn(15)
if(distance <= 1 && usr.stat != 1)
if(pulse == PULSE_NONE)
usr << "<span class='deadsay'>[t_He] has no pulse[src.client ? "" : " and [t_his] soul has departed"]...</span>"
usr << "<span class='deadsay'>[t_He] [t_has] no pulse[src.client ? "" : " and [t_his] soul has departed"]...</span>"
else
usr << "<span class='deadsay'>[t_He] has a pulse!</span>"
usr << "<span class='deadsay'>[t_He] [t_has] a pulse!</span>"
if(fire_stacks)
msg += "[t_He] [t_is] covered in some liquid.\n"
if(on_fire)
@@ -244,7 +257,7 @@
if(species.show_ssd && (!species.has_organ["brain"] || has_brain()) && stat != DEAD)
if(!key)
msg += "<span class='deadsay'>[t_He] [t_is] [species.show_ssd]. It doesn't look like they are waking up anytime soon.</span>\n"
msg += "<span class='deadsay'>[t_He] [t_is] fast asleep. It doesn't look like [t_he] [t_is] waking up anytime soon.</span>\n"
else if(!client)
msg += "<span class='deadsay'>[t_He] [t_is] [species.show_ssd].</span>\n"
@@ -269,6 +282,10 @@
for(var/obj/item/organ/external/temp in organs)
if(temp)
if(temp.status & ORGAN_DESTROYED)
is_destroyed["[temp.name]"] = 1
wound_flavor_text["[temp.name]"] = "<span class='warning'><b>[t_He] [t_is] missing [t_his] [temp.name].</b></span>\n"
continue
if(temp.status & ORGAN_ROBOT)
if(!(temp.brute_dam + temp.burn_dam))
wound_flavor_text["[temp.name]"] = "<span class='warning'>[t_He] has a robot [temp.name]!</span>\n"
@@ -301,7 +318,7 @@
if(wound_flavor_text["head"] && (is_destroyed["head"] || (!skipmask && !(wear_mask && istype(wear_mask, /obj/item/clothing/mask/gas)))))
msg += wound_flavor_text["head"]
else if(is_bleeding["head"])
msg += "<span class='warning'>[src] has blood running down [t_his] face!</span>\n"
msg += "<span class='warning'>[src] [t_has] blood running down [t_his] face!</span>\n"
if(wound_flavor_text["upper body"] && !w_uniform && !skipjumpsuit) //No need. A missing chest gibs you.
msg += wound_flavor_text["upper body"]
@@ -352,11 +369,11 @@
display_shoes = 1
if(display_chest)
msg += "<span class='danger'>[src] has blood soaking through from under [t_his] clothing!</span>\n"
msg += "<span class='danger'>[src] [t_has] blood soaking through from under [t_his] clothing!</span>\n"
if(display_shoes)
msg += "<span class='danger'>[src] has blood running from [t_his] shoes!</span>\n"
msg += "<span class='danger'>[src] [t_has] blood running from [t_his] shoes!</span>\n"
if(display_gloves)
msg += "<span class='danger'>[src] has blood running from under [t_his] gloves!</span>\n"
msg += "<span class='danger'>[src] [t_has] blood running from under [t_his] gloves!</span>\n"
*/
for(var/limb in wound_flavor_text)
@@ -365,7 +382,7 @@
for(var/limb in is_bleeding)
msg += is_bleeding[limb]
for(var/implant in get_visible_implants(0))
msg += "<span class='danger'>[src] has \a [implant] sticking out of [t_his] flesh!</span>\n"
msg += "<span class='danger'>[src] [t_has] \a [implant] sticking out of [t_his] flesh!</span>\n"
if(digitalcamo)
msg += "[t_He] [t_is] repulsively uncanny!\n"
@@ -421,7 +438,7 @@
if (pose)
if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 )
pose = addtext(pose,".") //Makes sure all emotes end with a period.
msg += "\n[t_He] is [pose]"
msg += "\n[t_He] [t_is] [pose]"
user << msg

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -445,7 +445,7 @@
else if(exhaled_pp > safe_exhaled_max * 0.7)
if (!co2_alert || prob(1))
var/word = pick("dizzy","short of breath","faint","momentarily confused")
src << "<span class='warning>You feel [word].</span>"
src << "<span class='warning'>You feel [word].</span>"
//scale linearly from 0 to 1 between safe_exhaled_max and safe_exhaled_max*0.7
var/ratio = 1.0 - (safe_exhaled_max - exhaled_pp)/(safe_exhaled_max*0.3)
@@ -459,7 +459,7 @@
else if(exhaled_pp > safe_exhaled_max * 0.6)
if (prob(0.3))
var/word = pick("a little dizzy","short of breath")
src << "<span class='warning>You feel [word].</span>"
src << "<span class='warning'>You feel [word].</span>"
else
co2_alert = 0
@@ -486,7 +486,7 @@
// Enough to make us sleep as well
if(SA_pp > SA_sleep_min)
sleeping = min(sleeping+2, 10)
Sleeping(5)
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
else if(SA_pp > 0.15)
@@ -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,20 +1208,8 @@
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_in_dark = species.darksight
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : SEE_INVISIBLE_LIVING
if(XRAY in mutations)
@@ -1237,6 +1225,10 @@
see_invisible = SEE_INVISIBLE_LIVING
seer = 0
else
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)
@@ -1248,6 +1240,10 @@
if(glasses && !glasses_processed)
glasses_processed = 1
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))
sight |= species.vision_flags
@@ -1272,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"
@@ -1399,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 */
@@ -1684,6 +1684,7 @@
holder.icon_state = "hudblank"
if(mind)
// TODO: Update to new antagonist system.
switch(mind.special_role)
if("traitor","Mercenary")
holder.icon_state = "hudsyndicate"
@@ -1746,5 +1747,9 @@
if (thermal_protection < 1 && bodytemperature < burn_temperature)
bodytemperature += round(BODYTEMP_HEATING_MAX*(1-thermal_protection), 1)
/mob/living/carbon/human/rejuvenate()
restore_blood()
..()
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS

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)
@@ -129,21 +126,15 @@
return verb
/mob/living/carbon/human/handle_speech_problems(var/message, var/verb)
if(!speech_problem_flag)
return ..()
var/list/returns[3]
speech_problem_flag = 0
if(silent || (sdisabilities & MUTE))
message = ""
speech_problem_flag = 1
if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
if(hoers.voicechange)
if(mind && mind.changeling && department_radio_keys[copytext(message, 1, 3)] != "changeling")
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
verb = pick("whinnies","neighs", "says")
speech_problem_flag = 1
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 != "")
var/list/parent = ..()
@@ -162,6 +153,7 @@
message = uppertext(message)
verb = "yells loudly"
var/list/returns[3]
returns[1] = message
returns[2] = verb
returns[3] = speech_problem_flag

View File

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

View File

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

View File

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

View File

@@ -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,13 +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 \
@@ -69,13 +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 \
@@ -116,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 \
@@ -124,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
@@ -147,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 \
@@ -251,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%

View File

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

View File

@@ -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)
@@ -59,6 +64,7 @@
return
if(!target_slot.canremove)
user << "<span class='warning'>You cannot remove \the [src]'s [target_slot.name].</span>"
return
stripping = 1
if(stripping)
@@ -73,11 +79,9 @@
return
if(stripping)
attack_log += "\[[time_stamp()]\] <font color='orange'>Has had \the [target_slot] removed by [user.name] ([user.ckey])</font>"
user.attack_log += "\[[time_stamp()]\] <font color='red'>Attempted to remove [name]'s ([ckey]) [target_slot.name]</font>"
drop_from_inventory(target_slot)
else
user.drop_from_inventory(held)
admin_attack_log(user, src, "Attempted to remove \a [target_slot]", "Target of an attempt to remove \a [target_slot].", "attempted to remove \a [target_slot] from")
unEquip(target_slot)
else if(user.unEquip(held))
equip_to_slot_if_possible(held, text2num(slot_to_strip), 0, 1, 1)
if(held.loc != src)
user.put_in_hands(held)
@@ -88,9 +92,9 @@
user << "<span class='warning'>\The [src] has nothing in their pockets.</span>"
return
if(r_store)
drop_from_inventory(r_store)
unEquip(r_store)
if(l_store)
drop_from_inventory(l_store)
unEquip(l_store)
visible_message("<span class='danger'>\The [user] empties \the [src]'s pockets!</span>")
// Modify the current target sensor level.

View File

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

View File

@@ -236,13 +236,22 @@ var/global/list/damage_icon_parts = list()
//CACHING: Generate an index key from visible bodyparts.
//0 = destroyed, 1 = normal, 2 = robotic, 3 = necrotic.
//Create a new, blank icon for our mob to use.
if(stand_icon)
qdel(stand_icon)
stand_icon = new(species.icon_template ? species.icon_template : 'icons/mob/human.dmi',"blank")
var/icon_key = ""
var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"]
var/g = "male"
if(gender == FEMALE)
g = "female"
var/icon_key = "[species.race_key][g][s_tone][r_skin][g_skin][b_skin]"
if(lip_style)
icon_key += "[lip_style]"
else
icon_key += "nolips"
var/obj/item/organ/eyes/eyes = internal_organs_by_name["eyes"]
if(eyes)
icon_key += "[rgb(eyes.eye_colour[1], eyes.eye_colour[2], eyes.eye_colour[3])]"
else
@@ -495,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
@@ -643,6 +652,7 @@ var/global/list/damage_icon_parts = list()
t_icon = head.icon_override
else if(head.sprite_sheets && head.sprite_sheets[species.name])
t_icon = head.sprite_sheets[species.name]
else if(head.item_icons && (slot_head_str in head.item_icons))
t_icon = head.item_icons[slot_head_str]
else
@@ -650,12 +660,17 @@ var/global/list/damage_icon_parts = list()
//Determine the state to use
var/t_state
if(head.item_state_slots && head.item_state_slots[slot_head_str])
t_state = head.item_state_slots[slot_head_str]
else if(head.item_state)
t_state = head.item_state
if(istype(head, /obj/item/weapon/paper))
/* I don't like this, but bandaid to fix half the hats in the game
being completely broken without re-breaking paper hats */
t_state = "paper"
else
t_state = head.icon_state
if(head.item_state_slots && head.item_state_slots[slot_head_str])
t_state = head.item_state_slots[slot_head_str]
else if(head.item_state)
t_state = head.item_state
else
t_state = head.icon_state
//Create the image
var/image/standing = image(icon = t_icon, icon_state = t_state)
@@ -852,11 +867,11 @@ var/global/list/damage_icon_parts = list()
//determine icon to use
var/icon/t_icon
if(r_hand.icon_override)
if(r_hand.item_icons && (slot_r_hand_str in r_hand.item_icons))
t_icon = r_hand.item_icons[slot_r_hand_str]
else if(r_hand.icon_override)
t_state += "_r"
t_icon = r_hand.icon_override
else if(r_hand.item_icons && (slot_r_hand_str in r_hand.item_icons))
t_icon = r_hand.item_icons[slot_r_hand_str]
else
t_icon = INV_R_HAND_DEF_ICON
@@ -884,11 +899,11 @@ var/global/list/damage_icon_parts = list()
//determine icon to use
var/icon/t_icon
if(l_hand.icon_override)
if(l_hand.item_icons && (slot_l_hand_str in l_hand.item_icons))
t_icon = l_hand.item_icons[slot_l_hand_str]
else if(l_hand.icon_override)
t_state += "_l"
t_icon = l_hand.icon_override
else if(l_hand.item_icons && (slot_l_hand_str in l_hand.item_icons))
t_icon = l_hand.item_icons[slot_l_hand_str]
else
t_icon = INV_L_HAND_DEF_ICON

View File

@@ -200,9 +200,12 @@
if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
if(Friends.len > 0 && prob(1))
var/mob/nofriend = pick(Friends)
--Friends[nofriend]
if (Friends[nofriend] <= 0)
Friends -= nofriend
if(nofriend && Friends[nofriend])
Friends[nofriend] -= 1
if (Friends[nofriend] <= 0)
Friends[nofriend] = null
Friends -= nofriend
Friends -= null
if(!Target)
if(will_hunt(hungry) || attacked || rabid) // Only add to the list if we need to

View File

@@ -399,7 +399,7 @@
adjustToxLoss(-10)
nutrition = max(nutrition, get_max_nutrition())
/mob/living/carbon/slime/can_use_vents()
/mob/living/carbon/slime/cannot_use_vents()
if(Victim)
return "You cannot ventcrawl while feeding."
..()
..()

View File

@@ -21,7 +21,7 @@
return "I cannot feed on other slimes..."
if (!Adjacent(M))
return "This subject is too far away..."
if (istype(M, /mob/living/carbon) && M.getCloneLoss() > 150 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
if (istype(M, /mob/living/carbon) && M.getCloneLoss() >= M.maxHealth * 1.5 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
return "This subject does not have an edible life energy..."
for(var/mob/living/carbon/slime/met in view())
if(met.Victim == M && met != src)

View File

@@ -399,6 +399,7 @@ default behaviour is:
fire_stacks = 0
/mob/living/proc/rejuvenate()
reagents.clear_reagents()
// shut down various types of badness
setToxLoss(0)
@@ -424,16 +425,11 @@ default behaviour is:
ear_damage = 0
heal_overall_damage(getBruteLoss(), getFireLoss())
// restore all of a human's blood
if(ishuman(src))
var/mob/living/carbon/human/human_mob = src
human_mob.restore_blood()
// fix all of our organs
restore_all_organs()
// remove the character from the list of the dead
if(stat == 2)
if(stat == DEAD)
dead_mob_list -= src
living_mob_list += src
tod = null
@@ -524,27 +520,30 @@ default behaviour is:
var/atom/movable/t = M.pulling
M.stop_pulling()
//this is the gay blood on floor shit -- Added back -- Skie
if (M.lying && (prob(M.getBruteLoss() / 6)))
var/turf/location = M.loc
if (istype(location, /turf/simulated))
location.add_blood(M)
//pull damage with injured people
if(prob(25))
M.adjustBruteLoss(1)
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state worsens": "wounds open more"] from being dragged!</span>")
if(M.pull_damage())
if(prob(25))
M.adjustBruteLoss(2)
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state" : "wounds"] worsen terribly from being dragged!</span>")
var/turf/location = M.loc
if (istype(location, /turf/simulated))
location.add_blood(M)
if(ishuman(M))
var/mob/living/carbon/H = M
var/blood_volume = round(H:vessel.get_reagent_amount("blood"))
if(blood_volume > 0)
H:vessel.remove_reagent("blood",1)
if(!istype(M.loc, /turf/space))
var/area/A = get_area(M)
if(A.has_gravity)
//this is the gay blood on floor shit -- Added back -- Skie
if (M.lying && (prob(M.getBruteLoss() / 6)))
var/turf/location = M.loc
if (istype(location, /turf/simulated))
location.add_blood(M)
//pull damage with injured people
if(prob(25))
M.adjustBruteLoss(1)
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state worsens": "wounds open more"] from being dragged!</span>")
if(M.pull_damage())
if(prob(25))
M.adjustBruteLoss(2)
visible_message("<span class='danger'>\The [M]'s [M.isSynthetic() ? "state" : "wounds"] worsen terribly from being dragged!</span>")
var/turf/location = M.loc
if (istype(location, /turf/simulated))
location.add_blood(M)
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/blood_volume = round(H.vessel.get_reagent_amount("blood"))
if(blood_volume > 0)
H.vessel.remove_reagent("blood", 1)
step(pulling, get_dir(pulling.loc, T))
@@ -668,9 +667,9 @@ default behaviour is:
src << "You can't vent crawl while you're stunned!"
return
var/special_fail_msg = can_use_vents()
var/special_fail_msg = cannot_use_vents()
if(special_fail_msg)
src << "\red [special_fail_msg]"
src << "<span class='warning'>[special_fail_msg]</span>"
return
if(vent_found) // one was passed in, probably from vent/AltClick()
@@ -759,7 +758,7 @@ default behaviour is:
if(new_area)
new_area.Entered(src)
/mob/living/proc/can_use_vents()
/mob/living/proc/cannot_use_vents()
return "You can't fit into that vent."
/mob/living/proc/has_brain()
@@ -791,7 +790,7 @@ default behaviour is:
inertia_dir = 1
else if(y >= world.maxy -TRANSITIONEDGE)
inertia_dir = 2
src << "<span class='warning>Something you are carrying is preventing you from leaving.</span>"
src << "<span class='warning'>Something you are carrying is preventing you from leaving.</span>"
return
..()

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