Merge branch 'master' of https://github.com/tgstation/-tg-station into ReagentReactionRuntimeFix

Conflicts:
	code/modules/reagents/Chemistry-Reagents/Toxin-Reagents.dm
	icons/obj/assemblies/new_assemblies.dmi
This commit is contained in:
phil235
2015-09-10 21:49:39 +02:00
634 changed files with 17053 additions and 20931 deletions
+22 -3
View File
@@ -48,9 +48,13 @@ var/global/floorIsLava = 0
body += "<A href='?_src_=holder;jobban2=\ref[M]'>Jobban</A> | "
body += "<A href='?_src_=holder;appearanceban=\ref[M]'>Identity Ban</A> | "
body += "<A href='?_src_=holder;shownoteckey=[M.ckey]'>Notes</A> | "
body += "<A href='?_src_=holder;watchlist=\ref[M]'>Watchlist Flag</A> "
if(M.client)
if(M.client.check_watchlist(M.client.ckey))
body += "<A href='?_src_=holder;watchremove=[M.ckey]'>Remove from Watchlist</A> | "
body += "<A href='?_src_=holder;watchedit=[M.ckey]'>Edit Watchlist reason</A> "
else
body += "<A href='?_src_=holder;watchadd=\ref[M.ckey]'>Add to Watchlist</A> "
body += "| <A href='?_src_=holder;sendtoprison=\ref[M]'>Prison</A> | "
body += "\ <A href='?_src_=holder;sendbacktolobby=\ref[M]'>Send back to Lobby</A> | "
var/muted = M.client.prefs.muted
@@ -508,9 +512,12 @@ var/global/floorIsLava = 0
message_admins("<font color='blue'>[usr.key] has started the game.</font>")
feedback_add_details("admin_verb","SN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return 1
else if (ticker.current_state == GAME_STATE_STARTUP)
usr << "<font color='red'>Error: Start Now: Game is in startup, please wait until it has finished.</font>"
else
usr << "<font color='red'>Error: Start Now: Game has already started.</font>"
return 0
return 0
/datum/admins/proc/toggleenter()
set category = "Server"
@@ -805,3 +812,15 @@ var/global/floorIsLava = 0
qdel(frommob)
return 1
/client/proc/adminGreet(logout)
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
var/string
if(logout && config && config.announce_admin_logout)
string = pick(
"Admin logout: [key_name(src)]")
else if(!logout && config && config.announce_admin_login && (prefs.toggles & ANNOUNCE_LOGIN))
string = pick(
"Admin login: [key_name(src)]")
if(string)
message_admins("[string]")
+3 -1
View File
@@ -22,7 +22,7 @@
F << "<small>[time_stamp()] \ref[src] ([x],[y],[z])</small> || [src] [message]<br>"
//ADMINVERBS
/client/proc/investigate_show( subject in list("hrefs","notes","ntsl","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "kudzu") )
/client/proc/investigate_show( subject in list("hrefs","notes","watchlist","ntsl","singulo","wires","telesci", "gravity", "records", "cargo", "supermatter", "atmos", "experimentor", "kudzu") )
set name = "Investigate"
set category = "Admin"
if(!holder) return
@@ -46,3 +46,5 @@
return
if("notes")
show_note()
if("watchlist")
watchlist_show()
+7 -7
View File
@@ -19,7 +19,7 @@
var/sql_ckey = sanitizeSQL(src.ckey)
switch(task)
if("Write")
var/DBQuery/query_memocheck = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")] WHERE (ckey = '[sql_ckey]')")
var/DBQuery/query_memocheck = dbcon.NewQuery("SELECT ckey FROM [format_table_name("memo")] WHERE ckey = '[sql_ckey]'")
if(!query_memocheck.Execute())
var/err = query_memocheck.ErrorMsg()
log_game("SQL ERROR obtaining ckey from memo table. Error : \[[err]\]\n")
@@ -27,7 +27,7 @@
if(query_memocheck.NextRow())
src << "You already have set a memo."
return
var/memotext = input(src,"Write your Memo","Memo") as text|null
var/memotext = input(src,"Write your Memo","Memo") as message
if(!memotext)
return
memotext = sanitizeSQL(memotext)
@@ -56,20 +56,20 @@
if(!target_ckey)
return
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_memofind = dbcon.NewQuery("SELECT ckey, memotext FROM [format_table_name("memo")] WHERE (ckey = '[target_sql_ckey]')")
var/DBQuery/query_memofind = dbcon.NewQuery("SELECT memotext FROM [format_table_name("memo")] WHERE ckey = '[target_sql_ckey]'")
if(!query_memofind.Execute())
var/err = query_memofind.ErrorMsg()
log_game("SQL ERROR obtaining ckey, memotext from memo table. Error : \[[err]\]\n")
log_game("SQL ERROR obtaining memotext from memo table. Error : \[[err]\]\n")
return
if(query_memofind.NextRow())
var/old_memo = query_memofind.item[2]
var/new_memo = input("Input new memo", "New Memo", "[old_memo]", null) as null|text
var/old_memo = query_memofind.item[1]
var/new_memo = input("Input new memo", "New Memo", "[old_memo]", null) as message
if(!new_memo)
return
new_memo = sanitizeSQL(new_memo)
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from<br>[old_memo]<br>to<br>[new_memo]<hr>"
edit_text = sanitizeSQL(edit_text)
var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE (ckey = '[target_sql_ckey]')")
var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("memo")] SET memotext = '[new_memo]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
if(!update_query.Execute())
var/err = update_query.ErrorMsg()
log_game("SQL ERROR editing memo. Error : \[[err]\]\n")
+1
View File
@@ -1,6 +1,7 @@
//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
var/list/admin_verbs_default = list(
/client/proc/toggleadminhelpsound, /*toggles whether we hear a sound when adminhelps/PMs are used*/
/client/proc/toggleannouncelogin, /*toggles if an admin's login is announced during a round*/
/client/proc/deadmin_self, /*destroys our own admin datum so we can play as a regular player*/
/client/proc/cmd_admin_say, /*admin-only ooc chat*/
/client/proc/hide_verbs, /*hides all our adminverbs*/
+5 -3
View File
@@ -3,13 +3,14 @@
usr << "<span class='danger'>Failed to establish database connection.</span>"
return
if(!target_ckey)
var/new_ckey = ckey(input(usr,"Who would you like to add a note for?","Enter a ckey",null) as text|null)
var/new_ckey = ckey(input(usr,"Who would you like to add a note for?","Enter a ckey",null) as text)
if(!new_ckey)
return
new_ckey = sanitizeSQL(new_ckey)
var/DBQuery/query_find_ckey = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
if(!query_find_ckey.Execute())
var/err = query_find_ckey.ErrorMsg()
log_game("SQL ERROR obtaining ckey from notes table. Error : \[[err]\]\n")
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
return
if(!query_find_ckey.NextRow())
usr << "<span class='redtext'>[new_ckey] has not been seen before, you can only add notes to known players.</span>"
@@ -147,7 +148,8 @@
var/search
output += "<center><a href='?_src_=holder;addnoteempty=1'>\[Add Note\]</a></center>"
output += ruler
index = sanitizeSQL(index)
if(!isnum(index))
index = sanitizeSQL(index)
switch(index)
if(1)
search = "^."
+49 -66
View File
@@ -443,15 +443,14 @@
mins = minutes - CMinutes
mins = input(usr,"How long (in minutes)? (Default: 1440)","Ban time",mins ? mins : 1440) as num|null
if(!mins) return
mins = min(525599,mins)
minutes = CMinutes + mins
duration = GetExp(minutes)
reason = input(usr,"Reason?","reason",reason2) as text|null
reason = input(usr,"Please State Reason","Reason",reason2) as message
if(!reason) return
if("No")
temp = 0
duration = "Perma"
reason = input(usr,"Reason?","reason",reason2) as text|null
reason = input(usr,"Please State Reason","Reason",reason2) as message
if(!reason) return
log_admin("[key_name(usr)] edited [banned_key]'s ban. Reason: [reason] Duration: [duration]")
@@ -497,7 +496,7 @@
else switch(alert("Appearance ban [M.ckey]?",,"Yes","No", "Cancel"))
if("Yes")
var/reason = input(usr,"Reason?","reason","Metafriender") as text|null
var/reason = input(usr,"Please State Reason","Reason") as message
if(!reason)
return
ban_unban_log_save("[key_name(usr)] appearance banned [key_name(M)]. reason: [reason]")
@@ -505,7 +504,7 @@
feedback_inc("ban_appearance",1)
DB_ban_record(BANTYPE_APPEARANCE, M, -1, reason)
appearance_fullban(M, "[reason]; By [usr.ckey] on [time2text(world.realtime)]")
add_note(M.ckey, "Appearance banned - [reason]", null, usr, 0)
add_note(M.ckey, "Appearance banned - [reason]", null, usr.ckey, 0)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] appearance banned [key_name_admin(M)]</span>")
M << "<span class='boldannounce'><BIG>You have been appearance banned by [usr.client.ckey].</BIG></span>"
M << "<span class='boldannounce'>The reason is: [reason]</span>"
@@ -905,7 +904,7 @@
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null
if(!mins)
return
var/reason = input(usr,"Reason?","Please State Reason","") as text|null
var/reason = input(usr,"Please State Reason","Reason") as message
if(!reason)
return
@@ -921,7 +920,7 @@
msg = job
else
msg += ", [job]"
add_note(M.ckey, "Banned from [msg] - [reason]", null, usr, 0)
add_note(M.ckey, "Banned from [msg] - [reason]", null, usr.ckey, 0)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] banned [key_name_admin(M)] from [msg] for [mins] minutes</span>")
M << "<span class='boldannounce'><BIG>You have been jobbanned by [usr.client.ckey] from: [msg].</BIG></span>"
M << "<span class='boldannounce'>The reason is: [reason]</span>"
@@ -929,7 +928,7 @@
href_list["jobban2"] = 1 // lets it fall through and refresh
return 1
if("No")
var/reason = input(usr,"Reason?","Please State Reason","") as text|null
var/reason = input(usr,"Please State Reason","Reason") as message
if(reason)
var/msg
for(var/job in notbannedlist)
@@ -941,7 +940,7 @@
jobban_fullban(M, job, "[reason]; By [usr.ckey] on [time2text(world.realtime)]")
if(!msg) msg = job
else msg += ", [job]"
add_note(M.ckey, "Banned from [msg] - [reason]", null, usr, 0)
add_note(M.ckey, "Banned from [msg] - [reason]", null, usr.ckey, 0)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] banned [key_name_admin(M)] from [msg]</span>")
M << "<span class='boldannounce'><BIG>You have been jobbanned by [usr.client.ckey] from: [msg].</BIG></span>"
M << "<span class='boldannounce'>The reason is: [reason]</span>"
@@ -1065,8 +1064,7 @@
var/mins = input(usr,"How long (in minutes)?","Ban time",1440) as num|null
if(!mins)
return
if(mins >= 525600) mins = 525599
var/reason = input(usr,"Reason?","reason","Griefer") as text|null
var/reason = input(usr,"Please State Reason","Reason") as message
if(!reason)
return
AddBan(M.ckey, M.computer_id, reason, usr.ckey, 1, mins)
@@ -1086,7 +1084,7 @@
del(M.client)
//qdel(M) // See no reason why to delete mob. Important stuff can be lost. And ban can be lifted before round ends.
if("No")
var/reason = input(usr,"Reason?","reason","Griefer") as text|null
var/reason = input(usr,"Please State Reason","Reason") as message
if(!reason)
return
switch(alert(usr,"IP ban?",,"Yes","No","Cancel"))
@@ -1126,61 +1124,46 @@
unjobbanpanel()
//Watchlist
else if(href_list["watchlist"])
if(!check_rights(R_ADMIN)) return
var/mob/M = locate(href_list["watchlist"])
if(!dbcon.IsConnected())
usr << "<span class='danger'>Failed to establish database connection.</span>"
else if(href_list["watchadd"])
var/target_ckey = locate(href_list["watchadd"])
usr.client.watchlist_add(target_ckey)
else if(href_list["watchremove"])
var/target_ckey = href_list["watchremove"]
usr.client.watchlist_remove(target_ckey)
else if(href_list["watchedit"])
var/target_ckey = href_list["watchedit"]
usr.client.watchlist_edit(target_ckey)
else if(href_list["watchaddbrowse"])
usr.client.watchlist_add(null, 1)
else if(href_list["watchremovebrowse"])
var/target_ckey = href_list["watchremovebrowse"]
usr.client.watchlist_remove(target_ckey, 1)
else if(href_list["watcheditbrowse"])
var/target_ckey = href_list["watcheditbrowse"]
usr.client.watchlist_edit(target_ckey, 1)
else if(href_list["watchsearch"])
var/target_ckey = href_list["watchsearch"]
usr.client.watchlist_show(target_ckey)
else if(href_list["watchshow"])
usr.client.watchlist_show()
else if(href_list["watcheditlog"])
var/target_ckey = sanitizeSQL("[href_list["watcheditlog"]]")
var/DBQuery/query_watchedits = dbcon.NewQuery("SELECT edits FROM [format_table_name("watch")] WHERE ckey = '[target_ckey]'")
if(!query_watchedits.Execute())
var/err = query_watchedits.ErrorMsg()
log_game("SQL ERROR obtaining edits from watch table. Error : \[[err]\]\n")
return
if(!ismob(M))
usr << "This can only be used on instances of type /mob"
return
if(!M.ckey)
usr << "This mob has no ckey"
return
var/sql_ckey = sanitizeSQL(M.ckey)
var/DBQuery/query = dbcon.NewQuery("SELECT ckey FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')")
query.Execute()
if(query.NextRow())
switch(alert(usr, "[sql_ckey] is already on the watchlist, do you want to:", "Ckey already flagged", "Remove", "Edit reason", "Cancel"))
if("Cancel")
return
if("Remove")
var/DBQuery/query_watchdel = dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[sql_ckey]'")
if(!query_watchdel.Execute())
var/err = query_watchdel.ErrorMsg()
log_game("SQL ERROR during removing watch entry. Error : \[[err]\]\n")
return
log_admin("[key_name(usr)] has removed [key_name_admin(M)] from the watchlist")
message_admins("[key_name_admin(usr)] has removed [key_name_admin(M)] from the watchlist", 1)
if("Edit reason")
var/DBQuery/query_reason = dbcon.NewQuery("SELECT ckey, reason FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')")
query_reason.Execute()
if(query_reason.NextRow())
var/watch_reason = query_reason.item[3]
var/new_reason = input("Insert new reason", "New Reason", "[watch_reason]", null) as null|text
new_reason = sanitizeSQL(new_reason)
if(!new_reason)
return
var/DBQuery/update_query = dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]' WHERE (ckey = '[sql_ckey]')")
if(!update_query.Execute())
var/err = update_query.ErrorMsg()
log_game("SQL ERROR during edit watch entry reason. Error : \[[err]\]\n")
return
log_admin("[key_name(usr)] has edited [sql_ckey]'s reason from [watch_reason] to [new_reason]",1)
message_admins("[key_name_admin(usr)] has edited [sql_ckey]'s reason from [watch_reason] to [new_reason]",1)
else
var/reason = input(usr,"Reason?","reason","Metagaming") as text|null
if(!reason)
return
reason = sanitizeSQL(reason)
var/DBQuery/query_watchadd = dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason) VALUES ('[sql_ckey]', '[reason]')")
if(!query_watchadd.Execute())
var/err = query_watchadd.ErrorMsg()
log_game("SQL ERROR during adding new watch entry. Error : \[[err]\]\n")
return
log_admin("[key_name(usr)] has added [key_name_admin(M)] to the watchlist - Reason: [reason]")
message_admins("[key_name_admin(usr)] has added [key_name_admin(M)] to the watchlist - Reason: [reason]", 1)
if(query_watchedits.NextRow())
var/edit_log = query_watchedits.item[1]
usr << browse(edit_log,"window=watchedits")
else if(href_list["mute"])
if(!check_rights(R_ADMIN)) return
+2 -2
View File
@@ -13,12 +13,12 @@
//Manifolds
for (var/obj/machinery/atmospherics/pipe/manifold/pipe in world)
if (!pipe.node1 || !pipe.node2 || !pipe.node3)
if (!pipe.NODE1 || !pipe.NODE2 || !pipe.NODE3)
usr << "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])"
//Pipes
for (var/obj/machinery/atmospherics/pipe/simple/pipe in world)
if (!pipe.node1 || !pipe.node2)
if (!pipe.NODE1 || !pipe.NODE2)
usr << "Unconnected [pipe.name] located at [pipe.x],[pipe.y],[pipe.z] ([get_area(pipe.loc)])"
/client/proc/powerdebug()
+6 -2
View File
@@ -120,7 +120,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
/client/proc/get_callproc_args()
var/argnum = input("Number of arguments","Number:",0) as num|null
if(!argnum && (argnum!=0)) return
var/list/lst = list()
//TODO: make a list to store whether each argument was initialised as null.
//Reason: So we can abort the proccall if say, one of our arguments was a mob which no longer exists
@@ -1100,6 +1100,10 @@ var/global/list/g_fancy_list_of_types = null
for(var/path in SSgarbage.didntgc)
dat += "[path] - [SSgarbage.didntgc[path]] times<BR>"
dat += "<B>List of paths that did not return a qdel hint in Destroy()</B><BR><BR>"
for(var/path in SSgarbage.noqdelhint)
dat += "[path]<BR>"
usr << browse(dat, "window=dellog")
@@ -1127,7 +1131,7 @@ var/global/list/g_fancy_list_of_types = null
M.equip_to_slot_or_del(new /obj/item/weapon/storage/box(M), slot_in_backpack)
M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_in_backpack)
M.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/hypospray/combat/nanites(M), slot_in_backpack)
M.equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(M), slot_in_backpack)
M.equip_to_slot_or_del(new /obj/item/weapon/storage/box/flashbangs(M), slot_in_backpack)
M.equip_to_slot_or_del(new /obj/item/device/flashlight(M), slot_in_backpack)
+2 -2
View File
@@ -1,7 +1,7 @@
/*
HOW DO I LOG RUNTIMES?
Firstly, start dreamdeamon if it isn't already running. Then select "world>Log Session" (or press the F3 key)
navigate the popup window to the data/logs/runtime/ folder from where your tgstation .dmb is located.
navigate the popup window to the data/logs/runtimes/ folder from where your tgstation .dmb is located.
(you may have to make this folder yourself)
OPTIONAL: you can select the little checkbox down the bottom to make dreamdeamon save the log everytime you
@@ -44,7 +44,7 @@
set desc = "Retrieve any session logfiles saved by dreamdeamon."
set category = null
var/path = browse_files("data/logs/runtime/")
var/path = browse_files("data/logs/runtimes/")
if(!path)
return
+1 -1
View File
@@ -171,7 +171,7 @@
return .(O.vars[variable])
if("text")
var/new_value = input("Enter new text:","Text",O.vars[variable]) as text|null
var/new_value = input("Enter new text:","Text",O.vars[variable]) as message|null
if(new_value == null) return
var/process_vars = 0
+4 -4
View File
@@ -49,7 +49,7 @@ var/list/VVckey_edit = list("key", "ckey")
switch(class)
if("text")
var_value = input("Enter new text:","Text") as null|text
var_value = input("Enter new text:","Text") as null|message
if("num")
var_value = input("Enter new number:","Num") as null|num
@@ -106,7 +106,7 @@ var/list/VVckey_edit = list("key", "ckey")
switch(class)
if("text")
var_value = input("Enter new text:","Text") as text
var_value = input("Enter new text:","Text") as message
if("num")
var_value = input("Enter new number:","Num") as num
@@ -302,7 +302,7 @@ var/list/VVckey_edit = list("key", "ckey")
return
if("text")
new_var = input("Enter new text:","Text") as text
new_var = input("Enter new text:","Text") as message
if(findtext(new_var,"\["))
var/process_vars = alert(usr,"\[] detected in string, process as variables?","Process Variables?","Yes","No")
@@ -557,7 +557,7 @@ var/list/VVckey_edit = list("key", "ckey")
return .(O.vars[variable])
if("text")
var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|text
var/var_new = input("Enter new text:","Text",O.vars[variable]) as null|message
if(var_new==null) return
if(findtext(var_new,"\["))
+118
View File
@@ -0,0 +1,118 @@
/client/proc/watchlist_add(target_ckey, browse = 0)
if(!target_ckey)
var/new_ckey = ckey(input(usr,"Who would you like to add to the watchlist?","Enter a ckey",null) as text)
if(!new_ckey)
return
new_ckey = sanitizeSQL(new_ckey)
var/DBQuery/query_watchfind = dbcon.NewQuery("SELECT ckey FROM [format_table_name("player")] WHERE ckey = '[new_ckey]'")
if(!query_watchfind.Execute())
var/err = query_watchfind.ErrorMsg()
log_game("SQL ERROR obtaining ckey from player table. Error : \[[err]\]\n")
return
if(!query_watchfind.NextRow())
usr << "<span class='redtext'>[new_ckey] has not been seen before, you can only add known players.</span>"
return
else
target_ckey = new_ckey
var/target_sql_ckey = sanitizeSQL(target_ckey)
if(check_watchlist(target_sql_ckey))
usr << "<span class='redtext'>[target_sql_ckey] is already on the watchlist.</span>"
return
var/reason = input(usr,"Please State Reason","Reason") as message
if(!reason)
return
reason = sanitizeSQL(reason)
var/timestamp = SQLtime()
var/adminckey = usr.ckey
if(!adminckey)
return
var/admin_sql_ckey = sanitizeSQL(adminckey)
var/DBQuery/query_watchadd = dbcon.NewQuery("INSERT INTO [format_table_name("watch")] (ckey, reason, adminckey, timestamp) VALUES ('[target_sql_ckey]', '[reason]', '[admin_sql_ckey]', '[timestamp]')")
if(!query_watchadd.Execute())
var/err = query_watchadd.ErrorMsg()
log_game("SQL ERROR during adding new watch entry. Error : \[[err]\]\n")
return
log_admin("[key_name(usr)] has added [target_ckey] to the watchlist - Reason: [reason]")
message_admins("[key_name_admin(usr)] has added [target_ckey] to the watchlist - Reason: [reason]", 1)
if(browse)
watchlist_show(target_sql_ckey)
/client/proc/watchlist_remove(target_ckey, browse = 0)
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_watchdel = dbcon.NewQuery("DELETE FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
if(!query_watchdel.Execute())
var/err = query_watchdel.ErrorMsg()
log_game("SQL ERROR during removing watch entry. Error : \[[err]\]\n")
return
log_admin("[key_name(usr)] has removed [target_ckey] from the watchlist")
message_admins("[key_name_admin(usr)] has removed [target_ckey] from the watchlist", 1)
if(browse)
watchlist_show()
/client/proc/watchlist_edit(target_ckey, browse = 0)
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_watchreason = dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
if(!query_watchreason.Execute())
var/err = query_watchreason.ErrorMsg()
log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n")
return
if(query_watchreason.NextRow())
var/watch_reason = query_watchreason.item[1]
var/new_reason = input("Input new reason", "New Reason", "[watch_reason]") as message
new_reason = sanitizeSQL(new_reason)
if(!new_reason)
return
var/sql_ckey = sanitizeSQL(usr.ckey)
var/edit_text = "Edited by [sql_ckey] on [SQLtime()] from<br>[watch_reason]<br>to<br>[new_reason]<hr>"
edit_text = sanitizeSQL(edit_text)
var/DBQuery/query_watchupdate = dbcon.NewQuery("UPDATE [format_table_name("watch")] SET reason = '[new_reason]', last_editor = '[sql_ckey]', edits = CONCAT(IFNULL(edits,''),'[edit_text]') WHERE ckey = '[target_sql_ckey]'")
if(!query_watchupdate.Execute())
var/err = query_watchupdate.ErrorMsg()
log_game("SQL ERROR editing watchlist reason. Error : \[[err]\]\n")
return
log_admin("[key_name(usr)] has edited [target_ckey]'s watchlist reason from [watch_reason] to [new_reason]")
message_admins("[key_name_admin(usr)] has edited [target_ckey]'s watchlist reason from<br>[watch_reason]<br>to<br>[new_reason]")
if(browse)
watchlist_show(target_sql_ckey)
/client/proc/watchlist_show(search)
var/output
output += "<form method='GET' name='search' action='?'>\
<input type='hidden' name='_src_' value='holder'>\
<input type='text' name='watchsearch' value='[search]'>\
<input type='submit' value='Search'></form>"
output += "<a href='?_src_=holder;watchshow=1'>\[Clear Search\]</a> <a href='?_src_=holder;watchaddbrowse=1'>\[Add Ckey\]</a>"
output += "<hr style='background:#000000; border:0; height:3px'>"
if(search)
search = "^[search]"
else
search = "^."
search = sanitizeSQL(search)
var/DBQuery/query_watchlist = dbcon.NewQuery("SELECT ckey, reason, adminckey, timestamp, last_editor FROM [format_table_name("watch")] WHERE ckey REGEXP '[search]' ORDER BY ckey")
if(!query_watchlist.Execute())
var/err = query_watchlist.ErrorMsg()
log_game("SQL ERROR obtaining ckey, reason, adminckey, timestamp, last_editor from watch table. Error : \[[err]\]\n")
return
while(query_watchlist.NextRow())
var/ckey = query_watchlist.item[1]
var/reason = query_watchlist.item[2]
var/adminckey = query_watchlist.item[3]
var/timestamp = query_watchlist.item[4]
var/last_editor = query_watchlist.item[5]
output += "<b>[ckey]</b> | Added by <b>[adminckey]</b> on <b>[timestamp]</b> <a href='?_src_=holder;watchremovebrowse=[ckey]'>\[Remove\]</a> <a href='?_src_=holder;watcheditbrowse=[ckey]'>\[Edit Reason\]</a>"
if(last_editor)
output += " <font size='2'>Last edit by [last_editor] <a href='?_src_=holder;watcheditlog=[ckey]'>(Click here to see edit log)</a></font>"
output += "<br>[reason]<hr style='background:#000000; border:0; height:1px'>"
usr << browse(output, "window=watchwin;size=900x500")
/client/proc/check_watchlist(target_ckey)
var/target_sql_ckey = sanitizeSQL(target_ckey)
var/DBQuery/query_watch = dbcon.NewQuery("SELECT reason FROM [format_table_name("watch")] WHERE ckey = '[target_sql_ckey]'")
if(!query_watch.Execute())
var/err = query_watch.ErrorMsg()
log_game("SQL ERROR obtaining reason from watch table. Error : \[[err]\]\n")
return
if(query_watch.NextRow())
return query_watch.item[1]
else
return 0
+5 -3
View File
@@ -51,10 +51,12 @@
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
/obj/item/device/assembly/proc/pulsed(radio = 0)
if(holder && (wires & WIRE_RECEIVE))
activate()
if(wires & WIRE_RECEIVE)
spawn(0)
activate()
if(radio && (wires & WIRE_RADIO_RECEIVE))
activate()
spawn(0)
activate()
return 1
+146
View File
@@ -0,0 +1,146 @@
/obj/item/device/assembly/control
name = "blast door controller"
desc = "A small electronic device able to control a blast door remotely."
icon_state = "control"
origin_tech = "magnets=1;programming=2"
attachable = 1
var/id = null
var/can_change_id = 0
/obj/item/device/assembly/control/examine(mob/user)
..()
if(id)
user << "It's channel ID is '[id]'."
/obj/item/device/assembly/control/activate()
cooldown = 1
var/openclose
for(var/obj/machinery/door/poddoor/M in machines)
if(M.id == src.id)
if(openclose == null)
openclose = M.density
spawn(0)
if(M)
if(openclose) M.open()
else M.close()
return
sleep(10)
cooldown = 0
/obj/item/device/assembly/control/airlock
name = "airlock controller"
desc = "A small electronic device able to control an airlock remotely."
id = "badmin" // Set it to null for MEGAFUN.
var/specialfunctions = OPEN
/*
Bitflag, 1= open (OPEN)
2= idscan (IDSCAN)
4= bolts (BOLTS)
8= shock (SHOCK)
16= door safties (SAFE)
*/
/obj/item/device/assembly/control/airlock/activate()
cooldown = 1
for(var/obj/machinery/door/airlock/D in airlocks)
if(D.id_tag == src.id)
if(specialfunctions & OPEN)
spawn(0)
if(D)
if(D.density) D.open()
else D.close()
return
if(specialfunctions & IDSCAN)
D.aiDisabledIdScanner = !D.aiDisabledIdScanner
if(specialfunctions & BOLTS)
if(!D.isWireCut(4) && D.hasPower())
D.locked = !D.locked
D.update_icon()
if(specialfunctions & SHOCK)
D.secondsElectrified = D.secondsElectrified ? 0 : -1
if(specialfunctions & SAFE)
D.safe = !D.safe
sleep(10)
cooldown = 0
/obj/item/device/assembly/control/massdriver
name = "mass driver controller"
desc = "A small electronic device able to control a mass driver."
/obj/item/device/assembly/control/massdriver/activate()
cooldown = 1
for(var/obj/machinery/door/poddoor/M in machines)
if (M.id == src.id)
spawn( 0 )
M.open()
return
sleep(10)
for(var/obj/machinery/mass_driver/M in machines)
if(M.id == src.id)
M.drive()
sleep(60)
for(var/obj/machinery/door/poddoor/M in machines)
if (M.id == src.id)
spawn( 0 )
M.close()
return
sleep(10)
cooldown = 0
/obj/item/device/assembly/control/igniter
name = "ignition controller"
desc = "A remote controller for a mounted igniter."
/obj/item/device/assembly/control/igniter/activate()
cooldown = 1
for(var/obj/machinery/sparker/M in machines)
if (M.id == src.id)
spawn( 0 )
M.ignite()
for(var/obj/machinery/igniter/M in machines)
if(M.id == src.id)
M.use_power(50)
M.on = !M.on
M.icon_state = "igniter[M.on]"
sleep(30)
cooldown = 0
/obj/item/device/assembly/control/flasher
name = "flasher controller"
desc = "A remote controller for a mounted flasher."
/obj/item/device/assembly/control/flasher/activate()
cooldown = 1
for(var/obj/machinery/flasher/M in machines)
if(M.id == src.id)
spawn(0)
M.flash()
sleep(50)
cooldown = 0
/obj/item/device/assembly/control/crematorium
name = "crematorium controller"
desc = "An evil-looking remote controller for a crematorium."
/obj/item/device/assembly/control/crematorium/activate()
cooldown = 1
for (var/obj/structure/bodycontainer/crematorium/C in crematoriums)
if (C.id == id)
C.cremate(usr)
sleep(50)
cooldown = 0
+197
View File
@@ -0,0 +1,197 @@
/obj/item/device/assembly/flash
name = "flash"
desc = "A powerful and versatile flashbulb device, with applications ranging from disorienting attackers to acting as visual receptors in robot production."
icon_state = "flash"
item_state = "flashtool"
throwforce = 0
w_class = 1
origin_tech = "magnets=2;combat=1"
crit_fail = 0 //Is the flash burnt out?
var/times_used = 0 //Number of times it's been used.
var/last_used = 0 //last world.time it was used.
/obj/item/device/assembly/flash/update_icon(var/flash = 0)
overlays.Cut()
attached_overlays = list()
if(crit_fail)
overlays += "flashburnt"
attached_overlays += "flashburnt"
if(flash)
overlays += "flash-f"
attached_overlays += "flash-f"
spawn(5)
update_icon()
if(holder)
holder.update_icon()
/obj/item/device/assembly/flash/proc/clown_check(mob/living/carbon/human/user)
if(user.disabilities & CLUMSY && prob(50))
flash_carbon(user, user, 15, 0)
return 0
return 1
/obj/item/device/assembly/flash/activate()
if(!try_use_flash())
return 0
var/turf/T = get_turf(src)
T.visible_message("<span class='disarm'>[src] emits a blinding light!</span>")
for(var/mob/living/carbon/M in viewers(3, null))
flash_carbon(M, null, 2, 0)
/obj/item/device/assembly/flash/proc/burn_out() //Made so you can override it if you want to have an invincible flash from R&D or something.
crit_fail = 1
update_icon()
var/turf/T = get_turf(src)
T.visible_message("The [src.name] burns out!")
/obj/item/device/assembly/flash/proc/flash_recharge(interval=10)
if(prob(times_used * 3)) //The more often it's used in a short span of time the more likely it will burn out
burn_out()
return 0
var/deciseconds_passed = world.time - last_used
for(var/seconds = deciseconds_passed/10, seconds>=interval, seconds-=interval) //get 1 charge every interval
times_used--
last_used = world.time
times_used = max(0, times_used) //sanity
return 1
/obj/item/device/assembly/flash/proc/try_use_flash(mob/user = null)
flash_recharge(10)
if(crit_fail)
return 0
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
update_icon(1)
times_used++
if(user && !clown_check(user))
return 0
return 1
/obj/item/device/assembly/flash/proc/flash_carbon(mob/living/carbon/M, mob/user = null, power = 5, targeted = 1)
add_logs(user, M, "flashed", src)
if(user && targeted)
if(M.weakeyes)
M.Weaken(3) //quick weaken bypasses eye protection but has no eye flash
if(M.flash_eyes(1, 1))
M.confused += power
terrible_conversion_proc(M, user)
M.Stun(1)
visible_message("<span class='disarm'>[user] blinds [M] with the flash!</span>")
user << "<span class='danger'>You blind [M] with the flash!</span>"
M << "<span class='userdanger'>[user] blinds you with the flash!</span>"
if(M.weakeyes)
M.Stun(2)
M.visible_message("<span class='disarm'>[M] gasps and shields their eyes!</span>", "<span class='userdanger'>You gasp and shields your eyes!</span>")
else
visible_message("<span class='disarm'>[user] fails to blind [M] with the flash!</span>")
user << "<span class='warning'>You fail to blind [M] with the flash!</span>"
M << "<span class='danger'>[user] fails to blind you with the flash!</span>"
else
if(M.flash_eyes())
M.confused += power
/obj/item/device/assembly/flash/attack(mob/living/M, mob/user)
if(!try_use_flash(user))
return 0
if(iscarbon(M))
flash_carbon(M, user, 5, 1)
return 1
else if(issilicon(M))
add_logs(user, M, "flashed", src)
update_icon(1)
M.Weaken(rand(5,10))
user.visible_message("<span class='disarm'>[user] overloads [M]'s sensors with the flash!</span>", "<span class='danger'>You overload [M]'s sensors with the flash!</span>")
return 1
user.visible_message("<span class='disarm'>[user] fails to blind [M] with the flash!</span>", "<span class='warning'>You fail to blind [M] with the flash!</span>")
/obj/item/device/assembly/flash/attack_self(mob/living/carbon/user, flag = 0, emp = 0)
if(holder)
return 0
if(!try_use_flash(user))
return 0
user.visible_message("<span class='disarm'>[user]'s flash emits a blinding light!</span>", "<span class='danger'>Your flash emits a blinding light!</span>")
for(var/mob/living/carbon/M in oviewers(3, null))
flash_carbon(M, user, 1, 0)
/obj/item/device/assembly/flash/emp_act(severity)
if(!try_use_flash())
return 0
for(var/mob/living/carbon/M in viewers(3, null))
flash_carbon(M, null, 10, 0)
burn_out()
..()
/obj/item/device/assembly/flash/proc/terrible_conversion_proc(mob/M, mob/user)
if(ishuman(M) && ishuman(user) && M.stat != DEAD)
if(user.mind && (user.mind in ticker.mode.head_revolutionaries))
if(M.client)
if(M.stat == CONSCIOUS)
M.mind_initialize() //give them a mind datum if they don't have one.
var/resisted
if(!isloyal(M))
if(user.mind in ticker.mode.head_revolutionaries)
if(ticker.mode.add_revolutionary(M.mind))
times_used -- //Flashes less likely to burn out for headrevs when used for conversion
else
resisted = 1
else
resisted = 1
if(resisted)
user << "<span class='warning'>This mind seems resistant to the flash!</span>"
else
user << "<span class='warning'>They must be conscious before you can convert them!</span>"
else
user << "<span class='warning'>This mind is so vacant that it is not susceptible to influence!</span>"
/obj/item/device/assembly/flash/cyborg
origin_tech = null
/obj/item/device/assembly/flash/cyborg/attack(mob/living/M, mob/user)
..()
cyborg_flash_animation(user)
/obj/item/device/assembly/flash/cyborg/attack_self(mob/user)
..()
cyborg_flash_animation(user)
/obj/item/device/assembly/flash/cyborg/attackby(obj/item/weapon/W, mob/user, params)
return
/obj/item/device/assembly/flash/cyborg/proc/cyborg_flash_animation(mob/living/user)
var/atom/movable/overlay/animation = new(user.loc)
animation.layer = user.layer + 1
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
animation.master = user
flick("blspell", animation)
sleep(5)
qdel(animation)
/obj/item/device/assembly/flash/memorizer
name = "memorizer"
desc = "If you see this, you're not likely to remember it any time soon."
icon = 'icons/obj/device.dmi'
icon_state = "memorizer"
item_state = "nullrod"
/obj/item/device/assembly/flash/handheld //this is now the regular pocket flashes
+105
View File
@@ -0,0 +1,105 @@
/obj/item/device/assembly/health
name = "health sensor"
desc = "Used for scanning and monitoring health."
icon_state = "health"
materials = list(MAT_METAL=800, MAT_GLASS=200)
origin_tech = "magnets=1;biotech=1"
attachable = 1
secured = 0
var/scanning = 0
var/health_scan
var/alarm_health = 0
/obj/item/device/assembly/health/activate()
if(!..()) return 0//Cooldown check
toggle_scan()
return 0
/obj/item/device/assembly/health/toggle_secure()
secured = !secured
if(secured && scanning)
SSobj.processing |= src
else
scanning = 0
SSobj.processing.Remove(src)
update_icon()
return secured
/obj/item/device/assembly/health/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/device/multitool))
if(alarm_health == 0)
alarm_health = -90
user.show_message("You toggle [src] to \"detect death\" mode.")
else
alarm_health = 0
user.show_message("You toggle [src] to \"detect critical state\" mode.")
return
else
return ..()
/obj/item/device/assembly/health/process()
if(!scanning || !secured)
return
var/atom/A = src
if(connected && connected.holder)
A = connected.holder
for(A, A && !ismob(A), A=A.loc);
// like get_turf(), but for mobs.
var/mob/living/M = A
if(M)
health_scan = M.health
if(health_scan <= alarm_health)
pulse()
audible_message("\icon[src] *beep* *beep*", "*beep* *beep*")
toggle_scan()
return
return
/obj/item/device/assembly/health/proc/toggle_scan()
if(!secured) return 0
scanning = !scanning
if(scanning)
SSobj.processing |= src
else
SSobj.processing.Remove(src)
return
/obj/item/device/assembly/health/interact(mob/user as mob)//TODO: Change this to the wires thingy
if(!secured)
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
return 0
var/dat = text("<TT><B>Health Sensor</B> <A href='?src=\ref[src];scanning=1'>[scanning?"On":"Off"]</A>")
if(scanning && health_scan)
dat += "<BR>Health: [health_scan]"
user << browse(dat, "window=hscan")
onclose(user, "hscan")
return
/obj/item/device/assembly/health/Topic(href, href_list)
..()
if(!ismob(usr))
return
var/mob/user = usr
if(!user.canUseTopic(user))
usr << browse(null, "window=hscan")
onclose(usr, "hscan")
return
if(href_list["scanning"])
toggle_scan()
if(href_list["close"])
usr << browse(null, "window=hscan")
return
attack_self(user)
return
+10 -3
View File
@@ -21,7 +21,7 @@
attach(A2,user)
name = "[A.name]-[A2.name] assembly"
update_icon()
feedback_add_details("assembly_made","[type]")
feedback_add_details("assembly_made","[A.name]-[A2.name]")
/obj/item/device/assembly_holder/proc/attach(obj/item/device/assembly/A, mob/user)
if(!A.remove_item_from_storage(src))
@@ -41,10 +41,17 @@
overlays += "[a_left.icon_state]_left"
for(var/O in a_left.attached_overlays)
overlays += "[O]_l"
if(a_right)
src.overlays += "[a_right.icon_state]_right"
var/list/images = list()
images += image(icon, icon_state = "[a_right.icon_state]_left")
for(var/O in a_right.attached_overlays)
overlays += "[O]_r"
images += image(icon, icon_state = "[O]_l")
var/matrix = matrix(-1, 0, 0, 0, 1, 0)
for(var/image/I in images)
I.transform = matrix
overlays += I
if(master)
master.update_icon()
+5
View File
@@ -12,6 +12,11 @@
sparks.set_up(2, 0, src)
sparks.attach(src)
/obj/item/device/assembly/igniter/Destroy()
qdel(sparks)
sparks = null
return ..()
/obj/item/device/assembly/igniter/activate()
if(!..()) return 0//Cooldown check
+1 -1
View File
@@ -223,4 +223,4 @@
if(previous)
previous.next = null
master.last = previous
..()
return ..()
+1
View File
@@ -4,6 +4,7 @@
icon_state = "mousetrap"
materials = list(MAT_METAL=100)
origin_tech = "combat=1"
attachable = 1
var/armed = 0
+1 -2
View File
@@ -11,8 +11,7 @@
/obj/item/assembly/shock_kit/Destroy()
qdel(part1)
qdel(part2)
..()
return
return ..()
/obj/item/assembly/shock_kit/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/wrench))
+1 -1
View File
@@ -22,7 +22,7 @@
/obj/item/device/assembly/signaler/Destroy()
if(radio_controller)
radio_controller.remove_object(src,frequency)
..()
return ..()
/obj/item/device/assembly/signaler/activate()
if(cooldown > 0) return 0
+6 -19
View File
@@ -129,6 +129,7 @@ var/next_external_rsc = 0
if(holder)
add_admin_verbs()
admin_memo_output("Show")
adminGreet()
if((global.comms_key == "default_pwd" || length(global.comms_key) <= 6) && global.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms.
src << "<span class='danger'>The server's API key is either too short or is the default value! Consider changing it immediately!</span>"
@@ -183,6 +184,7 @@ var/next_external_rsc = 0
//////////////
/client/Del()
if(holder)
adminGreet(1)
holder.owner = null
admins -= src
directory -= ckey
@@ -234,11 +236,10 @@ var/next_external_rsc = 0
while (query_cid.NextRow())
related_accounts_cid += "[query_cid.item[1]], "
var/DBQuery/query_watch = dbcon.NewQuery("SELECT ckey, reason FROM [format_table_name("watch")] WHERE (ckey = '[sql_ckey]')")
query_watch.Execute()
if(query_watch.NextRow())
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(src)] is flagged for watching and has just connected - Reason: [query_watch.item[2]]</font>")
send2irc_adminless_only("Watchlist", "[key_name(src)] is flagged for watching and has just connected - Reason: [query_watch.item[2]]")
var/watchreason = check_watchlist(sql_ckey)
if(watchreason)
message_admins("<font color='red'><B>Notice: </B></font><font color='blue'>[key_name_admin(src)] is on the watchlist and has just connected - Reason: [watchreason]</font>")
send2irc_adminless_only("Watchlist", "[key_name(src)] is on the watchlist and has just connected - Reason: [watchreason]")
var/admin_rank = "Player"
if (src.holder && src.holder.rank)
@@ -323,20 +324,6 @@ var/next_external_rsc = 0
'icons/pda_icons/pda_scanner.png',
'icons/pda_icons/pda_signaler.png',
'icons/pda_icons/pda_status.png',
'icons/spideros_icons/sos_1.png',
'icons/spideros_icons/sos_2.png',
'icons/spideros_icons/sos_3.png',
'icons/spideros_icons/sos_4.png',
'icons/spideros_icons/sos_5.png',
'icons/spideros_icons/sos_6.png',
'icons/spideros_icons/sos_7.png',
'icons/spideros_icons/sos_8.png',
'icons/spideros_icons/sos_9.png',
'icons/spideros_icons/sos_10.png',
'icons/spideros_icons/sos_11.png',
'icons/spideros_icons/sos_12.png',
'icons/spideros_icons/sos_13.png',
'icons/spideros_icons/sos_14.png',
'icons/stamp_icons/large_stamp-clown.png',
'icons/stamp_icons/large_stamp-deny.png',
'icons/stamp_icons/large_stamp-ok.png',
+4 -2
View File
@@ -345,8 +345,8 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set
if(user.client)
if(user.client.holder)
dat += "<b>Adminhelp Sound:</b> "
dat += "<a href='?_src_=prefs;preference=hear_adminhelps'>[(toggles & SOUND_ADMINHELP)?"On":"Off"]</a><br>"
dat += "<b>Adminhelp Sound:</b> <a href='?_src_=prefs;preference=hear_adminhelps'>[(toggles & SOUND_ADMINHELP)?"On":"Off"]</a><br>"
dat += "<b>Announce Login:</b> <a href='?_src_=prefs;preference=announce_login'>[(toggles & ANNOUNCE_LOGIN)?"On":"Off"]</a><br>"
if(unlock_content || check_rights_for(user.client, R_ADMIN))
dat += "<b>OOC:</b> <span style='border: 1px solid #161616; background-color: [ooccolor ? ooccolor : normal_ooc_colour];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=ooccolor;task=input'>Change</a><br>"
@@ -955,6 +955,8 @@ var/global/list/special_roles = list( //keep synced with the defines BE_* in set
if("hear_adminhelps")
toggles ^= SOUND_ADMINHELP
if("announce_login")
toggles ^= ANNOUNCE_LOGIN
if("ui")
switch(UI_style)
@@ -64,6 +64,16 @@
usr << "You will [(prefs.toggles & SOUND_ADMINHELP) ? "now" : "no longer"] hear a sound when adminhelps arrive."
feedback_add_details("admin_verb","AHS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggleannouncelogin()
set name = "Do/Don't Announce Login"
set category = "Preferences"
set desc = "Toggle if you want an announcement to admins when you login during a round"
if(!holder) return
prefs.toggles ^= ANNOUNCE_LOGIN
prefs.save_preferences()
usr << "You will [(prefs.toggles & ANNOUNCE_LOGIN) ? "now" : "no longer"] have an announcement to other admins when you login."
feedback_add_details("admin_verb","TAL") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/deadchat()
set name = "Show/Hide Deadchat"
set category = "Preferences"
+7
View File
@@ -149,6 +149,13 @@ BLIND // can't see anything
permeability_coefficient = 0.50
slowdown = SHOES_SLOWDOWN
var/blood_state = BLOOD_STATE_NOT_BLOODY
var/list/bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
/obj/item/clothing/shoes/clean_blood()
..()
bloody_shoes = list(BLOOD_STATE_HUMAN = 0,BLOOD_STATE_XENO = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0)
blood_state = BLOOD_STATE_NOT_BLOODY
/obj/item/proc/negates_gravity()
return 0
+57 -3
View File
@@ -188,12 +188,14 @@
..()
/obj/item/clothing/glasses/thermal/syndi //These are now a traitor item, concealed as mesons. -Pete
name = "Optical Meson Scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
icon_state = "meson"
name = "Chameleon Thermals"
desc = "A pair of thermal optic goggles with an onboard chameleon generator. Toggle to disguise."
origin_tech = "magnets=3;syndicate=4"
flash_protect = -1
/obj/item/clothing/glasses/thermal/syndi/attack_self(mob/user)
chameleon(user)
/obj/item/clothing/glasses/thermal/monocle
name = "Thermoncle"
desc = "A monocle thermal."
@@ -230,3 +232,55 @@
icon_state = "redglasses"
item_state = "redglasses"
/obj/item/clothing/glasses/proc/chameleon(var/mob/user)
var/input_glasses = input(user, "Choose a piece of eyewear to disguise as.", "Choose glasses style.") as null|anything in list("Sunglasses", "Medical HUD", "Mesons", "Science Goggles", "Glasses", "Security Sunglasses","Eyepatch","Welding","Gar")
if(user && src in user.contents)
switch(input_glasses)
if("Sunglasses")
desc = "Strangely ancient technology used to help provide rudimentary eye cover. Enhanced shielding blocks many flashes."
name = "sunglasses"
icon_state = "sun"
item_state = "sunglasses"
if("Medical HUD")
name = "Health Scanner HUD"
desc = "A heads-up display that scans the humans in view and provides accurate data about their health status."
icon_state = "healthhud"
item_state = "healthhud"
if("Mesons")
name = "Optical Meson Scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
icon_state = "meson"
item_state = "meson"
if("Science Goggles")
name = "Science Goggles"
desc = "A pair of snazzy goggles used to protect against chemical spills."
icon_state = "purple"
item_state = "glasses"
if("Glasses")
name = "Prescription Glasses"
desc = "Made by Nerd. Co."
icon_state = "glasses"
item_state = "glasses"
if("Security Sunglasses")
name = "HUDSunglasses"
desc = "Sunglasses with a HUD."
icon_state = "sunhud"
item_state = "sunglasses"
if("Eyepatch")
name = "eyepatch"
desc = "Yarr."
icon_state = "eyepatch"
item_state = "eyepatch"
if("Welding")
name = "welding goggles"
desc = "Protects the eyes from welders; approved by the mad scientist association."
icon_state = "welding-g"
item_state = "welding-g"
if("Gar")
desc = "Just who the hell do you think I am?!"
name = "gar glasses"
icon_state = "gar"
item_state = "gar"
+9
View File
@@ -46,6 +46,15 @@
icon_state = "securityhud"
hud_type = DATA_HUD_SECURITY_ADVANCED
/obj/item/clothing/glasses/hud/security/chameleon
name = "Chamleon Security HUD"
desc = "A stolen security HUD integrated with Syndicate chameleon technology. Toggle to disguise the HUD. Provides flash protection."
flash_protect = 1
/obj/item/clothing/glasses/hud/security/chameleon/attack_self(mob/user)
chameleon(user)
/obj/item/clothing/glasses/hud/security/sunglasses/eyepatch
name = "Eyepatch HUD"
desc = "A heads-up display that connects directly to the optical nerve of the user, replacing the need for that useless eyeball."
+1 -1
View File
@@ -81,7 +81,7 @@
can_toggle = 1
toggle_cooldown = 20
active_sound = 'sound/items/WEEOO1.ogg'
/obj/item/clothing/head/helmet/justice/escape
name = "alarm helmet"
desc = "WEEEEOOO. WEEEEEOOO. STOP THAT MONKEY. WEEEOOOO."
@@ -62,6 +62,16 @@
put_on_delay = 50
burn_state = -1 //Won't burn in fires
/obj/item/clothing/shoes/galoshes/dry
name = "absorbent galoshes"
desc = "A pair of orange rubber boots, designed to prevent slipping on wet surfaces while also drying them."
icon_state = "galoshes_dry"
/obj/item/clothing/shoes/galoshes/dry/step_action()
var/turf/simulated/t_loc = get_turf(src)
if(istype(t_loc) && t_loc.wet)
t_loc.MakeDry(TURF_WET_WATER)
/obj/item/clothing/shoes/clown_shoes
desc = "The prankster's standard-issue clowning shoes. Damn, they're huge!"
name = "clown shoes"
@@ -14,7 +14,7 @@
/obj/item/clothing/head/helmet/space/chronos/Destroy()
dropped()
..()
return ..()
/obj/item/clothing/suit/space/chronos
@@ -55,7 +55,7 @@
/obj/item/clothing/suit/space/chronos/Destroy()
dropped()
..()
return ..()
/obj/item/clothing/suit/space/chronos/emp_act(severity)
var/mob/living/carbon/human/user = src.loc
@@ -216,5 +216,5 @@
holder.remote_control = null
if(holder.client && (holder.client.eye == src))
holder.client.eye = holder
..()
return ..()
@@ -10,6 +10,7 @@
var/basestate = "hardsuit"
var/brightness_on = 4 //luminosity when on
var/on = 0
var/obj/item/clothing/suit/space/hardsuit/suit
item_color = "engineering" //Determines used sprites: hardsuit[on]-[color] and hardsuit[on]-[color]2 (lying down sprite)
action_button_name = "Toggle Helmet Light"
flags = BLOCKHAIR | STOPSPRESSUREDMAGE | THICKMATERIAL | NODROP
@@ -40,7 +40,7 @@ Contains:
desc = "That's not red paint. That's real blood."
icon_state = "deathsquad"
item_state = "deathsquad"
armor = list(melee = 50, bullet = 40, laser = 30, energy = 50, bomb = 50, bio = 100, rad = 100)
armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
unacidable = 1
@@ -55,7 +55,7 @@ Contains:
icon_state = "deathsquad"
item_state = "swat_suit"
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals)
armor = list(melee = 50, bullet = 40, laser = 30,energy = 50, bomb = 50, bio = 100, rad = 100)
armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
slowdown = 1
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
@@ -68,7 +68,7 @@ Contains:
icon_state = "beret_badge"
flags = STOPSPRESSUREDMAGE
flags_inv = 0
armor = list(melee = 50, bullet = 40, laser = 30, energy = 50, bomb = 50, bio = 100, rad = 100)
armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
unacidable = 1
@@ -83,7 +83,7 @@ Contains:
flags_inv = 0
w_class = 3
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/weapon/tank/internals)
armor = list(melee = 50, bullet = 40, laser = 30,energy = 50, bomb = 50, bio = 100, rad = 100)
armor = list(melee = 80, bullet = 80, laser = 50, energy = 50, bomb = 100, bio = 100, rad = 100)
slowdown = 1
strip_delay = 130
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
+1 -1
View File
@@ -105,7 +105,7 @@
/obj/item/clothing/suit/armor/laserproof/IsReflect(def_zone)
if(!(def_zone in list("chest", "groin"))) //If not shot where ablative is covering you, you don't get the reflection bonus!
hit_reflect_chance = 0
return 0
if (prob(hit_reflect_chance))
return 1
+1 -1
View File
@@ -20,7 +20,7 @@
item_state = "bio_suit"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
flags_inv = HIDEJUMPSUIT
allowed = list(/obj/item/weapon/disk, /obj/item/weapon/stamp, /obj/item/weapon/reagent_containers/food/drinks/flask, /obj/item/weapon/melee, /obj/item/weapon/storage/lockbox/medal, /obj/item/device/flash/handheld, /obj/item/weapon/storage/box/matches, /obj/item/weapon/lighter, /obj/item/clothing/mask/cigarette, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/tank/internals/emergency_oxygen)
allowed = list(/obj/item/weapon/disk, /obj/item/weapon/stamp, /obj/item/weapon/reagent_containers/food/drinks/flask, /obj/item/weapon/melee, /obj/item/weapon/storage/lockbox/medal, /obj/item/device/assembly/flash/handheld, /obj/item/weapon/storage/box/matches, /obj/item/weapon/lighter, /obj/item/clothing/mask/cigarette, /obj/item/weapon/storage/fancy/cigarettes, /obj/item/weapon/tank/internals/emergency_oxygen)
//Chaplain
/obj/item/clothing/suit/hooded/chaplain_hoodie
+13 -5
View File
@@ -10,7 +10,7 @@
/obj/item/clothing/suit/hooded/Destroy()
qdel(hood)
..()
return ..()
/obj/item/clothing/suit/hooded/proc/MakeHood()
if(!hood)
@@ -90,7 +90,6 @@
user << "Alt-click on [src] to toggle the [togglename]."
//Hardsuit toggle code
/obj/item/clothing/suit/space/hardsuit/New()
MakeHelmet()
if(!jetpack)
@@ -98,15 +97,24 @@
verbs -= /obj/item/clothing/suit/space/hardsuit/verb/Jetpack_Rockets
..()
/obj/item/clothing/suit/space/hardsuit/Destroy()
qdel(helmet)
if(helmet)
helmet.suit = null
qdel(helmet)
qdel(jetpack)
..()
return ..()
/obj/item/clothing/head/helmet/space/hardsuit/Destroy()
if(suit)
suit.helmet = null
qdel(suit)
return ..()
/obj/item/clothing/suit/space/hardsuit/proc/MakeHelmet()
if(!helmettype)
return
if(!helmet)
var/obj/item/clothing/head/helmet/space/hardsuit/W = new helmettype(src)
W.suit = src
helmet = W
/obj/item/clothing/suit/space/hardsuit/ui_action_click()
@@ -121,7 +129,7 @@
..()
/obj/item/clothing/suit/space/hardsuit/proc/RemoveHelmet()
if(!helmettype)
if(!helmet)
return
suittoggled = 0
if(ishuman(helmet.loc))
@@ -28,6 +28,9 @@
reagents.reaction(C, INGEST)
reagents.trans_to(C, reagents.total_volume)
C.visible_message("<span class='danger'>[user] has smothered \the [C] with \the [src]!</span>", "<span class='userdanger'>[user] has smothered you with \the [src]!</span>", "<span class='italics'>You hear some struggling and muffled cries of surprise.</span>")
var/reagentlist = pretty_string_from_reagent_list(A.reagents)
log_game("[key_name(user)] smothered [key_name(A)] with a damp rag containing [reagentlist]")
log_attack("[key_name(user)] smothered [key_name(A)] with a damp rag containing [reagentlist]")
else
reagents.reaction(C, TOUCH)
reagents.clear_reagents()
+1 -5
View File
@@ -7,7 +7,6 @@
/datum/round_event/brand_intelligence
announceWhen = 21
endWhen = 1000 //Ends when all vending machines are subverted anyway.
var/list/obj/machinery/vending/vendingMachines = list()
var/list/obj/machinery/vending/infectedMachines = list()
var/obj/machinery/vending/originMachine
@@ -28,11 +27,9 @@
for(var/obj/machinery/vending/V in machines)
if(V.z != 1) continue
vendingMachines.Add(V)
if(!vendingMachines.len)
kill()
return
originMachine = pick(vendingMachines)
vendingMachines.Remove(originMachine)
originMachine.shut_up = 0
@@ -48,7 +45,7 @@
originMachine.visible_message("[originMachine] beeps and seems lifeless.")
kill()
return
vendingMachines = removeNullsFromList(vendingMachines)
if(!vendingMachines.len) //if every machine is infected
for(var/obj/machinery/vending/upriser in infectedMachines)
if(prob(70) && !upriser.gc_destroyed)
@@ -62,7 +59,6 @@
kill()
return
if(IsMultiple(activeFor, 4))
var/obj/machinery/vending/rebel = pick(vendingMachines)
vendingMachines.Remove(rebel)
+2 -3
View File
@@ -66,7 +66,6 @@
color = "#aa77aa"
icon_state = "vinefloor"
broken_states = list()
ignoredirt = 1
//All of this shit is useless for vines
@@ -324,7 +323,7 @@
SetOpacity(0)
if(buckled_mob)
unbuckle_mob()
..()
return ..()
/obj/effect/spacevine/proc/on_chem_effect(datum/reagent/R)
var/override = 0
@@ -424,7 +423,7 @@
/obj/effect/spacevine_controller/Destroy()
SSobj.processing.Remove(src)
..()
return ..()
/obj/effect/spacevine_controller/proc/spawn_spacevine_piece(turf/location, obj/effect/spacevine/parent, list/muts)
var/obj/effect/spacevine/SV = new(location)
+1 -1
View File
@@ -18,7 +18,7 @@
endWhen = rand(25, 100)
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/temp_vent in machines)
if(temp_vent.loc.z == ZLEVEL_STATION && !temp_vent.welded)
var/datum/pipeline/temp_vent_parent = temp_vent.parents["p1"]
var/datum/pipeline/temp_vent_parent = temp_vent.PARENT1
if(temp_vent_parent.other_atmosmch.len > 20)
vents += temp_vent
if(!vents.len)
+1 -1
View File
@@ -78,4 +78,4 @@
M.color = initial(M.color)
message += "...</span>"
M << message
..()
return ..()
+16 -14
View File
@@ -107,6 +107,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
/obj/effect/hallucination/simple/Destroy()
if(target.client) target.client.images.Remove(current_image)
active = 0
return ..()
#define FAKE_FLOOD_EXPAND_TIME 30
#define FAKE_FLOOD_MAX_RADIUS 7
@@ -160,7 +161,7 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(target.client) target.client.images.Remove(flood_images)
target = null
qdel(flood_images)
return
return ..()
/obj/effect/hallucination/simple/xeno
image_icon = 'icons/mob/alien.dmi'
@@ -188,19 +189,20 @@ Gunshots/explosions/opening doors/less rare audio (done)
if(!U.welded)
pump = U
break
xeno = new(pump.loc,target)
sleep(10)
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
sleep(10)
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
sleep(10)
var/xeno_name = xeno.name
target << "<span class='notice'>[xeno_name] begins climbing into the ventilation system...</span>"
sleep(10)
qdel(xeno)
target << "<span class='notice'>[xeno_name] scrambles into the ventilation ducts!</span>"
if(pump)
xeno = new(pump.loc,target)
sleep(10)
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1)
sleep(10)
xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32)
xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1)
sleep(10)
var/xeno_name = xeno.name
target << "<span class='notice'>[xeno_name] begins climbing into the ventilation system...</span>"
sleep(10)
qdel(xeno)
target << "<span class='notice'>[xeno_name] scrambles into the ventilation ducts!</span>"
qdel(src)
/obj/effect/hallucination/singularity_scare
+1 -1
View File
@@ -223,7 +223,7 @@
if(contents)
for(var/atom/movable/something in contents)
something.loc = get_turf(src)
..()
return ..()
/obj/item/weapon/reagent_containers/food/snacks/attack_animal(mob/M)
if(isanimal(M))
+2 -2
View File
@@ -305,7 +305,7 @@
/obj/item/weapon/reagent_containers/food/snacks/grown/berries/glow/Destroy()
if(istype(loc,/mob))
loc.AddLuminosity(round(-potency / 5,1))
..()
return ..()
/obj/item/weapon/reagent_containers/food/snacks/grown/berries/glow/pickup(mob/user)
src.SetLuminosity(0)
@@ -1208,7 +1208,7 @@ obj/item/weapon/reagent_containers/food/snacks/grown/shell/eggy/add_juice()
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom/Destroy()
if(istype(loc,/mob))
loc.AddLuminosity(round(-potency / 10,1))
..()
return ..()
/obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/glowshroom/pickup(mob/user)
SetLuminosity(0)
+10 -2
View File
@@ -1339,21 +1339,29 @@
if(parent)
mutations = parent.mutations
/obj/item/seeds/kudzuseed/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] swallows the pack of kudzu seeds! It looks like \he's trying to commit suicide..</span>")
plant(user)
return (BRUTELOSS)
/obj/item/seeds/kudzuseed/harvest()
var/list/prod = ..()
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/kudzupod/K in prod)
K.mutations = mutations
/obj/item/seeds/kudzuseed/attack_self(mob/user)
/obj/item/seeds/kudzuseed/proc/plant(mob/user)
if(istype(user.loc,/turf/space))
return
var/turf/T = get_turf(src)
user << "<span class='notice'>You plant the kudzu. You monster.</span>"
message_admins("Kudzu planted by [key_name_admin(user)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) (<A HREF='?_src_=holder;adminplayerobservefollow=\ref[user]'>FLW</A>) at ([T.x],[T.y],[T.z] - <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>(JMP)</a>)",0,1)
investigate_log("was planted by [key_name(user)] at ([T.x],[T.y],[T.z])","kudzu")
new /obj/effect/spacevine_controller(user.loc, mutations, potency, production)
qdel(src)
/obj/item/seeds/kudzuseed/attack_self(mob/user)
plant(user)
user << "<span class='notice'>You plant the kudzu. You monster.</span>"
/obj/item/seeds/kudzuseed/get_analyzer_text()
var/list/mut_text = list()
var/text_string = ""
+1 -1
View File
@@ -43,7 +43,7 @@
new /obj/item/weapon/ore/diamond(src)
if(21 to 25)
for(var/i = 0, i < 5, i++)
new /obj/item/weapon/contraband/poster(src)
new /obj/item/weapon/poster/contraband(src)
if(26 to 30)
for(var/i = 0, i < 3, i++)
new /obj/item/weapon/reagent_containers/glass/beaker/noreact(src)
+1
View File
@@ -573,6 +573,7 @@
/**********************Facehugger toy**********************/
/obj/item/clothing/mask/facehugger/toy
item_state = "facehugger_inactive"
desc = "A toy often used to play pranks on other miners by putting it in their beds. It takes a bit to recharge after latching onto something."
throwforce = 0
real = 0
+6 -1
View File
@@ -509,7 +509,6 @@ var/global/list/rockTurfEdgeCache
icon_state = "asteroid"
icon_plating = "asteroid"
var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
ignoredirt = 1
/turf/simulated/floor/plating/asteroid/airless
oxygen = 0.01
@@ -603,6 +602,12 @@ var/global/list/rockTurfEdgeCache
icon_state = "asteroid_dug"
return
/turf/simulated/floor/plating/asteroid/singularity_act()
return
/turf/simulated/floor/plating/asteroid/singularity_pull(S, current_size)
return
/turf/proc/updateMineralOverlays()
src.overlays.Cut()
+9 -2
View File
@@ -121,6 +121,11 @@
var/attacher = "UNKNOWN"
var/datum/wires/explosive/gibtonite/wires
/obj/item/weapon/twohanded/required/gibtonite/Destroy()
qdel(wires)
wires = null
return ..()
/obj/item/weapon/twohanded/required/gibtonite/attackby(obj/item/I, mob/user, params)
if(!wires && istype(I, /obj/item/device/assembly/igniter))
user.visible_message("[user] attaches [I] to [src].", "<span class='notice'>You attach [I] to [src].</span>")
@@ -131,7 +136,7 @@
return
if(wires && !primed)
if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler))
if(wires.IsInteractionTool(I))
wires.Interact(user)
return
@@ -326,7 +331,9 @@
flick("coin_[cmineral]_flip", src)
icon_state = "coin_[cmineral]_[coinflip]"
playsound(user.loc, 'sound/items/coinflip.ogg', 50, 1)
if(do_after(user, 15, target = src))
var/oldloc = loc
sleep(15)
if(loc == oldloc && user && !user.incapacitated())
user.visible_message("[user] has flipped [src]. It lands on [coinflip].", \
"<span class='notice'>You flip [src]. It lands on [coinflip].</span>", \
"<span class='italics'>You hear the clattering of loose change.</span>")
-4
View File
@@ -14,10 +14,6 @@
/mob/camera/experience_pressure_difference()
return
/mob/camera/Destroy()
..()
qdel(src)
/mob/camera/Login()
..()
update_interface()
+1 -1
View File
@@ -69,7 +69,7 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi
qdel(ghostimage)
ghostimage = null
updateallghostimages()
..()
return ..()
/mob/dead/CanPass(atom/movable/mover, turf/target, height=0)
return 1
+3 -1
View File
@@ -293,7 +293,9 @@
/mob/living/carbon/human/interactive/Life()
..()
if(isnotfunc()) return
if(isnotfunc())
walk(src,0)
return
if(a_intent != "disarm")
a_intent = "disarm"
//---------------------------
+56 -85
View File
@@ -1,91 +1,6 @@
//Travel through pools of blood. Slaughter Demon powers for everyone!
#define BLOODCRAWL 1
#define BLOODCRAWL_EAT 2
/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
var/mob/living/kidnapped = null
var/turf/mobloc = get_turf(src.loc)
var/turf/bloodloc = get_turf(B.loc)
if(Adjacent(bloodloc))
src.notransform = TRUE
spawn(0)
src.visible_message("[src] sinks into the pool of blood.")
playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
src.ExtinguishMob()
if(src.buckled)
src.buckled.unbuckle_mob()
if(src.pulling && src.bloodcrawl == BLOODCRAWL_EAT)
if(istype(src.pulling, /mob/living))
var/mob/living/victim = src.pulling
if(victim.stat == CONSCIOUS)
src.visible_message("[victim] kicks free of the [src] at the last second!")
else
victim.loc = holder
src.visible_message("<span class='warning'><B>The [src] drags [victim] into the pool of blood!</B>")
kidnapped = victim
src.loc = holder
src.holder = holder
if(kidnapped)
src << "<B>You begin to feast on [kidnapped]. You can not move while you are doing this.</B>"
playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
sleep(30)
playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
sleep(30)
playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
sleep(30)
src << "<B>You devour [kidnapped]. Your health is fully restored.</B>"
src.adjustBruteLoss(-1000)
src.adjustFireLoss(-1000)
src.adjustOxyLoss(-1000)
src.adjustToxLoss(-1000)
kidnapped.ghostize()
qdel(kidnapped)
src.notransform = 0
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
if(src.notransform)
src << "<B>Finish eating first!</B>"
else
src.loc = B.loc
src.client.eye = src
src.visible_message("<span class='warning'><B>The [src] rises out of the pool of blood!</B>")
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
qdel(src.holder)
src.holder = null
/obj/effect/decal/cleanable/blood/CtrlClick(mob/living/user)
..()
if(user.bloodcrawl)
if(user.holder)
user.phasein(src)
else
user.phaseout(src)
/obj/effect/decal/cleanable/trail_holder/CtrlClick(mob/living/user)
..()
if(user.bloodcrawl)
if(user.holder)
user.phasein(src)
else
user.phaseout(src)
/turf/CtrlClick(var/mob/living/user)
..()
if(user.bloodcrawl)
for(var/obj/effect/decal/cleanable/B in src.contents)
if(istype(B, /obj/effect/decal/cleanable/blood) || istype(B, /obj/effect/decal/cleanable/trail_holder))
if(user.holder)
user.phasein(B)
break
else
user.phaseout(B)
break
/obj/effect/dummy/slaughter //Can't use the wizard one, blocked by jaunt/slow
name = "water"
icon = 'icons/effects/effects.dmi'
@@ -113,3 +28,59 @@ obj/effect/dummy/slaughter/relaymove(mob/user, direction)
/obj/effect/dummy/slaughter/Destroy()
return QDEL_HINT_PUTINPOOL
/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
var/mob/living/kidnapped = null
var/turf/mobloc = get_turf(src.loc)
src.notransform = TRUE
spawn(0)
src.visible_message("[src] sinks into the pool of blood.")
playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
src.ExtinguishMob()
if(src.buckled)
src.buckled.unbuckle_mob()
if(src.pulling && src.bloodcrawl == BLOODCRAWL_EAT)
if(istype(src.pulling, /mob/living))
var/mob/living/victim = src.pulling
if(victim.stat == CONSCIOUS)
src.visible_message("[victim] kicks free of the [src] at the last second!")
else
victim.loc = holder
src.visible_message("<span class='warning'><B>The [src] drags [victim] into the pool of blood!</B>")
kidnapped = victim
src.loc = holder
src.holder = holder
if(kidnapped)
src << "<B>You begin to feast on [kidnapped]. You can not move while you are doing this.</B>"
playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
sleep(30)
playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
sleep(30)
playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
sleep(30)
if(kidnapped)
src << "<B>You devour [kidnapped]. Your health is fully restored.</B>"
src.adjustBruteLoss(-1000)
src.adjustFireLoss(-1000)
src.adjustOxyLoss(-1000)
src.adjustToxLoss(-1000)
kidnapped.ghostize()
qdel(kidnapped)
else
src << "<B>You happily devour...nothing? Your meal vanished at some point!</B>"
src.notransform = 0
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
if(src.notransform)
src << "<B>Finish eating first!</B>"
return 0
src.loc = B.loc
src.client.eye = src
src.visible_message("<span class='warning'><B>The [src] rises out of the pool of blood!</B>")
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
qdel(src.holder)
src.holder = null
return 1
@@ -73,7 +73,19 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
adjustBruteLoss(damage)
switch(M.melee_damage_type)
if(BRUTE)
adjustBruteLoss(damage)
if(BURN)
adjustFireLoss(damage)
if(TOX)
adjustToxLoss(damage)
if(OXY)
adjustOxyLoss(damage)
if(CLONE)
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
@@ -1,4 +1,4 @@
/mob/living/carbon/alien/humanoid/emote(act)
/mob/living/carbon/alien/humanoid/emote(act,m_type=1,message = null)
var/param = null
if (findtext(act, "-", 1, null))
@@ -7,8 +7,6 @@
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
var/m_type = 1
var/message
switch(act) //Alphabetical please
if ("deathgasp","deathgasps")
@@ -25,6 +23,10 @@
message = "<span class='name'>[src]</span> hisses."
m_type = 2
if ("me")
..()
return
if ("moan","moans")
message = "<span class='name'>[src]</span> moans!"
m_type = 2
@@ -14,7 +14,6 @@
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/New()
create_reagents(1000)
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
..()
@@ -10,8 +10,6 @@
/mob/living/carbon/alien/humanoid/queen/New()
create_reagents(100)
//there should only be one queen
for(var/mob/living/carbon/alien/humanoid/queen/Q in living_mob_list)
if(Q == src) continue
@@ -77,17 +75,3 @@
icon_state = "queen_s"
pixel_x = -16
mob_size = MOB_SIZE_LARGE
/mob/living/carbon/alien/humanoid/queen/large/update_icons()
update_hud() //TODO: remove the need for this to be here
overlays.Cut()
if(stat == DEAD)
icon_state = "queen_dead"
else if((stat == UNCONSCIOUS && !sleeping) || weakened)
icon_state = "queen_l"
else if(sleeping || lying || resting)
icon_state = "queen_sleep"
else
icon_state = "queen_s"
for(var/image/I in overlays_standing)
overlays += I
@@ -50,4 +50,29 @@
if(lying > 0)
lying = 90 //Anything else looks retarded
..()
update_icons()
update_icons()
/mob/living/carbon/alien/humanoid/queen/large/update_icons()
update_hud() //TODO: remove the need for this to be here
overlays.Cut()
if(stat == DEAD)
icon_state = "queen_dead"
else if((stat == UNCONSCIOUS && !sleeping) || weakened)
icon_state = "queen_l"
else if(sleeping || lying || resting)
icon_state = "queen_sleep"
else
icon_state = "queen_s"
for(var/image/I in overlays_standing)
overlays += I
/mob/living/carbon/alien/humanoid/queen/large/update_inv_l_hand()
remove_overlay(L_HAND_LAYER)
if(handcuffed)
drop_l_hand()
/mob/living/carbon/alien/humanoid/queen/large/update_inv_r_hand()
remove_overlay(R_HAND_LAYER)
if(handcuffed)
drop_r_hand()
@@ -24,5 +24,5 @@
/mob/living/carbon/alien/larva/update_transform() //All this is handled in update_icons()
return update_icons()
/mob/living/carbon/larva/update_inv_handcuffed()
/mob/living/carbon/alien/larva/update_inv_handcuffed()
return
@@ -73,15 +73,17 @@
/obj/item/organ/internal/alien/plasmavessel/on_life()
//If there are alien weeds on the ground then heal if needed or give some plasma
if(locate(/obj/structure/alien/weeds) in owner.loc)
if(owner.health >= owner.maxHealth - owner.getCloneLoss())
if(owner.health >= owner.maxHealth)
owner.adjustPlasma(plasma_rate)
else
var/mod = 1
var/heal_amt = heal_rate
if(!isalien(owner))
mod = 0.2
owner.adjustBruteLoss(-heal_rate*mod)
owner.adjustFireLoss(-heal_rate*mod)
owner.adjustOxyLoss(-heal_rate*mod)
heal_amt *= 0.2
owner.adjustPlasma(plasma_rate*0.5)
owner.adjustBruteLoss(-heal_amt)
owner.adjustFireLoss(-heal_amt)
owner.adjustOxyLoss(-heal_amt)
owner.adjustCloneLoss(-heal_amt)
/obj/item/organ/internal/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
..()
+7 -3
View File
@@ -3,16 +3,20 @@
if(.)
playsound(loc, "hiss", 25, 1, 1) //erp just isn't the same without sound feedback
/mob/living/proc/alien_talk(message)
/mob/living/proc/alien_talk(message, shown_name = name)
log_say("[key_name(src)] : [message]")
message = trim(message)
if(!message) return
var/message_a = say_quote(message)
var/rendered = "<i><span class='game say'>Hivemind, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
for(var/mob/S in player_list)
if((!S.stat && S.hivecheck()) || (S in dead_mob_list))
S << rendered
/mob/living/carbon/alien/humanoid/queen/alien_talk(message, shown_name = name)
shown_name = "<FONT size = 3>[shown_name]</FONT>"
..(message, shown_name)
/mob/living/carbon/hivecheck()
return getorgan(/obj/item/organ/internal/alien/hivenode)
@@ -187,7 +187,6 @@ var/const/MAX_ACTIVE_TIME = 400
else
target.visible_message("<span class='danger'>[src] violates [target]'s face!</span>", \
"<span class='userdanger'>[src] violates [target]'s face!</span>")
return
/obj/item/clothing/mask/facehugger/proc/GoActive()
if(stat == DEAD || stat == CONSCIOUS)
@@ -196,20 +195,10 @@ var/const/MAX_ACTIVE_TIME = 400
stat = CONSCIOUS
icon_state = "[initial(icon_state)]"
/* for(var/mob/living/carbon/alien/alien in world)
var/image/activeIndicator = image('icons/mob/alien.dmi', loc = src, icon_state = "facehugger_active")
activeIndicator.override = 1
if(alien && alien.client)
alien.client.images += activeIndicator */
return
/obj/item/clothing/mask/facehugger/proc/GoIdle()
if(stat == DEAD || stat == UNCONSCIOUS)
return
/* RemoveActiveIndicators() */
stat = UNCONSCIOUS
icon_state = "[initial(icon_state)]_inactive"
@@ -221,15 +210,12 @@ var/const/MAX_ACTIVE_TIME = 400
if(stat == DEAD)
return
/* RemoveActiveIndicators() */
icon_state = "[initial(icon_state)]_dead"
item_state = "facehugger_inactive"
stat = DEAD
visible_message("<span class='danger'>[src] curls up into a ball!</span>")
return
/proc/CanHug(mob/living/M)
if(!istype(M))
return 0
+1 -1
View File
@@ -147,7 +147,7 @@
if(brainmob)
qdel(brainmob)
brainmob = null
..()
return ..()
/obj/item/device/mmi/examine(mob/user)
..()
@@ -8,16 +8,12 @@
var/alert = null
has_limbs = 0
/mob/living/carbon/brain/New()
create_reagents(1000)
..()
/mob/living/carbon/brain/Destroy()
if(key) //If there is a mob connected to this thing. Have to check key twice to avoid false death reporting.
if(stat!=DEAD) //If not dead.
death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA
ghostize() //Ghostize checks for key so nothing else is necessary.
..()
return ..()
/mob/living/carbon/brain/update_canmove()
if(in_contents_of(/obj/mecha)) canmove = 1
@@ -112,7 +112,7 @@
if(brainmob)
qdel(brainmob)
brainmob = null
..()
return ..()
/obj/item/organ/internal/brain/alien
name = "alien brain"
+13 -3
View File
@@ -1,3 +1,7 @@
/mob/living/carbon/New()
create_reagents(1000)
..()
/mob/living/carbon/prepare_huds()
..()
prepare_data_huds()
@@ -74,9 +78,9 @@
. = ..()
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0)
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, override = 0)
shock_damage *= siemens_coeff
if (shock_damage<1)
if(shock_damage<1 && !override)
return 0
take_overall_damage(0,shock_damage)
//src.burn_skin(shock_damage)
@@ -95,7 +99,10 @@
jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less
Stun(3)
Weaken(3)
return shock_damage
if(override)
return override
else
return shock_damage
/mob/living/carbon/swap_hand()
@@ -572,4 +579,7 @@ var/const/GALOSHES_DONT_HELP = 4
var/obj/item/organ/internal/alien/plasmavessel/vessel = getorgan(/obj/item/organ/internal/alien/plasmavessel)
if(vessel)
stat(null, "Plasma Stored: [vessel.storedPlasma]/[vessel.max_plasma]")
if(locate(/obj/item/device/assembly/health) in src)
stat(null, "Health: [health]")
add_abilities_to_panel()
+5
View File
@@ -111,6 +111,11 @@
else
message = "<B>[src]</B> makes a noise."
if ("me")
if(!silent)
..()
return
if ("nod","nods")
message = "<B>[src]</B> nods."
m_type = 1
@@ -1,45 +1,58 @@
/mob/living/carbon/monkey/examine(mob/user)
var/msg = "<span class='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n"
if (src.handcuffed)
msg += "It is \icon[src.handcuffed] handcuffed!\n"
if (src.head)
msg += "It has \icon[src.head] \a [src.head] on its head. \n"
if (src.wear_mask)
msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its face.\n"
if (src.l_hand)
msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n"
if (src.r_hand)
msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n"
if (src.back)
msg += "It has \icon[src.back] \a [src.back] on its back.\n"
if (src.stat == DEAD)
msg += "<span class='deadsay'>It is limp and unresponsive, with no signs of life.</span>\n"
else
msg += "<span class='warning'>"
if (src.getBruteLoss())
if (src.getBruteLoss() < 30)
msg += "It has minor bruising.\n"
else
msg += "<B>It has severe bruising!</B>\n"
if (src.getFireLoss())
if (src.getFireLoss() < 30)
msg += "It has minor burns.\n"
else
msg += "<B>It has severe burns!</B>\n"
if (src.fire_stacks > 0)
msg += "It's covered in something flammable.\n"
if (src.fire_stacks < 0)
msg += "It's soaked in water.\n"
if (src.stat == UNCONSCIOUS)
msg += "It isn't responding to anything around it; it seems to be asleep.\n"
msg += "</span>"
if (src.digitalcamo)
msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n"
msg += "*---------*</span>"
/mob/living/carbon/examine(mob/user)
var/msg = "<span class='info'>*---------*\nThis is \icon[src] \a <EM>[src]</EM>!\n"
if (handcuffed)
msg += "It is \icon[src.handcuffed] handcuffed!\n"
if (head)
msg += "It has \icon[src.head] \a [src.head] on its head. \n"
if (wear_mask)
msg += "It has \icon[src.wear_mask] \a [src.wear_mask] on its face.\n"
if (l_hand)
msg += "It has \icon[src.l_hand] \a [src.l_hand] in its left hand.\n"
if (r_hand)
msg += "It has \icon[src.r_hand] \a [src.r_hand] in its right hand.\n"
if (back)
msg += "It has \icon[src.back] \a [src.back] on its back.\n"
if (stat == DEAD)
msg += "<span class='deadsay'>It is limp and unresponsive, with no signs of life.</span>\n"
else
msg += "<span class='warning'>"
var/temp = getBruteLoss()
if(temp)
if (temp < 30)
msg += "It has minor bruising.\n"
else
msg += "<B>It has severe bruising!</B>\n"
temp = getFireLoss()
if(temp)
if (temp < 30)
msg += "It has minor burns.\n"
else
msg += "<B>It has severe burns!</B>\n"
temp = getCloneLoss()
if(temp)
if(getCloneLoss() < 30)
msg += "It is slightly deformed.\n"
else
msg += "<b>It is severely deformed.</b>\n"
if(getBrainLoss() > 60)
msg += "It seems to be clumsy and unable to think.\n"
if(fire_stacks > 0)
msg += "It's covered in something flammable.\n"
if(fire_stacks < 0)
msg += "It's soaked in water.\n"
if(stat == UNCONSCIOUS)
msg += "It isn't responding to anything around it; it seems to be asleep.\n"
msg += "</span>"
if (digitalcamo)
msg += "It is moving its body in an unnatural and blatantly unsimian manner.\n"
msg += "*---------*</span>"
user << msg
+33 -4
View File
@@ -14,7 +14,6 @@
/mob/living/carbon/human/New()
create_reagents(1000)
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
//initialise organs
@@ -270,7 +269,7 @@
spreadFire(AM)
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, safety = 0)
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, safety = 0, override = 0)
if(!safety)
if(gloves)
var/obj/item/clothing/gloves/G = gloves
@@ -280,7 +279,11 @@
heart_attack = 0
if(stat == CONSCIOUS)
src << "<span class='notice'>You feel your heart beating again!</span>"
return ..(shock_damage,source,siemens_coeff)
. = ..(shock_damage,source,siemens_coeff,safety,override)
if(.)
electrocution_animation(40)
/mob/living/carbon/human/Topic(href, href_list)
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
@@ -801,4 +804,30 @@
H.bloody_hands = 0
H.bloody_hands_mob = null
H.update_inv_gloves()
update_icons() //apply the now updated overlays to the mob
update_icons() //apply the now updated overlays to the mob
//Turns a mob black, flashes a skeleton overlay
//Just like a cartoon!
/mob/living/carbon/human/proc/electrocution_animation(anim_duration)
//Handle mutant parts if possible
if(dna && dna.species)
dna.species.handle_mutant_bodyparts(src,"black")
dna.species.handle_hair(src,"black")
dna.species.update_color(src,"black")
overlays += "electrocuted_base"
spawn(anim_duration)
if(src)
if(dna && dna.species)
dna.species.handle_mutant_bodyparts(src)
dna.species.handle_hair(src)
dna.species.update_color(src)
overlays -= "electrocuted_base"
else //or just do a generic animation
var/list/viewing = list()
for(var/mob/M in viewers(src))
if(M.client)
viewing += M.client
flick_overlay(image(icon,src,"electrocuted_generic",MOB_LAYER+1), viewing, anim_duration)
@@ -389,7 +389,7 @@ emp_act
var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")
var/obj/item/organ/limb/affecting = get_organ(ran_zone(dam_zone))
var/armor = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor)
apply_damage(damage, M.melee_damage_type, affecting, armor)
updatehealth()
@@ -45,7 +45,7 @@
return shoes && shoes.negates_gravity()
/mob/living/carbon/human/Move(NewLoc, direct)
. = ..()
. = ..()
if(dna)
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_move(src, NewLoc)
@@ -55,5 +55,23 @@
if(!has_gravity(loc))
return
var/obj/item/clothing/shoes/S = shoes
//Bloody footprints
var/turf/T = get_turf(src)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T
if(oldFP && oldFP.blood_state == S.blood_state)
return
else
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
FP.blood_state = S.blood_state
FP.entered_dirs |= dir
FP.bloodiness = S.bloody_shoes[S.blood_state]
FP.update_icon()
update_inv_shoes()
//End bloody footprints
S.step_action()
+2 -2
View File
@@ -8,7 +8,7 @@
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 3 //Amount of damage applied when your body temperature passes the 400K point
#define HEAT_DAMAGE_LEVEL_3 8 //Amount of damage applied when your body temperature passes the 460K point and you are on fire
#define HEAT_DAMAGE_LEVEL_3 10 //Amount of damage applied when your body temperature passes the 460K point and you are on fire
#define COLD_DAMAGE_LEVEL_1 0.5 //Amount of damage applied when your body temperature just passes the 260.15k safety point
#define COLD_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when your body temperature passes the 200K point
@@ -123,7 +123,7 @@
if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT)
bodytemperature += 11
else
bodytemperature += BODYTEMP_HEATING_MAX
bodytemperature += (BODYTEMP_HEATING_MAX + (fire_stacks * 12))
/mob/living/carbon/human/IgniteMob()
+50 -29
View File
@@ -118,24 +118,35 @@
else
return "[id]"
/datum/species/proc/update_color(mob/living/carbon/human/H)
/datum/species/proc/update_color(mob/living/carbon/human/H, forced_colour)
H.remove_overlay(SPECIES_LAYER)
var/image/standing
var/g = (H.gender == FEMALE) ? "f" : "m"
if(MUTCOLORS in specflags)
if((MUTCOLORS in specflags) || use_skintones)
var/image/spec_base
var/icon_state_string = "[id]_"
if(sexes)
icon_state_string += "[g]_s"
if(use_skintones)
if(sexes)
icon_state_string = "[H.skin_tone]_[g]_s"
else
icon_state_string = "[H.skin_tone]_s"
else
icon_state_string += "_s"
if(sexes)
icon_state_string += "[g]_s"
else
icon_state_string += "_s"
spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = icon_state_string, "layer" = -SPECIES_LAYER)
spec_base.color = "#[H.dna.features["mcolor"]]"
if(!forced_colour && !use_skintones)
spec_base.color = "#[H.dna.features["mcolor"]]"
else
spec_base.color = forced_colour
standing = spec_base
if(standing)
@@ -143,7 +154,7 @@
H.apply_overlay(SPECIES_LAYER)
/datum/species/proc/handle_hair(mob/living/carbon/human/H)
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
H.remove_overlay(HAIR_LAYER)
var/datum/sprite_accessory/S
@@ -156,13 +167,17 @@
img_facial_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER)
if(hair_color)
if(hair_color == "mutcolor")
img_facial_s.color = "#" + H.dna.features["mcolor"]
if(!forced_colour)
if(hair_color)
if(hair_color == "mutcolor")
img_facial_s.color = "#" + H.dna.features["mcolor"]
else
img_facial_s.color = "#" + hair_color
else
img_facial_s.color = "#" + hair_color
img_facial_s.color = "#" + H.facial_hair_color
else
img_facial_s.color = "#" + H.facial_hair_color
img_facial_s.color = forced_colour
img_facial_s.alpha = hair_alpha
standing += img_facial_s
@@ -184,13 +199,16 @@
img_hair_s = image("icon" = S.icon, "icon_state" = "[S.icon_state]_s", "layer" = -HAIR_LAYER)
if(hair_color)
if(hair_color == "mutcolor")
img_hair_s.color = "#" + H.dna.features["mcolor"]
if(!forced_colour)
if(hair_color)
if(hair_color == "mutcolor")
img_hair_s.color = "#" + H.dna.features["mcolor"]
else
img_hair_s.color = "#" + hair_color
else
img_hair_s.color = "#" + hair_color
img_hair_s.color = "#" + H.hair_color
else
img_hair_s.color = "#" + H.hair_color
img_hair_s.color = forced_colour
img_hair_s.alpha = hair_alpha
standing += img_hair_s
@@ -246,7 +264,7 @@
return
/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H)
/datum/species/proc/handle_mutant_bodyparts(mob/living/carbon/human/H, forced_colour)
var/list/bodyparts_to_add = mutant_bodyparts.Copy()
var/list/relevent_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
var/list/standing = list()
@@ -359,18 +377,21 @@
I = image("icon" = 'icons/mob/mutant_bodyparts.dmi', "icon_state" = icon_string, "layer" =- layer)
if(!(H.disabilities & HUSK))
switch(S.color_src)
if(MUTCOLORS)
I.color = "#[H.dna.features["mcolor"]]"
if(HAIR)
if(hair_color == "mutcolor")
if(!forced_colour)
switch(S.color_src)
if(MUTCOLORS)
I.color = "#[H.dna.features["mcolor"]]"
else
I.color = "#[H.hair_color]"
if(FACEHAIR)
I.color = "#[H.facial_hair_color]"
if(EYECOLOR)
I.color = "#[H.eye_color]"
if(HAIR)
if(hair_color == "mutcolor")
I.color = "#[H.dna.features["mcolor"]]"
else
I.color = "#[H.hair_color]"
if(FACEHAIR)
I.color = "#[H.facial_hair_color]"
if(EYECOLOR)
I.color = "#[H.eye_color]"
else
I.color = forced_colour
standing += I
if(S.hasinner)
@@ -53,7 +53,6 @@ Please contact me on #coderbus IRC. ~Carnie x
*/
/mob/living/carbon/human/proc/update_base_icon_state()
//var/race = dna ? dna.mutantrace : null
if(dna)
base_icon_state = dna.species.update_base_icon_state(src)
else
@@ -68,7 +67,6 @@ Please contact me on #coderbus IRC. ~Carnie x
//UPDATES OVERLAYS FROM OVERLAYS_STANDING
//TODO: Remove all instances where this proc is called. It used to be the fastest way to swap between standing/lying.
/mob/living/carbon/human/update_icons()
update_hud() //TODO: remove the need for this
if(overlays.len != overlays_standing.len)
@@ -79,7 +77,6 @@ Please contact me on #coderbus IRC. ~Carnie x
update_transform()
//DAMAGE OVERLAYS
//constructs damage icon for each organ from mask * damage field and saves it in our overlays_ lists
/mob/living/carbon/human/update_damage_overlays()
@@ -123,14 +120,9 @@ Please contact me on #coderbus IRC. ~Carnie x
/mob/living/carbon/human/proc/update_body()
remove_overlay(BODY_LAYER)
update_base_icon_state()
if(dna)
base_icon_state = dna.species.update_base_icon_state(src)
else
update_base_icon_state()
icon_state = "[base_icon_state]_s"
if(dna) // didn't want to have a duplicate if(dna) here, but due to the ordering of the code this was the only way
dna.species.handle_body(src)
/mob/living/carbon/human/update_fire()
@@ -370,7 +362,15 @@ Please contact me on #coderbus IRC. ~Carnie x
standing = image("icon"='icons/mob/feet.dmi', "icon_state"="[shoes.icon_state]", "layer"=-layer2use)
overlays_standing[SHOES_LAYER] = standing
//Bloody shoes
var/obj/item/clothing/shoes/S = shoes
var/bloody = 0
if(shoes.blood_DNA)
bloody = 1
else
bloody = S.bloody_shoes[BLOOD_STATE_HUMAN]
if(bloody)
standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="shoeblood")
apply_overlay(SHOES_LAYER)
+10 -9
View File
@@ -1,4 +1,4 @@
/mob/living/carbon/monkey/emote(act)
/mob/living/carbon/monkey/emote(act,m_type=1,message = null)
var/param = null
if (findtext(act, "-", 1, null))
@@ -6,10 +6,7 @@
param = copytext(act, t1 + 1, length(act) + 1)
act = copytext(act, 1, t1)
var/muzzled = is_muzzled()
var/m_type = 1
var/message
switch(act) //Ooh ooh ah ah keep this alphabetical ooh ooh ah ah!
if ("deathgasp","deathgasps")
@@ -21,15 +18,19 @@
message = "<B>[src]</B> gnarls and shows its teeth.."
m_type = 2
if ("paw")
if (!src.restrained())
message = "<B>[src]</B> flails its paw."
m_type = 1
if ("me")
..()
return
if ("moan","moans")
message = "<B>[src]</B> moans!"
m_type = 2
if ("paw")
if (!src.restrained())
message = "<B>[src]</B> flails its paw."
m_type = 1
if ("roar","roars")
if (!muzzled)
message = "<B>[src]</B> roars."
@@ -67,7 +68,7 @@
src << "Help for monkey emotes. You can use these emotes with say \"*emote\":\n\naflap, airguitar, blink, blink_r, blush, bow-(none)/mob, burp, choke, chuckle, clap, collapse, cough, dance, deathgasp, drool, flap, frown, gasp, gnarl, giggle, glare-(none)/mob, grin, jump, laugh, look, me, moan, nod, paw, point-(atom), roar, roll, scream, scratch, screech, shake, shiver, sigh, sign-#, sit, smile, sneeze, sniff, snore, stare-(none)/mob, sulk, sway, tail, tremble, twitch, twitch_s, wave whimper, wink, yawn"
else
..(act)
..()
if ((message && src.stat == 0))
if(src.client)
@@ -13,7 +13,6 @@
unique_name = 1
/mob/living/carbon/monkey/New()
create_reagents(1000)
verbs += /mob/living/proc/mob_sleep
verbs += /mob/living/proc/lay_down
@@ -155,7 +154,19 @@
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
adjustBruteLoss(damage)
switch(M.melee_damage_type)
if(BRUTE)
adjustBruteLoss(damage)
if(BURN)
adjustFireLoss(damage)
if(TOX)
adjustToxLoss(damage)
if(OXY)
adjustOxyLoss(damage)
if(CLONE)
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
+11
View File
@@ -2,6 +2,9 @@
set invisibility = 0
set background = BACKGROUND_ENABLED
if(digitalinvis)
handle_diginvis() //AI becomes unable to see mob
if (notransform)
return
if(!loc)
@@ -66,6 +69,14 @@
/mob/living/proc/handle_chemicals_in_body()
return
/mob/living/proc/handle_diginvis()
if(!digitaldisguise)
src.digitaldisguise = image(loc = src)
src.digitaldisguise.override = 1
for(var/mob/living/silicon/ai/AI in player_list)
AI.client.images |= src.digitaldisguise
/mob/living/proc/handle_blood()
return
+2 -2
View File
@@ -839,7 +839,7 @@ Sorry Giacom. Please don't be mad :(
else if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
var/obj/machinery/atmospherics/components/unary/cryo_cell/C = loc
var/datum/gas_mixture/G = C.airs["a1"]
var/datum/gas_mixture/G = C.AIR1
if(G.total_moles() < 10)
loc_temp = environment.temperature
@@ -883,7 +883,7 @@ Sorry Giacom. Please don't be mad :(
return 0
if(invisibility || alpha == 0)//cloaked
return 0
if(digitalcamo)
if(digitalcamo || digitalinvis)
return 0
// Now, are they viewable by a camera? (This is last because it's the most intensive check)
+2 -2
View File
@@ -133,7 +133,7 @@
if(!on_fire)
return 1
if(fire_stacks > 0)
adjust_fire_stacks(-0.2) //the fire is slowly consumed
adjust_fire_stacks(-0.1) //the fire is slowly consumed
else
ExtinguishMob()
return
@@ -145,7 +145,7 @@
location.hotspot_expose(700, 50, 1)
/mob/living/fire_act()
adjust_fire_stacks(0.5)
adjust_fire_stacks(3)
IgniteMob()
+18 -15
View File
@@ -147,7 +147,7 @@ var/list/ai_list = list()
shuttle_caller_list -= src
SSshuttle.autoEvac()
qdel(eyeobj) // No AI, no Eye
..()
return ..()
/mob/living/silicon/ai/verb/pick_icon()
@@ -300,9 +300,8 @@ var/list/ai_list = list()
onclose(src, "airoster")
/mob/living/silicon/ai/proc/ai_call_shuttle()
if(src.stat == DEAD)
src << "You can't call the shuttle because you are dead!"
return
if(stat == 2)
return //won't work if dead
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
@@ -330,6 +329,8 @@ var/list/ai_list = list()
set name = "Toggle Floor Bolts"
if(!isturf(loc)) // if their location isn't a turf
return // stop
if(stat == 2)
return //won't work if dead
anchored = !anchored // Toggles the anchor
src << "[anchored ? "<b>You are now anchored.</b>" : "<b>You are now unanchored.</b>"]"
@@ -340,9 +341,8 @@ var/list/ai_list = list()
/mob/living/silicon/ai/proc/ai_cancel_call()
set category = "Malfunction"
if(src.stat == 2)
src << "You can't send the shuttle back because you are dead!"
return
if(stat == 2)
return //won't work if dead
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
@@ -507,8 +507,7 @@ var/list/ai_list = list()
set name = "Access Robot Control"
set desc = "Wirelessly control various automatic robots."
if(stat == 2)
src << "<span class='danger'>Critical error. System offline.</span>"
return
return //won't work if dead
if(control_disabled)
src << "Wireless communication is disabled."
@@ -623,9 +622,8 @@ var/list/ai_list = list()
cameraFollow = null
var/cameralist[0]
if(usr.stat == 2)
usr << "You can't change your camera network because you are dead!"
return
if(stat == 2)
return //won't work if dead
var/mob/living/silicon/ai/U = usr
@@ -668,9 +666,8 @@ var/list/ai_list = list()
set category = "AI Commands"
set name = "AI Status"
if(usr.stat == 2)
usr <<"You cannot change your emotional status because you are dead!"
return
if(stat == 2)
return //won't work if dead
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/obj/machinery/M in machines) //change status
@@ -693,6 +690,8 @@ var/list/ai_list = list()
set desc = "Change the default hologram available to AI to something else."
set category = "AI Commands"
if(stat == 2)
return //won't work if dead
var/input
if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member")
@@ -788,6 +787,8 @@ var/list/ai_list = list()
set desc = "Allows you to change settings of your radio."
set category = "AI Commands"
if(stat == 2)
return //won't work if dead
src << "Accessing Subspace Transceiver control..."
if (radio)
radio.interact(src)
@@ -801,6 +802,8 @@ var/list/ai_list = list()
set desc = "Modify the default radio setting for your automatic announcements."
set category = "AI Commands"
if(stat == 2)
return //won't work if dead
set_autosay()
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
@@ -8,6 +8,7 @@
else
icon_state = "ai_dead"
anchored = 0 //unbolt floorbolts
update_canmove()
if(src.eyeobj)
src.eyeobj.setLoc(get_turf(src))
@@ -38,7 +38,7 @@
/mob/camera/aiEye/Destroy()
ai = null
..()
return ..()
/atom/proc/move_camera_by_click()
if(istype(usr, /mob/living/silicon/ai))
@@ -100,5 +100,7 @@
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
if(usr.stat == 2)
return //won't work if dead
acceleration = !acceleration
usr << "Camera acceleration has been toggled [acceleration ? "on" : "off"]."
@@ -26,7 +26,7 @@
/obj/structure/Destroy()
if(ticker)
cameranet.updateVisibility(src)
..()
return ..()
/obj/structure/New()
..()
@@ -38,7 +38,7 @@
/obj/effect/Destroy()
if(ticker)
cameranet.updateVisibility(src)
..()
return ..()
/obj/effect/New()
..()
@@ -94,6 +94,6 @@
/obj/machinery/camera/Destroy()
cameranet.cameras -= src
cameranet.removeCamera(src)
..()
return ..()
#undef BORG_CAMERA_BUFFER
@@ -2,6 +2,8 @@
/mob/living/silicon/ai/proc/show_laws_verb()
set category = "AI Commands"
set name = "Show Laws"
if(usr.stat == 2)
return //won't work if dead
src.show_laws()
/mob/living/silicon/ai/show_laws(everyone = 0)
@@ -69,6 +69,8 @@ var/const/VOX_DELAY = 600
set desc = "Display a list of vocal words to announce to the crew."
set category = "AI Commands"
if(usr.stat == 2)
return //won't work if dead
var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.<BR> \
<UL><LI>You can also click on the word to preview it.</LI>\
@@ -23,6 +23,7 @@
return
if(!gibbed)
emote("deathgasp")
locked = 0 //unlock cover
stat = DEAD
update_canmove()
if(camera)
@@ -1,6 +1,9 @@
/mob/living/silicon/robot/verb/cmd_show_laws()
set category = "Robot Commands"
set name = "Show Laws"
if(usr.stat == DEAD)
return //won't work if dead
show_laws()
/mob/living/silicon/robot/show_laws(everyone = 0)
+37 -7
View File
@@ -9,6 +9,7 @@
var/custom_name = ""
designation = "Default" //used for displaying the prefix & getting the current module of cyborg
has_limbs = 1
var/magpulse = 0
//Hud stuff
@@ -36,6 +37,7 @@
var/opened = 0
var/emagged = 0
var/emag_cooldown = 0
var/wiresexposed = 0
var/locked = 1
var/list/req_access = list(access_robotics)
@@ -138,7 +140,13 @@
mmi = null
if(connected_ai)
connected_ai.connected_robots -= src
..()
qdel(wires)
qdel(module)
wires = null
module = null
camera = null
cell = null
return ..()
/mob/living/silicon/robot/proc/pick_module()
@@ -213,6 +221,7 @@
animation_length = 45
modtype = "Eng"
feedback_inc("cyborg_engineering",1)
magpulse = 1
if("Janitor")
module = new /obj/item/weapon/robot_module/janitor(src)
@@ -255,6 +264,8 @@
/mob/living/silicon/robot/verb/cmd_robot_alerts()
set category = "Robot Commands"
set name = "Show Alerts"
if(usr.stat == DEAD)
return //won't work if dead
robot_alerts()
//for borg hotkeys, here module refers to borg inv slot, not core module
@@ -462,7 +473,7 @@
user << "<span class='notice'>You insert the power cell.</span>"
update_icons()
else if (istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool) || istype(W, /obj/item/device/assembly/signaler))
else if (wires.IsInteractionTool(W))
if (wiresexposed)
wires.Interact(user)
else
@@ -570,11 +581,26 @@
user << "<span class='warning'>The cover is already unlocked!</span>"
return
if(opened)//Cover is open
if(emagged) return//Prevents the X has hit Y with Z message also you cant emag them twice
if((world.time - 100) < emag_cooldown)
return
var/ai_is_antag = 0
if(connected_ai && connected_ai.mind)
if(connected_ai.mind.special_role)
ai_is_antag = (connected_ai.mind.special_role == "malfunction") || (connected_ai.mind.special_role == "traitor")
if(ai_is_antag)
user << "<span class='notice'>You emag [src]'s interface.</span>"
src << "<span class='danger'>ALERT: Foreign software execution prevented.</span>"
connected_ai << "<span class='danger'>ALERT: Cyborg unit \[[src]] successfuly defended against subversion.</span>"
log_game("[key_name(user)] attempted to emag cyborg [key_name(src)] slaved to traitor AI [connected_ai].")
emag_cooldown = world.time
return
if(wiresexposed)
user << "<span class='warning'>You must close the cover first!</span>"
return
else
emag_cooldown = world.time
sleep(6)
SetEmagged(1)
SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown
@@ -613,6 +639,8 @@
set category = "Robot Commands"
set name = "Unlock Cover"
set desc = "Unlocks your own cover if it is locked. You can not lock it again. A human will have to lock it for you."
if(stat == DEAD)
return //won't work if dead
if(locked)
switch(alert("You can not lock your cover again, are you sure?\n (You can still ask for a human to lock it)", "Unlock Own Cover", "Yes", "No"))
if("Yes")
@@ -862,9 +890,6 @@
var/turf/tile = loc
if(isturf(tile))
tile.clean_blood()
if (istype(tile, /turf/simulated/floor))
var/turf/simulated/floor/F = tile
F.dirt = 0
for(var/A in tile)
if(istype(A, /obj/effect))
if(is_cleanable(A))
@@ -981,12 +1006,17 @@
set category = "Robot Commands"
set name = "State Laws"
if(usr.stat == DEAD)
return //won't work if dead
checklaws()
/mob/living/silicon/robot/verb/set_automatic_say_channel() //Borg version of setting the radio for autosay messages.
set name = "Set Auto Announce Mode"
set desc = "Modify the default radio setting for stating your laws."
set category = "Robot Commands"
if(usr.stat == DEAD)
return //won't work if dead
set_autosay()
/mob/living/silicon/robot/proc/control_headlamp()
@@ -1054,7 +1084,7 @@
new /obj/item/robot_parts/head(T)
var/b
for(b=0, b!=2, b++)
var/obj/item/device/flash/handheld/F = new /obj/item/device/flash/handheld(T)
var/obj/item/device/assembly/flash/handheld/F = new /obj/item/device/assembly/flash/handheld(T)
F.burn_out()
if (cell) //Sanity check.
cell.loc = T
@@ -10,6 +10,12 @@
var/obj/item/emag = null
var/list/storages = list()
/obj/item/weapon/robot_module/Destroy()
modules.Cut()
emag = null
storages.Cut()
return ..()
/obj/item/weapon/robot_module/emp_act(severity)
if(modules)
for(var/obj/O in modules)
@@ -34,7 +40,7 @@
/obj/item/weapon/robot_module/New()
modules += new /obj/item/device/flash/cyborg(src)
modules += new /obj/item/device/assembly/flash/cyborg(src)
emag = new /obj/item/toy/sword(src)
emag.name = "Placeholder Emag Item"
return
@@ -13,3 +13,13 @@
tally = speed
return tally+config.robot_delay
/mob/living/silicon/robot/mob_negates_gravity()
return magpulse
/mob/living/silicon/robot/mob_has_gravity()
return ..() || mob_negates_gravity()
/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
if(!magpulse)
return ..()
+1 -1
View File
@@ -10,7 +10,7 @@
if(istype(src, /mob/living/silicon))
var/mob/living/silicon/S = src
desig = trim_left(S.designation + " " + S.job)
var/message_a = say_quote(message)
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
for(var/mob/M in player_list)
if(M.binarycheck() || (M in dead_mob_list))
+18 -1
View File
@@ -28,6 +28,11 @@
var/law_change_counter = 0
/mob/living/silicon/Destroy()
radio = null
aicamera = null
return ..()
/mob/living/silicon/contents_explosion(severity, target)
return
@@ -381,7 +386,19 @@
/mob/living/silicon/attack_animal(mob/living/simple_animal/M)
if(..())
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
adjustBruteLoss(damage)
switch(M.melee_damage_type)
if(BRUTE)
adjustBruteLoss(damage)
if(BURN)
adjustFireLoss(damage)
if(TOX)
adjustToxLoss(damage)
if(OXY)
adjustOxyLoss(damage)
if(CLONE)
adjustCloneLoss(damage)
if(STAMINA)
adjustStaminaLoss(damage)
updatehealth()
/mob/living/silicon/attack_paw(mob/living/user)
@@ -0,0 +1,529 @@
////Deactivated swarmer shell////
/obj/item/unactivated_swarmer
name = "unactivated swarmer"
desc = "A currently unactivated swarmer. Swarmers can self activate at any time, it would be wise to immediately dispose of this."
icon = 'icons/mob/swarmer.dmi'
icon_state = "swarmer_unactivated"
/obj/item/unactivated_swarmer/New()
notify_ghosts("An unactivated swarmer has been created in [get_area(src)]! <a href=?src=\ref[src];ghostjoin=1>(Click to enter)</a>")
..()
/obj/item/unactivated_swarmer/Topic(href, href_list)
if(href_list["ghostjoin"])
var/mob/dead/observer/ghost = usr
if(istype(ghost))
attack_ghost(ghost)
/obj/item/unactivated_swarmer/attack_ghost(mob/user)
var/be_swarmer = alert("Become a swarmer? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_swarmer == "No")
return
if(qdeleted(src))
user << "Swarmer has been occupied by someone else."
return
var/mob/living/simple_animal/hostile/swarmer/S = new /mob/living/simple_animal/hostile/swarmer(get_turf(loc))
S.key = user.key
qdel(src)
////The Mob itself////
/mob/living/simple_animal/hostile/swarmer
name = "Swarmer"
unique_name = 1
icon = 'icons/mob/swarmer.dmi'
desc = "A robot of unknown design, they seek only to consume materials and replicate themselves indefinitely."
speak_emote = list("tones")
health = 40
maxHealth = 40
status_flags = CANPUSH
icon_state = "swarmer"
icon_living = "swarmer"
icon_dead = "swarmer_unactivated"
icon_gib = null
wander = 0
harm_intent_damage = 5
minbodytemp = 0
maxbodytemp = 500
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 0
melee_damage_lower = 15
melee_damage_upper = 15
melee_damage_type = STAMINA
ignored_damage_types = list(BRUTE = 0, BURN = 0, TOX = 1, CLONE = 1, STAMINA = 1, OXY = 1)
languages = SWARMER
environment_smash = 0
attacktext = "shocks"
attack_sound = 'sound/effects/EMPulse.ogg'
friendly = "pinches"
speed = 0
faction = list("swarmer")
AIStatus = AI_OFF
projectiletype = /obj/item/projectile/beam/disabler
pass_flags = PASSTABLE | PASSMOB
ventcrawler = 2
ranged = 1
projectiletype = /obj/item/projectile/beam/disabler
ranged_cooldown_cap = 2
projectilesound = 'sound/weapons/taser2.ogg'
var/resources = 0 //Resource points, generated by consuming metal/glass
/mob/living/simple_animal/hostile/swarmer/Login()
..()
src << "<b>You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.</b>"
src << "<b>Ctrl + Click provides most of your swarmer specific interactions, such as cannibalizing metal or glass, destroying the environment, or teleporting mobs away from you."
src << "<b>Objectives:</b>"
src << "1. Consume resources and replicate until there are no more resources left."
src << "2. Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable."
src << "3. Biological resources will be harvested at a later date, do not harm them."
/mob/living/simple_animal/hostile/swarmer/New()
..()
verbs -= /mob/living/verb/pulled
/mob/living/simple_animal/hostile/swarmer/Stat()
..()
if(statpanel("Status"))
stat("Resources:",resources)
/mob/living/simple_animal/hostile/swarmer/death(gibbed)
..(gibbed)
new /obj/effect/decal/cleanable/robot_debris(src.loc)
ghostize()
qdel(src)
/mob/living/simple_animal/hostile/swarmer/emp_act()
if(health > 1)
health = 1
..()
health = 0
/mob/living/simple_animal/hostile/swarmer/CanPass(atom/movable/O)
if(istype(O, /obj/item/projectile/beam/disabler))//Allows for swarmers to fight as a group without wasting their shots hitting each other
return 1
if(isswarmer(O))
return 1
..()
////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S////
/mob/living/simple_animal/hostile/swarmer/CtrlClickOn(atom/A)
face_atom(A)
if(!isturf(loc))
return
if(next_move > world.time)
return
if(!A.Adjacent(src))
return
A.swarmer_act(src)
return
/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
/obj/item/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.Integrate(src)
/obj/item/weapon/gun/swarmer_act()//Stops you from eating the entire armory
return
/turf/simulated/floor/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor
return
/obj/machinery/atmospherics/swarmer_act()
return
/obj/structure/disposalpipe/swarmer_act()
return
/obj/machinery/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DismantleMachine(src)
/obj/machinery/light/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
deactivate(S, 0)
/obj/machinery/particle_accelerator/control_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
/obj/machinery/gravity_generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
/obj/machinery/vending/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//It's more visually interesting than dismantling the machine
S.DisIntegrate(src)
/obj/machinery/turretid/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
/obj/machinery/chem_dispenser/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>The volatile chemicals in this machine would destroy us. Aborting.</span>"
/obj/machinery/nuclearbomb/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>This device's destruction would result in the extermination of everything in the area. Aborting.</span>"
/obj/machinery/dominator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>This device is attempting to corrupt our entire network; attempting to interact with it is too risky. Aborting.</span>"
/obj/structure/reagent_dispensers/fueltank/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>Destroying this object would cause a chain reaction. Aborting.</span>"
/obj/structure/cable/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>"
/obj/machinery/portable_atmospherics/canister/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>"
/obj/machinery/power/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>"
/obj/machinery/gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>This bluespace source will be important to us later. Aborting.</span>"
/turf/simulated/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(locate(/turf/space) in range(1, src))
S << "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>"
return
..()
/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(locate(/turf/space) in range(1, src))
S << "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>"
return
..()
/obj/item/stack/cable_coil/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//Wiring would be too effective as a resource
S << "<span class='warning'>This object does not contain enough materials to work with.</span>"
/obj/machinery/porta_turret/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>"
/mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisperseTarget(src)
/mob/living/simple_animal/slime/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S << "<span class='warning'>This biological resource is somehow resisting our bluespace transceiver. Aborting.</span>"
////END CTRL CLICK FOR SWARMERS////
/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(var/atom/fabrication_object,var/fabrication_cost = 0)
if(!isturf(loc))
src << "<span class='warning'>This is not a suitable location for fabrication. We need more space.</span>"
if(resources >= fabrication_cost)
resources -= fabrication_cost
else
src << "<span class='warning'>You do not have the necessary resources to fabricate this object.</span>"
return 0
new fabrication_object(loc)
return 1
/mob/living/simple_animal/hostile/swarmer/proc/Integrate(var/obj/item/target)
if(resources >= 100)
src << "<span class='warning'>We cannot hold more materials!</span>"
return
if((target.materials[MAT_METAL]) || (target.materials[MAT_GLASS]))
resources++
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
if(istype(target, /obj/item/stack))
var/obj/item/stack/S = target
S.use(1)
if(S.amount)
return
qdel(target)
else
src << "<span class='warning'>\the [target] is incompatible with our internal matter recycler.</span>"
return
/mob/living/simple_animal/hostile/swarmer/proc/DisIntegrate(var/atom/movable/target)
new /obj/effect/effect/sparks(get_turf(target))
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
target.ex_act(3)
return
/mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(var/mob/living/target)
if(target != src)
src << "<span class='info'>Attempting to remove this being from our presence.</span>"
if(src.z != ZLEVEL_STATION)
src << "<span class='warning'>Our bluespace transceiver cannot locate a viable bluespace link, our teleportation abilities are useless in this area.</span>"
return
if(do_mob(src, target, 30))
var/cycle
for(cycle=0,cycle<100,cycle++)
var/random_location = locate(rand(37,202),rand(75,192),ZLEVEL_STATION)//Drunk dial a turf in the general ballpark of the station
if(istype(random_location, /turf/simulated/floor))
var/turf/simulated/floor/F = random_location
if(F.air)
var/datum/gas_mixture/A = F.air
if(A.oxygen >= 16 && !A.toxins && A.carbon_dioxide < 10 && !A.trace_gases.len)//Can most things breathe in this location?
if((A.temperature > 270) && (A.temperature < 360))//Not too hot, not too cold
var/pressure = A.return_pressure()
if((pressure > 20) && (pressure < 550))//Account for crushing pressure or vaccuums
if(ishuman(target))//If we're getting rid of a human, slap some zipties on them to keep them away from us a little longer
var/obj/item/weapon/restraints/handcuffs/cable/zipties/Z = new /obj/item/weapon/restraints/handcuffs/cable/zipties(src)
var/mob/living/carbon/human/H = target
Z.apply_cuffs(H, src)
do_teleport(target, F, 0)
playsound(src,'sound/effects/sparks4.ogg',50,1)
break
return
/mob/living/simple_animal/hostile/swarmer/proc/DismantleMachine(var/obj/machinery/target)
do_attack_animation(target)
src << "<span class='info'>We begin to dismantle this machine. We will need to be uninterrupted.</span>"
new /obj/effect/effect/sparks(get_turf(target))
if(do_mob(src, target, 100))
src << "<span class='info'>Dismantling complete.</span>"
var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(target.loc)
M.amount = 5
for(var/obj/item/I in target.component_parts)
I.loc = M.loc
new /obj/effect/effect/sparks(get_turf(target))
target.dropContents()
if(istype(target, /obj/machinery/computer))
var/obj/machinery/computer/C = target
if(C.circuit)
C.circuit.loc = M.loc
qdel(target)
/obj/effect/swarmer //Default destroyable object for swarmer constructions
name = "swarmer construction"
desc = "Debug swarmer item, this shouldn't be here. Yell at a coder."
gender = NEUTER
icon = 'icons/mob/swarmer.dmi'
icon_state = "ui_light"
luminosity = 1
var/health = 30
/obj/effect/swarmer/proc/TakeDamage(damage)
health -= damage
if(health <= 0)
qdel(src)
/obj/effect/swarmer/bullet_act(obj/item/projectile/Proj)
if(Proj.damage)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
TakeDamage(Proj.damage)
..()
/obj/effect/swarmer/attackby(obj/item/weapon/I, mob/living/user, params)
if(istype(I, /obj/item/weapon))
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
TakeDamage(I.force)
return
/obj/effect/swarmer/ex_act()
qdel(src)
return
/obj/effect/swarmer/blob_act()
qdel(src)
return
/obj/effect/swarmer/attack_animal(mob/living/user)
if(isanimal(user))
var/mob/living/simple_animal/S = user
S.do_attack_animation(src)
user.changeNext_move(CLICK_CD_MELEE)
if(S.melee_damage_type == BRUTE || S.melee_damage_type == BURN)
TakeDamage(rand(S.melee_damage_lower, S.melee_damage_upper))
return
/mob/living/simple_animal/hostile/swarmer/proc/CreateTrap()
set name = "Create trap"
set category = "Swarmer"
set desc = "Creates a simple trap that will non-lethally electrocute anything that steps on it. Costs 5 resources"
if(/obj/effect/swarmer/trap in loc)
src << "<span class='warning'>There is already a trap here. Aborting.</span>"
return
Fabricate(/obj/effect/swarmer/trap, 5)
return
/obj/effect/swarmer/trap
name = "swarmer trap"
desc = "A quickly assembled electric trap. Will not retain its form if damaged enough."
icon_state = "trap"
luminosity = 1
health = 10
/obj/effect/swarmer/trap/Crossed(var/atom/movable/AM)
if(isliving(AM))
var/mob/living/L = AM
if(!istype(L, /mob/living/simple_animal/hostile/swarmer))
L.electrocute_act(0, src, 1, 1)
qdel(src)
..()
/mob/living/simple_animal/hostile/swarmer/proc/CreateBarricade()
set name = "Create barricade"
set category = "Swarmer"
set desc = "Creates a barricade that will stop anything but swarmers and disabler beams from passing through."
if(/obj/effect/swarmer/blockade in loc)
src << "<span class='warning'>There is already a blockade here. Aborting.</span>"
return
Fabricate(/obj/effect/swarmer/blockade, 5)
return
/obj/effect/swarmer/blockade
name = "swarmer blockade"
desc = "A quickly assembled energy blockade. Will not retain its form if damaged enough, but disabler beams and swarmers pass right through."
icon_state = "barricade"
luminosity = 1
health = 50
density = 1
anchored = 1
/obj/effect/swarmer/blockade/CanPass(atom/movable/O)
if(isswarmer(O))
return 1
if(istype(O, /obj/item/projectile/beam/disabler))
return 1
/mob/living/simple_animal/hostile/swarmer/proc/CreateSwarmer()
set name = "Replicate"
set category = "Swarmer"
set desc = "Creates a shell for a new swarmer. Swarmers will self activate."
src << "<span class='info'>We are attempting to replicate ourselves. We will need to stand still until the process is complete.</span>"
if(resources < 50)
src << "<span class='warning'>We do not have the resources for this!</span>"
return
if(!isturf(loc))
src << "<span class='warning'>This is not a suitable location for replicating ourselves. We need more room.</span>"
return
if(do_mob(src, src, 100))
if(Fabricate(/obj/item/unactivated_swarmer, 50))
playsound(loc,'sound/items/poster_being_created.ogg',50, 1, -1)
/mob/living/simple_animal/hostile/swarmer/proc/RepairSelf()
set name = "Self Repair"
set category = "Swarmer"
set desc = "Attempts to repair damage to our body. You will have to remain motionless until repairs are complete."
if(!isturf(loc))
return
src << "<span class='info'>Attempting to repair damage to our body, stand by...</span>"
if(do_mob(src, src, 100))
adjustBruteLoss(-100)
src << "<span class='info'>We successfully repaired ourselves.</span>"
/mob/living/simple_animal/hostile/swarmer/proc/ToggleLight()
if(!luminosity)
SetLuminosity(3)
else
SetLuminosity(0)
/mob/living/simple_animal/hostile/swarmer/proc/ContactSwarmers()
var/message = input(src, "Announce to other swarmers", "Swarmer contact")
if(message)
for(var/mob/M in mob_list)
if(isswarmer(M) || (M in dead_mob_list))
M << "<B>Swarm communication - </b> [src] states: [message]"
////HUD NONSENSE////
/obj/screen/swarmer
icon = 'icons/mob/swarmer.dmi'
/obj/screen/swarmer/FabricateTrap
icon_state = "ui_trap"
name = "Create trap"
desc = "Creates a trap that will nonlethally shock any non-swarmer that attempts to cross it. (Costs 5 resources)"
/obj/screen/swarmer/FabricateTrap/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.CreateTrap()
/obj/screen/swarmer/Barricade
icon_state = "ui_barricade"
name = "Create barricade"
desc = "Creates a destructible barricade that will stop any non swarmer from passing it. Also allows disabler beams to pass through. (Costs 5 resources)"
/obj/screen/swarmer/Barricade/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.CreateBarricade()
/obj/screen/swarmer/Replicate
icon_state = "ui_replicate"
name = "Replicate"
desc = "Creates a another of our kind. (Costs 50 resources)"
/obj/screen/swarmer/Replicate/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.CreateSwarmer()
/obj/screen/swarmer/RepairSelf
icon_state = "ui_self_repair"
name = "Repair self"
desc = "Repairs damage to our body."
/obj/screen/swarmer/RepairSelf/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.RepairSelf()
/obj/screen/swarmer/ToggleLight
icon_state = "ui_light"
name = "Toggle light"
desc = "Toggles our inbuilt light on or off."
/obj/screen/swarmer/ToggleLight/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.ToggleLight()
/obj/screen/swarmer/ContactSwarmers
icon_state = "ui_contact_swarmers"
name = "Contact swarmers"
desc = "Sends a message to all other swarmers, should they exist."
/obj/screen/swarmer/ContactSwarmers/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.ContactSwarmers()
/datum/hud/proc/swarmer_hud(ui_style = 'icons/mob/screen_midnight.dmi')
adding = list()
var/obj/screen/using
using = new /obj/screen/swarmer/FabricateTrap()
using.screen_loc = ui_rhand
adding += using
using = new /obj/screen/swarmer/Barricade()
using.screen_loc = ui_lhand
adding += using
using = new /obj/screen/swarmer/Replicate()
using.screen_loc = ui_zonesel
adding += using
using = new /obj/screen/swarmer/RepairSelf()
using.screen_loc = ui_storage1
adding += using
using = new /obj/screen/swarmer/ToggleLight()
using.screen_loc = ui_back
adding += using
using = new /obj/screen/swarmer/ContactSwarmers()
using.screen_loc = ui_inventory
adding += using
mymob.client.screen = list()
mymob.client.screen += mymob.client.void
mymob.client.screen += adding
@@ -16,6 +16,7 @@
attack_sound = 'sound/weapons/punch1.ogg'
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
healable = 0
faction = list("cult")
flying = 1
unique_name = 1
@@ -16,6 +16,7 @@
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = 2
mob_size = MOB_SIZE_TINY
gold_core_spawnable = 2
/mob/living/simple_animal/butterfly/New()
..()
@@ -20,6 +20,7 @@
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
gold_core_spawnable = 2
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -31,6 +32,7 @@
gender = FEMALE
var/turns_since_scan = 0
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = 0
/mob/living/simple_animal/pet/cat/Runtime/Life()
//MICE!
@@ -69,6 +71,7 @@
/mob/living/simple_animal/pet/cat/Proc
name = "Proc"
gold_core_spawnable = 0
/mob/living/simple_animal/pet/cat/kitten
name = "kitten"
@@ -19,6 +19,7 @@
ventcrawler = 2
var/obj/item/inventory_head
var/obj/item/inventory_mask
gold_core_spawnable = 2
/mob/living/simple_animal/crab/Life()
..()
@@ -40,4 +41,5 @@
desc = "It's Coffee, the other pet!"
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "stomps"
response_harm = "stomps"
gold_core_spawnable = 0
@@ -29,6 +29,7 @@
var/obj/item/inventory_head
var/obj/item/inventory_back
var/facehugger
gold_core_spawnable = 2
/mob/living/simple_animal/pet/dog/pug
name = "\improper pug"
@@ -39,6 +40,7 @@
icon_living = "pug"
icon_dead = "pug_dead"
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = 2
/mob/living/simple_animal/pet/dog/corgi/New()
..()
@@ -275,7 +277,9 @@
return valid
/mob/living/simple_animal/pet/dog/corgi/proc/update_corgi_fluff()
switch(src.inventory_head.type)
if(!inventory_head)
return
switch(inventory_head.type)
if(/obj/item/clothing/head/helmet)
name = "Sergeant [real_name]"
desc = "The ever-loyal, the ever-vigilant."
@@ -388,6 +392,7 @@
response_help = "pets"
response_disarm = "bops"
response_harm = "kicks"
gold_core_spawnable = 0
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
..()
@@ -511,6 +516,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
gold_core_spawnable = 0
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
@@ -532,7 +538,7 @@
dir = i
sleep(1)
/mob/living/simple_animal/pet/pug/Life()
/mob/living/simple_animal/pet/dog/pug/Life()
..()
if(!stat && !resting && !buckled)
@@ -24,6 +24,7 @@
wander = 0
speed = 0
ventcrawler = 2
healable = 0
density = 0
pass_flags = PASSTABLE | PASSMOB
sight = (SEE_TURFS | SEE_OBJS)
@@ -79,7 +80,7 @@
/mob/living/simple_animal/drone/Destroy()
qdel(access_card) //Otherwise it ends up on the floor!
..()
return ..()
/mob/living/simple_animal/drone/Login()
..()
@@ -25,11 +25,14 @@
melee_damage_upper = 2
environment_smash = 0
stop_automated_movement_when_pulled = 1
var/datum/reagents/udder = null
var/obj/udder/udder = null
/mob/living/simple_animal/hostile/retaliate/goat/New()
udder = new(50)
udder.my_atom = src
udder = new()
..()
/mob/living/simple_animal/hostile/retaliate/goat/Destroy()
qdel(udder)
udder = null
..()
/mob/living/simple_animal/hostile/retaliate/goat/Life()
@@ -43,15 +46,11 @@
enemies = list()
LoseTarget()
src.visible_message("<span class='notice'>[src] calms down.</span>")
if(stat == CONSCIOUS)
if(udder && prob(5))
udder.add_reagent("milk", rand(5, 10))
udder.generateMilk()
if(locate(/obj/effect/spacevine) in loc)
var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc
SV.eat(src)
if(!pulledby)
for(var/direction in shuffle(list(1,2,4,8,5,6,9,10)))
var/step = get_step(src, direction)
@@ -70,18 +69,12 @@
var/obj/effect/spacevine/SV = locate(/obj/effect/spacevine) in loc
SV.eat(src)
/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
user.visible_message("[user] milks [src] using \the [O].", "<span class='notice'>You milk [src] using \the [O].</span>")
var/obj/item/weapon/reagent_containers/glass/G = O
var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
if(G.reagents.total_volume >= G.volume)
user << "<span class='warning'>[O] is full!</span>"
if(!transfered)
user << "<span class='warning'>The udder is dry! Wait a bit longer...</span>"
udder.milkAnimal(O, user)
else
..()
//cow
/mob/living/simple_animal/cow
name = "cow"
@@ -104,30 +97,28 @@
attacktext = "kicks"
attack_sound = 'sound/weapons/punch1.ogg'
health = 50
var/datum/reagents/udder = null
var/obj/udder/udder = null
gold_core_spawnable = 2
/mob/living/simple_animal/cow/New()
udder = new(50)
udder.my_atom = src
udder = new()
..()
/mob/living/simple_animal/cow/Destroy()
qdel(udder)
udder = null
..()
/mob/living/simple_animal/cow/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
user.visible_message("[user] milks [src] using \the [O].", "<span class='notice'>You milk [src] using \the [O].</span>")
var/obj/item/weapon/reagent_containers/glass/G = O
var/transfered = udder.trans_id_to(G, "milk", rand(5,10))
if(G.reagents.total_volume >= G.volume)
user << "<span class='danger'>[O] is full.</span>"
if(!transfered)
user << "<span class='danger'>The udder is dry. Wait a bit longer...</span>"
udder.milkAnimal(O, user)
else
..()
/mob/living/simple_animal/cow/Life()
. = ..()
if(stat == CONSCIOUS)
if(udder && prob(5))
udder.add_reagent("milk", rand(5, 10))
udder.generateMilk()
/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M)
if(!stat && M.a_intent == "disarm" && icon_state != icon_dead)
@@ -169,6 +160,7 @@
var/amount_grown = 0
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
gold_core_spawnable = 2
/mob/living/simple_animal/chick/New()
..()
@@ -219,6 +211,7 @@ var/global/chicken_count = 0
var/list/feedMessages = list("It clucks happily.","It clucks happily.")
var/list/layMessage = list("lays an egg.","squats down and croons.","begins making a huge racket.","begins clucking raucously.")
var/list/validColors = list("brown","black","white")
gold_core_spawnable = 2
/mob/living/simple_animal/chicken/New()
..()
@@ -274,3 +267,29 @@ var/global/chicken_count = 0
qdel(src)
else
SSobj.processing.Remove(src)
/obj/udder
/obj/udder/New()
reagents = new(50)
reagents.my_atom = src
reagents.add_reagent("milk", 20)
/obj/udder/proc/generateMilk()
if(prob(5))
reagents.add_reagent("milk", rand(5, 10))
/obj/udder/proc/milkAnimal(obj/O, mob/user)
var/obj/item/weapon/reagent_containers/glass/G = O
if(G.reagents.total_volume >= G.volume)
user << "<span class='danger'>[O] is full.</span>"
return
var/transfered = reagents.trans_id_to(G, "milk", rand(5,10))
if(transfered)
user.visible_message("[user] milks [src] using \the [O].", "<span class='notice'>You milk [src] using \the [O].</span>")
else
user << "<span class='danger'>The udder is dry. Wait a bit longer...</span>"
/obj/udder/Destroy()
qdel(reagents)
..()

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