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

Conflicts:
	icons/mob/head.dmi
This commit is contained in:
phil235
2015-03-02 13:45:15 +01:00
180 changed files with 6419 additions and 10483 deletions
+9 -4
View File
@@ -42,10 +42,15 @@ world/IsBanned(key,address,computer_id)
return ..()
//Guest Checking
if(!guests_allowed && IsGuestKey(key))
log_access("Failed Login: [key] - Guests not allowed")
message_admins("<span class='adminnotice'>Failed Login: [key] - Guests not allowed</span>")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
if(IsGuestKey(key))
if (!guests_allowed)
log_access("Failed Login: [key] - Guests not allowed")
message_admins("<span class='adminnotice'>Failed Login: [key] - Guests not allowed</span>")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
if (config.panic_bunker && dbcon && dbcon.IsConnected())
log_access("Failed Login: [key] - Guests not allowed during panic bunker")
message_admins("<span class='adminnotice'>Failed Login: [key] - Guests not allowed during panic bunker</span>")
return list("reason"="guest", "desc"="\nReason: Sorry but the server is currently not accepting connections from never before seen players or guests. If you have played on this server with a byond account before, please log in to the byond account you have played from.")
//Population Cap Checking
if(config.extreme_popcap && living_player_count() >= config.extreme_popcap && !(ckey(key) in admin_datums))
+13 -6
View File
@@ -815,22 +815,29 @@ var/global/floorIsLava = 0
var/J_title = html_encode(job.title)
var/J_opPos = html_encode(job.total_positions - (job.total_positions - job.current_positions))
var/J_totPos = html_encode(job.total_positions)
if(job.total_positions <= 0)
dat += "[J_title]: [J_opPos]"
if(job.total_positions < 0)
dat += "[J_title]: [J_opPos] (unlimited)"
else
dat += "[J_title]: [J_opPos]/[J_totPos]"
if(initial(job.total_positions) > 0)
if(job.title == "AI" || job.title == "Cyborg")
dat += " (Cannot Late Join)<br>"
continue
if(job.total_positions >= 0)
dat += " <A href='?src=\ref[src];addjobslot=[job.title]'>Add</A> | "
if(job.total_positions > job.current_positions)
dat += "<A href='?src=\ref[src];removejobslot=[job.title]'>Remove</A>"
dat += "<A href='?src=\ref[src];removejobslot=[job.title]'>Remove</A> | "
else
dat += "Remove"
dat += "Remove | "
dat += "<A href='?src=\ref[src];unlimitjobslot=[job.title]'>Unlimit</A>"
else
dat += " <A href='?src=\ref[src];limitjobslot=[job.title]'>Limit</A>"
dat += "<br>"
dat += "</body>"
var/winheight = 100 + (count * 20)
winheight = min(winheight, 690)
usr << browse(dat, "window=players;size=316x[winheight]")
usr << browse(dat, "window=players;size=375x[winheight]")
//
//
+4 -2
View File
@@ -100,7 +100,8 @@ var/list/admin_verbs_server = list(
/datum/admins/proc/toggleAI,
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
/client/proc/cmd_debug_del_all,
/client/proc/toggle_random_events
/client/proc/toggle_random_events,
/client/proc/panicbunker
)
var/list/admin_verbs_debug = list(
/client/proc/restart_controller,
@@ -190,7 +191,8 @@ var/list/admin_verbs_hideable = list(
/proc/possess,
/proc/release,
/client/proc/reload_admins,
/client/proc/reset_all_tcs
/client/proc/reset_all_tcs,
/client/proc/panicbunker
)
/client/proc/add_admin_verbs()
+26 -1
View File
@@ -1364,7 +1364,7 @@
if (1) status = "<font color='orange'><b>Unconscious</b></font>"
if (2) status = "<font color='red'><b>Dead</b></font>"
health_description = "Status = [status]"
health_description += "<BR>Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()]"
health_description += "<BR>Oxy: [L.getOxyLoss()] - Tox: [L.getToxLoss()] - Fire: [L.getFireLoss()] - Brute: [L.getBruteLoss()] - Clone: [L.getCloneLoss()] - Brain: [L.getBrainLoss()] - Stamina: [L.getStaminaLoss()]"
else
health_description = "This mob type has no health to speak of."
@@ -1404,6 +1404,31 @@
src.manage_free_slots()
else if(href_list["unlimitjobslot"])
if(!check_rights(R_ADMIN)) return
var/Unlimit = href_list["unlimitjobslot"]
for(var/datum/job/job in SSjob.occupations)
if(job.title == Unlimit)
job.total_positions = -1
break
src.manage_free_slots()
else if(href_list["limitjobslot"])
if(!check_rights(R_ADMIN)) return
var/Limit = href_list["limitjobslot"]
for(var/datum/job/job in SSjob.occupations)
if(job.title == Limit)
job.total_positions = job.current_positions
break
src.manage_free_slots()
else if(href_list["adminspawncookie"])
if(!check_rights(R_ADMIN|R_FUN)) return
+25 -14
View File
@@ -85,9 +85,26 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(!mob) return //this doesn't happen
var/ref_mob = "\ref[mob]"
msg = "<span class='adminnotice'><b><font color=red>HELP: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) [ai_found ? " (<A HREF='?_src_=holder;adminchecklaws=[ref_mob]'>CL</A>)" : ""]:</b> [msg]</span>"
msg = "<span class='adminnotice'><b><font color=red>HELP: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>) (<A HREF='?_src_=holder;traitor=[ref_mob]'>TP</A>) [ai_found ? " (<A HREF='?_src_=holder;adminchecklaws=[ref_mob]'>CL</A>)" : ""]:</b> [msg]</span>"
//send this msg to all admins
for(var/client/X in admins)
if(X.prefs.toggles & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
X << msg
//show it to the person adminhelping too
src << "<span class='adminnotice'>PM to-<b>Admins</b>: [original_msg]</span>"
//send it to irc if nobody is on and tell us how many were on
var/admin_number_present = send2irc_adminless_only(original_msg)
log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.")
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
proc/send2irc_adminless_only(source, msg, requiredflags = R_BAN)
var/admin_number_total = 0 //Total number of admins
var/admin_number_afk = 0 //Holds the number of admins who are afk
var/admin_number_ignored = 0 //Holds the number of admins without +BAN (so admins who are not really admins)
@@ -95,30 +112,24 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
for(var/client/X in admins)
admin_number_total++;
var/invalid = 0
if(!check_rights_for(X, R_BAN))
if(requiredflags != 0 && !check_rights_for(X, requiredflags))
admin_number_ignored++
invalid = 1
if(X.is_afk())
admin_number_afk++
invalid = 1
if(X.holder.fakekey)
admin_number_ignored++
invalid = 1
if(invalid)
admin_number_decrease++
if(X.prefs.toggles & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
X << msg
//show it to the person adminhelping too
src << "<span class='adminnotice'>PM to-<b>Admins</b>: [original_msg]</span>"
var/admin_number_present = admin_number_total - admin_number_decrease //Number of admins who are neither afk nor invalid
log_admin("HELP: [key_name(src)]: [original_msg] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
if(!admin_number_afk && !admin_number_ignored)
send2irc(ckey, "[original_msg] - No admins online")
send2irc(source, "[msg] - No admins online")
else
send2irc(ckey, "[original_msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])")
feedback_add_details("admin_verb","AH") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
send2irc(source, "[msg] - All admins AFK ([admin_number_afk]/[admin_number_total]) or skipped ([admin_number_ignored]/[admin_number_total])")
return admin_number_present
proc/send2irc(msg,msg2)
if(config.useircbot)
+15
View File
@@ -0,0 +1,15 @@
/client/proc/panicbunker()
set category = "Server"
set name = "Toggle Panic Bunker"
if (!config.sql_enabled)
usr << "<span class='adminnotice'>The Database is not enabled!</span>"
return
config.panic_bunker = (!config.panic_bunker)
log_admin("[key_name(usr)] has toggled the Panic Bunker, it is now [(config.panic_bunker?"on":"off")]")
message_admins("[key_name_admin(usr)] has toggled the Panic Bunker, it is now [(config.panic_bunker?"enabled":"disabled")].")
if (config.panic_bunker && (!dbcon || !dbcon.IsConnected()))
message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.")
feedback_add_details("admin_verb","PANIC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+4 -4
View File
@@ -17,7 +17,7 @@
return
var/image/cross = image('icons/obj/storage.dmi',"bible")
msg = "<span class='adminnotice'>\icon[cross] <b><font color=purple>PRAY: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[src]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[src]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>):</b> [msg]</span>"
msg = "<span class='adminnotice'>\icon[cross] <b><font color=purple>PRAY: </font>[key_name(src, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[src]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[src]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[src]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[src]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[src]'>JMP</A>) (<A HREF='?_src_=holder;traitor=\ref[src]'>TP</A>) (<A HREF='?_src_=holder;adminspawncookie=\ref[src]'>SC</a>):</b> [msg]</span>"
for(var/client/C in admins)
if(C.prefs.toggles & CHAT_PRAYER)
@@ -29,16 +29,16 @@
/proc/Centcomm_announce(var/text , var/mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'> <b><font color=orange>CENTCOM:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[Sender]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;CentcommReply=\ref[Sender]'>RPLY</A>):</b> [msg]</span>"
msg = "<span class='adminnotice'> <b><font color=orange>CENTCOM:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[Sender]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;traitor=\ref[Sender]'>TP</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;CentcommReply=\ref[Sender]'>RPLY</A>):</b> [msg]</span>"
admins << msg
/proc/Syndicate_announce(var/text , var/mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'><b><font color=crimson>SYNDICATE:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[Sender]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;SyndicateReply=\ref[Sender]'>RPLY</A>):</b> [msg]</span>"
msg = "<span class='adminnotice'><b><font color=crimson>SYNDICATE:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[Sender]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;traitor=\ref[Sender]'>TP</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;SyndicateReply=\ref[Sender]'>RPLY</A>):</b> [msg]</span>"
admins << msg
/proc/Nuke_request(var/text , var/mob/Sender)
var/msg = copytext(sanitize(text), 1, MAX_MESSAGE_LEN)
msg = "<span class='adminnotice'> <b><font color=orange>NUKE CODE REQUEST:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[Sender]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;CentcommReply=\ref[Sender]'>RPLY</A>):</b> [msg]</span>"
msg = "<span class='adminnotice'> <b><font color=orange>NUKE CODE REQUEST:</font>[key_name(Sender, 1)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[Sender]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=\ref[Sender]'>PP</A>) (<A HREF='?_src_=vars;Vars=\ref[Sender]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=\ref[Sender]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=\ref[Sender]'>JMP</A>) (<A HREF='?_src_=holder;traitor=\ref[Sender]'>TP</A>) (<A HREF='?_src_=holder;BlueSpaceArtillery=\ref[Sender]'>BSA</A>) (<A HREF='?_src_=holder;CentcommReply=\ref[Sender]'>RPLY</A>):</b> [msg]</span>"
admins << msg
admins << "<span class='adminnotice'><b>At this current time, the nuke must have the code manually set via varedit.</b></span>"
+29 -23
View File
@@ -90,7 +90,9 @@ var/list/external_rsc_urls
var/next_external_rsc = 0
#endif
/client/New(TopicData)
TopicData = null //Prevent calls to client.Topic from connect
if(connection != "seeker") //Invalid connection type.
@@ -136,6 +138,25 @@ var/next_external_rsc = 0
add_verbs_from_config()
set_client_age_from_db()
if (isnum(player_age) && player_age == -1) //first connection
if (config.panic_bunker && !holder && !(ckey in deadmins))
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
message_admins("<span class='adminnotice'>Failed Login: [key] - New account attempting to connect during panic bunker</span>")
src << "Sorry but the server is currently not accepting connections from never before seen players."
del(src)
return 0
if (config.notify_new_player_age >= 0)
message_admins("New user: [key_name_admin(src)] is connecting here for the first time.")
if (config.irc_first_connection_alert)
send2irc_adminless_only("New user", "[key_name(src)] is connecting for the first time!")
player_age = 0 // set it from -1 to 0 so the job selection code doesn't have a panic attack
else if (isnum(player_age) && player_age < config.notify_new_player_age)
message_admins("New user: [key_name_admin(src)] just connected with an age of [player_age] day[(player_age==1?"":"s")]")
if (!ticker || ticker.current_state == GAME_STATE_PREGAME)
spawn (rand(10,150))
if (src)
@@ -146,7 +167,7 @@ var/next_external_rsc = 0
send_resources()
if(prefs.lastchangelog != changelog_hash) //bolds the changelog button on the interface so we know there are updates.
winset(src, "rpane.changelog", "background-color=#eaeaea;font-style=bold")
winset(src, "rpane.changelogb", "background-color=#eaeaea;font-style=bold")
//////////////
@@ -172,14 +193,15 @@ var/next_external_rsc = 0
var/sql_ckey = sanitizeSQL(src.ckey)
var/DBQuery/query = dbcon.NewQuery("SELECT id, datediff(Now(),firstseen) as age FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
query.Execute()
if (!query.Execute())
return
while (query.NextRow())
player_age = text2num(query.item[2])
return
//player not found.
player_age = 0
message_admins("[key_name_admin(src)] is connecting here for the first time.")
//no match mark it as a first connection for use in client/New()
player_age = -1
/client/proc/sync_client_with_db()
@@ -239,25 +261,9 @@ var/next_external_rsc = 0
//send resources to the client. It's here in its own proc so we can move it around easiliy if need be
/client/proc/send_resources()
//Send nanoui files to client
SSnano.send_resources(src)
getFiles(
'nano/js/libraries.min.js',
'nano/js/nano_update.js',
'nano/js/nano_config.js',
'nano/js/nano_base_helpers.js',
'nano/css/shared.css',
'nano/css/icons.css',
'nano/templates/chem_dispenser.tmpl',
'nano/templates/chem_heater.tmpl',
'nano/templates/smes.tmpl',
'nano/templates/apc.tmpl',
'nano/templates/cryo.tmpl',
'nano/templates/solar_control.tmpl',
'nano/images/uiBackground.png',
'nano/images/uiIcons16.png',
'nano/images/uiIcons24.png',
'nano/images/uiLinkPendingIcon.gif',
'nano/images/uiNoticeBackground.jpg',
'nano/images/uiTitleFluff.png',
'html/search.js',
'html/panels.css',
'html/browser/common.css',
+5 -1
View File
@@ -39,6 +39,7 @@ datum/preferences
var/UI_style = "Midnight"
var/toggles = TOGGLES_DEFAULT
var/ghost_form = "ghost"
var/allow_midround_antag = 1
//character preferences
var/real_name //our character's name
@@ -226,7 +227,7 @@ datum/preferences
dat += "<b>Ghost sight:</b> <a href='?_src_=prefs;preference=ghost_sight'>[(toggles & CHAT_GHOSTSIGHT) ? "Nearest Creatures" : "All Emotes"]</a><br>"
dat += "<b>Ghost whispers:</b> <a href='?_src_=prefs;preference=ghost_whispers'>[(toggles & CHAT_GHOSTWHISPER) ? "Nearest Creatures" : "All Speech"]</a><br>"
dat += "<b>Pull requests:</b> <a href='?_src_=prefs;preference=pull_requests'>[(toggles & CHAT_PULLR) ? "Yes" : "No"]</a><br>"
dat += "<b>Midround Antagonist:</b> <a href='?_src_=prefs;preference=allow_midround_antag'>[(toggles & MIDROUND_ANTAG) ? "Yes" : "No"]</a><br>"
if(config.allow_Metadata)
dat += "<b>OOC Notes:</b> <a href='?_src_=prefs;preference=metadata;task=input'> Edit </a><br>"
@@ -785,6 +786,9 @@ datum/preferences
if("pull_requests")
toggles ^= CHAT_PULLR
if("allow_midround_antag")
toggles ^= MIDROUND_ANTAG
if("save")
save_preferences()
save_character()
@@ -73,6 +73,15 @@
src << "You will [(prefs.toggles & CHAT_PULLR) ? "now" : "no longer"] see new pull request announcements."
feedback_add_details("admin_verb","TPullR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/togglemidroundantag()
set name = "Toggle Midround Antagonist"
set category = "Preferences"
set desc = "Toggles whether or not you will be considered for antagonist status given during a round."
prefs.toggles ^= MIDROUND_ANTAG
prefs.save_preferences()
src << "You will [(prefs.toggles & MIDROUND_ANTAG) ? "now" : "no longer"] be considered for midround antagonist positions."
feedback_add_details("admin_verb","TMidroundA") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/verb/toggletitlemusic()
set name = "Hear/Silence LobbyMusic"
set category = "Preferences"
+1 -2
View File
@@ -7,7 +7,7 @@
var/visor_flags_inv = 0 // same as visor_flags, but for flags_inv
lefthand_file = 'icons/mob/inhands/clothing_lefthand.dmi'
righthand_file = 'icons/mob/inhands/clothing_righthand.dmi'
var/alt_desc = null
//Ears: currently only used for headsets and earmuffs
/obj/item/clothing/ears
@@ -191,7 +191,6 @@ BLIND // can't see anything
strip_delay = 80
put_on_delay = 80
//Under clothing
/obj/item/clothing/under
icon = 'icons/obj/clothing/uniforms.dmi'
+8
View File
@@ -144,6 +144,14 @@
flags = BLOCKHAIR
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
/obj/item/clothing/head/griffin
name = "griffon head"
desc = "Why not 'eagle head'? Who knows."
icon_state = "griffinhat"
item_state = "griffinhat"
flags = BLOCKHAIR
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
/obj/item/clothing/head/bearpelt
name = "bear pelt hat"
desc = "Fuzzy."
+7 -1
View File
@@ -137,4 +137,10 @@
icon_state = "roman"
item_state = "roman"
strip_delay = 100
put_on_delay = 100
put_on_delay = 100
/obj/item/clothing/shoes/griffin
name = "griffon boots"
desc = "A pair of costume boots fashioned after bird talons."
icon_state = "griffinboots"
item_state = "griffinboots"
+30 -8
View File
@@ -116,6 +116,7 @@
/obj/item/clothing/head/helmet/space/hardsuit/syndi
name = "blood-red hardsuit helmet"
desc = "A dual-mode advanced helmet designed for work in special operations. It is in travel mode. Property of Gorlex Marauders."
alt_desc = "A dual-mode advanced helmet designed for work in special operations. It is in combat mode. Property of Gorlex Marauders."
icon_state = "hardsuit1-syndi"
item_state = "syndie_helm"
item_color = "syndi"
@@ -134,16 +135,16 @@
on = !on
if(on)
user << "<span class='notice'>You switch your helmet to travel mode.</span>"
name = "blood-red hardsuit helmet"
desc = "A dual-mode advanced helmet designed for work in special operations. It is in travel mode. Property of Gorlex Marauders."
name = initial(name)
desc = initial(desc)
flags = HEADCOVERSEYES | BLOCKHAIR | HEADCOVERSMOUTH | STOPSPRESSUREDMAGE | THICKMATERIAL
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
cold_protection = HEAD
user.AddLuminosity(brightness_on)
else
user << "<span class='notice'>You switch your helmet to combat mode.</span>"
name = "blood-red hardsuit helmet (combat)"
desc = "A dual-mode advanced helmet designed for work in special operations. It is in combat mode. Property of Gorlex Marauders."
name += " (combat)"
desc = alt_desc
flags = BLOCKHAIR
flags_inv = HIDEEARS
cold_protection = null
@@ -156,6 +157,7 @@
/obj/item/clothing/suit/space/hardsuit/syndi
name = "blood-red hardsuit"
desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in travel mode. Property of Gorlex Marauders."
alt_desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in combat mode. Property of Gorlex Marauders."
icon_state = "hardsuit1-syndi"
item_state = "syndie_hardsuit"
item_color = "syndi"
@@ -174,16 +176,16 @@
on = !on
if(on)
user << "<span class='notice'>You switch your hardsuit to travel mode.</span>"
name = "blood-red hardsuit helmet"
desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in travel mode. Property of Gorlex Marauders."
name = initial(name)
desc = initial(desc)
slowdown = 1
flags = STOPSPRESSUREDMAGE | THICKMATERIAL
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS
else
user << "<span class='notice'>You switch your hardsuit to combat mode.</span>"
name = "blood-red hardsuit helmet (combat)"
desc = "A dual-mode advanced hardsuit designed for work in special operations. It is in combat mode. Property of Gorlex Marauders."
name += " (combat)"
desc = alt_desc
slowdown = 0
flags = BLOCKHAIR
flags_inv = null
@@ -194,6 +196,26 @@
user.update_inv_wear_suit()
user.update_inv_w_uniform()
//The Owl Hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/syndi/owl
name = "owl hardsuit helmet"
desc = "A dual-mode advanced helmet designed for any crime-fighting situation. It is in travel mode."
alt_desc = "A dual-mode advanced helmet designed for any crime-fighting situation. It is in combat mode."
icon_state = "hardsuit1-owl"
item_state = "s_helmet"
item_color = "owl"
/obj/item/clothing/suit/space/hardsuit/syndi/owl
name = "owl hardsuit"
desc = "A dual-mode advanced hardsuit designed for any crime-fighting situation. It is in travel mode."
alt_desc = "A dual-mode advanced hardsuit designed for any crime-fighting situation. It is in combat mode."
icon_state = "hardsuit1-owl"
item_state = "s_suit"
item_color = "owl"
/obj/item/clothing/head/helmet/space/hardsuit/syndi/update_icon()
icon_state = "hardsuit[on]-[item_color]"
//Wizard hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/wizard
@@ -126,6 +126,22 @@
body_parts_covered = CHEST|ARMS|GROIN|LEGS|FEET|HANDS
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
/obj/item/clothing/suit/toggle/owlwings
name = "owl cloak"
desc = "A soft brown cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive the ladies mad."
icon_state = "owl_wings"
item_state = "owl_wings"
togglename = "wings"
body_parts_covered = ARMS|CHEST
allowed = list(/obj/item/weapon/gun/energy,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/weapon/gun/projectile,/obj/item/ammo_box,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs,/obj/item/device/flashlight/seclite,/obj/item/weapon/melee/classic_baton/telescopic)
action_button_name = "Toggle Owl Wings"
/obj/item/clothing/suit/toggle/owlwings/griffinwings
name = "griffon cloak"
desc = "A plush white cloak made of synthetic feathers. Soft to the touch, stylish, and a 2 meter wing span that will drive your captives mad."
icon_state = "griffin_wings"
item_state = "griffin_wings"
/obj/item/clothing/suit/holidaypriest
name = "holiday priest"
+8 -1
View File
@@ -128,11 +128,18 @@
/obj/item/clothing/under/owl
name = "owl uniform"
desc = "A jumpsuit with owl wings. Photorealistic owl feathers! Twooooo!"
desc = "A soft brown jumpsuit made of synthetic feathers and strong conviction."
icon_state = "owl"
item_color = "owl"
can_adjust = 0
/obj/item/clothing/under/griffin
name = "griffon uniform"
desc = "A soft brown jumpsuit with a white feather collar made of synthetic feathers and a lust for mayhem."
icon_state = "griffin"
item_color = "griffin"
can_adjust = 0
/obj/item/clothing/under/rainbow
name = "rainbow"
desc = "rainbow"
@@ -518,7 +518,7 @@
name = "shot of nothing"
desc = "The mime insists there's booze in the glass. You're not so sure."
if ("goldschlager")
icon_state = "shotglassschlag"
icon_state = "shotglassgold"
name = "shot of goldschlager"
desc = "Yup. You're officially a college girl."
if ("cognac")
+1 -2
View File
@@ -168,7 +168,7 @@
/obj/item/weapon/reagent_containers/food/snacks/grown/harebell
seed = /obj/item/seeds/harebell
name = "harebell"
desc = "\"I'll sweeten thy sad grave: thou shalt not lack the flower that's like thy face, pale primrose, nor the azured hare-bell, like thy veins; no, nor the leaf of eglantine, whom not to slander, out-sweetend not thy breath.\""
desc = "\"I'll sweeten thy sad grave: thou shalt not lack the flower that's like thy face, pale primrose, nor the azured hare-bell, like thy veins; no, nor the leaf of eglantine, whom not to slander, out-sweetend not thy breath.\""
icon_state = "harebell"
slot_flags = SLOT_HEAD
filling_color = "#E6E6FA"
@@ -392,7 +392,6 @@
..()
reagents.add_reagent("omnizine", 1 + round(potency / 8, 1))
reagents.add_reagent("synaptizine", 1 + round(potency / 8, 1))
reagents.add_reagent("morphine", 1 + round(potency / 10, 1))
reagents.add_reagent("space_drugs", 1 + round(potency / 10, 1))
reagents.add_reagent("vitamin", 1 + round((potency / 25), 1))
+1 -1
View File
@@ -842,7 +842,7 @@ obj/machinery/hydroponics/attackby(var/obj/item/O as obj, var/mob/user as mob, p
podman.ckey = ckey_holder
podman.gender = blood_gender
podman.faction |= factions
hardset_dna(podman,null,null,podman.real_name,blood_type,/datum/species/plant/pod,"#59CE00")//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
hardset_dna(podman,null,null,podman.real_name,blood_type,/datum/species/plant/pod)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
podman.set_cloned_appearance()
else //else, one packet of seeds. maybe two
+6
View File
@@ -2,4 +2,10 @@
..()
if(client.prefs.unlock_content)
icon_state = client.prefs.ghost_form
if (ghostimage)
ghostimage.icon_state = src.icon_state
updateghostimages()
update_interface()
+2
View File
@@ -1,4 +1,6 @@
/mob/dead/observer/Logout()
if (client)
client.images -= ghost_darkness_images
..()
spawn(0)
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
+48 -4
View File
@@ -1,9 +1,10 @@
var/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness
/mob/dead/observer
name = "ghost"
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
icon = 'icons/mob/mob.dmi'
icon_state = "ghost"
layer = 4
layer = MOB_LAYER + 1
stat = DEAD
density = 0
canmove = 0
@@ -18,6 +19,9 @@
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
var/atom/movable/following = null
var/fun_verbs = 0
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
var/ghostvision = 1 //is the ghost able to see things humans can't?
var/seedarkness = 1
/mob/dead/observer/New(mob/body)
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
@@ -26,6 +30,9 @@
verbs += /mob/dead/observer/proc/dead_tele
stat = DEAD
ghostimage = image(src.icon,src,src.icon_state)
ghost_darkness_images |= ghostimage
updateallghostimages()
var/turf/T
if(ismob(body))
T = get_turf(body) //Where is the body located?
@@ -55,6 +62,14 @@
animate(src, pixel_y = 2, time = 10, loop = -1)
..()
/mob/dead/observer/Destroy()
if (ghostimage)
ghost_darkness_images -= ghostimage
qdel(ghostimage)
ghostimage = null
updateallghostimages()
..()
/mob/dead/CanPass(atom/movable/mover, turf/target, height=0)
@@ -254,14 +269,43 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set hidden = 1
src << "<span class='danger'>You are dead! You have no mind to store memory!</span>"
/mob/dead/observer/verb/toggle_ghostsee()
set name = "Toggle Ghost Vision"
set desc = "Toggles your ability to see things only ghosts can see, like other ghosts"
set category = "Ghost"
ghostvision = !(ghostvision)
updateghostsight()
usr << "You [(ghostvision?"now":"no longer")] have ghost vision."
/mob/dead/observer/verb/toggle_darkness()
set name = "Toggle Darkness"
set category = "Ghost"
seedarkness = !(seedarkness)
updateghostsight()
if (see_invisible == SEE_INVISIBLE_OBSERVER_NOLIGHTING)
see_invisible = SEE_INVISIBLE_OBSERVER
else
/mob/dead/observer/proc/updateghostsight()
if (!seedarkness)
see_invisible = SEE_INVISIBLE_OBSERVER_NOLIGHTING
else
see_invisible = SEE_INVISIBLE_OBSERVER
if (!ghostvision)
see_invisible = SEE_INVISIBLE_LIVING;
updateghostimages()
/proc/updateallghostimages()
for (var/mob/dead/observer/O in player_list)
O.updateghostimages()
/mob/dead/observer/proc/updateghostimages()
if (!client)
return
if (seedarkness || !ghostvision)
client.images -= ghost_darkness_images
else
//add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now
client.images |= ghost_darkness_images
if (ghostimage)
client.images -= ghostimage //remove ourself
/mob/dead/observer/verb/possess()
set category = "Ghost"
@@ -82,6 +82,9 @@
else if(copytext(input,1,9) == "exclaims")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,6) == "yells")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(input,1,5) == "asks")
src << "<span class='danger'>Invalid emote.</span>"
return
@@ -203,6 +206,9 @@
else if(copytext(message,1,9) == "exclaims")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,6) == "yells")
src << "<span class='danger'>Invalid emote.</span>"
return
else if(copytext(message,1,5) == "asks")
src << "<span class='danger'>Invalid emote.</span>"
return
@@ -717,3 +717,19 @@
H.w_uniform.add_fingerprint(M)
..()
/mob/living/carbon/human/generateStaticOverlay()
var/image/staticOverlay = image(icon('icons/effects/effects.dmi', "static"), loc = src)
staticOverlay.override = 1
staticOverlays["static"] = staticOverlay
staticOverlay = image(icon('icons/effects/effects.dmi', "blank"), loc = src)
staticOverlay.override = 1
staticOverlays["blank"] = staticOverlay
staticOverlay = getLetterImage(src, "H", 1)
staticOverlay.override = 1
staticOverlays["letter"] = staticOverlay
+4 -2
View File
@@ -10,9 +10,11 @@
var/mob/living/L = src
if (L.getBrainLoss() >= 60)
return "gibbers, \"[text]\"";
if (ending == "?")
if(ending == "?")
return "asks, \"[text]\"";
if (ending == "!")
if(copytext(text, length(text) - 1) == "!!")
return "yells, \"<span class = 'yell'>[text]</span>\"";
if(ending == "!")
return "exclaims, \"[text]\"";
if(dna)
@@ -1,8 +1,11 @@
// This code handles different species in the game.
#define SPECIES_LAYER 23
#define BODY_LAYER 22
#define HAIR_LAYER 8
#define SPECIES_LAYER 26
#define BODY_BEHIND_LAYER 25
#define BODY_LAYER 24
#define BODY_ADJ_LAYER 23
#define HAIR_LAYER 9
#define BODY_FRONT_LAYER 2
#define TINT_IMPAIR 2
#define TINT_BLIND 3
@@ -44,6 +47,8 @@
var/say_mod = "says" // affects the speech message
var/list/mutant_bodyparts = list() // Parts of the body that are diferent enough from the standard human model that they cause clipping with some equipment
var/speedmod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
var/armor = 0 // overall defense for the race... or less defense, if it's negative.
var/brutemod = 1 // multiplier for brute damage
@@ -87,19 +92,24 @@
var/g = (H.gender == FEMALE) ? "f" : "m"
if(!config.mutant_colors)
H.dna.mutant_color = default_color
if(MUTCOLORS in specflags)
var/image/spec_base
var/icon_state_string = "[id]_"
if(sexes)
spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = "[id]_[g]_s", "layer" = -SPECIES_LAYER)
icon_state_string += "[g]_s"
else
spec_base = image("icon" = 'icons/mob/human.dmi', "icon_state" = "[id]_s", "layer" = -SPECIES_LAYER)
if(!config.mutant_colors)
H.dna.mutant_color = default_color
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.mutant_color]"
standing = spec_base
if(standing)
H.overlays_standing[SPECIES_LAYER] = standing
H.overlays_standing[SPECIES_LAYER] += standing
H.apply_overlay(SPECIES_LAYER)
@@ -172,6 +182,8 @@
var/list/standing = list()
handle_mutant_bodyparts(H)
// lipstick
if(H.lip_style && LIPS in specflags)
standing += image("icon"='icons/mob/human_face.dmi', "icon_state"="lips_[H.lip_style]_s", "layer" = -BODY_LAYER)
@@ -208,6 +220,53 @@
return
/datum/species/proc/handle_mutant_bodyparts(var/mob/living/carbon/human/H)
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()
H.remove_overlay(BODY_BEHIND_LAYER)
H.remove_overlay(BODY_ADJ_LAYER)
H.remove_overlay(BODY_FRONT_LAYER)
if(!mutant_bodyparts)
return
if("tail" in mutant_bodyparts)
if(H.wear_suit && (H.wear_suit.flags_inv & HIDEJUMPSUIT))
bodyparts_to_add -= "tail"
if("snout" in mutant_bodyparts) //Take a closer look at that snout!
if(H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE))
bodyparts_to_add -= "snout"
if(!bodyparts_to_add)
return
var/icon_state_string = "[id]_"
var/g = (H.gender == FEMALE) ? "f" : "m"
var/image/I
if(sexes)
icon_state_string += "[g]_s"
else
icon_state_string += "_s"
if(!config.mutant_colors)
H.dna.mutant_color = default_color
for(var/layer in relevent_layers)
for(var/bodypart in bodyparts_to_add)
I = image("icon" = 'icons/mob/mutant_bodyparts.dmi', "icon_state" = "[icon_state_string]_[bodypart]_[layer]", "layer" =- layer)
I.color = "#[H.dna.mutant_color]"
standing += I
H.overlays_standing[layer] = standing.Copy()
standing = list()
H.apply_overlay(BODY_BEHIND_LAYER)
H.apply_overlay(BODY_ADJ_LAYER)
H.apply_overlay(BODY_FRONT_LAYER)
/datum/species/proc/spec_life(var/mob/living/carbon/human/H)
return
@@ -1336,8 +1395,11 @@
H.update_fire()
#undef SPECIES_LAYER
#undef BODY_BEHIND_LAYER
#undef BODY_LAYER
#undef BODY_ADJ_LAYER
#undef HAIR_LAYER
#undef BODY_FRONT_LAYER
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
@@ -30,6 +30,7 @@
default_color = "00FF00"
roundstart = 1
specflags = list(MUTCOLORS,EYECOLOR,LIPS)
mutant_bodyparts = list("tail", "snout")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -55,30 +55,33 @@ Please contact me on #coderbus IRC. ~Carnie x
*/
//Human Overlays Indexes/////////
#define SPECIES_LAYER 23 // mutantrace colors... these are on a seperate layer in order to prvent
#define BODY_LAYER 22 //underwear, undershirts, socks, eyes, lips(makeup)
#define MUTATIONS_LAYER 21 //Tk headglows etc.
#define AUGMENTS_LAYER 20
#define DAMAGE_LAYER 19 //damage indicators (cuts and burns)
#define UNIFORM_LAYER 18
#define ID_LAYER 17
#define SHOES_LAYER 16
#define GLOVES_LAYER 15
#define EARS_LAYER 14
#define SUIT_LAYER 13
#define GLASSES_LAYER 12
#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 10
#define BACK_LAYER 9
#define HAIR_LAYER 8 //TODO: make part of head layer?
#define FACEMASK_LAYER 7
#define HEAD_LAYER 6
#define HANDCUFF_LAYER 5
#define LEGCUFF_LAYER 4
#define L_HAND_LAYER 3
#define R_HAND_LAYER 2 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands
#define SPECIES_LAYER 26 // mutantrace colors... these are on a seperate layer in order to prvent
#define BODY_BEHIND_LAYER 25
#define BODY_LAYER 24 //underwear, undershirts, socks, eyes, lips(makeup)
#define BODY_ADJ_LAYER 23
#define MUTATIONS_LAYER 22 //Tk headglows etc.
#define AUGMENTS_LAYER 21
#define DAMAGE_LAYER 20 //damage indicators (cuts and burns)
#define UNIFORM_LAYER 19
#define ID_LAYER 18
#define SHOES_LAYER 17
#define GLOVES_LAYER 16
#define EARS_LAYER 15
#define SUIT_LAYER 14
#define GLASSES_LAYER 13
#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 11
#define BACK_LAYER 10
#define HAIR_LAYER 9 //TODO: make part of head layer?
#define FACEMASK_LAYER 8
#define HEAD_LAYER 7
#define HANDCUFF_LAYER 6
#define LEGCUFF_LAYER 5
#define L_HAND_LAYER 4
#define R_HAND_LAYER 3 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands
#define BODY_FRONT_LAYER 2
#define FIRE_LAYER 1 //If you're on fire
#define TOTAL_LAYERS 23 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
#define TOTAL_LAYERS 26 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
//////////////////////////////////
/mob/living/carbon/human
@@ -158,6 +161,11 @@ Please contact me on #coderbus IRC. ~Carnie x
if(dna && !(disabilities & HUSK))
dna.species.update_color(src)
/mob/living/carbon/human/proc/update_mutant_bodyparts()
if(dna)
dna.species.handle_mutant_bodyparts(src)
/mob/living/carbon/human/proc/update_body()
remove_overlay(BODY_LAYER)
@@ -438,8 +446,9 @@ Please contact me on #coderbus IRC. ~Carnie x
standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="[S.blood_overlay_type]blood")
src.update_hair()
apply_overlay(SUIT_LAYER)
src.update_mutant_bodyparts()
apply_overlay(SUIT_LAYER)
/mob/living/carbon/human/update_inv_pockets()
if(l_store)
@@ -467,10 +476,10 @@ Please contact me on #coderbus IRC. ~Carnie x
if(wear_mask.blood_DNA && !istype(wear_mask, /obj/item/clothing/mask/cigarette))
standing.overlays += image("icon"='icons/effects/blood.dmi', "icon_state"="maskblood")
update_mutant_bodyparts()
apply_overlay(FACEMASK_LAYER)
/mob/living/carbon/human/update_inv_back()
remove_overlay(BACK_LAYER)
+41 -4
View File
@@ -8,12 +8,49 @@ Sorry Giacom. Please don't be mad :(
push_mob_back(src, A.push_dir)
*/
/mob/living/New()
. = ..()
generateStaticOverlay()
if(staticOverlays.len)
for(var/mob/living/simple_animal/drone/D in player_list)
if(D && D.seeStatic)
if(D.staticChoice in staticOverlays)
D.staticOverlays |= staticOverlays[D.staticChoice]
D.client.images |= staticOverlays[D.staticChoice]
else //no choice? force static
D.staticOverlays |= staticOverlays["static"]
D.client.images |= staticOverlays["static"]
/mob/living/Destroy()
// if(mind)
// mind.current = null
..()
. = ..()
for(var/mob/living/simple_animal/drone/D in player_list)
for(var/image/I in staticOverlays)
D.staticOverlays.Remove(I)
D.client.images.Remove(I)
del(I)
staticOverlays.len = 0
del(src)
/mob/living/proc/generateStaticOverlay()
staticOverlays.Add(list("static", "blank", "letter"))
var/image/staticOverlay = image(getStaticIcon(new/icon(icon,icon_state)), loc = src)
staticOverlay.override = 1
staticOverlays["static"] = staticOverlay
staticOverlay = image(getBlankIcon(new/icon(icon, icon_state)), loc = src)
staticOverlay.override = 1
staticOverlays["blank"] = staticOverlay
staticOverlay = getLetterImage(src)
staticOverlay.override = 1
staticOverlays["letter"] = staticOverlay
//Generic Bump(). Override MobBump() and ObjBump() instead of this.
/mob/living/Bump(atom/A, yes)
if (buckled || !yes || now_pushing)
@@ -495,7 +532,7 @@ Sorry Giacom. Please don't be mad :(
M.stop_pulling()
//this is the gay blood on floor shit -- Added back -- Skie
if(M.lying && (prob(M.getBruteLoss() / 2)))
if(M.lying && !M.buckled && (prob(M.getBruteLoss() / 2)))
makeTrail(T, M)
pulling.Move(T, get_dir(pulling, T))
if(M)
+3 -1
View File
@@ -41,4 +41,6 @@
var/floating = 0
var/nightvision = 0
var/mob_size = 1 //size of the mob. 0 is small, 1 is human sized, and 2 is large.
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature..
var/list/image/staticOverlays = list()
+5 -3
View File
@@ -22,10 +22,12 @@
/mob/living/silicon/ai/say_quote(var/text)
var/ending = copytext(text, length(text))
if (ending == "?")
if(ending == "?")
return "queries, \"<span class = 'robot'>[text]</span>\"";
else if (ending == "!")
return "declares, \"<span class = 'robot'>[text]</span>\"";
else if(copytext(text, length(text) - 1) == "!!")
return "alarms, \"<span class = 'robot'><span class = 'yell'>[text]</span></span>\"";
else if(ending == "!")
return "declares, \"[text]\"";
return "states, \"<span class = 'robot'>[text]</span>\"";
@@ -15,6 +15,7 @@
var/speakStatement = "states"
var/speakExclamation = "declares"
var/speakDoubleExclamation = "alarms"
var/speakQuery = "queries"
var/obj/item/weapon/pai_cable/cable // The cable we produce and use when door or camera jacking
@@ -3,6 +3,8 @@
if (ending == "?")
return "[src.speakQuery], \"<span class = 'robot'>[text]</span>\"";
else if(copytext(text, length(text) - 1) == "!!")
return "[src.speakDoubleExclamation], \"<span class = 'robot'><span class = 'yell'>[text]</span></span>\"";
else if (ending == "!")
return "[src.speakExclamation], \"<span class = 'robot'>[text]</span>\"";
+4 -2
View File
@@ -1,9 +1,11 @@
/mob/living/silicon/robot/say_quote(var/text)
var/ending = copytext(text, length(text))
if (ending == "?")
if(ending == "?")
return "queries, \"<span class = 'robot'>[text]</span>\"";
else if (ending == "!")
else if(copytext(text, length(text) - 1) == "!!")
return "alarms, \"<span class = 'robot'><span class = 'yell'>[text]</span></span>\"";
else if(ending == "!")
return "declares, \"<span class = 'robot'>[text]</span>\"";
return "states, \"<span class = 'robot'>[text]</span>\"";
@@ -150,6 +150,7 @@
//The objects that corgis can wear on their backs.
var/list/allowed_types = list(
/obj/item/clothing/suit/armor/vest,
/obj/item/clothing/suit/space/deathsquad,
/obj/item/device/radio,
/obj/item/device/radio/off,
/obj/item/clothing/suit/cardborg,
@@ -253,7 +254,7 @@
if(/obj/item/clothing/head/nursehat)
name = "Nurse [real_name]"
desc = "[name] needs 100cc of beef jerky...STAT!"
desc = "[name] needs 100cc of beef jerky... STAT!"
valid = 1
if(/obj/item/clothing/head/pirate, /obj/item/clothing/head/collectable/pirate)
@@ -267,10 +268,10 @@
if(/obj/item/clothing/head/ushanka)
name = "[pick("Comrade","Commissar","Glorious Leader")] [real_name]"
desc = "A follower of Karl Barx."
emote_see = list("contemplates the failings of the capitalist economic model.", "ponders the pros and cons of vangaurdism.")
emote_see = list("contemplates the failings of the capitalist economic model.", "ponders the pros and cons of vanguardism.")
valid = 1
if(/obj/item/clothing/head/collectable/police)
if(/obj/item/clothing/head/warden, /obj/item/clothing/head/collectable/police)
name = "Officer [real_name]"
emote_see = list("drools.","looks for donuts.")
desc = "Stop right there criminal scum!"
@@ -298,7 +299,7 @@
if(/obj/item/clothing/head/helmet/space/santahat)
name = "Santa's Corgi Helper"
emote_hear = list("barks christmas songs.", "yaps merrily!")
emote_hear = list("barks Christmas songs.", "yaps merrily!")
emote_see = list("looks for presents.", "checks his list.")
desc = "He's very fond of milk and cookies."
valid = 1
@@ -325,6 +326,11 @@
desc = "Can actually be trusted to not run off on his own."
valid = 1
if(/obj/item/clothing/head/helmet/space/deathsquad)
name = "Trooper [real_name]"
desc = "That's not red paint. That's real corgi blood."
valid = 1
if(valid)
if(user && !user.drop_item())
user << "<span class='notice'>\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s head!</span>"
@@ -1,609 +0,0 @@
#define HANDS_LAYER 1
#define HEAD_LAYER 2
#define TOTAL_LAYERS 2
#define DRONE_NET_CONNECT "<span class='notice'>DRONE NETWORK: [name] connected.</span>"
#define DRONE_NET_DISCONNECT "<span class='danger'>DRONE NETWORK: [name] is not responding.</span>"
/mob/living/simple_animal/drone
name = "Drone"
desc = "A maintenance drone, an expendable robot built to perform station repairs."
icon = 'icons/mob/drone.dmi'
icon_state = "drone_grey"
icon_living = "drone_grey"
icon_dead = "drone_dead"
gender = NEUTER
health = 30
maxHealth = 30
heat_damage_per_tick = 0
cold_damage_per_tick = 0
unsuitable_atmos_damage = 0
wander = 0
speed = 0
ventcrawler = 2
pass_flags = PASSTABLE | PASSMOB
sight = (SEE_TURFS | SEE_OBJS)
status_flags = (CANPUSH | CANSTUN | CANWEAKEN)
gender = NEUTER
voice_name = "synthesized chirp"
languages = DRONE
mob_size = 0
has_unlimited_silicon_privilege = 1
var/picked = FALSE
var/list/drone_overlays[TOTAL_LAYERS]
var/laws = \
"1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone.\n"+\
"2. You may not harm any being, regardless of intent or circumstance.\n"+\
"3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals."
var/light_on = 0
var/heavy_emp_damage = 25 //Amount of damage sustained if hit by a heavy EMP pulse
var/health_repair_max = 0 //Drone will only be able to be repaired/reactivated up to this point, defaults to health
var/alarms = list("Atmosphere" = list(), "Fire" = list(), "Power" = list())
var/obj/item/internal_storage //Drones can store one item, of any size/type in their body
var/obj/item/head
var/obj/item/default_storage = /obj/item/weapon/storage/toolbox/drone //If this exists, it will spawn in internal storage
var/obj/item/default_hatmask //If this exists, it will spawn in the hat/mask slot if it can fit
/mob/living/simple_animal/drone/New()
..()
name = name + " ([rand(100,999)])"
real_name = name
access_card = new /obj/item/weapon/card/id(src)
var/datum/job/captain/C = new /datum/job/captain
access_card.access = C.get_access()
if(!health_repair_max)
health_repair_max = initial(health)
if(default_storage)
var/obj/item/I = new default_storage(src)
equip_to_slot_or_del(I, "drone_storage_slot")
if(default_hatmask)
var/obj/item/I = new default_hatmask(src)
equip_to_slot_or_del(I, slot_head)
alert_drones(DRONE_NET_CONNECT)
/mob/living/simple_animal/drone/attack_hand(mob/user)
if(isdrone(user))
var/mob/living/simple_animal/drone/D = user
if(D != src)
if(stat == DEAD)
var/d_input = alert(D,"Perform which action?","Drone Interaction","Reactivate","Cannibalize","Nothing")
if(d_input)
switch(d_input)
if("Reactivate")
var/mob/dead/observer/G = get_ghost()
if(!client && (!G || !G.client))
var/list/faux_gadgets = list("hypertext inflator","failsafe directory","DRM switch","stack initializer",\
"anti-freeze capacitor","data stream diode","TCP bottleneck","supercharged I/O bolt",\
"tradewind stablizer","radiated XML cable","registry fluid tank","open-source debunker")
var/list/faux_problems = list("won't be able to tune their bootstrap projector","will constantly remix their binary pool"+\
" even though the BMX calibrator is working","will start leaking their XSS coolant",\
"can't tell if their ethernet detour is moving or not", "won't be able to reseed enough"+\
" kernels to function properly","can't start their neurotube console")
D << "<span class='notice'>You can't seem to find the [pick(faux_gadgets)]. Without it, [src] [pick(faux_problems)].</span>"
return
D.visible_message("<span class='notice'>[D] begins to reactivate [src].</span>")
if(do_after(user,30,needhand = 1))
health = health_repair_max
stat = CONSCIOUS
icon_state = icon_living
dead_mob_list -= src
living_mob_list += src
D.visible_message("<span class='notice'>[D] reactivates [src]!</span>")
alert_drones(DRONE_NET_CONNECT)
if(G)
G << "<span class='boldnotice'>DRONE NETWORK: </span><span class='ghostalert'>You were reactivated by [D]!</span>"
else
D << "<span class='notice'>You need to remain still to reactivate [src].</span>"
if("Cannibalize")
if(D.health < D.maxHealth)
D.visible_message("<span class='notice'>[D] begins to cannibalize parts from [src].</span>")
if(do_after(D, 60,5,0))
D.visible_message("<span class='notice'>[D] repairs itself using [src]'s remains!</span>")
D.adjustBruteLoss(-src.maxHealth)
new /obj/effect/decal/cleanable/oil/streak(get_turf(src))
qdel(src)
else
D << "<span class='notice'>You need to remain still to cannibalize [src].</span>"
else
D << "<span class='notice'>You're already in perfect condition!</span>"
if("Nothing")
return
return
if(ishuman(user))
if(stat == DEAD)
..()
return
if(user.get_active_hand())
user << "<span class='notice'>Your hands are full.</span>"
return
src << "<span class='warning'>[user] is trying to pick you up!</span>"
user << "<span class='notice'>You pick [src] up.</span>"
drop_l_hand()
drop_r_hand()
var/obj/item/clothing/head/drone_holder/DH = new /obj/item/clothing/head/drone_holder(src)
DH.contents += src
DH.drone = src
user.put_in_hands(DH)
src.loc = DH
return
..()
/mob/living/simple_animal/drone/Destroy()
qdel(access_card) //Otherwise it ends up on the floor!
..()
/mob/living/simple_animal/drone/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver) && stat != DEAD)
if(health < health_repair_max)
user << "<span class='notice'>You start to tighten loose screws on [src].</span>"
if(do_after(user,80))
health = health_repair_max
visible_message("<span class='notice'>[user] tightens [src == user ? "their" : "[src]'s"] loose screws!</span>")
else
user << "<span class='notice'>You need to remain still to tighten [src]'s screws.</span>"
else
user << "<span class='notice'>[src]'s screws can't get any tighter!</span>"
else
..()
/mob/living/simple_animal/drone/examine(mob/user)
. = ..()
if(!client && stat != DEAD)
user << "<span class='notice'>A small blue LED is blinking on and off at a steady rate.</span>"
/mob/living/simple_animal/drone/Move()
if(pullin)
if(pulling)
pullin.icon_state = "pull"
else
pullin.icon_state = "pull0"
..()
/mob/living/simple_animal/drone/IsAdvancedToolUser()
return 1
/mob/living/simple_animal/drone/say(var/message)
return ..(message, "R")
/mob/living/simple_animal/drone/lang_treat(atom/movable/speaker, message_langs, raw_message) //This is so drones can understand humans without being able to speak human
. = ..()
var/hear_override_langs = HUMAN
if(message_langs & hear_override_langs)
return ..(speaker, languages, raw_message)
/mob/living/simple_animal/drone/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_BINARY)
drone_chat(message)
return ITALICS | REDUCE_RANGE
else
..()
/mob/living/simple_animal/drone/UnarmedAttack(atom/A, proximity)
A.attack_hand(src)
/mob/living/simple_animal/drone/swap_hand()
var/obj/item/held_item = get_active_hand()
if(held_item)
if(istype(held_item, /obj/item/weapon/twohanded))
var/obj/item/weapon/twohanded/T = held_item
if(T.wielded == 1)
usr << "<span class='warning'>Your other hand is too busy holding the [T.name].</span>"
return
hand = !hand
if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object)
if(hand)
hud_used.l_hand_hud_object.icon_state = "hand_l_active"
hud_used.r_hand_hud_object.icon_state = "hand_r_inactive"
else
hud_used.l_hand_hud_object.icon_state = "hand_l_inactive"
hud_used.r_hand_hud_object.icon_state = "hand_r_active"
/mob/living/simple_animal/drone/verb/check_laws()
set category = "Drone"
set name = "Check Laws"
src << "<b>Drone Laws</b>"
src << laws
/mob/living/simple_animal/drone/verb/toggle_light()
set category = "Drone"
set name = "Toggle drone light"
if(light_on)
AddLuminosity(-4)
else
AddLuminosity(4)
light_on = !light_on
src << "<span class='notice'>Your light is now [light_on ? "on" : "off"]</span>"
/mob/living/simple_animal/drone/verb/drone_ping()
set category = "Drone"
set name = "Drone ping"
var/alert_s = input(src,"Alert severity level","Drone ping",null) as null|anything in list("Low","Medium","High","Critical")
var/area/A = get_area(loc)
if(alert_s && A && stat != DEAD)
var/msg = "<span class='boldnotice'>DRONE PING: [name]: [alert_s] priority alert in [A.name]!</span>"
alert_drones(msg)
/mob/living/simple_animal/drone/proc/alert_drones(msg, dead_can_hear = 0)
for(var/mob/M in player_list)
var/send_msg = 0
if(istype(M, /mob/living/simple_animal/drone) && M.stat != DEAD)
for(var/F in src.faction)
if(F in M.faction)
send_msg = 1
break
else if(dead_can_hear && (M in dead_mob_list))
send_msg = 1
if(send_msg)
M << msg
/mob/living/simple_animal/drone/proc/drone_chat(msg)
var/rendered = "<i><span class='game say'>DRONE CHAT: <span class='name'>[name]</span>: [msg]</span></i>"
alert_drones(rendered, 1)
/mob/living/simple_animal/drone/Login()
..()
update_inv_hands()
update_inv_head()
update_inv_internal_storage()
check_laws()
if(!picked)
pick_colour()
/mob/living/simple_animal/drone/Die()
..()
drop_l_hand()
drop_r_hand()
if(internal_storage)
unEquip(internal_storage)
if(head)
unEquip(head)
alert_drones(DRONE_NET_DISCONNECT)
/mob/living/simple_animal/drone/gib()
dust()
/mob/living/simple_animal/drone/unEquip(obj/item/I, force)
if(..(I,force))
update_inv_hands()
if(I == head)
head = null
update_inv_head()
if(I == internal_storage)
internal_storage = null
update_inv_internal_storage()
return 1
return 0
/mob/living/simple_animal/drone/can_equip(obj/item/I, slot)
switch(slot)
if(slot_head)
if(head)
return 0
if(!((I.slot_flags & SLOT_HEAD) || (I.slot_flags & SLOT_MASK)))
return 0
return 1
if("drone_storage_slot")
if(internal_storage)
return 0
return 1
..()
/mob/living/simple_animal/drone/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_head)
return head
if("drone_storage_slot")
return internal_storage
..()
/mob/living/simple_animal/drone/equip_to_slot(obj/item/I, slot)
if(!slot) return
if(!istype(I)) return
if(I == l_hand)
l_hand = null
else if(I == r_hand)
r_hand = null
update_inv_hands()
I.screen_loc = null // will get moved if inventory is visible
I.loc = src
I.equipped(src, slot)
I.layer = 20
switch(slot)
if(slot_head)
head = I
update_inv_head()
if("drone_storage_slot")
internal_storage = I
update_inv_internal_storage()
else
src << "<span class='danger'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>"
return
/mob/living/simple_animal/drone/stripPanelUnequip(obj/item/what, mob/who, where)
..(what, who, where, 1)
/mob/living/simple_animal/drone/stripPanelEquip(obj/item/what, mob/who, where)
..(what, who, where, 1)
/mob/living/simple_animal/drone/emp_act(severity)
Stun(5)
src << "<span class='danger'><b>ER@%R: MME^RY CO#RU9T!</b> R&$b@0tin)...</span>"
if(severity == 1)
adjustBruteLoss(heavy_emp_damage)
src << "<span class='userdanger'>HeAV% DA%^MMA+G TO I/O CIR!%UUT!</span>"
/mob/living/simple_animal/drone/proc/triggerAlarm(var/class, area/A, var/O, var/obj/alarmsource)
if(alarmsource.z != z)
return
if(stat != DEAD)
var/list/L = src.alarms[class]
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/sources = alarm[2]
if (!(alarmsource in sources))
sources += alarmsource
return
L[A.name] = list(A, list(alarmsource))
src << "--- [class] alarm detected in [A.name]!"
/mob/living/simple_animal/drone/proc/cancelAlarm(var/class, area/A as area, obj/origin)
if(stat != DEAD)
var/list/L = alarms[class]
var/cleared = 0
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/srcs = alarm[2]
if (origin in srcs)
srcs -= origin
if (srcs.len == 0)
cleared = 1
L -= I
if(cleared)
src << "--- [class] alarm in [A.name] has been cleared."
/mob/living/simple_animal/drone/proc/pick_colour()
var/colour = input("Choose your colour!", "Colour", "grey") in list("grey", "blue", "red", "green", "pink", "orange")
icon_state = "drone_[colour]"
icon_living = "drone_[colour]"
picked = TRUE
/mob/living/simple_animal/drone/proc/apply_overlay(cache_index)
var/image/I = drone_overlays[cache_index]
if(I)
overlays += I
/mob/living/simple_animal/drone/proc/remove_overlay(cache_index)
if(drone_overlays[cache_index])
overlays -= drone_overlays[cache_index]
drone_overlays[cache_index] = null
/mob/living/simple_animal/drone/proc/update_inv_hands()
remove_overlay(HANDS_LAYER)
var/list/hands_overlays = list()
if(r_hand)
var/r_state = r_hand.item_state
if(!r_state)
r_state = r_hand.icon_state
hands_overlays += image("icon" = r_hand.righthand_file, "icon_state"="[r_state]", "layer"=-HANDS_LAYER)
if(client && hud_used)
r_hand.layer = 20
r_hand.screen_loc = ui_rhand
client.screen |= r_hand
if(l_hand)
var/l_state = l_hand.item_state
if(!l_state)
l_state = l_hand.icon_state
hands_overlays += image("icon" = l_hand.lefthand_file, "icon_state"="[l_state]", "layer"=-HANDS_LAYER)
if(client && hud_used)
l_hand.layer = 20
l_hand.screen_loc = ui_lhand
client.screen |= l_hand
if(hands_overlays.len)
drone_overlays[HANDS_LAYER] = hands_overlays
apply_overlay(HANDS_LAYER)
/mob/living/simple_animal/drone/proc/update_inv_internal_storage()
if(internal_storage && client && hud_used)
internal_storage.screen_loc = ui_drone_storage
client.screen += internal_storage
/mob/living/simple_animal/drone/update_inv_head()
remove_overlay(HEAD_LAYER)
if(head)
if(client && hud_used)
head.screen_loc = ui_drone_head
client.screen += head
var/image/head_overlay = image("icon"='icons/mob/head.dmi', "icon_state"="[head.icon_state]", "layer"=-HEAD_LAYER)
if(istype(head, /obj/item/clothing/mask))
head_overlay.icon = 'icons/mob/mask.dmi'
head_overlay.color = head.color
head_overlay.alpha = head.alpha
head_overlay.pixel_y = -15
drone_overlays[HEAD_LAYER] = head_overlay
apply_overlay(HEAD_LAYER)
//These procs serve as redirection so that the drone updates as expected when other things call these procs
/mob/living/simple_animal/drone/update_inv_l_hand()
update_inv_hands()
/mob/living/simple_animal/drone/update_inv_r_hand()
update_inv_hands()
/mob/living/simple_animal/drone/update_inv_wear_mask()
update_inv_head()
/mob/living/simple_animal/drone/canUseTopic()
if(stat)
return
return 1
/mob/living/simple_animal/drone/activate_hand(var/selhand)
if(istext(selhand))
selhand = lowertext(selhand)
if(selhand == "right" || selhand == "r")
selhand = 0
if(selhand == "left" || selhand == "l")
selhand = 1
if(selhand != src.hand)
swap_hand()
else
mode()
/mob/living/simple_animal/drone/assess_threat() //Secbots won't hunt maintenance drones.
return -10
#undef HANDS_LAYER
#undef HEAD_LAYER
#undef TOTAL_LAYERS
#undef DRONE_NET_CONNECT
#undef DRONE_NET_DISCONNECT
//DRONE SHELL
/obj/item/drone_shell
name = "drone shell"
desc = "A shell of a maintenance drone, an expendable robot built to perform station repairs."
icon = 'icons/mob/drone.dmi'
icon_state = "drone_item"
origin_tech = "programming=2;biotech=4"
var/drone_type = /mob/living/simple_animal/drone //Type of drone that will be spawned
/obj/item/drone_shell/attack_ghost(mob/user)
if(jobban_isbanned(user,"pAI"))
return
var/be_drone = alert("Become a drone? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_drone == "No" || gc_destroyed)
return
var/mob/living/simple_animal/drone/D = new drone_type(get_turf(loc))
D.key = user.key
qdel(src)
//DRONE HOLDER
/obj/item/clothing/head/drone_holder//Only exists in someones hand.or on their head
name = "drone (hiding)"
desc = "This drone is scared and has curled up into a ball"
icon = 'icons/mob/drone.dmi'
icon_state = "drone_item"
var/mob/living/simple_animal/drone/drone //stored drone
/obj/item/clothing/head/drone_holder/proc/uncurl()
if(!drone)
return
if(istype(loc, /mob/living))
var/mob/living/L = loc
L.show_message("<span class='notice'>[drone] is trying to escape!</span>")
if(!do_after(L, 50) || loc != L)
return
L.unEquip(src)
contents -= drone
drone.loc = get_turf(src)
drone.reset_view()
drone.dir = SOUTH //Looks better
drone.visible_message("<span class='notice'>[drone] uncurls!</span>")
drone = null
qdel(src)
/obj/item/clothing/head/drone_holder/relaymove()
uncurl()
/obj/item/clothing/head/drone_holder/container_resist()
uncurl()
//More types of drones
/mob/living/simple_animal/drone/syndrone
name = "Syndrone"
desc = "A modified maintenance drone. This one brings with it the feeling of terror."
icon_state = "drone_synd"
icon_living = "drone_synd"
picked = TRUE
health = 30
maxHealth = 120 //If you murder other drones and cannibalize them you can get much stronger
faction = list("syndicate")
heavy_emp_damage = 10
laws = \
"1. Interfere.\n"+\
"2. Kill.\n"+\
"3. Destroy."
default_storage = /obj/item/device/radio/uplink
default_hatmask = /obj/item/clothing/head/helmet/space/hardsuit/syndi
/mob/living/simple_animal/drone/syndrone/New()
..()
if(internal_storage && internal_storage.hidden_uplink)
internal_storage.hidden_uplink.uses = (initial(internal_storage.hidden_uplink.uses) / 2)
internal_storage.name = "syndicate uplink"
/mob/living/simple_animal/drone/syndrone/Login()
..()
src << "<span class='notice'>You can kill and eat other drones to increase your health!</span>" //Inform the evil lil guy
/obj/item/drone_shell/syndrone
name = "syndrone shell"
desc = "A shell of a syndrone, a modified maintenance drone designed to infiltrate and annihilate."
icon_state = "syndrone_item"
drone_type = /mob/living/simple_animal/drone/syndrone
@@ -0,0 +1,183 @@
#define DRONE_HANDS_LAYER 1
#define DRONE_HEAD_LAYER 2
#define DRONE_TOTAL_LAYERS 2
#define DRONE_NET_CONNECT "<span class='notice'>DRONE NETWORK: [name] connected.</span>"
#define DRONE_NET_DISCONNECT "<span class='danger'>DRONE NETWORK: [name] is not responding.</span>"
#define MAINTDRONE "drone_maint"
#define REPAIRDRONE "drone_repair"
/mob/living/simple_animal/drone
name = "Drone"
desc = "A maintenance drone, an expendable robot built to perform station repairs."
icon = 'icons/mob/drone.dmi'
icon_state = "drone_maint_grey"
icon_living = "drone_maint_grey"
icon_dead = "drone_maint_dead"
gender = NEUTER
health = 30
maxHealth = 30
heat_damage_per_tick = 0
cold_damage_per_tick = 0
unsuitable_atmos_damage = 0
wander = 0
speed = 0
ventcrawler = 2
pass_flags = PASSTABLE | PASSMOB
sight = (SEE_TURFS | SEE_OBJS)
status_flags = (CANPUSH | CANSTUN | CANWEAKEN)
gender = NEUTER
voice_name = "synthesized chirp"
languages = DRONE
mob_size = 0
has_unlimited_silicon_privilege = 1
staticOverlays = list()
var/staticChoice = "static"
var/list/staticChoices = list("static", "blank", "letter")
var/picked = FALSE //Have we picked our visual appearence (+ colour if applicable)
var/list/drone_overlays[DRONE_TOTAL_LAYERS]
var/laws = \
"1. You may not involve yourself in the matters of another being, even if such matters conflict with Law Two or Law Three, unless the other being is another Drone.\n"+\
"2. You may not harm any being, regardless of intent or circumstance.\n"+\
"3. Your goals are to build, maintain, repair, improve, and power to the best of your abilities, You must never actively work against these goals."
var/light_on = 0
var/heavy_emp_damage = 25 //Amount of damage sustained if hit by a heavy EMP pulse
var/health_repair_max = 0 //Drone will only be able to be repaired/reactivated up to this point, defaults to health
var/alarms = list("Atmosphere" = list(), "Fire" = list(), "Power" = list())
var/obj/item/internal_storage //Drones can store one item, of any size/type in their body
var/obj/item/head
var/obj/item/default_storage = /obj/item/weapon/storage/toolbox/drone //If this exists, it will spawn in internal storage
var/obj/item/default_hatmask //If this exists, it will spawn in the hat/mask slot if it can fit
var/seeStatic = 1 //Whether we see static instead of mobs
var/visualAppearence = MAINTDRONE //What we appear as
/mob/living/simple_animal/drone/New()
..()
name = name + " ([rand(100,999)])"
real_name = name
access_card = new /obj/item/weapon/card/id(src)
var/datum/job/captain/C = new /datum/job/captain
access_card.access = C.get_access()
if(!health_repair_max)
health_repair_max = initial(health)
if(default_storage)
var/obj/item/I = new default_storage(src)
equip_to_slot_or_del(I, "drone_storage_slot")
if(default_hatmask)
var/obj/item/I = new default_hatmask(src)
equip_to_slot_or_del(I, slot_head)
alert_drones(DRONE_NET_CONNECT)
/mob/living/simple_animal/drone/Destroy()
qdel(access_card) //Otherwise it ends up on the floor!
..()
/mob/living/simple_animal/drone/Login()
..()
update_inv_hands()
update_inv_head()
update_inv_internal_storage()
check_laws()
updateSeeStaticMobs()
if(!picked)
pickVisualAppearence()
/mob/living/simple_animal/drone/Die()
..()
drop_l_hand()
drop_r_hand()
if(internal_storage)
unEquip(internal_storage)
if(head)
unEquip(head)
alert_drones(DRONE_NET_DISCONNECT)
/mob/living/simple_animal/drone/gib()
dust()
/mob/living/simple_animal/drone/examine(mob/user)
. = ..()
if(!client && stat != DEAD)
user << "<span class='notice'>A small blue LED is blinking on and off at a steady rate.</span>"
if(stat == DEAD)
user << "<span class='notice'>The drone's LED screen shows a BSOD, Blue screen of Death!</span>"
/mob/living/simple_animal/drone/Move()
if(pullin)
if(pulling)
pullin.icon_state = "pull"
else
pullin.icon_state = "pull0"
..()
/mob/living/simple_animal/drone/IsAdvancedToolUser()
return 1
/mob/living/simple_animal/drone/canUseTopic()
if(stat)
return
return 1
/mob/living/simple_animal/drone/assess_threat() //Secbots won't hunt maintenance drones.
return -10
/mob/living/simple_animal/drone/emp_act(severity)
Stun(5)
src << "<span class='danger'><b>ER@%R: MME^RY CO#RU9T!</b> R&$b@0tin)...</span>"
if(severity == 1)
adjustBruteLoss(heavy_emp_damage)
src << "<span class='userdanger'>HeAV% DA%^MMA+G TO I/O CIR!%UUT!</span>"
/mob/living/simple_animal/drone/proc/triggerAlarm(var/class, area/A, var/O, var/obj/alarmsource)
if(alarmsource.z != z)
return
if(stat != DEAD)
var/list/L = src.alarms[class]
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/sources = alarm[2]
if (!(alarmsource in sources))
sources += alarmsource
return
L[A.name] = list(A, list(alarmsource))
src << "--- [class] alarm detected in [A.name]!"
/mob/living/simple_animal/drone/proc/cancelAlarm(var/class, area/A as area, obj/origin)
if(stat != DEAD)
var/list/L = alarms[class]
var/cleared = 0
for (var/I in L)
if (I == A.name)
var/list/alarm = L[I]
var/list/srcs = alarm[2]
if (origin in srcs)
srcs -= origin
if (srcs.len == 0)
cleared = 1
L -= I
if(cleared)
src << "--- [class] alarm in [A.name] has been cleared."
@@ -0,0 +1,69 @@
///////////////////
//DRONES AS ITEMS//
///////////////////
//Drone shells
//Drones as hats
//DRONE SHELL
/obj/item/drone_shell
name = "drone shell"
desc = "A shell of a maintenance drone, an expendable robot built to perform station repairs."
icon = 'icons/mob/drone.dmi'
icon_state = "drone_maint_hat"//yes reuse the _hat state.
origin_tech = "programming=2;biotech=4"
var/drone_type = /mob/living/simple_animal/drone //Type of drone that will be spawned
/obj/item/drone_shell/attack_ghost(mob/user)
if(jobban_isbanned(user,"pAI"))
return
var/be_drone = alert("Become a drone? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_drone == "No" || gc_destroyed)
return
var/mob/living/simple_animal/drone/D = new drone_type(get_turf(loc))
D.key = user.key
qdel(src)
//DRONE HOLDER
/obj/item/clothing/head/drone_holder//Only exists in someones hand.or on their head
name = "drone (hiding)"
desc = "This drone is scared and has curled up into a ball"
icon = 'icons/mob/drone.dmi'
icon_state = "drone_maint_hat"
var/mob/living/simple_animal/drone/drone //stored drone
/obj/item/clothing/head/drone_holder/proc/uncurl()
if(!drone)
return
if(istype(loc, /mob/living))
var/mob/living/L = loc
L.show_message("<span class='notice'>[drone] is trying to escape!</span>")
if(!do_after(L, 50) || loc != L)
return
L.unEquip(src)
contents -= drone
drone.loc = get_turf(src)
drone.reset_view()
drone.dir = SOUTH //Looks better
drone.visible_message("<span class='notice'>[drone] uncurls!</span>")
drone = null
qdel(src)
/obj/item/clothing/head/drone_holder/relaymove()
uncurl()
/obj/item/clothing/head/drone_holder/container_resist()
uncurl()
/obj/item/clothing/head/drone_holder/proc/updateVisualAppearence(var/mob/living/simple_animal/drone/D)
if(!D)
return
icon_state = "[D.visualAppearence]_hat"
. = icon_state
@@ -0,0 +1,46 @@
////////////////////
//MORE DRONE TYPES//
////////////////////
//Drones with custom laws
//Drones with custom shells
//Drones with overriden procs
//More types of drones
/mob/living/simple_animal/drone/syndrone
name = "Syndrone"
desc = "A modified maintenance drone. This one brings with it the feeling of terror."
icon_state = "drone_synd"
icon_living = "drone_synd"
picked = TRUE //the appearence of syndrones is static, you don't get to change it.
health = 30
maxHealth = 120 //If you murder other drones and cannibalize them you can get much stronger
faction = list("syndicate")
heavy_emp_damage = 10
laws = \
"1. Interfere.\n"+\
"2. Kill.\n"+\
"3. Destroy."
default_storage = /obj/item/device/radio/uplink
default_hatmask = /obj/item/clothing/head/helmet/space/hardsuit/syndi
seeStatic = 0 //Our programming is superior.
/mob/living/simple_animal/drone/syndrone/New()
..()
if(internal_storage && internal_storage.hidden_uplink)
internal_storage.hidden_uplink.uses = (initial(internal_storage.hidden_uplink.uses) / 2)
internal_storage.name = "syndicate uplink"
/mob/living/simple_animal/drone/syndrone/Login()
..()
src << "<span class='notice'>You can kill and eat other drones to increase your health!</span>" //Inform the evil lil guy
/obj/item/drone_shell/syndrone
name = "syndrone shell"
desc = "A shell of a syndrone, a modified maintenance drone designed to infiltrate and annihilate."
icon_state = "syndrone_item"
drone_type = /mob/living/simple_animal/drone/syndrone
@@ -0,0 +1,106 @@
/////////////////////
//DRONE INTERACTION//
/////////////////////
//How drones interact with the world
//How the world interacts with drones
/mob/living/simple_animal/drone/UnarmedAttack(atom/A, proximity)
A.attack_hand(src)
/mob/living/simple_animal/drone/attack_hand(mob/user)
if(isdrone(user))
var/mob/living/simple_animal/drone/D = user
if(D != src)
if(stat == DEAD)
var/d_input = alert(D,"Perform which action?","Drone Interaction","Reactivate","Cannibalize","Nothing")
if(d_input)
switch(d_input)
if("Reactivate")
var/mob/dead/observer/G = get_ghost()
if(!client && (!G || !G.client))
var/list/faux_gadgets = list("hypertext inflator","failsafe directory","DRM switch","stack initializer",\
"anti-freeze capacitor","data stream diode","TCP bottleneck","supercharged I/O bolt",\
"tradewind stablizer","radiated XML cable","registry fluid tank","open-source debunker")
var/list/faux_problems = list("won't be able to tune their bootstrap projector","will constantly remix their binary pool"+\
" even though the BMX calibrator is working","will start leaking their XSS coolant",\
"can't tell if their ethernet detour is moving or not", "won't be able to reseed enough"+\
" kernels to function properly","can't start their neurotube console")
D << "<span class='notice'>You can't seem to find the [pick(faux_gadgets)]. Without it, [src] [pick(faux_problems)].</span>"
return
D.visible_message("<span class='notice'>[D] begins to reactivate [src].</span>")
if(do_after(user,30,needhand = 1))
health = health_repair_max
stat = CONSCIOUS
icon_state = icon_living
dead_mob_list -= src
living_mob_list += src
D.visible_message("<span class='notice'>[D] reactivates [src]!</span>")
alert_drones(DRONE_NET_CONNECT)
if(G)
G << "<span class='boldnotice'>DRONE NETWORK: </span><span class='ghostalert'>You were reactivated by [D]!</span>"
else
D << "<span class='notice'>You need to remain still to reactivate [src].</span>"
if("Cannibalize")
if(D.health < D.maxHealth)
D.visible_message("<span class='notice'>[D] begins to cannibalize parts from [src].</span>")
if(do_after(D, 60,5,0))
D.visible_message("<span class='notice'>[D] repairs itself using [src]'s remains!</span>")
D.adjustBruteLoss(-src.maxHealth)
new /obj/effect/decal/cleanable/oil/streak(get_turf(src))
qdel(src)
else
D << "<span class='notice'>You need to remain still to cannibalize [src].</span>"
else
D << "<span class='notice'>You're already in perfect condition!</span>"
if("Nothing")
return
return
if(ishuman(user))
if(stat == DEAD)
..()
return
if(user.get_active_hand())
user << "<span class='notice'>Your hands are full.</span>"
return
src << "<span class='warning'>[user] is trying to pick you up!</span>"
if(buckled)
user << "<span class='warning'>[src] is buckled to the [buckled.name] and cannot be picked up!</span>"
return
user << "<span class='notice'>You pick [src] up.</span>"
drop_l_hand()
drop_r_hand()
var/obj/item/clothing/head/drone_holder/DH = new /obj/item/clothing/head/drone_holder(src)
DH.updateVisualAppearence(src)
DH.contents += src
DH.drone = src
user.put_in_hands(DH)
src.loc = DH
return
..()
/mob/living/simple_animal/drone/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/screwdriver) && stat != DEAD)
if(health < health_repair_max)
user << "<span class='notice'>You start to tighten loose screws on [src].</span>"
if(do_after(user,80))
health = health_repair_max
visible_message("<span class='notice'>[user] tightens [src == user ? "their" : "[src]'s"] loose screws!</span>")
else
user << "<span class='notice'>You need to remain still to tighten [src]'s screws.</span>"
else
user << "<span class='notice'>[src]'s screws can't get any tighter!</span>"
else
..()
@@ -0,0 +1,115 @@
///////////////////
//DRONE INVENTORY//
///////////////////
//Drone inventory
//Drone hands
/mob/living/simple_animal/drone/activate_hand(var/selhand)
if(istext(selhand))
selhand = lowertext(selhand)
if(selhand == "right" || selhand == "r")
selhand = 0
if(selhand == "left" || selhand == "l")
selhand = 1
if(selhand != src.hand)
swap_hand()
else
mode()
/mob/living/simple_animal/drone/swap_hand()
var/obj/item/held_item = get_active_hand()
if(held_item)
if(istype(held_item, /obj/item/weapon/twohanded))
var/obj/item/weapon/twohanded/T = held_item
if(T.wielded == 1)
usr << "<span class='warning'>Your other hand is too busy holding the [T.name].</span>"
return
hand = !hand
if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object)
if(hand)
hud_used.l_hand_hud_object.icon_state = "hand_l_active"
hud_used.r_hand_hud_object.icon_state = "hand_r_inactive"
else
hud_used.l_hand_hud_object.icon_state = "hand_l_inactive"
hud_used.r_hand_hud_object.icon_state = "hand_r_active"
/mob/living/simple_animal/drone/unEquip(obj/item/I, force)
if(..(I,force))
update_inv_hands()
if(I == head)
head = null
update_inv_head()
if(I == internal_storage)
internal_storage = null
update_inv_internal_storage()
return 1
return 0
/mob/living/simple_animal/drone/can_equip(obj/item/I, slot)
switch(slot)
if(slot_head)
if(head)
return 0
if(!((I.slot_flags & SLOT_HEAD) || (I.slot_flags & SLOT_MASK)))
return 0
return 1
if("drone_storage_slot")
if(internal_storage)
return 0
return 1
..()
/mob/living/simple_animal/drone/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_head)
return head
if("drone_storage_slot")
return internal_storage
..()
/mob/living/simple_animal/drone/equip_to_slot(obj/item/I, slot)
if(!slot) return
if(!istype(I)) return
if(I == l_hand)
l_hand = null
else if(I == r_hand)
r_hand = null
update_inv_hands()
I.screen_loc = null // will get moved if inventory is visible
I.loc = src
I.equipped(src, slot)
I.layer = 20
switch(slot)
if(slot_head)
head = I
update_inv_head()
if("drone_storage_slot")
internal_storage = I
update_inv_internal_storage()
else
src << "<span class='danger'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>"
return
/mob/living/simple_animal/drone/stripPanelUnequip(obj/item/what, mob/who, where)
..(what, who, where, 1)
/mob/living/simple_animal/drone/stripPanelEquip(obj/item/what, mob/who, where)
..(what, who, where, 1)
@@ -0,0 +1,46 @@
/////////////
//DRONE SAY//
/////////////
//Drone speach
//Drone hearing
/mob/living/simple_animal/drone/say(var/message)
return ..(message, "R")
/mob/living/simple_animal/drone/lang_treat(atom/movable/speaker, message_langs, raw_message) //This is so drones can understand humans without being able to speak human
. = ..()
var/hear_override_langs = HUMAN
if(message_langs & hear_override_langs)
return ..(speaker, languages, raw_message)
/mob/living/simple_animal/drone/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_BINARY)
drone_chat(message)
return ITALICS | REDUCE_RANGE
else
..()
/mob/living/simple_animal/drone/proc/alert_drones(msg, dead_can_hear = 0)
for(var/mob/M in player_list)
var/send_msg = 0
if(istype(M, /mob/living/simple_animal/drone) && M.stat != DEAD)
for(var/F in src.faction)
if(F in M.faction)
send_msg = 1
break
else if(dead_can_hear && (M in dead_mob_list))
send_msg = 1
if(send_msg)
M << msg
/mob/living/simple_animal/drone/proc/drone_chat(msg)
var/rendered = "<i><span class='game say'>DRONE CHAT: <span class='name'>[name]</span>: [msg]</span></i>"
alert_drones(rendered, 1)
@@ -0,0 +1,53 @@
///////////////
//DRONE VERBS//
///////////////
//Drone verbs that appear in the Drone tab and on buttons
/mob/living/simple_animal/drone/verb/check_laws()
set category = "Drone"
set name = "Check Laws"
src << "<b>Drone Laws</b>"
src << laws
/mob/living/simple_animal/drone/verb/toggle_light()
set category = "Drone"
set name = "Toggle drone light"
if(light_on)
AddLuminosity(-4)
else
AddLuminosity(4)
light_on = !light_on
src << "<span class='notice'>Your light is now [light_on ? "on" : "off"]</span>"
/mob/living/simple_animal/drone/verb/drone_ping()
set category = "Drone"
set name = "Drone ping"
var/alert_s = input(src,"Alert severity level","Drone ping",null) as null|anything in list("Low","Medium","High","Critical")
var/area/A = get_area(loc)
if(alert_s && A && stat != DEAD)
var/msg = "<span class='boldnotice'>DRONE PING: [name]: [alert_s] priority alert in [A.name]!</span>"
alert_drones(msg)
/mob/living/simple_animal/drone/verb/toggle_statics()
set name = "Change Vision Filter"
set desc = "Change the filter on the system used to remove non drone beings from your viewscreen."
set category = "Drone"
if(!seeStatic)
src << "<span class='notice'>You have no vision filter to change!</span>"
return
var/selectedStatic = input("Select a vision filter", "Vision Filter") as null|anything in staticChoices
if(selectedStatic in staticChoices)
staticChoice = selectedStatic
updateSeeStaticMobs()
@@ -0,0 +1,159 @@
/////////////////
//DRONE VISUALS//
/////////////////
//Drone overlays
//Drone visuals
/mob/living/simple_animal/drone/proc/apply_overlay(cache_index)
var/image/I = drone_overlays[cache_index]
if(I)
overlays += I
/mob/living/simple_animal/drone/proc/remove_overlay(cache_index)
if(drone_overlays[cache_index])
overlays -= drone_overlays[cache_index]
drone_overlays[cache_index] = null
/mob/living/simple_animal/drone/proc/update_inv_hands()
remove_overlay(DRONE_HANDS_LAYER)
var/list/hands_overlays = list()
var/y_shift = getItemPixelShiftY()
if(r_hand)
var/r_state = r_hand.item_state
if(!r_state)
r_state = r_hand.icon_state
var/image/r_hand_image = image("icon" = r_hand.righthand_file, "icon_state"="[r_state]", "layer"=-DRONE_HANDS_LAYER)
if(y_shift != 0)
r_hand_image.pixel_y = y_shift
hands_overlays += r_hand_image
if(client && hud_used)
r_hand.layer = 20
r_hand.screen_loc = ui_rhand
client.screen |= r_hand
if(l_hand)
var/l_state = l_hand.item_state
if(!l_state)
l_state = l_hand.icon_state
var/image/l_hand_image = image("icon" = l_hand.lefthand_file, "icon_state"="[l_state]", "layer"=-DRONE_HANDS_LAYER)
if(y_shift != 0)
l_hand_image.pixel_y = y_shift
hands_overlays += l_hand_image
if(client && hud_used)
l_hand.layer = 20
l_hand.screen_loc = ui_lhand
client.screen |= l_hand
if(hands_overlays.len)
drone_overlays[DRONE_HANDS_LAYER] = hands_overlays
apply_overlay(DRONE_HANDS_LAYER)
/mob/living/simple_animal/drone/proc/update_inv_internal_storage()
if(internal_storage && client && hud_used)
internal_storage.screen_loc = ui_drone_storage
client.screen += internal_storage
/mob/living/simple_animal/drone/update_inv_head()
remove_overlay(DRONE_HEAD_LAYER)
if(head)
if(client && hud_used)
head.screen_loc = ui_drone_head
client.screen += head
var/image/head_overlay = image("icon"='icons/mob/head.dmi', "icon_state"="[head.icon_state]", "layer"=-DRONE_HEAD_LAYER)
if(istype(head, /obj/item/clothing/mask))
head_overlay.icon = 'icons/mob/mask.dmi'
head_overlay.color = head.color
head_overlay.alpha = head.alpha
head_overlay.pixel_y = -15
drone_overlays[DRONE_HEAD_LAYER] = head_overlay
apply_overlay(DRONE_HEAD_LAYER)
//These procs serve as redirection so that the drone updates as expected when other things call these procs
/mob/living/simple_animal/drone/update_inv_l_hand()
update_inv_hands()
/mob/living/simple_animal/drone/update_inv_r_hand()
update_inv_hands()
/mob/living/simple_animal/drone/update_inv_wear_mask()
update_inv_head()
/mob/living/simple_animal/drone/proc/pickVisualAppearence()
picked = FALSE
var/appearence = input("Choose your appearence!", "Appearence", "Maintenance Drone") in list("Maintenance Drone", "Repair Drone")
switch(appearence)
if("Maintenance Drone")
visualAppearence = MAINTDRONE
var/colour = input("Choose your colour!", "Colour", "grey") in list("grey", "blue", "red", "green", "pink", "orange")
icon_state = "[visualAppearence]_[colour]"
icon_living = "[visualAppearence]_[colour]"
icon_dead = "[visualAppearence]_dead"
if("Repair Drone")
visualAppearence = REPAIRDRONE
icon_state = visualAppearence
icon_living = visualAppearence
icon_dead = "[visualAppearence]_dead"
else
return
picked = TRUE
/mob/living/simple_animal/drone/proc/getItemPixelShiftY()
switch(visualAppearence)
if(MAINTDRONE)
. = 0
if(REPAIRDRONE)
. = -6
/mob/living/simple_animal/drone/proc/updateSeeStaticMobs()
if(!client)
return
for(var/i in staticOverlays)
client.images.Remove(i)
staticOverlays.Remove(i)
staticOverlays.len = 0
if(seeStatic)
for(var/mob/living/L in mob_list)
if(isdrone(L))
continue
var/image/chosen
if(staticChoice in L.staticOverlays)
chosen = L.staticOverlays[staticChoice]
else
chosen = L.staticOverlays["static"]
staticOverlays |= chosen
client.images |= chosen
/mob/living/simple_animal/drone/generateStaticOverlay()
return
@@ -7,7 +7,7 @@
status_flags = CANPUSH
var/icon_living = ""
var/icon_dead = ""
var/icon_dead = "" //icon when the animal is dead. Don't use animated icons for this.
var/icon_gib = null //We only try to show a gibbing animation if this exists.
var/list/speak = list()
+1 -10
View File
@@ -470,13 +470,6 @@ var/list/slot_equipment_priority = list( \
if (popup)
memory()
/*
/mob/verb/help()
set name = "Help"
src << browse('html/help.html', "window=help")
return
*/
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
@@ -513,8 +506,6 @@ var/list/slot_equipment_priority = list( \
set name = "Changelog"
set category = "OOC"
getFiles(
'html/postcardsmall.jpg',
'html/somerights20.png',
'html/88x31.png',
'html/bug-minus.png',
'html/cross-circle.png',
@@ -537,7 +528,7 @@ var/list/slot_equipment_priority = list( \
if(prefs.lastchangelog != changelog_hash)
prefs.lastchangelog = changelog_hash
prefs.save_preferences()
winset(src, "rpane.changelog", "background-color=none;font-style=;")
winset(src, "rpane.changelogb", "background-color=none;font-style=;")
/mob/verb/observe()
set name = "Observe"
+3 -2
View File
@@ -135,17 +135,18 @@
if(isturf(mob.loc))
move_delay = world.time//set move delay
if(mob.restrained()) //Why being pulled while cuffed prevents you from moving
for(var/mob/M in range(mob, 1))
if(M.pulling == mob)
if(!M.incapacitated() && mob.Adjacent(M))
src << "<span class='notice'>You're restrained! You can't move!</span>"
move_delay += 10
return 0
else
M.stop_pulling()
move_delay = world.time//set move delay
switch(mob.m_intent)
if("run")
if(mob.drowsyness > 0)
+17 -3
View File
@@ -126,8 +126,12 @@
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
usr << "<span class='danger'>The round is either not ready, or has already finished...</span>"
return
var/relevent_cap = max(config.hard_popcap, config.extreme_popcap)
if(relevent_cap && living_player_count() >= relevent_cap && !(ckey(key) in admin_datums))
var/relevant_cap
if(config.hard_popcap && config.extreme_popcap)
relevant_cap = min(config.hard_popcap, config.extreme_popcap)
else
relevant_cap = max(config.hard_popcap, config.extreme_popcap)
if(relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in admin_datums))
usr << "<span class='danger'>[config.hard_popcap_message]</span>"
return
LateChoices()
@@ -246,7 +250,12 @@
if(!job)
return 0
if((job.current_positions >= job.total_positions) && job.total_positions != -1)
return 0
if(job.title == "Assistant")
for(var/datum/job/J in SSjob.occupations)
if(J && J.current_positions < J.total_positions && J.title != job.title)
return 0
else
return 0
if(jobban_isbanned(src,rank))
return 0
if(!job.player_old_enough(src.client))
@@ -329,6 +338,11 @@
if (job.title in command_positions)
position_class = "commandPosition"
dat += "<a class='[position_class]' href='byond://?src=\ref[src];SelectedJob=[job.title]'>[job.title] ([job.current_positions])</a><br>"
if(!job_count) //if there's nowhere to go, assistant opens up.
for(var/datum/job/job in SSjob.occupations)
if(job.title != "Assistant") continue
dat += "<a class='otherPosition' href='byond://?src=\ref[src];SelectedJob=[job.title]'>[job.title] ([job.current_positions])</a><br>"
break
dat += "</div></div>"
// Removing the old window method but leaving it here for reference
+4
View File
@@ -182,3 +182,7 @@
return 1 // success
//Send all needed nano ui files to the client
/datum/subsystem/nano/proc/send_resources(client)
for(var/file in asset_files)
client << browse_rsc(file)
@@ -228,7 +228,7 @@ datum/reagent/crank/addiction_act_stage4(var/mob/living/M as mob)
name = "methamphetamine"
id = "methamphetamine"
result = "methamphetamine"
required_reagents = list("ephedrine" = 1, "iodine" = 1, "phosphorous" = 1, "hydrogen" = 1)
required_reagents = list("ephedrine" = 1, "iodine" = 1, "phosphorus" = 1, "hydrogen" = 1)
result_amount = 4
required_temp = 374
@@ -506,4 +506,4 @@ datum/reagent/hotline/addiction_act_stage4(var/mob/living/M as mob)
M.visible_message("<span class = 'userdanger'>[M] clutches at their chest! It looks like they're having a heart attack!</span>")
M.adjustBruteLoss(80) // don't do drugs kids
..()
return
return
@@ -101,10 +101,10 @@
id = "liquid_dark_matter"
result = "liquid_dark_matter"
required_reagents = list("stable_plasma" = 1, "radium" = 1, "carbon" = 1)
result_amount = 3
result_amount = null
required_temp = 474
/datum/reagent/liquid_dark_matter/reaction_turf(var/turf/simulated/T, var/volume)
/*/datum/reagent/liquid_dark_matter/reaction_turf(var/turf/simulated/T, var/volume)
if(istype(T, /turf/simulated/floor/))
goonchem_vortex(T, 0, 5, 3)
return
@@ -114,13 +114,13 @@
if(method == TOUCH)
var/turf/simulated/T = get_turf(M)
goonchem_vortex(T, 0, 5, 3)
return
return*/ //o god what the fuck goof
/datum/chemical_reaction/liquid_dark_matter/on_reaction(var/datum/reagents/holder, var/created_volume)
var/turf/simulated/T = get_turf(holder.my_atom)
goonchem_vortex(T, 0, 5, 6)
return
proc/goonchem_vortex(var/turf/simulated/T, var/setting_type, var/range, var/pull_times)
/proc/goonchem_vortex(var/turf/simulated/T, var/setting_type, var/range, var/pull_times)
for(var/atom/movable/X in orange(range, T))
if(istype(X, /obj/effect))
continue //stop pulling smoke and hotspots please
@@ -67,6 +67,7 @@ datum/reagent/blob/lung_destroying_toxin
datum/reagent/blob/lung_destroying_toxin/reaction_mob(var/mob/living/M as mob, var/method=TOUCH, var/volume,var/show_message = 1)
if(method == TOUCH)
M.apply_damage(20, OXY)
M.losebreath += 15
M.apply_damage(20, TOX)
if(show_message)
M << "<span class = 'userdanger'>The blob strikes you, and your lungs feel heavy and weak!</span>"
@@ -95,13 +96,11 @@ datum/reagent/blob/radioactive_liquid/reaction_mob(var/mob/living/M as mob, var/
if(method == TOUCH)
if(istype(M, /mob/living/carbon/human))
M.apply_damage(10, BRUTE)
M.apply_effect(10,IRRADIATE,0)
M.apply_effect(40,IRRADIATE,0) // irradiate the shit out of these fuckers
if(prob(33))
randmuti(M)
if(prob(98))
randmutb(M)
else
randmutg(M)
domutcheck(M, null)
updateappearance(M)
if(show_message)
@@ -151,7 +150,7 @@ datum/reagent/blob/explosive/reaction_mob(var/mob/living/M as mob, var/method=TO
var/turf/pull = get_turf(M)
for(var/atom/movable/X in orange(4,pull))
if(istype(X, /atom/movable))
if((X))
if((X) && !X.anchored)
if(setting_type)
step_away(X,pull)
step_away(X,pull)
@@ -261,10 +261,12 @@ datum/reagent/water/reaction_turf(var/turf/simulated/T, var/volume)
G.temperature = max(min(G.temperature-(CT*1000),G.temperature/CT),0)
G.react()
qdel(hotspot)
T.color = initial(T.color)
return
datum/reagent/water/reaction_obj(var/obj/O, var/volume)
src = null
O.color = initial(O.color)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/monkeycube))
var/obj/item/weapon/reagent_containers/food/snacks/monkeycube/cube = O
if(!cube.wrapped)
@@ -274,6 +276,7 @@ datum/reagent/water/reaction_obj(var/obj/O, var/volume)
datum/reagent/water/reaction_mob(var/mob/living/M, var/method=TOUCH, var/volume)//Splashing people with water can help put them out!
if(!istype(M, /mob/living))
return
M.color = initial(M.color)
if(method == TOUCH)
M.adjust_fire_stacks(-(volume / 10))
if(M.fire_stacks <= 0)
@@ -721,7 +724,7 @@ datum/reagent/cryptobiolin
id = "cryptobiolin"
description = "Cryptobiolin causes confusion and dizzyness."
color = "#C8A5DC" // rgb: 200, 165, 220
metabolization_rate = 0.5 * REAGENTS_METABOLISM
metabolization_rate = 1.5 * REAGENTS_METABOLISM
datum/reagent/cryptobiolin/on_mob_life(var/mob/living/M as mob)
M.Dizzy(1)
@@ -315,9 +315,10 @@ datum/reagent/consumable/ethanol/beepsky_smash
description = "Deny drinking this and prepare for THE LAW."
color = "#664300" // rgb: 102, 67, 0
boozepwr = 25
metabolization_rate = 0.8
datum/reagent/consumable/ethanol/beepsky_smash/on_mob_life(var/mob/living/M as mob)
M.Stun(2)
M.Stun(1)
..()
return
@@ -255,7 +255,7 @@ datum/reagent/toxin/chloralhydrate
reagent_state = SOLID
color = "#000067" // rgb: 0, 0, 103
toxpwr = 0
metabolization_rate = 0.5 * REAGENTS_METABOLISM
metabolization_rate = 1.5 * REAGENTS_METABOLISM
datum/reagent/toxin/chloralhydrate/on_mob_life(var/mob/living/M as mob)
if(!data)
@@ -278,7 +278,7 @@ datum/reagent/toxin/beer2 //disguised as normal beer for use by emagged brobots
id = "beer2"
description = "An alcoholic beverage made from malted grains, hops, yeast, and water."
color = "#664300" // rgb: 102, 67, 0
metabolization_rate = 0.5 * REAGENTS_METABOLISM
metabolization_rate = 1.5 * REAGENTS_METABOLISM
datum/reagent/toxin/beer2/on_mob_life(var/mob/living/M as mob)
if(!data)
@@ -187,7 +187,7 @@
amount_per_transfer_from_this = (amount_per_transfer_from_this == 10 ? 5 : 10)
user << "<span class='notice'>You adjust the output switch. You'll now use [amount_per_transfer_from_this] units per spray.</span>"
/obj/item/weapon/reagent_containers/spray/chemsprayer/bioterror/New()
/obj/item/weapon/reagent_containers/spray/chemsprayer/bioterror
list_reagents = list("spore" = 150, "cryptobiolin" = 150, "mutagen" = 150, "chloralhydrate" = 150)
// Plant-B-Gone
@@ -98,6 +98,8 @@
..()
if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
if(Proj.nodamage)
return
message_admins("[key_name_admin(Proj.firer)] triggered a fueltank explosion.")
log_game("[key_name(Proj.firer)] triggered a fueltank explosion.")
explosion(src.loc,-1,0,2, flame_range = 2)
+4 -4
View File
@@ -61,13 +61,13 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
/obj/machinery/r_n_d/circuit_imprinter/proc/check_mat(datum/design/being_built, var/M)
switch(M)
if("$glass")
return (g_amount - (being_built.materials[M]/efficiency_coeff) >= 0) ? 1 : 0
return (g_amount - (being_built.materials[M]/efficiency_coeff) >= 0)
if("$gold")
return (gold_amount - (being_built.materials[M]/efficiency_coeff) >= 0) ? 1 : 0
return (gold_amount - (being_built.materials[M]/efficiency_coeff) >= 0)
if("$diamond")
return (diamond_amount - (being_built.materials[M]/efficiency_coeff) >= 0) ? 1 : 0
return (diamond_amount - (being_built.materials[M]/efficiency_coeff) >= 0)
else
return (reagents.has_reagent(M, (being_built.materials[M]/efficiency_coeff)) != 0) ? 1 : 0
return (reagents.has_reagent(M, (being_built.materials[M]/efficiency_coeff)) != 0)
/obj/machinery/r_n_d/circuit_imprinter/proc/TotalMaterials()
+3 -3
View File
@@ -328,8 +328,8 @@
R.delete()
ejectItem(TRUE)
if(prob(EFFECT_PROB_VERYLOW-badThingCoeff))
visible_message("<span class='notice'>[src]'s chemical chamber has sprung a leak!.</span>")
chosenchem = pick("mutationtoxin","nanomachines","xenomicrobes")
visible_message("<span class='danger'>[src]'s chemical chamber has sprung a leak!</span>")
chosenchem = pick("mutationtoxin","nanomachines","sacid")
var/datum/reagents/R = new/datum/reagents(50)
R.my_atom = src
R.add_reagent(chosenchem , 50)
@@ -720,4 +720,4 @@
/obj/item/weapon/relic/proc/warn_admins(var/mob/user, var/RelicType)
var/turf/T = get_turf(src)
message_admins("[RelicType] relic activated by [key_name(user, user.client)](<A HREF='?_src_=holder;adminmoreinfo=\ref[user]'>?</A>) in ([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)
log_game("[RelicType] relic used by [user.ckey]([user]) in ([T.x],[T.y],[T.z])")
log_game("[RelicType] relic used by [user.ckey]([user]) in ([T.x],[T.y],[T.z])")
+32 -28
View File
@@ -369,34 +369,38 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if (g2g) //If input is incorrect, nothing happens
var/enough_materials = 1
linked_lathe.busy = 1
flick("protolathe_n",linked_lathe)
use_power(power)
for(var/M in being_built.materials)
if(!linked_lathe.check_mat(being_built, M))
if(linked_lathe.check_mat(being_built, M) < amount)
src.visible_message("<span class='notice'>The [src.name] beeps, \"Not enough materials to complete prototype.\"</span>")
enough_materials = 0
g2g = 0
break
switch(M)
if("$metal")
linked_lathe.m_amount = max(0, (linked_lathe.m_amount-(being_built.materials[M]/coeff * amount)))
if("$glass")
linked_lathe.g_amount = max(0, (linked_lathe.g_amount-(being_built.materials[M]/coeff * amount)))
if("$gold")
linked_lathe.gold_amount = max(0, (linked_lathe.gold_amount-(being_built.materials[M]/coeff * amount)))
if("$silver")
linked_lathe.silver_amount = max(0, (linked_lathe.silver_amount-(being_built.materials[M]/coeff * amount)))
if("$plasma")
linked_lathe.plasma_amount = max(0, (linked_lathe.plasma_amount-(being_built.materials[M]/coeff * amount)))
if("$uranium")
linked_lathe.uranium_amount = max(0, (linked_lathe.uranium_amount-(being_built.materials[M]/coeff * amount)))
if("$diamond")
linked_lathe.diamond_amount = max(0, (linked_lathe.diamond_amount-(being_built.materials[M]/coeff * amount)))
if("$bananium")
linked_lathe.clown_amount = max(0, (linked_lathe.clown_amount-(being_built.materials[M]/coeff * amount)))
else
linked_lathe.reagents.remove_reagent(M, being_built.materials[M]/coeff * amount)
if(enough_materials)
for(var/M in being_built.materials)
switch(M)
if("$metal")
linked_lathe.m_amount = max(0, (linked_lathe.m_amount-(being_built.materials[M]/coeff * amount)))
if("$glass")
linked_lathe.g_amount = max(0, (linked_lathe.g_amount-(being_built.materials[M]/coeff * amount)))
if("$gold")
linked_lathe.gold_amount = max(0, (linked_lathe.gold_amount-(being_built.materials[M]/coeff * amount)))
if("$silver")
linked_lathe.silver_amount = max(0, (linked_lathe.silver_amount-(being_built.materials[M]/coeff * amount)))
if("$plasma")
linked_lathe.plasma_amount = max(0, (linked_lathe.plasma_amount-(being_built.materials[M]/coeff * amount)))
if("$uranium")
linked_lathe.uranium_amount = max(0, (linked_lathe.uranium_amount-(being_built.materials[M]/coeff * amount)))
if("$diamond")
linked_lathe.diamond_amount = max(0, (linked_lathe.diamond_amount-(being_built.materials[M]/coeff * amount)))
if("$bananium")
linked_lathe.clown_amount = max(0, (linked_lathe.clown_amount-(being_built.materials[M]/coeff * amount)))
else
linked_lathe.reagents.remove_reagent(M, being_built.materials[M]/coeff * amount)
var/P = being_built.build_path //lets save these values before the spawn() just in case. Nobody likes runtimes.
var/R = being_built.reliability
@@ -827,17 +831,17 @@ won't update every console in existence) but it's more of a hassle to do. Also,
for(var/M in D.materials)
t = linked_lathe.check_mat(D, M)
temp_material += " | "
if (!t)
if (t < 1)
temp_material += "<span class='bad'>[D.materials[M]/coeff] [CallMaterialName(M)]</span>"
else
temp_material += " [D.materials[M]/coeff] [CallMaterialName(M)]"
c = min(c,t)
if (c)
if (c >= 1)
dat += "<A href='?src=\ref[src];build=[D.id];amount=1'>[D.name]</A>"
if(c >= 5.0)
if(c >= 5)
dat += "<A href='?src=\ref[src];build=[D.id];amount=5'>x5</A>"
if(c >= 10.0)
if(c >= 10)
dat += "<A href='?src=\ref[src];build=[D.id];amount=10'>x10</A>"
dat += "[temp_material]"
else
@@ -860,17 +864,17 @@ won't update every console in existence) but it's more of a hassle to do. Also,
for(var/M in D.materials)
t = linked_lathe.check_mat(D, M)
temp_material += " | "
if (!t)
if (t < 1)
temp_material += "<span class='bad'>[D.materials[M]/coeff] [CallMaterialName(M)]</span>"
else
temp_material += " [D.materials[M]/coeff] [CallMaterialName(M)]"
c = min(c,t)
if (c)
if (c >= 1)
dat += "<A href='?src=\ref[src];build=[D.id];amount=1'>[D.name]</A>"
if(c >= 5.0)
if(c >= 5)
dat += "<A href='?src=\ref[src];build=[D.id];amount=5'>x5</A>"
if(c >= 10.0)
if(c >= 10)
dat += "<A href='?src=\ref[src];build=[D.id];amount=10'>x10</A>"
dat += "[temp_material]"
else