Merge branch 'master' into crewobjectivesandmiscreants

This commit is contained in:
deathride58
2017-10-01 23:45:49 +00:00
committed by GitHub
485 changed files with 81708 additions and 13183 deletions
+7 -6
View File
@@ -20,7 +20,7 @@
admin = 1
//Whitelist
if(config.usewhitelist)
if(CONFIG_GET(flag/usewhitelist))
if(!check_whitelist(ckey(key)))
if (admin)
log_admin("The admin [key] has been allowed to bypass the whitelist")
@@ -32,19 +32,20 @@
//Guest Checking
if(IsGuestKey(key))
if (!GLOB.guests_allowed)
if (CONFIG_GET(flag/guest_ban))
log_access("Failed Login: [key] - Guests not allowed")
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
if (config.panic_bunker && SSdbcore && SSdbcore.IsConnected())
if (CONFIG_GET(flag/panic_bunker) && SSdbcore.Connect())
log_access("Failed Login: [key] - Guests not allowed during panic bunker")
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 && !admin)
var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
if(extreme_popcap && living_player_count() >= extreme_popcap && !admin)
log_access("Failed Login: [key] - Population cap reached")
return list("reason"="popcap", "desc"= "\nReason: [config.extreme_popcap_message]")
return list("reason"="popcap", "desc"= "\nReason: [CONFIG_GET(string/extreme_popcap_message)]")
if(config.ban_legacy_system)
if(CONFIG_GET(flag/ban_legacy_system))
//Ban Checking
. = CheckBan( ckey(key), computer_id, address )
+3 -2
View File
@@ -11,8 +11,9 @@ GLOBAL_PROTECT(Banlist)
. = list()
var/appeal
if(config && config.banappeals)
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[config.banappeals]'>[config.banappeals]</a>"
var/bran = CONFIG_GET(string/banappeals)
if(bran)
appeal = "\nFor more information on your ban, or to appeal, head to <a href='[bran]'>[bran]</a>"
GLOB.Banlist.cd = "/base"
if( "[ckey][id]" in GLOB.Banlist.dir )
GLOB.Banlist.cd = "[ckey][id]"
+28 -22
View File
@@ -31,7 +31,7 @@
if(M.client)
body += " played by <b>[M.client]</b> "
body += "\[<A href='?_src_=holder;[HrefToken()];editrights=rank;ckey=[M.ckey]'>[M.client.holder ? M.client.holder.rank : "Player"]</A>\]"
if(config.use_exp_tracking)
if(CONFIG_GET(flag/use_exp_tracking))
body += "\[<A href='?_src_=holder;[HrefToken()];getplaytimewindow=\ref[M]'>" + M.client.get_exp_living() + "</a>\]"
if(isnewplayer(M))
@@ -421,8 +421,8 @@
return
var/list/options = list("Regular Restart", "Hard Restart (No Delay/Feeback Reason)", "Hardest Restart (No actions, just reboot)")
if(world.RunningService())
options += "Service Restart (Force restart DD)";
if(SERVER_TOOLS_PRESENT)
options += "Server Restart (Kill and restart DD)";
var/rebootconfirm
if(SSticker.admin_delay_notice)
@@ -434,16 +434,19 @@
var/result = input(usr, "Select reboot method", "World Reboot", options[1]) as null|anything in options
if(result)
SSblackbox.add_details("admin_verb","Reboot World") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/init_by = "Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key]."
switch(result)
if("Regular Restart")
SSticker.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
SSticker.Reboot(init_by, "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", 10)
if("Hard Restart (No Delay, No Feeback Reason)")
to_chat(world, "World reboot - [init_by]")
world.Reboot()
if("Hardest Restart (No actions, just reboot)")
to_chat(world, "Hard world reboot - [init_by]")
world.Reboot(fast_track = TRUE)
if("Service Restart (Force restart DD)")
GLOB.reboot_mode = REBOOT_MODE_HARD
world.ServiceReboot()
if("Server Restart (Kill and restart DD)")
to_chat(world, "Server restart - [init_by]")
SERVER_TOOLS_REBOOT_BYOND
/datum/admins/proc/end_round()
set category = "Server"
@@ -555,28 +558,30 @@
set category = "Server"
set desc="People can't be AI"
set name="Toggle AI"
config.allow_ai = !( config.allow_ai )
if (!( config.allow_ai ))
var/alai = CONFIG_GET(flag/allow_ai)
CONFIG_SET(flag/allow_ai, !alai)
if (alai)
to_chat(world, "<B>The AI job is no longer chooseable.</B>")
else
to_chat(world, "<B>The AI job is chooseable now.</B>")
log_admin("[key_name(usr)] toggled AI allowed.")
world.update_status()
SSblackbox.add_details("admin_toggle","Toggle AI|[config.allow_ai]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
SSblackbox.add_details("admin_toggle","Toggle AI|[!alai]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/toggleaban()
set category = "Server"
set desc="Respawn basically"
set name="Toggle Respawn"
GLOB.abandon_allowed = !( GLOB.abandon_allowed )
if (GLOB.abandon_allowed)
var/new_nores = !CONFIG_GET(flag/norespawn)
CONFIG_SET(flag/norespawn, new_nores)
if (!new_nores)
to_chat(world, "<B>You may now respawn.</B>")
else
to_chat(world, "<B>You may no longer respawn :(</B>")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].</span>")
log_admin("[key_name(usr)] toggled respawn to [GLOB.abandon_allowed ? "On" : "Off"].")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled respawn to [!new_nores ? "On" : "Off"].</span>")
log_admin("[key_name(usr)] toggled respawn to [!new_nores ? "On" : "Off"].")
world.update_status()
SSblackbox.add_details("admin_toggle","Toggle Respawn|[GLOB.abandon_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
SSblackbox.add_details("admin_toggle","Toggle Respawn|[!new_nores]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/delay()
set category = "Server"
@@ -683,14 +688,15 @@
set category = "Server"
set desc="Guests can't enter"
set name="Toggle guests"
GLOB.guests_allowed = !( GLOB.guests_allowed )
if (!( GLOB.guests_allowed ))
var/new_guest_ban = !CONFIG_GET(flag/guest_ban)
CONFIG_SET(flag/guest_ban, new_guest_ban)
if (new_guest_ban)
to_chat(world, "<B>Guests may no longer enter the game.</B>")
else
to_chat(world, "<B>Guests may now enter the game.</B>")
log_admin("[key_name(usr)] toggled guests game entering [GLOB.guests_allowed?"":"dis"]allowed.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled guests game entering [GLOB.guests_allowed?"":"dis"]allowed.</span>")
SSblackbox.add_details("admin_toggle","Toggle Guests|[GLOB.guests_allowed]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled guests game entering [!new_guest_ban ? "" : "dis"]allowed.</span>")
SSblackbox.add_details("admin_toggle","Toggle Guests|[!new_guest_ban]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/output_ai_laws()
var/ai_number = 0
@@ -828,10 +834,10 @@
/client/proc/adminGreet(logout)
if(SSticker.HasRoundStarted())
var/string
if(logout && config && config.announce_admin_logout)
if(logout && CONFIG_GET(flag/announce_admin_logout))
string = pick(
"Admin logout: [key_name(src)]")
else if(!logout && config && config.announce_admin_login && (prefs.toggles & ANNOUNCE_LOGIN))
else if(!logout && CONFIG_GET(flag/announce_admin_login) && (prefs.toggles & ANNOUNCE_LOGIN))
string = pick(
"Admin login: [key_name(src)]")
if(string)
+4 -6
View File
@@ -117,7 +117,7 @@ GLOBAL_PROTECT(admin_ranks)
return
GLOB.admin_ranks.Cut()
if(config.admin_legacy_system)
if(CONFIG_GET(flag/admin_legacy_system))
var/previous_rights = 0
//load text from file and process each line separately
for(var/line in world.file2list("config/admin_ranks.txt"))
@@ -143,7 +143,7 @@ GLOBAL_PROTECT(admin_ranks)
if(!SSdbcore.Connect())
log_world("Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
WRITE_FILE(GLOB.world_game_log, "Failed to connect to database in load_admin_ranks(). Reverting to legacy system.")
config.admin_legacy_system = 1
CONFIG_SET(flag/admin_legacy_system, TRUE)
load_admin_ranks()
return
@@ -191,7 +191,7 @@ GLOBAL_PROTECT(admin_ranks)
for(var/datum/admin_rank/R in GLOB.admin_ranks)
rank_names[R.name] = R
if(config.admin_legacy_system)
if(CONFIG_GET(flag/admin_legacy_system))
//load text from file
var/list/lines = world.file2list("config/admins.txt")
@@ -214,14 +214,12 @@ GLOBAL_PROTECT(admin_ranks)
var/datum/admins/D = new(rank_names[rank], ckey) //create the admin datum and store it for later use
if(!D)
continue //will occur if an invalid rank is provided
if(D.rank.rights & R_DEBUG) //grant profile access
world.SetConfig("APP/admin", ckey, "role=admin")
D.associate(GLOB.directory[ckey]) //find the client for a ckey if they are connected and associate them with the new admin datum
else
if(!SSdbcore.Connect())
log_world("Failed to connect to database in load_admins(). Reverting to legacy system.")
WRITE_FILE(GLOB.world_game_log, "Failed to connect to database in load_admins(). Reverting to legacy system.")
config.admin_legacy_system = 1
CONFIG_SET(flag/admin_legacy_system, TRUE)
load_admins()
return
+2 -2
View File
@@ -262,7 +262,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
verbs += GLOB.admin_verbs_poll
if(rights & R_SOUNDS)
verbs += GLOB.admin_verbs_sounds
if(config.invoke_youtubedl)
if(CONFIG_GET(string/invoke_youtubedl))
verbs += /client/proc/play_web_sound
if(rights & R_SPAWN)
verbs += GLOB.admin_verbs_spawn
@@ -399,7 +399,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
set name = "Unban Panel"
set category = "Admin"
if(holder)
if(config.ban_legacy_system)
if(CONFIG_GET(flag/ban_legacy_system))
holder.unbanpanel()
else
holder.DB_ban_panel()
+62
View File
@@ -0,0 +1,62 @@
#define IRC_STATUS_THROTTLE 5
/datum/server_tools_command/ircstatus
name = "status"
help_text = "Gets the admincount, playercount, gamemode, and true game mode of the server"
admin_only = TRUE
var/static/last_irc_status = 0
/datum/server_tools_command/ircstatus/Run(sender, params)
var/rtod = REALTIMEOFDAY
if(rtod - last_irc_status < IRC_STATUS_THROTTLE)
return
last_irc_status = rtod
var/list/adm = get_admin_counts()
var/list/allmins = adm["total"]
var/status = "Admins: [allmins.len] (Active: [english_list(adm["present"])] AFK: [english_list(adm["afk"])] Stealth: [english_list(adm["stealth"])] Skipped: [english_list(adm["noflags"])]). "
status += "Players: [GLOB.clients.len] (Active: [get_active_player_count(0,1,0)]). Mode: [SSticker.mode ? SSticker.mode.name : "Not started"]."
return status
/datum/server_tools_command/irccheck
name = "check"
help_text = "Gets the playercount, gamemode, and address of the server"
var/static/last_irc_check = 0
/datum/server_tools_command/irccheck/Run(sender, params)
var/rtod = REALTIMEOFDAY
if(rtod - last_irc_check < IRC_STATUS_THROTTLE)
return
last_irc_check = rtod
var/server = CONFIG_GET(string/server)
return "[GLOB.round_id ? "Round #[GLOB.round_id]: " : ""][GLOB.clients.len] players on [SSmapping.config.map_name], Mode: [GLOB.master_mode]; Round [SSticker.HasRoundStarted() ? (SSticker.IsRoundInProgress() ? "Active" : "Finishing") : "Starting"] -- [server ? server : "[world.internet_address]:[world.port]"]"
/datum/server_tools_command/ahelp
name = "ahelp"
help_text = "<ckey> <message|ticket <close|resolve|icissue|reject|reopen <ticket #>|list>>"
required_parameters = 2
admin_only = TRUE
/datum/server_tools_command/ahelp/Run(sender, params)
var/list/all_params = splittext(params, " ")
var/target = all_params[1]
all_params.Cut(1, 2)
return IrcPm(target, all_params.Join(" "), sender)
/datum/server_tools_command/namecheck
name = "namecheck"
help_text = "Returns info on the specified target"
required_parameters = 1
admin_only = TRUE
/datum/server_tools_command/namecheck/Run(sender, params)
log_admin("IRC Name Check: [sender] on [params]")
message_admins("IRC name checking on [params] from [sender]")
return keywords_lookup(params, 1)
/datum/server_tools_command/adminwho
name = "adminwho"
help_text = "Lists administrators currently on the server"
admin_only = TRUE
/datum/server_tools_command/adminwho/Run(sender, params)
return ircadminwho()
+2
View File
@@ -34,6 +34,8 @@ GLOBAL_PROTECT(href_token)
admin_signature = "Nanotrasen Officer #[rand(0,9)][rand(0,9)][rand(0,9)]"
href_token = GenerateToken()
GLOB.admin_datums[ckey] = src
if(R.rights & R_DEBUG) //grant profile access
world.SetConfig("APP/admin", ckey, "role=admin")
/proc/GenerateToken()
. = ""
+10 -9
View File
@@ -14,18 +14,18 @@
. = FALSE
if (intel < 0)
return
if (intel <= config.ipintel_rating_bad)
if (world.realtime < cacherealtime+(config.ipintel_save_good*60*60*10))
if (intel <= CONFIG_GET(number/ipintel_rating_bad))
if (world.realtime < cacherealtime + (CONFIG_GET(number/ipintel_save_good) * 60 * 60 * 10))
return TRUE
else
if (world.realtime < cacherealtime+(config.ipintel_save_bad*60*60*10))
if (world.realtime < cacherealtime + (CONFIG_GET(number/ipintel_save_bad) * 60 * 60 * 10))
return TRUE
/proc/get_ip_intel(ip, bypasscache = FALSE, updatecache = TRUE)
var/datum/ipintel/res = new()
res.ip = ip
. = res
if (!ip || !config.ipintel_email || !SSipintel.enabled)
if (!ip || !CONFIG_GET(string/ipintel_email) || !SSipintel.enabled)
return
if (!bypasscache)
var/datum/ipintel/cachedintel = SSipintel.cache[ip]
@@ -34,19 +34,20 @@
return cachedintel
if(SSdbcore.Connect())
var/rating_bad = CONFIG_GET(number/ipintel_rating_bad)
var/datum/DBQuery/query_get_ip_intel = SSdbcore.NewQuery({"
SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW())
FROM [format_table_name("ipintel")]
WHERE
ip = INET_ATON('[ip]')
AND ((
intel < [config.ipintel_rating_bad]
intel < [rating_bad]
AND
date + INTERVAL [config.ipintel_save_good] HOUR > NOW()
date + INTERVAL [CONFIG_GET(number/ipintel_save_good)] HOUR > NOW()
) OR (
intel >= [config.ipintel_rating_bad]
intel >= [rating_bad]
AND
date + INTERVAL [config.ipintel_save_bad] HOUR > NOW()
date + INTERVAL [CONFIG_GET(number/ipintel_save_bad)] HOUR > NOW()
))
"})
if(!query_get_ip_intel.Execute())
@@ -77,7 +78,7 @@
if (!SSipintel.enabled)
return
var/list/http[] = world.Export("http://[config.ipintel_domain]/check.php?ip=[ip]&contact=[config.ipintel_email]&format=json&flags_1=f")
var/list/http[] = world.Export("http://[CONFIG_GET(string/ipintel_domain)]/check.php?ip=[ip]&contact=[CONFIG_GET(string/ipintel_email)]&format=json&flags=f")
if (http)
var/status = text2num(http["STATUS"])
@@ -51,7 +51,7 @@
usr << browse(output,"window=editrights;size=900x650")
/datum/admins/proc/log_admin_rank_modification(adm_ckey, new_rank)
if(config.admin_legacy_system)
if(CONFIG_GET(flag/admin_legacy_system))
return
if(!usr.client)
@@ -105,7 +105,7 @@
/datum/admins/proc/log_admin_permission_modification(adm_ckey, new_permission)
if(config.admin_legacy_system)
if(CONFIG_GET(flag/admin_legacy_system))
return
if(!usr.client)
return
+6 -6
View File
@@ -329,14 +329,14 @@
else
dat += "ETA: <a href='?_src_=holder;[HrefToken()];edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "<B>Continuous Round Status</B><BR>"
dat += "<a href='?_src_=holder;[HrefToken()];toggle_continuous=1'>[config.continuous[SSticker.mode.config_tag] ? "Continue if antagonists die" : "End on antagonist death"]</a>"
if(config.continuous[SSticker.mode.config_tag])
dat += ", <a href='?_src_=holder;[HrefToken()];toggle_midround_antag=1'>[config.midround_antag[SSticker.mode.config_tag] ? "creating replacement antagonists" : "not creating new antagonists"]</a><BR>"
dat += "<a href='?_src_=holder;[HrefToken()];toggle_continuous=1'>[CONFIG_GET(keyed_flag_list/continuous)[SSticker.mode.config_tag] ? "Continue if antagonists die" : "End on antagonist death"]</a>"
if(CONFIG_GET(keyed_flag_list/continuous)[SSticker.mode.config_tag])
dat += ", <a href='?_src_=holder;[HrefToken()];toggle_midround_antag=1'>[CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag] ? "creating replacement antagonists" : "not creating new antagonists"]</a><BR>"
else
dat += "<BR>"
if(config.midround_antag[SSticker.mode.config_tag])
dat += "Time limit: <a href='?_src_=holder;[HrefToken()];alter_midround_time_limit=1'>[config.midround_antag_time_check] minutes into round</a><BR>"
dat += "Living crew limit: <a href='?_src_=holder;[HrefToken()];alter_midround_life_limit=1'>[config.midround_antag_life_check * 100]% of crew alive</a><BR>"
if(CONFIG_GET(keyed_flag_list/midround_antag)[SSticker.mode.config_tag])
dat += "Time limit: <a href='?_src_=holder;[HrefToken()];alter_midround_time_limit=1'>[CONFIG_GET(number/midround_antag_time_check)] minutes into round</a><BR>"
dat += "Living crew limit: <a href='?_src_=holder;[HrefToken()];alter_midround_life_limit=1'>[CONFIG_GET(number/midround_antag_life_check) * 100]% of crew alive</a><BR>"
dat += "If limits past: <a href='?_src_=holder;[HrefToken()];toggle_noncontinuous_behavior=1'>[SSticker.mode.round_ends_with_antag_death ? "End The Round" : "Continue As Extended"]</a><BR>"
dat += "<a href='?_src_=holder;[HrefToken()];end_round=\ref[usr]'>End Round Now</a><br>"
dat += "<a href='?_src_=holder;[HrefToken()];delay_round_end=1'>[SSticker.delay_end ? "End Round Normally" : "Delay Round End"]</a>"
+1 -8
View File
@@ -354,16 +354,9 @@
SSblackbox.add_details("admin_secrets_fun_used","Bomb Cap")
var/newBombCap = input(usr,"What would you like the new bomb cap to be. (entered as the light damage range (the 3rd number in common (1,2,3) notation)) Must be above 4)", "New Bomb Cap", GLOB.MAX_EX_LIGHT_RANGE) as num|null
if (newBombCap < 4)
if (!CONFIG_SET(number/bombcap, newBombCap))
return
GLOB.MAX_EX_DEVESTATION_RANGE = round(newBombCap/4)
GLOB.MAX_EX_HEAVY_RANGE = round(newBombCap/2)
GLOB.MAX_EX_LIGHT_RANGE = newBombCap
//I don't know why these are their own variables, but fuck it, they are.
GLOB.MAX_EX_FLASH_RANGE = newBombCap
GLOB.MAX_EX_FLAME_RANGE = newBombCap
message_admins("<span class='boldannounce'>[key_name_admin(usr)] changed the bomb cap to [GLOB.MAX_EX_DEVESTATION_RANGE], [GLOB.MAX_EX_HEAVY_RANGE], [GLOB.MAX_EX_LIGHT_RANGE]</span>")
log_admin("[key_name(usr)] changed the bomb cap to [GLOB.MAX_EX_DEVESTATION_RANGE], [GLOB.MAX_EX_HEAVY_RANGE], [GLOB.MAX_EX_LIGHT_RANGE]")
+10 -6
View File
@@ -33,8 +33,9 @@
if(!timestamp)
timestamp = SQLtime()
if(!server)
if (config && config.server_sql_name)
server = config.server_sql_name
var/ssqlname = CONFIG_GET(string/serversqlname)
if (ssqlname)
server = ssqlname
server = sanitizeSQL(server)
if(isnull(secret))
switch(alert("Hide note from being viewed by players?", "Secret note?","Yes","No","Cancel"))
@@ -216,8 +217,10 @@
var/editor_ckey = query_get_messages.item[8]
var/age = text2num(query_get_messages.item[9])
var/alphatext = ""
if (agegate && type == "note" && isnum(config.note_stale_days) && isnum(config.note_fresh_days) && config.note_stale_days > config.note_fresh_days)
var/alpha = Clamp(100 - (age - config.note_fresh_days) * (85 / (config.note_stale_days - config.note_fresh_days)), 15, 100)
var/nsd = CONFIG_GET(number/note_stale_days)
var/nfd = CONFIG_GET(number/note_fresh_days)
if (agegate && type == "note" && isnum(nsd) && isnum(nfd) && nsd > nfd)
var/alpha = Clamp(100 - (age - nfd) * (85 / (nsd - nfd)), 15, 100)
if (alpha < 100)
if (alpha <= 15)
if (skipped)
@@ -353,8 +356,9 @@ proc/get_message_output(type, target_ckey)
var/notetext
notesfile >> notetext
var/server
if(config && config.server_sql_name)
server = config.server_sql_name
var/ssqlname = CONFIG_GET(string/serversqlname)
if (ssqlname)
server = ssqlname
var/regex/note = new("^(\\d{2}-\\w{3}-\\d{4}) \\| (.+) ~(\\w+)$", "i")
note.Find(notetext)
var/timestamp = note.group[1]
+26 -21
View File
@@ -5,7 +5,7 @@
return
var/msg = !auth ? "no" : "a bad"
message_admins("[key_name_admin(usr)] clicked an href with [msg] authorization key!")
if(config.debug_admin_hrefs)
if(CONFIG_GET(flag/debug_admin_hrefs))
message_admins("Debug mode enabled, call not blocked. Please ask your coders to review this round's logs.")
log_world("UAH: [href]")
return TRUE
@@ -318,35 +318,36 @@
else if(href_list["toggle_continuous"])
if(!check_rights(R_ADMIN))
return
if(!config.continuous[SSticker.mode.config_tag])
config.continuous[SSticker.mode.config_tag] = 1
var/list/continuous = CONFIG_GET(keyed_flag_list/continuous)
if(!continuous[SSticker.mode.config_tag])
continuous[SSticker.mode.config_tag] = TRUE
else
config.continuous[SSticker.mode.config_tag] = 0
continuous[SSticker.mode.config_tag] = FALSE
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled the round to [config.continuous[SSticker.mode.config_tag] ? "continue if all antagonists die" : "end with the antagonists"].</span>")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled the round to [continuous[SSticker.mode.config_tag] ? "continue if all antagonists die" : "end with the antagonists"].</span>")
check_antagonists()
else if(href_list["toggle_midround_antag"])
if(!check_rights(R_ADMIN))
return
if(!config.midround_antag[SSticker.mode.config_tag])
config.midround_antag[SSticker.mode.config_tag] = 1
var/list/midround_antag = CONFIG_GET(keyed_flag_list/midround_antag)
if(!midround_antag[SSticker.mode.config_tag])
midround_antag[SSticker.mode.config_tag] = TRUE
else
config.midround_antag[SSticker.mode.config_tag] = 0
midround_antag[SSticker.mode.config_tag] = FALSE
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled the round to [config.midround_antag[SSticker.mode.config_tag] ? "use" : "skip"] the midround antag system.</span>")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled the round to [midround_antag[SSticker.mode.config_tag] ? "use" : "skip"] the midround antag system.</span>")
check_antagonists()
else if(href_list["alter_midround_time_limit"])
if(!check_rights(R_ADMIN))
return
var/timer = input("Enter new maximum time",, config.midround_antag_time_check ) as num|null
var/timer = input("Enter new maximum time",, CONFIG_GET(number/midround_antag_time_check)) as num|null
if(!timer)
return
config.midround_antag_time_check = timer
CONFIG_SET(number/midround_antag_time_check, timer)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] edited the maximum midround antagonist time to [timer] minutes.</span>")
check_antagonists()
@@ -354,9 +355,10 @@
if(!check_rights(R_ADMIN))
return
var/ratio = input("Enter new life ratio",, config.midround_antag_life_check*100) as num
if(ratio)
config.midround_antag_life_check = ratio/100
var/ratio = input("Enter new life ratio",, CONFIG_GET(number/midround_antag_life_check) * 100) as num
if(!ratio)
return
CONFIG_SET(number/midround_antag_life_check, ratio / 100)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] edited the midround antagonist living crew ratio to [ratio]% alive.</span>")
check_antagonists()
@@ -586,8 +588,9 @@
to_chat(M, "<span class='boldannounce'><BIG>You have been appearance banned by [usr.client.ckey].</BIG></span>")
to_chat(M, "<span class='boldannounce'>The reason is: [reason]</span>")
to_chat(M, "<span class='danger'>Appearance ban can be lifted only upon request.</span>")
if(config.banappeals)
to_chat(M, "<span class='danger'>To try to resolve this matter head to [config.banappeals]</span>")
var/bran = CONFIG_GET(string/banappeals)
if(bran)
to_chat(M, "<span class='danger'>To try to resolve this matter head to [bran]</span>")
else
to_chat(M, "<span class='danger'>No ban appeals URL has been set.</span>")
if("No")
@@ -1156,8 +1159,9 @@
to_chat(M, "<span class='danger'>This is a temporary ban, it will be removed in [mins] minutes.</span>")
SSblackbox.inc("ban_tmp",1)
SSblackbox.inc("ban_tmp_mins",mins)
if(config.banappeals)
to_chat(M, "<span class='danger'>To try to resolve this matter head to [config.banappeals]</span>")
var/bran = CONFIG_GET(string/banappeals)
if(bran)
to_chat(M, "<span class='danger'>To try to resolve this matter head to [bran]</span>")
else
to_chat(M, "<span class='danger'>No ban appeals URL has been set.</span>")
log_admin_private("[key_name(usr)] has banned [M.ckey].\nReason: [key_name(M)]\nThis will be removed in [mins] minutes.")
@@ -1180,8 +1184,9 @@
AddBan(M.ckey, M.computer_id, reason, usr.ckey, 0, 0)
to_chat(M, "<span class='boldannounce'><BIG>You have been banned by [usr.client.ckey].\nReason: [reason]</BIG></span>")
to_chat(M, "<span class='danger'>This is a permanent ban.</span>")
if(config.banappeals)
to_chat(M, "<span class='danger'>To try to resolve this matter head to [config.banappeals]</span>")
var/bran = CONFIG_GET(string/banappeals)
if(bran)
to_chat(M, "<span class='danger'>To try to resolve this matter head to [bran]</span>")
else
to_chat(M, "<span class='danger'>No ban appeals URL has been set.</span>")
if(!DB_ban_record(BANTYPE_PERMA, M, -1, reason))
+7 -8
View File
@@ -587,21 +587,20 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
/proc/send2irc(msg,msg2)
if(world.RunningService())
world.ExportService("[SERVICE_REQUEST_IRC_ADMIN_CHANNEL_MESSAGE] [msg] | [msg2]")
else if(config.useircbot)
shell("python nudge.py [msg] [msg2]")
if(SERVER_TOOLS_PRESENT)
SERVER_TOOLS_RELAY_BROADCAST("[msg] | [msg2]")
/proc/send2otherserver(source,msg,type = "Ahelp")
if(config.cross_allowed)
var/comms_key = CONFIG_GET(string/comms_key)
if(comms_key)
var/list/message = list()
message["message_sender"] = source
message["message"] = msg
message["source"] = "([config.cross_name])"
message["key"] = global.comms_key
message["source"] = "([CONFIG_GET(string/cross_comms_name)])"
message["key"] = comms_key
message["crossmessage"] = type
world.Export("[config.cross_address]?[list2params(message)]")
world.Export("[CONFIG_GET(string/cross_server_address)]?[list2params(message)]")
/proc/ircadminwho()
+2 -2
View File
@@ -185,7 +185,7 @@
SEND_SOUND(recipient, sound('sound/effects/adminhelp.ogg'))
//AdminPM popup for ApocStation and anybody else who wants to use it. Set it with POPUP_ADMIN_PM in config.txt ~Carn
if(config.popup_admin_pm)
if(CONFIG_GET(flag/popup_admin_pm))
spawn() //so we don't hold the caller proc up
var/sender = src
var/sendername = key
@@ -277,7 +277,7 @@
return "Error: Ticket could not be found"
var/static/stealthkey
var/adminname = config.showircname ? irc_tagged : "Administrator"
var/adminname = CONFIG_GET(flag/show_irc_name) ? irc_tagged : "Administrator"
if(!C)
return "Error: No client"
+11 -18
View File
@@ -1,18 +1,11 @@
/client/proc/cinematic(cinematic as anything in list("explosion",null))
set name = "cinematic"
set category = "Fun"
set desc = "Shows a cinematic." // Intended for testing but I thought it might be nice for events on the rare occasion Feel free to comment it out if it's not wanted.
set hidden = 1
if(!SSticker)
return
switch(cinematic)
if("explosion")
var/parameter = input(src,"station_missed = ?","Enter Parameter",0) as num
var/override
switch(parameter)
if(1)
override = input(src,"mode = ?","Enter Parameter",null) as anything in list("nuclear emergency","gang war","fake","no override")
if(0)
override = input(src,"mode = ?","Enter Parameter",null) as anything in list("blob","nuclear emergency","AI malfunction","no override")
SSticker.station_explosion_cinematic(parameter,override)
return
/client/proc/cinematic()
set name = "cinematic"
set category = "Fun"
set desc = "Shows a cinematic." // Intended for testing but I thought it might be nice for events on the rare occasion Feel free to comment it out if it's not wanted.
set hidden = 1
if(!SSticker)
return
var/datum/cinematic/choice = input(src,"Cinematic","Choose",null) as anything in subtypesof(/datum/cinematic)
if(choice)
Cinematic(initial(choice.id),world,null)
+13 -4
View File
@@ -96,10 +96,16 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
to_chat(usr, .)
SSblackbox.add_details("admin_verb","Advanced ProcCall") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
GLOBAL_VAR_INIT(AdminProcCaller, null)
GLOBAL_VAR(AdminProcCaller)
GLOBAL_PROTECT(AdminProcCaller)
GLOBAL_VAR_INIT(AdminProcCallCount, 0)
GLOBAL_PROTECT(AdminProcCallCount)
GLOBAL_VAR(LastAdminCalledTargetRef)
GLOBAL_PROTECT(LastAdminCalledTargetRef)
GLOBAL_VAR(LastAdminCalledTarget)
GLOBAL_PROTECT(LastAdminCalledTarget)
GLOBAL_VAR(LastAdminCalledProc)
GLOBAL_PROTECT(LastAdminCalledProc)
/proc/WrapAdminProcCall(target, procname, list/arguments)
var/current_caller = GLOB.AdminProcCaller
@@ -108,6 +114,9 @@ GLOBAL_PROTECT(AdminProcCallCount)
to_chat(usr, "<span class='adminnotice'>Another set of admin called procs are still running, your proc will be run after theirs finish.</span>")
UNTIL(!GLOB.AdminProcCaller)
to_chat(usr, "<span class='adminnotice'>Running your proc</span>")
GLOB.LastAdminCalledProc = procname
if(target != GLOBAL_PROC)
GLOB.LastAdminCalledTargetRef = "\ref[target]"
GLOB.AdminProcCaller = ckey //if this runtimes, too bad for you
++GLOB.AdminProcCallCount
. = world.WrapAdminProcCall(target, procname, arguments)
@@ -836,11 +845,11 @@ GLOBAL_PROTECT(AdminProcCallCount)
if(!holder)
return
global.medals_enabled = !global.medals_enabled
GLOB.medals_enabled = !GLOB.medals_enabled
message_admins("<span class='adminnotice'>[key_name_admin(src)] [global.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.</span>")
message_admins("<span class='adminnotice'>[key_name_admin(src)] [GLOB.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.</span>")
SSblackbox.add_details("admin_verb","Toggle Medal Disable") // If...
log_admin("[key_name(src)] [global.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.")
log_admin("[key_name(src)] [GLOB.medals_enabled ? "disabled" : "enabled"] the medal hub lockout.")
/client/proc/view_runtimes()
set category = "Debug"
+5 -3
View File
@@ -7,13 +7,14 @@
if(!check_rights(R_DEBUG))
return
var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [config.fps])","FPS", world.fps) as num|null)
var/cfg_fps = CONFIG_GET(number/fps)
var/new_fps = round(input("Sets game frames-per-second. Can potentially break the game (default: [cfg_fps])","FPS", world.fps) as num|null)
if(new_fps <= 0)
to_chat(src, "<span class='danger'>Error: set_server_fps(): Invalid world.fps value. No changes made.</span>")
return
if(new_fps > config.fps*1.5)
if(alert(src, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [config.fps]","Warning!","Confirm","ABORT-ABORT-ABORT") != "Confirm")
if(new_fps > cfg_fps * 1.5)
if(alert(src, "You are setting fps to a high value:\n\t[new_fps] frames-per-second\n\tconfig.fps = [cfg_fps]","Warning!","Confirm","ABORT-ABORT-ABORT") != "Confirm")
return
var/msg = "[key_name(src)] has modified world.fps to [new_fps]"
@@ -21,4 +22,5 @@
message_admins(msg, 0)
SSblackbox.add_details("admin_toggle","Set Server FPS|[new_fps]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
CONFIG_SET(number/fps, new_fps)
world.fps = new_fps
+13 -13
View File
@@ -31,10 +31,10 @@
/datum/admins/proc/makeTraitors()
var/datum/game_mode/traitor/temp = new
if(config.protect_roles_from_antagonist)
if(CONFIG_GET(flag/protect_roles_from_antagonist))
temp.restricted_jobs += temp.protected_jobs
if(config.protect_assistant_from_antagonist)
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
temp.restricted_jobs += "Assistant"
var/list/mob/living/carbon/human/candidates = list()
@@ -67,10 +67,10 @@
/datum/admins/proc/makeChanglings()
var/datum/game_mode/changeling/temp = new
if(config.protect_roles_from_antagonist)
if(CONFIG_GET(flag/protect_roles_from_antagonist))
temp.restricted_jobs += temp.protected_jobs
if(config.protect_assistant_from_antagonist)
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
temp.restricted_jobs += "Assistant"
var/list/mob/living/carbon/human/candidates = list()
@@ -100,10 +100,10 @@
/datum/admins/proc/makeRevs()
var/datum/game_mode/revolution/temp = new
if(config.protect_roles_from_antagonist)
if(CONFIG_GET(flag/protect_roles_from_antagonist))
temp.restricted_jobs += temp.protected_jobs
if(config.protect_assistant_from_antagonist)
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
temp.restricted_jobs += "Assistant"
var/list/mob/living/carbon/human/candidates = list()
@@ -142,10 +142,10 @@
/datum/admins/proc/makeCult()
var/datum/game_mode/cult/temp = new
if(config.protect_roles_from_antagonist)
if(CONFIG_GET(flag/protect_roles_from_antagonist))
temp.restricted_jobs += temp.protected_jobs
if(config.protect_assistant_from_antagonist)
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
temp.restricted_jobs += "Assistant"
var/list/mob/living/carbon/human/candidates = list()
@@ -175,10 +175,10 @@
/datum/admins/proc/makeClockCult()
var/datum/game_mode/clockwork_cult/temp = new
if(config.protect_roles_from_antagonist)
if(CONFIG_GET(flag/protect_roles_from_antagonist))
temp.restricted_jobs += temp.protected_jobs
if(config.protect_assistant_from_antagonist)
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
temp.restricted_jobs += "Assistant"
var/list/mob/living/carbon/human/candidates = list()
@@ -340,7 +340,7 @@
missiondesc += "<BR><B>Your Mission</B>: [mission]"
to_chat(Commando, missiondesc)
if(config.enforce_human_authority)
if(CONFIG_GET(flag/enforce_human_authority))
Commando.set_species(/datum/species/human)
//Logging and cleanup
@@ -382,7 +382,7 @@
missionobj.completed = 1
newmob.mind.objectives += missionobj
if(config.enforce_human_authority)
if(CONFIG_GET(flag/enforce_human_authority))
newmob.set_species(/datum/species/human)
//Greet the official
@@ -497,7 +497,7 @@
missiondesc += "<BR><B>Your Mission</B>: [mission]"
to_chat(ERTOperative, missiondesc)
if(config.enforce_human_authority)
if(CONFIG_GET(flag/enforce_human_authority))
ERTOperative.set_species(/datum/species/human)
//Logging and cleanup
+7 -6
View File
@@ -1,15 +1,16 @@
/client/proc/panicbunker()
set category = "Server"
set name = "Toggle Panic Bunker"
if (!config.sql_enabled)
if (!CONFIG_GET(flag/sql_enabled))
to_chat(usr, "<span class='adminnotice'>The Database is not enabled!</span>")
return
config.panic_bunker = (!config.panic_bunker)
var/new_pb = !CONFIG_GET(flag/panic_bunker)
CONFIG_SET(flag/panic_bunker, new_pb)
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 && (!SSdbcore || !SSdbcore.IsConnected()))
log_admin("[key_name(usr)] has toggled the Panic Bunker, it is now [new_pb ? "on" : "off"]")
message_admins("[key_name_admin(usr)] has toggled the Panic Bunker, it is now [new_pb ? "enabled" : "disabled"].")
if (new_pb && !SSdbcore.Connect())
message_admins("The Database is not connected! Panic bunker will not work until the connection is reestablished.")
SSblackbox.add_details("admin_toggle","Toggle Panic Bunker|[config.panic_bunker]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
SSblackbox.add_details("admin_toggle","Toggle Panic Bunker|[new_pb]") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
+4 -2
View File
@@ -62,7 +62,8 @@
if(!check_rights(R_SOUNDS))
return
if(!config.invoke_youtubedl)
var/ytdl = CONFIG_GET(string/invoke_youtubedl)
if(!ytdl)
to_chat(src, "<span class='boldwarning'>Youtube-dl was not configured, action unavailable</span>") //Check config.txt for the INVOKE_YOUTUBEDL value
return
@@ -79,7 +80,7 @@
to_chat(src, "<span class='warning'>For youtube-dl shortcuts like ytsearch: please use the appropriate full url from the website.</span>")
return
var/shell_scrubbed_input = shell_url_scrub(web_sound_input)
var/list/output = world.shelleo("[config.invoke_youtubedl] --format \"bestaudio\[ext=mp3]/best\[ext=mp4]\[height<=360]/bestaudio\[ext=m4a]/bestaudio\[ext=aac]\" --get-url \"[shell_scrubbed_input]\"")
var/list/output = world.shelleo("[ytdl] --format \"bestaudio\[ext=mp3]/best\[ext=mp4]\[height<=360]/bestaudio\[ext=m4a]/bestaudio\[ext=aac]\" --get-url \"[shell_scrubbed_input]\"")
var/errorlevel = output[SHELLEO_ERRORLEVEL]
var/stdout = output[SHELLEO_STDOUT]
var/stderr = output[SHELLEO_STDERR]
@@ -92,6 +93,7 @@
pitch = pick(0.5, 0.7, 0.8, 0.85, 0.9, 0.95, 1.1, 1.2, 1.4, 1.6, 2.0, 2.5)
to_chat(src, "You feel the Honkmother messing with your song...")
SSblackbox.add_details("played_url", web_sound_input)
log_admin("[key_name(src)] played web sound: [web_sound_input]")
message_admins("[key_name(src)] played web sound: [web_sound_input]")
else
+1 -1
View File
@@ -2,7 +2,7 @@
set name = "Possess Obj"
set category = "Object"
if(O.dangerous_possession && config.forbid_singulo_possession)
if(O.dangerous_possession && CONFIG_GET(flag/forbid_singulo_possession))
to_chat(usr, "[O] is too powerful for you to possess.")
return
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,7 @@
/client/proc/reestablish_db_connection()
set category = "Special Verbs"
set name = "Reestablish DB Connection"
if (!config.sql_enabled)
if (!CONFIG_GET(flag/sql_enabled))
to_chat(usr, "<span class='adminnotice'>The Database is not enabled!</span>")
return
@@ -34,6 +34,11 @@ Pipelines + Other Objects -> Pipe network
var/device_type = 0
var/list/obj/machinery/atmospherics/nodes
/obj/machinery/atmospherics/examine(mob/living/user)
..()
if(is_type_in_list(src, GLOB.ventcrawl_machinery) && user.ventcrawler)
to_chat(user, "<span class='notice'>Alt-click to crawl through it.</span>")
/obj/machinery/atmospherics/New(loc, process = TRUE)
nodes = new(device_type)
if (!armor)
@@ -300,4 +305,3 @@ Pipelines + Other Objects -> Pipe network
//Used for certain children of obj/machinery/atmospherics to not show pipe vision when mob is inside it.
/obj/machinery/atmospherics/proc/can_see_pipes()
return TRUE
@@ -320,7 +320,7 @@
for(var/atm in A)
if(!is_type_in_typecache(atm, ctf_object_typecache))
qdel(atm)
if(istype(atm, /obj/structure))
if(isstructure(atm))
var/obj/structure/S = atm
S.obj_integrity = S.max_integrity
+1 -1
View File
@@ -80,7 +80,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
if(!GLOB.the_gateway)
GLOB.the_gateway = src
update_icon()
wait = world.time + config.gateway_delay //+ thirty minutes default
wait = world.time + CONFIG_GET(number/gateway_delay) //+ thirty minutes default
awaygate = locate(/obj/machinery/gateway/centeraway)
/obj/machinery/gateway/centerstation/Destroy()
+42 -37
View File
@@ -42,7 +42,8 @@
to_chat(src, "<span class='danger'>An error has been detected in how your client is receiving resources. Attempting to correct.... (If you keep seeing these messages you might want to close byond and reconnect)</span>")
src << browse("...", "window=asset_cache_browser")
if (!holder && config.minutetopiclimit)
var/mtl = CONFIG_GET(number/minute_topic_limit)
if (!holder && mtl)
var/minute = round(world.time, 600)
if (!topiclimiter)
topiclimiter = new(LIMITER_SIZE)
@@ -50,17 +51,18 @@
topiclimiter[CURRENT_MINUTE] = minute
topiclimiter[MINUTE_COUNT] = 0
topiclimiter[MINUTE_COUNT] += 1
if (topiclimiter[MINUTE_COUNT] > config.minutetopiclimit)
if (topiclimiter[MINUTE_COUNT] > mtl)
var/msg = "Your previous action was ignored because you've done too many in a minute."
if (minute != topiclimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
topiclimiter[ADMINSWARNED_AT] = minute
msg += " Administrators have been informed."
log_game("[key_name(src)] Has hit the per-minute topic limit of [config.minutetopiclimit] topic calls in a given game minute")
message_admins("[key_name_admin(src)] [ADMIN_FLW(usr)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [config.minutetopiclimit] topic calls in a given game minute")
log_game("[key_name(src)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
message_admins("[key_name_admin(src)] [ADMIN_FLW(usr)] [ADMIN_KICK(usr)] Has hit the per-minute topic limit of [mtl] topic calls in a given game minute")
to_chat(src, "<span class='danger'>[msg]</span>")
return
if (!holder && config.secondtopiclimit)
var/stl = CONFIG_GET(number/second_topic_limit)
if (!holder && stl)
var/second = round(world.time, 10)
if (!topiclimiter)
topiclimiter = new(LIMITER_SIZE)
@@ -68,7 +70,7 @@
topiclimiter[CURRENT_SECOND] = second
topiclimiter[SECOND_COUNT] = 0
topiclimiter[SECOND_COUNT] += 1
if (topiclimiter[SECOND_COUNT] > config.secondtopiclimit)
if (topiclimiter[SECOND_COUNT] > stl)
to_chat(src, "<span class='danger'>Your previous action was ignored because you've done too many in a second</span>")
return
@@ -110,7 +112,7 @@
return 1
/client/proc/handle_spam_prevention(message, mute_type)
if(config.automute_on && !holder && src.last_message == message)
if(CONFIG_GET(flag/automute_on) && !holder && last_message == message)
src.last_message_count++
if(src.last_message_count >= SPAM_TRIGGER_AUTOMUTE)
to_chat(src, "<span class='danger'>You have exceeded the spam filter limit for identical messages. An auto-mute was applied.</span>")
@@ -174,11 +176,11 @@ GLOBAL_LIST(external_rsc_urls)
if(localhost_rank)
var/datum/admins/localhost_holder = new(localhost_rank, ckey)
localhost_holder.associate(src)
if(config.autoadmin)
if(CONFIG_GET(flag/autoadmin))
if(!GLOB.admin_datums[ckey])
var/datum/admin_rank/autorank
for(var/datum/admin_rank/R in GLOB.admin_ranks)
if(R.name == config.autoadmin_rank)
if(R.name == CONFIG_GET(string/autoadmin_rank))
autorank = R
break
if(!autorank)
@@ -206,7 +208,7 @@ GLOBAL_LIST(external_rsc_urls)
log_access("Login: [key_name(src)] from [address ? address : "localhost"]-[computer_id] || BYOND v[byond_version]")
var/alert_mob_dupe_login = FALSE
if(config.log_access)
if(CONFIG_GET(flag/log_access))
for(var/I in GLOB.clients)
if(!I || I == src)
continue
@@ -240,30 +242,32 @@ GLOBAL_LIST(external_rsc_urls)
connection_realtime = world.realtime
connection_timeofday = world.timeofday
winset(src, null, "command=\".configure graphics-hwmode on\"")
if (byond_version < config.client_error_version) //Out of date client.
var/cev = CONFIG_GET(number/client_error_version)
var/cwv = CONFIG_GET(number/client_warn_version)
if (byond_version < cev) //Out of date client.
to_chat(src, "<span class='danger'><b>Your version of byond is too old:</b></span>")
to_chat(src, config.client_error_message)
to_chat(src, CONFIG_GET(string/client_error_message))
to_chat(src, "Your version: [byond_version]")
to_chat(src, "Required version: [config.client_error_version] or later")
to_chat(src, "Required version: [cev] or later")
to_chat(src, "Visit http://www.byond.com/download/ to get the latest version of byond.")
if (holder)
to_chat(src, "Because you are an admin, you are being allowed to walk past this limitation, But it is still STRONGLY suggested you upgrade")
else
qdel(src)
return 0
else if (byond_version < config.client_warn_version) //We have words for this client.
else if (byond_version < cwv) //We have words for this client.
to_chat(src, "<span class='danger'><b>Your version of byond may be getting out of date:</b></span>")
to_chat(src, config.client_warn_message)
to_chat(src, CONFIG_GET(string/client_warn_message))
to_chat(src, "Your version: [byond_version]")
to_chat(src, "Required version to remove this message: [config.client_warn_version] or later")
to_chat(src, "Required version to remove this message: [cwv] or later")
to_chat(src, "Visit http://www.byond.com/download/ to get the latest version of byond.")
if (connection == "web" && !holder)
if (!config.allowwebclient)
if (!CONFIG_GET(flag/allow_webclient))
to_chat(src, "Web client is disabled")
qdel(src)
return 0
if (config.webclientmembersonly && !IsByondMember())
if (CONFIG_GET(flag/webclient_only_byond_members) && !IsByondMember())
to_chat(src, "Sorry, but the web client is restricted to byond members only.")
qdel(src)
return 0
@@ -276,25 +280,24 @@ GLOBAL_LIST(external_rsc_urls)
add_admin_verbs()
to_chat(src, get_message_output("memo"))
adminGreet()
if((global.comms_key == "default_pwd" || length(global.comms_key) <= 6) && global.comms_allowed) //It's the default value or less than 6 characters long, but it somehow didn't disable comms.
to_chat(src, "<span class='danger'>The server's API key is either too short or is the default value! Consider changing it immediately!</span>")
add_verbs_from_config()
var/cached_player_age = set_client_age_from_db(tdata) //we have to cache this because other shit may change it and we need it's current value now down below.
if (isnum(cached_player_age) && cached_player_age == -1) //first connection
player_age = 0
var/nnpa = CONFIG_GET(number/notify_new_player_age)
if (isnum(cached_player_age) && cached_player_age == -1) //first connection
if (config.notify_new_player_age >= 0)
if (nnpa >= 0)
message_admins("New user: [key_name_admin(src)] is connecting here for the first time.")
if (config.irc_first_connection_alert)
if (CONFIG_GET(flag/irc_first_connection_alert))
send2irc_adminless_only("New-user", "[key_name(src)] is connecting for the first time!")
else if (isnum(cached_player_age) && cached_player_age < config.notify_new_player_age)
else if (isnum(cached_player_age) && cached_player_age < nnpa)
message_admins("New user: [key_name_admin(src)] just connected with an age of [cached_player_age] day[(player_age==1?"":"s")]")
if(config.use_account_age_for_jobs && account_age >= 0)
if(CONFIG_GET(flag/use_account_age_for_jobs) && account_age >= 0)
player_age = account_age
if(account_age >= 0 && account_age < config.notify_new_player_account_age)
if(account_age >= 0 && account_age < nnpa)
message_admins("[key_name_admin(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].")
if (config.irc_first_connection_alert)
if (CONFIG_GET(flag/irc_first_connection_alert))
send2irc_adminless_only("new_byond_user", "[key_name(src)] (IP: [address], ID: [computer_id]) is a new BYOND account [account_age] day[(account_age==1?"":"s")] old, created on [account_join_date].")
get_message_output("watchlist entry", ckey)
check_ip_intel()
@@ -306,7 +309,7 @@ GLOBAL_LIST(external_rsc_urls)
if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates.
to_chat(src, "<span class='info'>You have unread updates in the changelog.</span>")
if(config.aggressive_changelog)
if(CONFIG_GET(flag/aggressive_changelog))
changelog()
else
winset(src, "infowindow.changelog", "font-style=bold")
@@ -316,7 +319,7 @@ GLOBAL_LIST(external_rsc_urls)
to_chat(src, message)
GLOB.clientmessages.Remove(ckey)
if(config && config.autoconvert_notes)
if(CONFIG_GET(flag/autoconvert_notes))
convert_notes_sql(ckey)
to_chat(src, get_message_output("message", ckey))
if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them.
@@ -432,15 +435,17 @@ GLOBAL_LIST(external_rsc_urls)
if(!query_client_in_db.Execute())
return
if(!query_client_in_db.NextRow())
if (config.panic_bunker && !holder && !(ckey in GLOB.deadmins))
if (CONFIG_GET(flag/panic_bunker) && !holder && !(ckey in GLOB.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>")
to_chat(src, "Sorry but the server is currently not accepting connections from never before seen players.")
var/list/connectiontopic_a = params2list(connectiontopic)
if(config.panic_address && !connectiontopic_a["redirect"])
to_chat(src, "<span class='notice'>Sending you to [config.panic_server_name ? config.panic_server_name : config.panic_address].</span>")
var/list/panic_addr = CONFIG_GET(string/panic_address)
if(panic_addr && !connectiontopic_a["redirect"])
var/panic_name = CONFIG_GET(string/panic_server_name)
to_chat(src, "<span class='notice'>Sending you to [panic_name ? panic_name : panic_addr].</span>")
winset(src, null, "command=.options")
src << link("[config.panic_address]?redirect=1")
src << link("[panic_addr]?redirect=1")
qdel(src)
return
@@ -501,7 +506,7 @@ GLOBAL_LIST(external_rsc_urls)
if (connection != "seeker")
return
topic = params2list(topic)
if (!config.check_randomizer)
if (!CONFIG_GET(flag/check_randomizer))
return
var/static/cidcheck = list()
var/static/tokens = list()
@@ -594,15 +599,15 @@ GLOBAL_LIST(external_rsc_urls)
/client/proc/check_ip_intel()
set waitfor = 0 //we sleep when getting the intel, no need to hold up the client connection while we sleep
if (config.ipintel_email)
if (CONFIG_GET(string/ipintel_email))
var/datum/ipintel/res = get_ip_intel(address)
if (res.intel >= config.ipintel_rating_bad)
if (res.intel >= CONFIG_GET(number/ipintel_rating_bad))
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.</span>")
ip_intel = res.intel
/client/proc/add_verbs_from_config()
if(config.see_own_notes)
if(CONFIG_GET(flag/see_own_notes))
verbs += /client/proc/self_notes
@@ -612,7 +617,7 @@ GLOBAL_LIST(external_rsc_urls)
//checks if a client is afk
//3000 frames = 5 minutes
/client/proc/is_afk(duration = config.inactivity_period)
/client/proc/is_afk(duration = CONFIG_GET(number/inactivity_period))
if(inactivity > duration)
return inactivity
return FALSE
+173 -11
View File
@@ -46,7 +46,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/preferred_map = null
var/uses_glasses_colour = 0
var/screenshake = 100
var/damagescreenshake = 2
@@ -277,6 +277,168 @@ GLOBAL_LIST_EMPTY(preferences_datums)
// dat += "<b>Size:</b> <a href='?_src_=prefs;preference=character_size;task=input'>[character_size]</a><BR>"
dat += "<br>"
dat += "<h2>Body</h2>"
dat += "<a href='?_src_=prefs;preference=all;task=random'>Random Body</A> "
dat += "<a href='?_src_=prefs;preference=all'>Always Random Body: [be_random_body ? "Yes" : "No"]</A><br>"
dat += "<table width='100%'><tr><td width='24%' valign='top'>"
if(CONFIG_GET(flag/join_with_mutant_race))
dat += "<b>Species:</b><BR><a href='?_src_=prefs;preference=species;task=input'>[pref_species.name]</a><BR>"
else
dat += "<b>Species:</b> Human<BR>"
dat += "<b>Underwear:</b><BR><a href ='?_src_=prefs;preference=underwear;task=input'>[underwear]</a><BR>"
dat += "<b>Undershirt:</b><BR><a href ='?_src_=prefs;preference=undershirt;task=input'>[undershirt]</a><BR>"
dat += "<b>Socks:</b><BR><a href ='?_src_=prefs;preference=socks;task=input'>[socks]</a><BR>"
dat += "<b>Backpack:</b><BR><a href ='?_src_=prefs;preference=bag;task=input'>[backbag]</a><BR>"
dat += "<b>Uplink Spawn Location:</b><BR><a href ='?_src_=prefs;preference=uplink_loc;task=input'>[uplink_spawn_loc]</a><BR></td>"
if(pref_species.use_skintones)
dat += "<td valign='top' width='21%'>"
dat += "<h3>Skin Tone</h3>"
dat += "<a href='?_src_=prefs;preference=s_tone;task=input'>[skin_tone]</a><BR>"
dat += "</td>"
if(HAIR in pref_species.species_traits)
dat += "<td valign='top' width='21%'>"
dat += "<h3>Hair Style</h3>"
dat += "<a href='?_src_=prefs;preference=hair_style;task=input'>[hair_style]</a><BR>"
dat += "<a href='?_src_=prefs;preference=previous_hair_style;task=input'>&lt;</a> <a href='?_src_=prefs;preference=next_hair_style;task=input'>&gt;</a><BR>"
dat += "<span style='border:1px solid #161616; background-color: #[hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=hair;task=input'>Change</a><BR>"
dat += "</td><td valign='top' width='21%'>"
dat += "<h3>Facial Hair Style</h3>"
dat += "<a href='?_src_=prefs;preference=facial_hair_style;task=input'>[facial_hair_style]</a><BR>"
dat += "<a href='?_src_=prefs;preference=previous_facehair_style;task=input'>&lt;</a> <a href='?_src_=prefs;preference=next_facehair_style;task=input'>&gt;</a><BR>"
dat += "<span style='border: 1px solid #161616; background-color: #[facial_hair_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=facial;task=input'>Change</a><BR>"
dat += "</td>"
if(EYECOLOR in pref_species.species_traits)
dat += "<td valign='top' width='21%'>"
dat += "<h3>Eye Color</h3>"
dat += "<span style='border: 1px solid #161616; background-color: #[eye_color];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=eyes;task=input'>Change</a><BR>"
dat += "</td>"
if(CONFIG_GET(flag/join_with_mutant_race)) //We don't allow mutant bodyparts for humans either unless this is true.
if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits))
dat += "<td valign='top' width='14%'>"
dat += "<h3>Mutant Color</h3>"
dat += "<span style='border: 1px solid #161616; background-color: #[features["mcolor"]];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=mutant_color;task=input'>Change</a><BR>"
dat += "</td>"
if("tail_lizard" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Tail</h3>"
dat += "<a href='?_src_=prefs;preference=tail_lizard;task=input'>[features["tail_lizard"]]</a><BR>"
dat += "</td>"
if("snout" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Snout</h3>"
dat += "<a href='?_src_=prefs;preference=snout;task=input'>[features["snout"]]</a><BR>"
dat += "</td>"
if("horns" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Horns</h3>"
dat += "<a href='?_src_=prefs;preference=horns;task=input'>[features["horns"]]</a><BR>"
dat += "</td>"
if("frills" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Frills</h3>"
dat += "<a href='?_src_=prefs;preference=frills;task=input'>[features["frills"]]</a><BR>"
dat += "</td>"
if("spines" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Spines</h3>"
dat += "<a href='?_src_=prefs;preference=spines;task=input'>[features["spines"]]</a><BR>"
dat += "</td>"
if("body_markings" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Body Markings</h3>"
dat += "<a href='?_src_=prefs;preference=body_markings;task=input'>[features["body_markings"]]</a><BR>"
dat += "</td>"
if("legs" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Legs</h3>"
dat += "<a href='?_src_=prefs;preference=legs;task=input'>[features["legs"]]</a><BR>"
dat += "</td>"
if(CONFIG_GET(flag/join_with_mutant_humans))
if("tail_human" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Tail</h3>"
dat += "<a href='?_src_=prefs;preference=tail_human;task=input'>[features["tail_human"]]</a><BR>"
dat += "</td>"
if("ears" in pref_species.mutant_bodyparts)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Ears</h3>"
dat += "<a href='?_src_=prefs;preference=ears;task=input'>[features["ears"]]</a><BR>"
dat += "</td>"
if("wings" in pref_species.mutant_bodyparts && GLOB.r_wings_list.len >1)
dat += "<td valign='top' width='7%'>"
dat += "<h3>Wings</h3>"
dat += "<a href='?_src_=prefs;preference=wings;task=input'>[features["wings"]]</a><BR>"
dat += "</td>"
dat += "</tr></table>"
if (1) // Game Preferences
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>General Settings</h2>"
@@ -295,7 +457,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Ghost pda:</b> <a href='?_src_=prefs;preference=ghost_pda'>[(chat_toggles & CHAT_GHOSTPDA) ? "All Messages" : "Nearest Creatures"]</a><br>"
dat += "<b>Pull requests:</b> <a href='?_src_=prefs;preference=pull_requests'>[(chat_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)
if(CONFIG_GET(flag/allow_metadata))
dat += "<b>OOC Notes:</b> <a href='?_src_=prefs;preference=metadata;task=input'>Edit </a><br>"
if(user.client)
@@ -332,7 +494,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Ghosts of Others:</b> <a href='?_src_=prefs;task=input;preference=ghostothers'>[button_name]</a><br>"
if (config.maprotation)
if (CONFIG_GET(flag/maprotation))
var/p_map = preferred_map
if (!p_map)
p_map = "Default"
@@ -347,7 +509,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
p_map = VM.map_name
else
p_map += " (No longer exists)"
if(config.allow_map_voting)
if(CONFIG_GET(flag/allow_map_voting))
dat += "<b>Preferred Map:</b> <a href='?_src_=prefs;preference=preferred_map;task=input'>[p_map]</a><br>"
dat += "<b>FPS:</b> <a href='?_src_=prefs;preference=clientfps;task=input'>[clientfps]</a><br>"
@@ -385,7 +547,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<b>Be [capitalize(i)]:</b> <a href='?_src_=prefs;jobbancheck=[i]'>BANNED</a><br>"
else
var/days_remaining = null
if(config.use_age_restriction_for_jobs && ispath(GLOB.special_roles[i])) //If it's a game mode antag, check if the player meets the minimum age
if(ispath(GLOB.special_roles[i]) && CONFIG_GET(flag/use_age_restriction_for_jobs)) //If it's a game mode antag, check if the player meets the minimum age
var/mode_path = GLOB.special_roles[i]
var/datum/game_mode/temp_mode = new mode_path
days_remaining = temp_mode.get_remaining_days(user.client)
@@ -409,7 +571,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "[features["flavor_text"]]"
else
dat += "[TextPreview(features["flavor_text"])]...<BR>"
if(config.mutant_races)//really don't need this check, but fuck un-tabbing all those lines
if(CONFIG_GET(flag/join_with_mutant_race))//really don't need this check, but fuck un-tabbing all those lines
dat += "<h2>Body</h2>"
dat += "<b>Gender:</b> <a href='?_src_=prefs;preference=gender'>[gender == MALE ? "Male" : "Female"]</a><BR>"
dat += "<b>Species:</b><a href='?_src_=prefs;preference=species;task=input'>[pref_species.id]</a><BR>"
@@ -599,7 +761,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if((job_civilian_low & ASSISTANT) && (rank != "Assistant") && !jobban_isbanned(user, "Assistant"))
HTML += "<font color=orange>[rank]</font></td><td></td></tr>"
continue
if(config.enforce_human_authority && !user.client.prefs.pref_species.qualifies_for_rank(rank, user.client.prefs.features))
if(CONFIG_GET(flag/enforce_human_authority) && !user.client.prefs.pref_species.qualifies_for_rank(rank, user.client.prefs.features))
if(user.client.prefs.pref_species.id == "human")
HTML += "<font color=red>[rank]</font></td><td><font color=red><b> \[MUTANT\]</b></font></td></tr>"
else
@@ -1023,10 +1185,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("species")
var/result = input(user, "Select a species", "Species Selection") as null|anything in GLOB.roundstart_species
var/result = input(user, "Select a species", "Species Selection") as null|anything in CONFIG_GET(keyed_flag_list/roundstart_races)
if(result)
var/newtype = GLOB.roundstart_species[result]
var/newtype = GLOB.species_list[result]
pref_species = new newtype()
//Now that we changed our species, we must verify that the mutant colour is still allowed.
var/temp_hsv = RGBtoHSV(features["mcolor"])
@@ -1622,7 +1784,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(be_random_body)
random_character(gender)
if(config.humans_need_surnames)
if(CONFIG_GET(flag/humans_need_surnames))
var/firstspace = findtext(real_name, " ")
var/name_length = length(real_name)
if(!firstspace) //we need a surname
@@ -1657,7 +1819,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
character.dna.features = features.Copy() //Flavor text is now a DNA feature
character.dna.real_name = character.real_name
var/datum/species/chosen_species
if(pref_species != /datum/species/human && config.mutant_races)
if(pref_species != /datum/species/human && CONFIG_GET(flag/join_with_mutant_race))
chosen_species = pref_species.type
else
chosen_species = /datum/species/human
+11 -6
View File
@@ -290,11 +290,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//Species
var/species_id
S["species"] >> species_id
if(config.mutant_races && species_id && (species_id in GLOB.roundstart_species))
var/newtype = GLOB.roundstart_species[species_id]
var/list/roundstart_races = CONFIG_GET(keyed_flag_list/roundstart_races)
if(species_id && (species_id in roundstart_races) && CONFIG_GET(flag/join_with_mutant_race))
var/newtype = GLOB.species_list[species_id]
pref_species = new newtype()
else if (config.roundstart_races.len)
var/rando_race = pick(config.roundstart_races)
else if (roundstart_races.len)
var/rando_race = pick(roundstart_races)
if (rando_race)
pref_species = new rando_race()
@@ -327,8 +328,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["feature_lizard_spines"] >> features["spines"]
S["feature_lizard_body_markings"] >> features["body_markings"]
S["feature_lizard_legs"] >> features["legs"]
S["feature_human_tail"] >> features["tail_human"]
S["feature_human_ears"] >> features["ears"]
if(!CONFIG_GET(flag/join_with_mutant_humans))
features["tail_human"] = "none"
features["ears"] = "none"
else
S["feature_human_tail"] >> features["tail_human"]
S["feature_human_ears"] >> features["ears"]
S["clown_name"] >> custom_names["clown"]
S["mime_name"] >> custom_names["mime"]
S["ai_name"] >> custom_names["ai"]
+2 -2
View File
@@ -62,7 +62,7 @@
if(holder)
if(!holder.fakekey || C.holder)
if(check_rights_for(src, R_ADMIN))
to_chat(C, "<span class='adminooc'>[config.allow_admin_ooccolor && prefs.ooccolor ? "<font color=[prefs.ooccolor]>" :"" ]<span class='prefix'>OOC:</span> <EM>[keyname][holder.fakekey ? "/([holder.fakekey])" : ""]:</EM> <span class='message'>[msg]</span></span></font>")
to_chat(C, "<span class='adminooc'>[CONFIG_GET(flag/allow_admin_ooccolor) && prefs.ooccolor ? "<font color=[prefs.ooccolor]>" :"" ]<span class='prefix'>OOC:</span> <EM>[keyname][holder.fakekey ? "/([holder.fakekey])" : ""]:</EM> <span class='message'>[msg]</span></span></font>")
else
to_chat(C, "<span class='adminobserverooc'><span class='prefix'>OOC:</span> <EM>[keyname][holder.fakekey ? "/([holder.fakekey])" : ""]:</EM> <span class='message'>[msg]</span></span>")
else
@@ -239,7 +239,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, OOC_COLOR)
set category = "OOC"
set desc = "View the notes that admins have written about you"
if(!config.see_own_notes)
if(!CONFIG_GET(flag/see_own_notes))
to_chat(usr, "<span class='notice'>Sorry, that function is not enabled on this server.</span>")
return
+7
View File
@@ -211,6 +211,13 @@
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/under/chameleon/ratvar
name = "ratvarian engineer's jumpsuit"
desc = "A tough jumpsuit woven from alloy threads. It can take on the appearance of other jumpsuits."
icon_state = "engine"
item_state = "engi_suit"
item_color = "engine"
/obj/item/clothing/under/chameleon/New()
..()
chameleon_action = new(src)
+6
View File
@@ -3,6 +3,11 @@
materials = list(MAT_GLASS = 250)
var/glass_colour_type = null //colors your vision when worn
/obj/item/clothing/glasses/examine(mob/user)
..()
if(glass_colour_type && ishuman(user))
to_chat(user, "<span class='notice'>Alt-click to toggle its colors.</span>")
/obj/item/clothing/glasses/visor_toggling()
..()
if(visor_vars_to_toggle & VISOR_VISIONFLAGS)
@@ -85,6 +90,7 @@
item_state = "glasses"
origin_tech = "materials=4;magnets=4;plasmatech=4;engineering=4"
darkness_view = 8
vision_flags = SEE_BLACKNESS
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
glass_colour_type = /datum/client_colour/glass_colour/green
+5 -1
View File
@@ -82,6 +82,10 @@
pockets = /obj/item/storage/internal/pocket/small/detective
dog_fashion = /datum/dog_fashion/head/detective
/obj/item/clothing/head/fedora/det_hat/examine(mob/user)
..()
to_chat(user, "<span class='notice'>Alt-click to take a candy corn.</span>")
/obj/item/clothing/head/fedora/det_hat/AltClick()
..()
if(ismob(loc))
@@ -172,4 +176,4 @@
/obj/item/clothing/head/fedora/curator
name = "treasure hunter's fedora"
desc = "You got red text today kid, but it doesn't mean you have to like it."
icon_state = "curator"
icon_state = "curator"
+3 -5
View File
@@ -23,7 +23,7 @@
icon_state = initial(icon_state)
desc = initial(desc)
/obj/item/evidencebag/proc/evidencebagEquip(obj/item/I, mob/user)
/obj/item/evidencebag/proc/evidencebagEquip(obj/item/I, mob/user)
if(!istype(I) || I.anchored == 1)
return
@@ -43,9 +43,7 @@
if(istype(I.loc, /obj/item/storage)) //in a container.
var/obj/item/storage/U = I.loc
U.remove_from_storage(I, src)
if(user.is_holding(I))
user.dropItemToGround(I)
else
if(!user.dropItemToGround(I))
return
user.visible_message("[user] puts [I] into [src].", "<span class='notice'>You put [I] inside [src].</span>",\
@@ -62,7 +60,7 @@
add_overlay("evidence") //should look nicer for transparent stuff. not really that important, but hey.
desc = "An evidence bag containing [I]. [I.desc]"
I.loc = src
I.forceMove(src)
w_class = I.w_class
return 1
+1 -1
View File
@@ -1,6 +1,6 @@
/proc/emoji_parse(text)
. = text
if(!config.emojis)
if(!CONFIG_GET(flag/emojis))
return
var/static/list/emojis = icon_states(icon('icons/emoji.dmi'))
var/parsed = ""
+13 -7
View File
@@ -33,14 +33,20 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0)
// We can runtime before config is initialized because BYOND initialize objs/map before a bunch of other stuff happens.
// This is a bunch of workaround code for that. Hooray!
var/configured_error_cooldown = initial(config.error_cooldown)
var/configured_error_limit = initial(config.error_limit)
var/configured_error_silence_time = initial(config.error_silence_time)
var/configured_error_cooldown
var/configured_error_limit
var/configured_error_silence_time
if(config)
configured_error_cooldown = config.error_cooldown
configured_error_limit = config.error_limit
configured_error_silence_time = config.error_silence_time
configured_error_cooldown = CONFIG_GET(number/error_cooldown)
configured_error_limit = CONFIG_GET(number/error_limit)
configured_error_silence_time = CONFIG_GET(number/error_silence_time)
else
var/datum/config_entry/CE = /datum/config_entry/number/error_cooldown
configured_error_cooldown = initial(CE.value)
CE = /datum/config_entry/number/error_limit
configured_error_limit = initial(CE.value)
CE = /datum/config_entry/number/error_silence_time
configured_error_silence_time = initial(CE.value)
//Each occurence of a unique error adds to its cooldown time...
+3 -2
View File
@@ -119,9 +119,10 @@ GLOBAL_DATUM(error_cache, /datum/error_viewer/error_cache)
//log_debug("Runtime in <b>[e.file]</b>, line <b>[e.line]</b>: <b>[html_encode(e.name)]</b> [error_entry.make_link(viewtext)]")
var/err_msg_delay
if(config)
err_msg_delay = config.error_msg_delay
err_msg_delay = CONFIG_GET(number/error_msg_delay)
else
err_msg_delay = initial(config.error_msg_delay)
var/datum/config_entry/CE = /datum/config_entry/number/error_msg_delay
err_msg_delay = initial(CE.value)
error_source.next_message_at = world.time + err_msg_delay
/datum/error_viewer/error_source
+11 -3
View File
@@ -28,10 +28,9 @@
var/triggering //admin cancellation
/datum/round_event_control/New()
..()
if(config && !wizardevent) // Magic is unaffected by configs
earliest_start = Ceiling(earliest_start * config.events_min_time_mul)
min_players = Ceiling(min_players * config.events_min_players_mul)
earliest_start = Ceiling(earliest_start * CONFIG_GET(number/events_min_time_mul))
min_players = Ceiling(min_players * CONFIG_GET(number/events_min_players_mul))
/datum/round_event_control/wizard
wizardevent = 1
@@ -158,19 +157,28 @@
return
if(activeFor == startWhen)
processing = FALSE
start()
processing = TRUE
if(activeFor == announceWhen)
processing = FALSE
announce()
processing = TRUE
if(startWhen < activeFor && activeFor < endWhen)
processing = FALSE
tick()
processing = TRUE
if(activeFor == endWhen)
processing = FALSE
end()
processing = TRUE
// Everything is done, let's clean up.
if(activeFor >= endWhen && activeFor >= announceWhen && activeFor >= startWhen)
processing = FALSE
kill()
activeFor++
+2 -1
View File
@@ -7,4 +7,5 @@
/datum/round_event/wizard/fake_explosion/start()
sound_to_playing_players('sound/machines/alarm.ogg')
addtimer(CALLBACK(SSticker, /datum/controller/subsystem/ticker/.proc/station_explosion_cinematic, 1, "fake"), 100) //:o)
sleep(100)
Cinematic(CINEMATIC_NUKE_FAKE,world)
+2 -2
View File
@@ -6,7 +6,7 @@
earliest_start = 0
/datum/round_event_control/wizard/summonguns/New()
if(config.no_summon_guns)
if(CONFIG_GET(flag/no_summon_guns))
weight = 0
..()
@@ -21,7 +21,7 @@
earliest_start = 0
/datum/round_event_control/wizard/summonmagic/New()
if(config.no_summon_magic)
if(CONFIG_GET(flag/no_summon_magic))
weight = 0
..()
+6 -5
View File
@@ -30,6 +30,7 @@
//Processing
var/process_inner_turfs = FALSE //Don't do this unless it's absolutely necessary
var/process_edge_turfs = FALSE //Don't do this either unless it's absolutely necessary, you can just track what things are inside manually or on the initial setup.
var/requires_processing = FALSE
var/setup_edge_turfs = FALSE //Setup edge turfs/all field turfs. Set either or both to ON when you need it, it's defaulting to off unless you do to save CPU.
var/setup_field_turfs = FALSE
var/use_host_turf = FALSE //For fields from items carried on mobs to check turf instead of loc...
@@ -41,6 +42,7 @@
/datum/proximity_monitor/advanced/Destroy()
full_cleanup()
STOP_PROCESSING(SSfields, src)
return ..()
/datum/proximity_monitor/advanced/proc/assume_params(list/field_params)
@@ -76,6 +78,10 @@
/datum/proximity_monitor/advanced/proc/process_edge_turf(turf/T)
/datum/proximity_monitor/advanced/New()
if(requires_processing)
START_PROCESSING(SSfields, src)
/datum/proximity_monitor/advanced/proc/Initialize()
setup_field()
post_setup_field()
@@ -250,11 +256,6 @@
setup_field_turfs = TRUE
setup_edge_turfs = TRUE
/datum/proximity_monitor/advanced/debug/recalculate_field()
..()
/datum/proximity_monitor/advanced/debug/post_setup_field()
..()
/datum/proximity_monitor/advanced/debug/setup_edge_turf(turf/T)
T.color = set_edgeturf_color
+1 -2
View File
@@ -5,6 +5,7 @@
name = "\improper Hyperkinetic Dampener Field"
setup_edge_turfs = TRUE
setup_field_turfs = TRUE
requires_processing = TRUE
field_shape = FIELD_SHAPE_RADIUS_SQUARE
var/static/image/edgeturf_south = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_south")
var/static/image/edgeturf_north = image('icons/effects/fields.dmi', icon_state = "projectile_dampen_north")
@@ -21,13 +22,11 @@
use_host_turf = TRUE
/datum/proximity_monitor/advanced/peaceborg_dampener/New()
START_PROCESSING(SSfields, src)
tracked = list()
staging = list()
..()
/datum/proximity_monitor/advanced/peaceborg_dampener/Destroy()
STOP_PROCESSING(SSfields, src)
return ..()
/datum/proximity_monitor/advanced/peaceborg_dampener/process()
+131
View File
@@ -0,0 +1,131 @@
/obj/effect/timestop
anchored = TRUE
name = "chronofield"
desc = "ZA WARUDO"
icon = 'icons/effects/160x160.dmi'
icon_state = "time"
layer = FLY_LAYER
pixel_x = -64
pixel_y = -64
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
var/list/immune = list() // the one who creates the timestop is immune
var/turf/target
var/freezerange = 2
var/duration = 140
var/datum/proximity_monitor/advanced/timestop/chronofield
alpha = 125
/obj/effect/timestop/Initialize(mapload, radius, time, list/immune_atoms, start = TRUE) //Immune atoms assoc list atom = TRUE
. = ..()
if(immune_atoms)
immune = immune_atoms.Copy()
if(!isnull(time))
duration = time
if(!isnull(radius))
freezerange = radius
for(var/mob/living/L in GLOB.player_list)
if(locate(/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop) in L.mind.spell_list) //People who can stop time are immune to its effects
immune[L] = TRUE
if(start)
timestop()
/obj/effect/timestop/Destroy()
qdel(chronofield)
playsound(src, 'sound/magic/timeparadox2.ogg', 75, TRUE, frequency = -1) //reverse!
return ..()
/obj/effect/timestop/proc/timestop()
target = get_turf(src)
playsound(src, 'sound/magic/timeparadox2.ogg', 75, 1, -1)
chronofield = make_field(/datum/proximity_monitor/advanced/timestop, list("current_range" = freezerange, "host" = src, "immune" = immune))
QDEL_IN(src, duration)
/obj/effect/timestop/wizard
duration = 100
/datum/proximity_monitor/advanced/timestop
name = "chronofield"
setup_field_turfs = TRUE
field_shape = FIELD_SHAPE_RADIUS_SQUARE
requires_processing = TRUE
var/list/immune = list()
var/list/mob/living/frozen_mobs = list()
var/list/obj/item/projectile/frozen_projectiles = list()
var/list/atom/movable/frozen_throws = list()
/datum/proximity_monitor/advanced/timestop/Destroy()
unfreeze_all()
return ..()
/datum/proximity_monitor/advanced/timestop/field_turf_crossed(atom/movable/AM)
freeze_atom(AM)
/datum/proximity_monitor/advanced/timestop/proc/freeze_atom(atom/movable/A)
if(immune[A] || !istype(A))
return FALSE
if(A.throwing)
freeze_throwing(A)
if(isliving(A))
freeze_mob(A)
else if(istype(A, /obj/item/projectile))
freeze_projectile(A)
else
return FALSE
return TRUE
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_all()
for(var/i in frozen_projectiles)
unfreeze_projectile(i)
for(var/i in frozen_mobs)
unfreeze_mob(i)
for(var/i in frozen_throws)
unfreeze_throw(i)
/datum/proximity_monitor/advanced/timestop/proc/freeze_throwing(atom/movable/AM)
var/datum/thrownthing/T = AM.throwing
T.paused = TRUE
frozen_throws[AM] = T
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_throw(atom/movable/AM)
var/datum/thrownthing/T = frozen_throws[AM]
T.paused = FALSE
frozen_throws -= AM
/datum/proximity_monitor/advanced/timestop/process()
for(var/i in frozen_mobs)
var/mob/living/m = i
if(get_dist(get_turf(m), get_turf(host)) > current_range)
unfreeze_mob(m)
else
m.Stun(20, 1, 1)
/datum/proximity_monitor/advanced/timestop/setup_field_turf(turf/T)
for(var/i in T.contents)
freeze_atom(i)
return ..()
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_projectile(obj/item/projectile/P)
frozen_projectiles -= P
P.paused = FALSE
/datum/proximity_monitor/advanced/timestop/proc/freeze_projectile(obj/item/projectile/P)
frozen_projectiles[P] = TRUE
P.paused = TRUE
/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L)
L.Stun(20, 1, 1)
frozen_mobs[L] = L.anchored
L.anchored = TRUE
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
H.AIStatus = AI_OFF
H.LoseTarget()
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L)
L.AdjustStun(-20, 1, 1)
L.anchored = frozen_mobs[L]
frozen_mobs -= L
if(ishostile(L))
var/mob/living/simple_animal/hostile/H = L
H.AIStatus = initial(H.AIStatus)
@@ -185,6 +185,37 @@
icon_state = ""
bitesize = 2
/obj/item/reagent_containers/food/snacks/deepfryholder/proc/fry(obj/item/frying, datum/reagents/reagents, cook_time = 30)
if(istype(frying, /obj/item/reagent_containers/))
var/obj/item/reagent_containers/food = frying
food.reagents.trans_to(src, food.reagents.total_volume)
icon = frying.icon
overlays = frying.overlays
icon_state = frying.icon_state
desc = frying.desc
w_class = frying.w_class
reagents.trans_to(src, 2*(cook_time/15))
switch(cook_time)
if(0 to 15)
add_atom_colour(rgb(166,103,54), FIXED_COLOUR_PRIORITY)
name = "lightly-fried [frying.name]"
if(16 to 49)
add_atom_colour(rgb(103,63,24), FIXED_COLOUR_PRIORITY)
name = "fried [frying.name]"
if(50 to 59)
add_atom_colour(rgb(63,23,4), FIXED_COLOUR_PRIORITY)
name = "deep-fried [frying.name]"
if(60 to INFINITY)
add_atom_colour(rgb(33,19,9), FIXED_COLOUR_PRIORITY)
name = "the physical manifestation of the very concept of fried foods"
desc = "A heavily fried...something. Who can tell anymore?"
filling_color = color
foodtype |= FRIED
if(istype(frying, /obj/item/reagent_containers/food/snacks/))
qdel(frying)
else
frying.forceMove(src)
/obj/item/reagent_containers/food/snacks/butteredtoast
name = "buttered toast"
desc = "Butter lightly spread over a piece of toast."
@@ -82,36 +82,7 @@ insert ascii eagle on american flag background here
if(frying.loc == src)
to_chat(user, "<span class='notice'>You eject [frying] from [src].</span>")
var/obj/item/reagent_containers/food/snacks/deepfryholder/S = new(get_turf(src))
if(istype(frying, /obj/item/reagent_containers/))
var/obj/item/reagent_containers/food = frying
food.reagents.trans_to(S, food.reagents.total_volume)
S.icon = frying.icon
S.overlays = frying.overlays
S.icon_state = frying.icon_state
S.desc = frying.desc
S.w_class = frying.w_class
reagents.trans_to(S, 2*(cook_time/15))
switch(cook_time)
if(0 to 15)
S.add_atom_colour(rgb(166,103,54), FIXED_COLOUR_PRIORITY)
S.name = "lightly-fried [frying.name]"
if(16 to 49)
S.add_atom_colour(rgb(103,63,24), FIXED_COLOUR_PRIORITY)
S.name = "fried [frying.name]"
if(50 to 59)
S.add_atom_colour(rgb(63,23,4), FIXED_COLOUR_PRIORITY)
S.name = "deep-fried [frying.name]"
if(60 to INFINITY)
S.add_atom_colour(rgb(33,19,9), FIXED_COLOUR_PRIORITY)
S.name = "the physical manifestation of the very concept of fried foods"
S.desc = "A heavily fried...something. Who can tell anymore?"
S.filling_color = S.color
S.foodtype |= FRIED
if(istype(frying, /obj/item/reagent_containers/food/snacks/))
qdel(frying)
else
frying.forceMove(S)
S.fry(frying, reagents, cook_time)
icon_state = "fryer_off"
user.put_in_hands(S)
frying = null
+3 -1
View File
@@ -104,12 +104,14 @@
var/buffertext = "A funny bit of text."
/obj/item/toy/cards/singlecard/cas/examine(mob/user)
..()
if (flipped)
to_chat(user, "<span class='notice'>The card is face down.</span>")
else if (blank)
to_chat(user, "<span class='notice'>The card is blank. Write on it with a pen.</span>")
else
to_chat(user, "<span class='notice'>The card reads: [name]</span>")
to_chat(user, "<span class='notice'>Alt-click to flip it.</span>")
/obj/item/toy/cards/singlecard/cas/Flip()
set name = "Flip Card"
@@ -145,4 +147,4 @@
return
name = cardtext
buffertext = cardtext
blank = 0
blank = 0
@@ -353,6 +353,8 @@ h1.alert, h2.alert {color: #000000;}
.borer {color: #543354; font-style: italic;}
.changeling {color: #800080; font-style: italic;}
.spider {color: #4d004d;}
.interface {color: #330033;}
.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
+2 -2
View File
@@ -55,7 +55,7 @@
var/obj/machinery/hydroponics/parent = loc
var/make_podman = 0
var/ckey_holder = null
if(config.revival_pod_plants)
if(CONFIG_GET(flag/revival_pod_plants))
if(ckey)
for(var/mob/M in GLOB.player_list)
if(isobserver(M))
@@ -99,7 +99,7 @@
podman.faction |= factions
if(!features["mcolor"])
features["mcolor"] = "#59CE00"
podman.hardset_dna(null,null,podman.real_name,blood_type, /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
podman.hardset_dna(null,null,podman.real_name,blood_type, new /datum/species/pod,features)//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
+12 -11
View File
@@ -6,13 +6,13 @@ GLOBAL_PROTECT(exp_to_update)
/datum/job/proc/required_playtime_remaining(client/C)
if(!C)
return 0
if(!config.use_exp_tracking)
if(!CONFIG_GET(flag/use_exp_tracking))
return 0
if(!exp_requirements || !exp_type)
return 0
if(!job_is_xp_locked(src.title))
return 0
if(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, FALSE, C.mob))
if(CONFIG_GET(flag/use_exp_restrictions_admin_bypass) && check_rights(R_ADMIN, FALSE, C.mob))
return 0
var/isexempt = C.prefs.db_flags & DB_FLAG_EXEMPT
if(isexempt)
@@ -26,20 +26,21 @@ GLOBAL_PROTECT(exp_to_update)
/datum/job/proc/get_exp_req_amount()
if(title in GLOB.command_positions)
if(config.use_exp_restrictions_heads_hours)
return config.use_exp_restrictions_heads_hours * 60
var/uerhh = CONFIG_GET(number/use_exp_restrictions_heads_hours)
if(uerhh)
return uerhh * 60
return exp_requirements
/datum/job/proc/get_exp_req_type()
if(title in GLOB.command_positions)
if(config.use_exp_restrictions_heads_department && exp_type_department)
if(CONFIG_GET(flag/use_exp_restrictions_heads_department) && exp_type_department)
return exp_type_department
return exp_type
/proc/job_is_xp_locked(jobtitle)
if(!config.use_exp_restrictions_heads && jobtitle in GLOB.command_positions)
if(!CONFIG_GET(flag/use_exp_restrictions_heads) && jobtitle in GLOB.command_positions)
return FALSE
if(!config.use_exp_restrictions_other && !(jobtitle in GLOB.command_positions))
if(!CONFIG_GET(flag/use_exp_restrictions_other) && !(jobtitle in GLOB.command_positions))
return FALSE
return TRUE
@@ -55,7 +56,7 @@ GLOBAL_PROTECT(exp_to_update)
return amount
/client/proc/get_exp_report()
if(!config.use_exp_tracking)
if(!CONFIG_GET(flag/use_exp_tracking))
return "Tracking is disabled in the server configuration file."
var/list/play_records = prefs.exp
if(!play_records.len)
@@ -86,7 +87,7 @@ GLOBAL_PROTECT(exp_to_update)
return_text += "<LI>[dep] [get_exp_format(exp_data[dep])] ([percentage]%)</LI>"
else
return_text += "<LI>[dep] [get_exp_format(exp_data[dep])] </LI>"
if(config.use_exp_restrictions_admin_bypass && check_rights(R_ADMIN, 0, mob))
if(CONFIG_GET(flag/use_exp_restrictions_admin_bypass) && check_rights(R_ADMIN, 0, mob))
return_text += "<LI>Admin (all jobs auto-unlocked)</LI>"
return_text += "</UL>"
var/list/jobs_locked = list()
@@ -139,7 +140,7 @@ GLOBAL_PROTECT(exp_to_update)
//resets a client's exp to what was in the db.
/client/proc/set_exp_from_db()
if(!config.use_exp_tracking)
if(!CONFIG_GET(flag/use_exp_tracking))
return -1
if(!SSdbcore.Connect())
return -1
@@ -181,7 +182,7 @@ GLOBAL_PROTECT(exp_to_update)
/client/proc/update_exp_list(minutes, announce_changes = FALSE)
if(!config.use_exp_tracking)
if(!CONFIG_GET(flag/use_exp_tracking))
return -1
if(!SSdbcore.Connect())
return -1
+42 -41
View File
@@ -1,42 +1,43 @@
/*
Assistant
*/
/datum/job/assistant
title = "Assistant"
flag = ASSISTANT
department_flag = CIVILIAN
faction = "Station"
total_positions = -1
spawn_positions = -1
supervisors = "absolutely everyone"
selection_color = "#dddddd"
access = list() //See /datum/job/assistant/get_access()
minimal_access = list() //See /datum/job/assistant/get_access()
outfit = /datum/outfit/job/assistant
/datum/job/assistant/get_access()
if((config.jobs_have_maint_access & ASSISTANTS_HAVE_MAINT_ACCESS) || !config.jobs_have_minimal_access) //Config has assistant maint access set
. = ..()
/*
Assistant
*/
/datum/job/assistant
title = "Assistant"
flag = ASSISTANT
department_flag = CIVILIAN
faction = "Station"
total_positions = -1
spawn_positions = -1
supervisors = "absolutely everyone"
selection_color = "#dddddd"
access = list() //See /datum/job/assistant/get_access()
minimal_access = list() //See /datum/job/assistant/get_access()
outfit = /datum/outfit/job/assistant
/datum/job/assistant/get_access()
if(CONFIG_GET(flag/assistants_have_maint_access) || !CONFIG_GET(flag/jobs_have_minimal_access)) //Config has assistant maint access set
. = ..()
. |= list(ACCESS_MAINT_TUNNELS)
else
return ..()
/datum/job/assistant/config_check()
if(config && !(config.assistant_cap == 0))
total_positions = config.assistant_cap
spawn_positions = config.assistant_cap
return 1
return 0
/datum/outfit/job/assistant
name = "Assistant"
jobtype = /datum/job/assistant
/datum/outfit/job/assistant/pre_equip(mob/living/carbon/human/H)
..()
if (config.grey_assistants)
uniform = /obj/item/clothing/under/color/grey
else
uniform = /obj/item/clothing/under/color/random
else
return ..()
/datum/job/assistant/config_check()
var/ac = CONFIG_GET(number/assistant_cap)
if(ac != 0)
total_positions = ac
spawn_positions = ac
return 1
return 0
/datum/outfit/job/assistant
name = "Assistant"
jobtype = /datum/job/assistant
/datum/outfit/job/assistant/pre_equip(mob/living/carbon/human/H)
..()
if (CONFIG_GET(flag/grey_assistants))
uniform = /obj/item/clothing/under/color/grey
else
uniform = /obj/item/clothing/under/color/random
+4 -4
View File
@@ -75,7 +75,7 @@
if(!visualsOnly && announce)
announce(H)
if(config.enforce_human_authority && (title in GLOB.command_positions))
if(CONFIG_GET(flag/enforce_human_authority) && (title in GLOB.command_positions))
H.dna.features["tail_human"] = "None"
H.dna.features["ears"] = "None"
H.regenerate_icons()
@@ -86,12 +86,12 @@
. = list()
if(config.jobs_have_minimal_access)
if(CONFIG_GET(flag/jobs_have_minimal_access))
. = src.minimal_access.Copy()
else
. = src.access.Copy()
if(config.jobs_have_maint_access & EVERYONE_HAS_MAINT_ACCESS) //Config has global maint access set
if(CONFIG_GET(flag/everyone_has_maint_access)) //Config has global maint access set
. |= list(ACCESS_MAINT_TUNNELS)
/datum/job/proc/announce_head(var/mob/living/carbon/human/H, var/channels) //tells the given channel that the given mob is the new department head. See communications.dm for valid channels.
@@ -109,7 +109,7 @@
/datum/job/proc/available_in_days(client/C)
if(!C)
return 0
if(!config.use_age_restriction_for_jobs)
if(!CONFIG_GET(flag/use_age_restriction_for_jobs))
return 0
if(!isnum(C.player_age))
return 0 //This is only a number if the db connection is established, otherwise it is text: "Requires database", meaning these restrictions cannot be enforced
+2 -2
View File
@@ -1,6 +1,6 @@
//Warden and regular officers add this result to their get_access()
/datum/job/proc/check_config_for_sec_maint()
if(config.jobs_have_maint_access & SECURITY_HAS_MAINT_ACCESS)
if(CONFIG_GET(flag/security_has_maint_access))
return list(ACCESS_MAINT_TUNNELS)
return list()
@@ -246,7 +246,7 @@ GLOBAL_LIST_INIT(available_depts, list(SEC_DEPT_ENGINEERING, SEC_DEPT_MEDICAL, S
W.access |= dep_access
var/teleport = 0
if(!config.sec_start_brig)
if(!CONFIG_GET(flag/sec_start_brig))
if(destination || spawn_point)
teleport = 1
if(teleport)
+51 -53
View File
@@ -1,57 +1,55 @@
/*
AI
*/
/datum/job/ai
title = "AI"
flag = AI_JF
department_flag = ENGSEC
faction = "Station"
total_positions = 0
spawn_positions = 1
selection_color = "#ccffcc"
supervisors = "your laws"
req_admin_notify = 1
minimal_player_age = 30
/*
AI
*/
/datum/job/ai
title = "AI"
flag = AI_JF
department_flag = ENGSEC
faction = "Station"
total_positions = 0
spawn_positions = 1
selection_color = "#ccffcc"
supervisors = "your laws"
req_admin_notify = 1
minimal_player_age = 30
exp_requirements = 180
exp_type = EXP_TYPE_CREW
/datum/job/ai/equip(mob/living/carbon/human/H)
return H.AIize(FALSE)
/datum/job/ai/after_spawn(mob/living/silicon/ai/AI, mob/M)
AI.rename_self("ai", M.client)
//we may have been created after our borg
if(SSticker.current_state == GAME_STATE_SETTING_UP)
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
if(!R.connected_ai)
R.TryConnectToAI()
/datum/job/ai/config_check()
if(config && config.allow_ai)
return 1
return 0
/*
Cyborg
*/
/datum/job/cyborg
title = "Cyborg"
flag = CYBORG
department_flag = ENGSEC
faction = "Station"
total_positions = 0
spawn_positions = 1
supervisors = "your laws and the AI" //Nodrak
selection_color = "#ddffdd"
minimal_player_age = 21
/datum/job/ai/equip(mob/living/carbon/human/H)
return H.AIize(FALSE)
/datum/job/ai/after_spawn(mob/living/silicon/ai/AI, mob/M)
AI.rename_self("ai", M.client)
//we may have been created after our borg
if(SSticker.current_state == GAME_STATE_SETTING_UP)
for(var/mob/living/silicon/robot/R in GLOB.silicon_mobs)
if(!R.connected_ai)
R.TryConnectToAI()
/datum/job/ai/config_check()
return CONFIG_GET(flag/allow_ai)
/*
Cyborg
*/
/datum/job/cyborg
title = "Cyborg"
flag = CYBORG
department_flag = ENGSEC
faction = "Station"
total_positions = 0
spawn_positions = 1
supervisors = "your laws and the AI" //Nodrak
selection_color = "#ddffdd"
minimal_player_age = 21
exp_requirements = 120
exp_type = EXP_TYPE_CREW
/datum/job/cyborg/equip(mob/living/carbon/human/H)
return H.Robotize(FALSE, FALSE)
/datum/job/cyborg/after_spawn(mob/living/silicon/robot/R, mob/M)
if(config.rename_cyborg) //name can't be set in robot/New without the client
R.rename_self("cyborg", M.client)
/datum/job/cyborg/equip(mob/living/carbon/human/H)
return H.Robotize(FALSE, FALSE)
/datum/job/cyborg/after_spawn(mob/living/silicon/robot/R, mob/M)
if(CONFIG_GET(flag/rename_cyborg)) //name can't be set in robot/New without the client
R.rename_self("cyborg", M.client)
+1 -1
View File
@@ -184,7 +184,7 @@
/obj/structure/closet/crate/secure/loot/AltClick(mob/living/user)
if(!user.canUseTopic(src))
return
attack_hand(user)
attack_hand(user) //this helps you not blow up so easily by overriding unlocking which results in an immediate boom.
/obj/structure/closet/crate/secure/loot/attackby(obj/item/W, mob/user)
if(locked)
+15 -1
View File
@@ -8,6 +8,7 @@
density = TRUE
anchored = TRUE
circuit = /obj/item/circuitboard/machine/mining_equipment_vendor
var/icon_deny = "mining-deny"
var/obj/item/card/id/inserted_id
var/list/prize_list = list( //if you add something to this, please, for the love of god, use tabs and not spaces.
new /datum/data/mining_equipment("1 Marker Beacon", /obj/item/stack/marker_beacon, 10),
@@ -108,6 +109,7 @@
if(href_list["choice"])
if(istype(inserted_id))
if(href_list["choice"] == "eject")
to_chat(usr, "<span class='notice'>You eject the ID from [src]'s card slot.</span>")
inserted_id.loc = loc
inserted_id.verb_pickup()
inserted_id = null
@@ -118,20 +120,31 @@
return
I.loc = src
inserted_id = I
else to_chat(usr, "<span class='danger'>No valid ID.</span>")
to_chat(usr, "<span class='notice'>You insert the ID into [src]'s card slot.</span>")
else
to_chat(usr, "<span class='warning'>Error: No valid ID!</span>")
flick(icon_deny, src)
if(href_list["purchase"])
if(istype(inserted_id))
var/datum/data/mining_equipment/prize = locate(href_list["purchase"])
if (!prize || !(prize in prize_list))
to_chat(usr, "<span class='warning'>Error: Invalid choice!</span>")
flick(icon_deny, src)
return
if(prize.cost > inserted_id.mining_points)
to_chat(usr, "<span class='warning'>Error: Insufficent points for [prize.equipment_name]!</span>")
flick(icon_deny, src)
else
inserted_id.mining_points -= prize.cost
to_chat(usr, "<span class='notice'>[src] clanks to life briefly before vending [prize.equipment_name]!</span>")
new prize.equipment_path(src.loc)
SSblackbox.add_details("mining_equipment_bought",
"[src.type]|[prize.equipment_path]")
// Add src.type to keep track of free golem purchases
// separately.
else
to_chat(usr, "<span class='warning'>Error: Please insert a valid ID!</span>")
flick(icon_deny, src)
updateUsrDialog()
return
@@ -146,6 +159,7 @@
return
C.loc = src
inserted_id = C
to_chat(usr, "<span class='notice'>You insert the ID into [src]'s card slot.</span>")
interact(user)
return
if(default_deconstruction_screwdriver(user, "mining-open", "mining", I))
+7 -6
View File
@@ -11,7 +11,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
prepare_huds()
if(config.cross_allowed)
if(CONFIG_GET(string/cross_server_address))
verbs += /mob/dead/proc/server_hop
return INITIALIZE_HINT_NORMAL
@@ -32,19 +32,20 @@ INITIALIZE_IMMEDIATE(/mob/dead)
set desc= "Jump to the other server"
if(notransform)
return
if(!config.cross_allowed)
var/csa = CONFIG_GET(string/cross_server_address)
if(csa)
verbs -= /mob/dead/proc/server_hop
to_chat(src, "<span class='notice'>Server Hop has been disabled.</span>")
return
if (alert(src, "Jump to server running at [config.cross_address]?", "Server Hop", "Yes", "No") != "Yes")
if (alert(src, "Jump to server running at [csa]?", "Server Hop", "Yes", "No") != "Yes")
return 0
if (client && config.cross_allowed)
to_chat(src, "<span class='notice'>Sending you to [config.cross_address].</span>")
if (client && csa)
to_chat(src, "<span class='notice'>Sending you to [csa].</span>")
new /obj/screen/splash(client)
notransform = TRUE
sleep(29) //let the animation play
notransform = FALSE
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
client << link(config.cross_address + "?server_hop=[key]")
client << link(csa + "?server_hop=[key]")
else
to_chat(src, "<span class='error'>There is no other server configured!</span>")
+7 -6
View File
@@ -1,5 +1,5 @@
/mob/dead/new_player/Login()
if(config.use_exp_tracking)
if(CONFIG_GET(flag/use_exp_tracking))
client.set_exp_from_db()
client.set_db_player_flags()
if(!mind)
@@ -15,8 +15,9 @@
if(GLOB.admin_notice)
to_chat(src, "<span class='notice'><b>Admin Notice:</b>\n \t [GLOB.admin_notice]</span>")
if(config.soft_popcap && living_player_count() >= config.soft_popcap)
to_chat(src, "<span class='notice'><b>Server Notice:</b>\n \t [config.soft_popcap_message]</span>")
var/spc = CONFIG_GET(number/soft_popcap)
if(spc && living_player_count() >= spc)
to_chat(src, "<span class='notice'><b>Server Notice:</b>\n \t [CONFIG_GET(string/soft_popcap_message)]</span>")
sight |= SEE_TURFS
@@ -32,10 +33,10 @@
new_player_panel()
client.playtitlemusic()
if(SSticker.current_state < GAME_STATE_SETTING_UP)
var/tl = round(SSticker.GetTimeLeft(), 1)/10
var/tl = SSticker.GetTimeLeft()
var/postfix
if(tl >= 0)
postfix = "in about [tl] seconds"
if(tl > 0)
postfix = "in about [DisplayTimeText(tl)]"
else
postfix = "soon"
to_chat(src, "Please set up your character and select \"Ready\". The game will start [postfix].")
+21 -18
View File
@@ -97,10 +97,12 @@
//Determines Relevent Population Cap
var/relevant_cap
if(config.hard_popcap && config.extreme_popcap)
relevant_cap = min(config.hard_popcap, config.extreme_popcap)
var/hpc = CONFIG_GET(number/hard_popcap)
var/epc = CONFIG_GET(number/extreme_popcap)
if(hpc && epc)
relevant_cap = min(hpc, epc)
else
relevant_cap = max(config.hard_popcap, config.extreme_popcap)
relevant_cap = max(hpc, epc)
if(href_list["show_preferences"])
client.prefs.ShowChoices(src)
@@ -113,6 +115,15 @@
//no longer is required
if(SSticker.current_state <= GAME_STATE_PREGAME)
ready = tready
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No")
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
ready = PLAYER_NOT_READY
src << browse(null, "window=playersetup") //closes the player setup window
new_player_panel()
return FALSE
//if it's post initialisation and they're trying to observe we do the needful
if(!SSticker.current_state < GAME_STATE_PREGAME && tready == PLAYER_READY_TO_OBSERVE)
ready = tready
@@ -133,7 +144,7 @@
return
if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in GLOB.admin_datums)))
to_chat(usr, "<span class='danger'>[config.hard_popcap_message]</span>")
to_chat(usr, "<span class='danger'>[CONFIG_GET(string/hard_popcap_message)]</span>")
var/queue_position = SSticker.queued_players.Find(usr)
if(queue_position == 1)
@@ -257,15 +268,7 @@
if(QDELETED(src) || !src.client)
ready = PLAYER_NOT_READY
return FALSE
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No")
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
ready = PLAYER_NOT_READY
src << browse(null, "window=playersetup") //closes the player setup window
new_player_panel()
return FALSE
var/mob/dead/observer/observer = new()
spawning = TRUE
@@ -309,7 +312,7 @@
return 0
if(job.required_playtime_remaining(client))
return 0
if(config.enforce_human_authority && !client.prefs.pref_species.qualifies_for_rank(rank, client.prefs.features))
if(CONFIG_GET(flag/enforce_human_authority) && !client.prefs.pref_species.qualifies_for_rank(rank, client.prefs.features))
return 0
return 1
@@ -326,11 +329,11 @@
var/arrivals_docked = TRUE
if(SSshuttle.arrivals)
close_spawn_windows() //In case we get held up
if(SSshuttle.arrivals.damaged && config.arrivals_shuttle_require_safe_latejoin)
if(SSshuttle.arrivals.damaged && CONFIG_GET(flag/arrivals_shuttle_require_safe_latejoin))
src << alert("The arrivals shuttle is currently malfunctioning! You cannot join.")
return FALSE
if(config.arrivals_shuttle_require_undocked)
if(CONFIG_GET(flag/arrivals_shuttle_require_undocked))
SSshuttle.arrivals.RequireUndocked(src)
arrivals_docked = SSshuttle.arrivals.mode != SHUTTLE_CALL
@@ -379,7 +382,7 @@
GLOB.joined_player_list += character.ckey
GLOB.latejoiners += character
if(config.allow_latejoin_antagonists && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
if(CONFIG_GET(flag/allow_latejoin_antagonists) && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
if(SSshuttle.emergency)
switch(SSshuttle.emergency.mode)
if(SHUTTLE_RECALL, SHUTTLE_IDLE)
@@ -463,7 +466,7 @@
var/mob/living/carbon/human/H = new(loc)
if(config.force_random_names || jobban_isbanned(src, "appearance"))
if(CONFIG_GET(flag/force_random_names) || jobban_isbanned(src, "appearance"))
client.prefs.random_character()
client.prefs.real_name = client.prefs.pref_species.random_name(gender,1)
client.prefs.copy_to(H)
@@ -14,7 +14,7 @@
facial_hair_color = hair_color
eye_color = random_eye_color()
if(!pref_species)
var/rando_race = pick(config.roundstart_races)
var/rando_race = pick(CONFIG_GET(keyed_flag_list/roundstart_races))
pref_species = new rando_race()
features = random_features()
age = rand(AGE_MIN,AGE_MAX)
@@ -67,30 +67,317 @@
/datum/sprite_accessory/hair
icon = 'icons/mob/human_face.dmi' // default icon for all hairs
/datum/sprite_accessory/hair/short
name = "Short Hair" // try to capatilize the names please~ // try to spell
icon_state = "hair_a" // you do not need to define _s or _l sub-states, game automatically does this for you
//Place in order by major style E.G "Afro, Bun, Ponytail"
//Place different versions under the same style E.G "Bun > Large Bun, Ponytail > Long Ponytail"
//A
/datum/sprite_accessory/hair/shorthair2
name = "Short Hair 2"
icon_state = "hair_shorthair2"
/datum/sprite_accessory/hair/afro
name = "Afro" // try to capatilize the names please~ // try to spell
icon_state = "hair_afro" // you do not need to define _s or _l sub-states, game automatically does this for you
/datum/sprite_accessory/hair/shorthair3
name = "Short Hair 3"
icon_state = "hair_shorthair3"
/datum/sprite_accessory/hair/afro2
name = "Afro 2"
icon_state = "hair_afro2"
/datum/sprite_accessory/hair/afro_large
name = "Big Afro"
icon_state = "hair_bigafro"
/datum/sprite_accessory/hair/antenna
name = "Ahoge"
icon_state = "hair_antenna"
//B
/datum/sprite_accessory/hair/bald
name = "Bald"
icon_state = null
/datum/sprite_accessory/hair/balding
name = "Balding Hair"
icon_state = "hair_e"
/datum/sprite_accessory/hair/longbangs
name = "Long Bangs"
icon_state = "hair_lbangs"
/datum/sprite_accessory/hair/bedhead
name = "Bedhead"
icon_state = "hair_bedhead"
/datum/sprite_accessory/hair/bedhead2
name = "Bedhead 2"
icon_state = "hair_bedheadv2"
/datum/sprite_accessory/hair/bedhead3
name = "Bedhead 3"
icon_state = "hair_bedheadv3"
/datum/sprite_accessory/hair/beehive
name = "Beehive"
icon_state = "hair_beehive"
/datum/sprite_accessory/hair/beehive2
name = "Beehive 2"
icon_state = "hair_beehivev2"
/datum/sprite_accessory/hair/bob
name = "Bob"
icon_state = "hair_bobcut"
/datum/sprite_accessory/hair/bobcurl
name = "Bobcurl"
icon_state = "hair_bobcurl"
/datum/sprite_accessory/hair/bob
name = "Bob Hair"
icon_state = "hair_bob"
/datum/sprite_accessory/hair/bob2
name = "Bob Hair 2"
icon_state = "hair_bob2"
/datum/sprite_accessory/hair/boddicker
name = "Boddicker"
icon_state = "hair_boddicker"
/datum/sprite_accessory/hair/bowl
name = "Bowl"
icon_state = "hair_bowlcut"
/datum/sprite_accessory/hair/braided
name = "Braided"
icon_state = "hair_braided"
/datum/sprite_accessory/hair/front_braid
name = "Braided front"
icon_state = "hair_braidfront"
/datum/sprite_accessory/hair/braidtail
name = "Braided Tail"
icon_state = "hair_braidtail"
/datum/sprite_accessory/hair/lowbraid
name = "Low Braid"
icon_state = "hair_hbraid"
/datum/sprite_accessory/hair/not_floorlength_braid
name = "High Braid"
icon_state = "hair_braid2"
/datum/sprite_accessory/hair/shortbraid
name = "Short Braid"
icon_state = "hair_shortbraid"
/datum/sprite_accessory/hair/braid
name = "Floorlength Braid"
icon_state = "hair_braid"
/datum/sprite_accessory/hair/business
name = "Business Hair"
icon_state = "hair_business"
/datum/sprite_accessory/hair/business2
name = "Business Hair 2"
icon_state = "hair_business2"
/datum/sprite_accessory/hair/business3
name = "Business Hair 3"
icon_state = "hair_business3"
/datum/sprite_accessory/hair/business4
name = "Business Hair 4"
icon_state = "hair_business4"
/datum/sprite_accessory/hair/bun
name = "Bun Head"
icon_state = "hair_bun"
/datum/sprite_accessory/hair/bun2
name = "Bun Head 2"
icon_state = "hair_bunhead2"
/datum/sprite_accessory/hair/largebun
name = "Large Bun"
icon_state = "hair_largebun"
/datum/sprite_accessory/hair/buzz
name = "Buzzcut"
icon_state = "hair_buzzcut"
//C
/datum/sprite_accessory/hair/crew
name = "Crewcut"
icon_state = "hair_crewcut"
/datum/sprite_accessory/hair/combover
name = "Combover"
icon_state = "hair_combover"
/datum/sprite_accessory/hair/curls
name = "Curls"
icon_state = "hair_curls"
//D
/datum/sprite_accessory/hair/devillock
name = "Devil Lock"
icon_state = "hair_devilock"
/datum/sprite_accessory/hair/dreadlocks
name = "Dreadlocks"
icon_state = "hair_dreads"
/datum/sprite_accessory/hair/drillhair
name = "Drill Hair"
icon_state = "hair_drillhair"
//E
/datum/sprite_accessory/hair/emo
name = "Emo"
icon_state = "hair_emo"
/datum/sprite_accessory/hair/longemo
name = "Long Emo"
icon_state = "hair_longemo"
//F
/datum/sprite_accessory/hair/feather
name = "Feather"
icon_state = "hair_feather"
/datum/sprite_accessory/hair/sargeant
name = "Flat Top"
icon_state = "hair_sargeant"
/datum/sprite_accessory/hair/bigflattop
name = "Big Flat Top"
icon_state = "hair_bigflattop"
/datum/sprite_accessory/hair/fag
name = "Flow Hair"
icon_state = "hair_f"
/datum/sprite_accessory/hair/longfringe
name = "Long Fringe"
icon_state = "hair_longfringe"
/datum/sprite_accessory/hair/longestalt
name = "Longer Fringe"
icon_state = "hair_vlongfringe"
//G
/datum/sprite_accessory/hair/gelled
name = "Gelled Back"
icon_state = "hair_gelled"
/datum/sprite_accessory/hair/gentle
name = "Gentle"
icon_state = "hair_gentle"
//H
/datum/sprite_accessory/hair/cut
name = "Cut Hair"
icon_state = "hair_c"
/datum/sprite_accessory/hair/long
name = "Shoulder-length Hair"
icon_state = "hair_b"
/datum/sprite_accessory/hair/halfbang
name = "Half-banged Hair"
icon_state = "hair_halfbang"
/datum/sprite_accessory/hair/halfbang2
name = "Half-banged Hair 2"
icon_state = "hair_halfbang2"
/datum/sprite_accessory/hair/hedgehog
name = "Hedgehog Hair"
icon_state = "hair_hedgehog"
/datum/sprite_accessory/hair/hitop
name = "Hitop"
icon_state = "hair_hitop"
/datum/sprite_accessory/hair/himecut
name = "Hime Cut"
icon_state = "hair_himecut"
/datum/sprite_accessory/hair/himecut2
name = "Hime Cut 2"
icon_state = "hair_himecut2"
/datum/sprite_accessory/hair/himeup
name = "Hime Updo"
icon_state = "hair_himeup"
//I
//J
/datum/sprite_accessory/hair/jensen
name = "Jensen Hair"
icon_state = "hair_jensen"
//K
/datum/sprite_accessory/hair/keanu
name = "Keanu Hair"
icon_state = "hair_keanu"
/datum/sprite_accessory/hair/kusangi
name = "Kusanagi Hair"
icon_state = "hair_kusanagi"
//L
/datum/sprite_accessory/hair/longer
name = "Long Hair"
icon_state = "hair_vlong"
/datum/sprite_accessory/hair/long
name = "Long Hair 1"
icon_state = "hair_long"
/datum/sprite_accessory/hair/long2
name = "Long Hair 2"
icon_state = "hair_long2"
/datum/sprite_accessory/hair/longest
name = "Very Long Hair"
icon_state = "hair_longest"
//M
/datum/sprite_accessory/hair/megaeyebrows
name = "Mega Eyebrows"
icon_state = "hair_megaeyebrows"
/datum/sprite_accessory/hair/messy
name = "Messy"
icon_state = "hair_messy"
/datum/sprite_accessory/hair/mohawk
name = "Mohawk"
icon_state = "hair_d"
/datum/sprite_accessory/hair/reversemohawk
name = "Reverse Mohawk"
icon_state = "hair_reversemohawk"
//N
//O
/datum/sprite_accessory/hair/odango
name = "Odango"
icon_state = "hair_odango"
/datum/sprite_accessory/hair/ombre
name = "Ombre"
icon_state = "hair_ombre"
/datum/sprite_accessory/hair/over_eye
name = "Over Eye"
icon_state = "hair_shortovereye"
@@ -103,29 +390,39 @@
name = "Very Long Over Eye"
icon_state = "hair_longest2"
/datum/sprite_accessory/hair/longest
name = "Very Long Hair"
icon_state = "hair_longest"
//P
/datum/sprite_accessory/hair/longfringe
name = "Long Fringe"
icon_state = "hair_longfringe"
/datum/sprite_accessory/hair/parted
name = "Parted"
icon_state = "hair_parted"
/datum/sprite_accessory/hair/longestalt
name = "Longer Fringe"
icon_state = "hair_vlongfringe"
/datum/sprite_accessory/hair/sidepartlongalt
name = "Long Side Part"
icon_state = "hair_longsidepart"
/datum/sprite_accessory/hair/gentle
name = "Gentle"
icon_state = "hair_gentle"
/datum/sprite_accessory/hair/kagami
name = "Pigtails"
icon_state = "hair_kagami"
/datum/sprite_accessory/hair/halfbang
name = "Half-banged Hair"
icon_state = "hair_halfbang"
/datum/sprite_accessory/hair/pigtail
name = "Pigtails 2"
icon_state = "hair_pigtails"
/datum/sprite_accessory/hair/halfbang2
name = "Half-banged Hair 2"
icon_state = "hair_halfbang2"
/datum/sprite_accessory/hair/pigtail
name = "Pigtails 3"
icon_state = "hair_pigtails2"
/datum/sprite_accessory/hair/pixie
name = "Pixie Cut"
icon_state = "hair_pixie"
/datum/sprite_accessory/hair/pompadour
name = "Pompadour"
icon_state = "hair_pompadour"
/datum/sprite_accessory/hair/bigpompadour
name = "Big Pompadour"
icon_state = "hair_bigpompadour"
/datum/sprite_accessory/hair/ponytail1
name = "Ponytail"
@@ -147,6 +444,36 @@
name = "Ponytail 5"
icon_state = "hair_ponytail5"
/datum/sprite_accessory/hair/highponytail
name = "High Ponytail"
icon_state = "hair_highponytail"
/datum/sprite_accessory/hair/longponytail
name = "Long Ponytail"
icon_state = "hair_longstraightponytail"
//Q
/datum/sprite_accessory/hair/quiff
name = "Quiff"
icon_state = "hair_quiff"
//R
//S
/datum/sprite_accessory/hair/oneshoulder
name = "One Shoulder"
icon_state = "hair_oneshoulder"
/datum/sprite_accessory/hair/tressshoulder
name = "Tress Shoulder"
icon_state = "hair_tressshoulder"
/datum/sprite_accessory/hair/sidecut
name = "Sidecut"
icon_state = "hair_sidecut"
/datum/sprite_accessory/hair/sidetail
name = "Side Pony"
@@ -164,141 +491,33 @@
name = "Side Pony 4"
icon_state = "hair_sidetail4"
/datum/sprite_accessory/hair/oneshoulder
name = "One Shoulder"
icon_state = "hair_oneshoulder"
/datum/sprite_accessory/hair/short
name = "Short Hair"
icon_state = "hair_a"
/datum/sprite_accessory/hair/tressshoulder
name = "Tress Shoulder"
icon_state = "hair_tressshoulder"
/datum/sprite_accessory/hair/shorthair2
name = "Short Hair 2"
icon_state = "hair_shorthair2"
/datum/sprite_accessory/hair/shorthair3
name = "Short Hair 3"
icon_state = "hair_shorthair3"
/datum/sprite_accessory/hair/long
name = "Shoulder-length Hair"
icon_state = "hair_b"
/datum/sprite_accessory/hair/parted
name = "Parted"
icon_state = "hair_parted"
name = "Side Part"
icon_state = "hair_part"
/datum/sprite_accessory/hair/pompadour
name = "Pompadour"
icon_state = "hair_pompadour"
/datum/sprite_accessory/hair/skinhead
name = "Skinhead"
icon_state = "hair_skinhead"
/datum/sprite_accessory/hair/bigpompadour
name = "Big Pompadour"
icon_state = "hair_bigpompadour"
/datum/sprite_accessory/hair/quiff
name = "Quiff"
icon_state = "hair_quiff"
/datum/sprite_accessory/hair/bedhead
name = "Bedhead"
icon_state = "hair_bedhead"
/datum/sprite_accessory/hair/bedhead2
name = "Bedhead 2"
icon_state = "hair_bedheadv2"
/datum/sprite_accessory/hair/bedhead3
name = "Bedhead 3"
icon_state = "hair_bedheadv3"
/datum/sprite_accessory/hair/messy
name = "Messy"
icon_state = "hair_messy"
/datum/sprite_accessory/hair/beehive
name = "Beehive"
icon_state = "hair_beehive"
/datum/sprite_accessory/hair/beehive2
name = "Beehive 2"
icon_state = "hair_beehivev2"
/datum/sprite_accessory/hair/bobcurl
name = "Bobcurl"
icon_state = "hair_bobcurl"
/datum/sprite_accessory/hair/bob
name = "Bob"
icon_state = "hair_bobcut"
/datum/sprite_accessory/hair/bowl
name = "Bowl"
icon_state = "hair_bowlcut"
/datum/sprite_accessory/hair/buzz
name = "Buzzcut"
icon_state = "hair_buzzcut"
/datum/sprite_accessory/hair/crew
name = "Crewcut"
icon_state = "hair_crewcut"
/datum/sprite_accessory/hair/combover
name = "Combover"
icon_state = "hair_combover"
/datum/sprite_accessory/hair/devillock
name = "Devil Lock"
icon_state = "hair_devilock"
/datum/sprite_accessory/hair/dreadlocks
name = "Dreadlocks"
icon_state = "hair_dreads"
/datum/sprite_accessory/hair/curls
name = "Curls"
icon_state = "hair_curls"
/datum/sprite_accessory/hair/afro
name = "Afro"
icon_state = "hair_afro"
/datum/sprite_accessory/hair/afro2
name = "Afro 2"
icon_state = "hair_afro2"
/datum/sprite_accessory/hair/afro_large
name = "Big Afro"
icon_state = "hair_bigafro"
/datum/sprite_accessory/hair/sargeant
name = "Flat Top"
icon_state = "hair_sargeant"
/datum/sprite_accessory/hair/emo
name = "Emo"
icon_state = "hair_emo"
/datum/sprite_accessory/hair/longemo
name = "Long Emo"
icon_state = "hair_longemo"
/datum/sprite_accessory/hair/fag
name = "Flow Hair"
icon_state = "hair_f"
/datum/sprite_accessory/hair/feather
name = "Feather"
icon_state = "hair_feather"
/datum/sprite_accessory/hair/hitop
name = "Hitop"
icon_state = "hair_hitop"
/datum/sprite_accessory/hair/mohawk
name = "Mohawk"
icon_state = "hair_d"
/datum/sprite_accessory/hair/reversemohawk
name = "Reverse Mohawk"
icon_state = "hair_reversemohawk"
/datum/sprite_accessory/hair/jensen
name = "Jensen Hair"
icon_state = "hair_jensen"
/datum/sprite_accessory/hair/gelled
name = "Gelled Back"
icon_state = "hair_gelled"
/datum/sprite_accessory/hair/protagonist
name = "Slightly Long"
icon_state = "hair_protagonist"
/datum/sprite_accessory/hair/spiky
name = "Spiky"
@@ -312,122 +531,6 @@
name = "Spiky 3"
icon_state = "hair_spiky2"
/datum/sprite_accessory/hair/protagonist
name = "Slightly Long"
icon_state = "hair_protagonist"
/datum/sprite_accessory/hair/kusangi
name = "Kusanagi Hair"
icon_state = "hair_kusanagi"
/datum/sprite_accessory/hair/kagami
name = "Pigtails"
icon_state = "hair_kagami"
/datum/sprite_accessory/hair/pigtail
name = "Pigtails 2"
icon_state = "hair_pigtails"
/datum/sprite_accessory/hair/pigtail
name = "Pigtails 3"
icon_state = "hair_pigtails2"
/datum/sprite_accessory/hair/himecut
name = "Hime Cut"
icon_state = "hair_himecut"
/datum/sprite_accessory/hair/himecut2
name = "Hime Cut 2"
icon_state = "hair_himecut2"
/datum/sprite_accessory/hair/himeup
name = "Hime Updo"
icon_state = "hair_himeup"
/datum/sprite_accessory/hair/antenna
name = "Ahoge"
icon_state = "hair_antenna"
/datum/sprite_accessory/hair/front_braid
name = "Braided front"
icon_state = "hair_braidfront"
/datum/sprite_accessory/hair/lowbraid
name = "Low Braid"
icon_state = "hair_hbraid"
/datum/sprite_accessory/hair/not_floorlength_braid
name = "High Braid"
icon_state = "hair_braid2"
/datum/sprite_accessory/hair/shortbraid
name = "Short Braid"
icon_state = "hair_shortbraid"
/datum/sprite_accessory/hair/braid
name = "Floorlength Braid"
icon_state = "hair_braid"
/datum/sprite_accessory/hair/odango
name = "Odango"
icon_state = "hair_odango"
/datum/sprite_accessory/hair/ombre
name = "Ombre"
icon_state = "hair_ombre"
/datum/sprite_accessory/hair/updo
name = "Updo"
icon_state = "hair_updo"
/datum/sprite_accessory/hair/skinhead
name = "Skinhead"
icon_state = "hair_skinhead"
/datum/sprite_accessory/hair/longbangs
name = "Long Bangs"
icon_state = "hair_lbangs"
/datum/sprite_accessory/hair/balding
name = "Balding Hair"
icon_state = "hair_e"
/datum/sprite_accessory/hair/bald
name = "Bald"
icon_state = null
/datum/sprite_accessory/hair/parted
name = "Side Part"
icon_state = "hair_part"
/datum/sprite_accessory/hair/braided
name = "Braided"
icon_state = "hair_braided"
/datum/sprite_accessory/hair/bun
name = "Bun Head"
icon_state = "hair_bun"
/datum/sprite_accessory/hair/bun2
name = "Bun Head 2"
icon_state = "hair_bunhead2"
/datum/sprite_accessory/hair/braidtail
name = "Braided Tail"
icon_state = "hair_braidtail"
/datum/sprite_accessory/hair/bigflattop
name = "Big Flat Top"
icon_state = "hair_bigflattop"
/datum/sprite_accessory/hair/drillhair
name = "Drill Hair"
icon_state = "hair_drillhair"
/datum/sprite_accessory/hair/keanu
name = "Keanu Hair"
icon_state = "hair_keanu"
/datum/sprite_accessory/hair/swept
name = "Swept Back Hair"
icon_state = "hair_swept"
@@ -436,73 +539,24 @@
name = "Swept Back Hair 2"
icon_state = "hair_swept2"
/datum/sprite_accessory/hair/business
name = "Business Hair"
icon_state = "hair_business"
//T
/datum/sprite_accessory/hair/business2
name = "Business Hair 2"
icon_state = "hair_business2"
//U
/datum/sprite_accessory/hair/business3
name = "Business Hair 3"
icon_state = "hair_business3"
/datum/sprite_accessory/hair/updo
name = "Updo"
icon_state = "hair_updo"
/datum/sprite_accessory/hair/business4
name = "Business Hair 4"
icon_state = "hair_business4"
//V
/datum/sprite_accessory/hair/hedgehog
name = "Hedgehog Hair"
icon_state = "hair_hedgehog"
//W
/datum/sprite_accessory/hair/bob
name = "Bob Hair"
icon_state = "hair_bob"
//X
/datum/sprite_accessory/hair/bob2
name = "Bob Hair 2"
icon_state = "hair_bob2"
//Y
/datum/sprite_accessory/hair/boddicker
name = "Boddicker"
icon_state = "hair_boddicker"
//Z
/datum/sprite_accessory/hair/long
name = "Long Hair 1"
icon_state = "hair_long"
/datum/sprite_accessory/hair/long2
name = "Long Hair 2"
icon_state = "hair_long2"
/datum/sprite_accessory/hair/pixie
name = "Pixie Cut"
icon_state = "hair_pixie"
/datum/sprite_accessory/hair/megaeyebrows
name = "Mega Eyebrows"
icon_state = "hair_megaeyebrows"
/datum/sprite_accessory/hair/highponytail
name = "High Ponytail"
icon_state = "hair_highponytail"
/datum/sprite_accessory/hair/longponytail
name = "Long Ponytail"
icon_state = "hair_longstraightponytail"
/datum/sprite_accessory/hair/sidepartlongalt
name = "Long Side Part"
icon_state = "hair_longsidepart"
/datum/sprite_accessory/hair/sidecut
name = "Sidecut"
icon_state = "hair_sidecut"
/datum/sprite_accessory/hair/largebun
name = "Large Bun"
icon_state = "hair_largebun"
/////////////////////////////
// Facial Hair Definitions //
@@ -516,82 +570,81 @@
icon_state = null
gender = NEUTER
/datum/sprite_accessory/facial_hair/watson
name = "Watson Mustache"
icon_state = "facial_watson"
/datum/sprite_accessory/facial_hair/hogan
name = "Hulk Hogan Mustache"
icon_state = "facial_hogan" //-Neek
/datum/sprite_accessory/facial_hair/vandyke
name = "Van Dyke Mustache"
icon_state = "facial_vandyke"
/datum/sprite_accessory/facial_hair/chaplin
name = "Square Mustache"
icon_state = "facial_chaplin"
/datum/sprite_accessory/facial_hair/selleck
name = "Selleck Mustache"
icon_state = "facial_selleck"
/datum/sprite_accessory/facial_hair/neckbeard
name = "Neckbeard"
icon_state = "facial_neckbeard"
/datum/sprite_accessory/facial_hair/fullbeard
name = "Full Beard"
icon_state = "facial_fullbeard"
/datum/sprite_accessory/facial_hair/longbeard
name = "Long Beard"
icon_state = "facial_longbeard"
/datum/sprite_accessory/facial_hair/vlongbeard
name = "Very Long Beard"
icon_state = "facial_wise"
/datum/sprite_accessory/facial_hair/elvis
name = "Elvis Sideburns"
icon_state = "facial_elvis"
/datum/sprite_accessory/facial_hair/abe
name = "Abraham Lincoln Beard"
icon_state = "facial_abe"
/datum/sprite_accessory/facial_hair/brokenman
name = "Broken Man"
icon_state = "facial_brokenman"
/datum/sprite_accessory/facial_hair/chinstrap
name = "Chinstrap"
icon_state = "facial_chin"
/datum/sprite_accessory/facial_hair/dwarf
name = "Dwarf Beard"
icon_state = "facial_dwarf"
/datum/sprite_accessory/facial_hair/elvis
name = "Elvis Sideburns"
icon_state = "facial_elvis"
/datum/sprite_accessory/facial_hair/fiveoclock
name = "Five o Clock Shadow"
icon_state = "facial_fiveoclock"
/datum/sprite_accessory/facial_hair/fullbeard
name = "Full Beard"
icon_state = "facial_fullbeard"
/datum/sprite_accessory/facial_hair/fu
name = "Fu Manchu"
icon_state = "facial_fumanchu"
/datum/sprite_accessory/facial_hair/gt
name = "Goatee"
icon_state = "facial_gt"
/datum/sprite_accessory/facial_hair/hip
name = "Hipster Beard"
icon_state = "facial_hip"
/datum/sprite_accessory/facial_hair/gt
name = "Goatee"
icon_state = "facial_gt"
/datum/sprite_accessory/facial_hair/hogan
name = "Hulk Hogan Mustache"
icon_state = "facial_hogan" //-Neek
/datum/sprite_accessory/facial_hair/jensen
name = "Jensen Beard"
icon_state = "facial_jensen"
/datum/sprite_accessory/facial_hair/dwarf
name = "Dwarf Beard"
icon_state = "facial_dwarf"
/datum/sprite_accessory/facial_hair/fiveoclock
name = "Five o Clock Shadow"
icon_state = "facial_fiveoclock"
/datum/sprite_accessory/facial_hair/fu
name = "Fu Manchu"
icon_state = "facial_fumanchu"
/datum/sprite_accessory/facial_hair/brokenman
name = "Broken Man"
icon_state = "facial_brokenman"
/datum/sprite_accessory/facial_hair/longbeard
name = "Long Beard"
icon_state = "facial_longbeard"
/datum/sprite_accessory/facial_hair/neckbeard
name = "Neckbeard"
icon_state = "facial_neckbeard"
/datum/sprite_accessory/facial_hair/selleck
name = "Selleck Mustache"
icon_state = "facial_selleck"
/datum/sprite_accessory/facial_hair/chaplin
name = "Square Mustache"
icon_state = "facial_chaplin"
/datum/sprite_accessory/facial_hair/vandyke
name = "Van Dyke Mustache"
icon_state = "facial_vandyke"
/datum/sprite_accessory/facial_hair/vlongbeard
name = "Very Long Beard"
icon_state = "facial_wise"
/datum/sprite_accessory/facial_hair/watson
name = "Watson Mustache"
icon_state = "facial_watson"
///////////////////////////
// Underwear Definitions //
+2
View File
@@ -199,6 +199,8 @@
else
to_chat(user, "<span class='notice'>The MMI indicates the brain is active.</span>")
/obj/item/device/mmi/relaymove()
return //so that the MMI won't get a warning about not being able to move if it tries to move
/obj/item/device/mmi/syndie
name = "Syndicate Man-Machine Interface"
+1 -1
View File
@@ -19,7 +19,7 @@
/mob/living/brain/proc/create_dna()
stored_dna = new /datum/dna/stored(src)
if(!stored_dna.species)
var/rando_race = pick(config.roundstart_races)
var/rando_race = pick(CONFIG_GET(keyed_flag_list/roundstart_races))
stored_dna.species = new rando_race()
/mob/living/brain/Destroy()
@@ -10,15 +10,15 @@ Doesn't work on other aliens/AI.*/
name = "Alien Power"
panel = "Alien"
var/plasma_cost = 0
var/check_turf = 0
var/has_action = 1
var/datum/action/spell_action/alien/action = null
var/action_icon = 'icons/mob/actions/actions_xeno.dmi'
var/action_icon_state = "spell_default"
var/action_background_icon_state = "bg_alien"
var/check_turf = FALSE
has_action = TRUE
datum/action/spell_action/alien/action
action_icon = 'icons/mob/actions/actions_xeno.dmi'
action_icon_state = "spell_default"
action_background_icon_state = "bg_alien"
/obj/effect/proc_holder/alien/New()
..()
/obj/effect/proc_holder/alien/Initialize()
. = ..()
action = new(src)
/obj/effect/proc_holder/alien/Click()
@@ -30,15 +30,20 @@ Doesn't work on other aliens/AI.*/
user.adjustPlasma(-plasma_cost)
return 1
/obj/effect/proc_holder/alien/proc/on_gain(mob/living/carbon/user)
/obj/effect/proc_holder/alien/on_gain(mob/living/carbon/user)
return
/obj/effect/proc_holder/alien/proc/on_lose(mob/living/carbon/user)
/obj/effect/proc_holder/alien/on_lose(mob/living/carbon/user)
return
/obj/effect/proc_holder/alien/proc/fire(mob/living/carbon/user)
/obj/effect/proc_holder/alien/fire(mob/living/carbon/user)
return 1
/obj/effect/proc_holder/alien/get_panel_text()
. = ..()
if(plasma_cost > 0)
return "[plasma_cost]"
/obj/effect/proc_holder/alien/proc/cost_check(check_turf=0,mob/living/carbon/user,silent = 0)
if(user.stat)
if(!silent)
@@ -168,7 +173,6 @@ Doesn't work on other aliens/AI.*/
if(user.getPlasma() > A.plasma_cost && A.corrode(O))
user.adjustPlasma(-A.plasma_cost)
/obj/effect/proc_holder/alien/neurotoxin
name = "Spit Neurotoxin"
desc = "Spits neurotoxin at someone, paralyzing them for a short time."
@@ -179,7 +183,7 @@ Doesn't work on other aliens/AI.*/
var/message
if(active)
message = "<span class='notice'>You empty your neurotoxin gland.</span>"
remove_ranged_ability(user,message)
remove_ranged_ability(message)
else
message = "<span class='notice'>You prepare your neurotoxin gland. <B>Left-click to fire at a target!</B></span>"
add_ranged_ability(user, message, TRUE)
@@ -193,7 +197,7 @@ Doesn't work on other aliens/AI.*/
return
var/p_cost = 50
if(!iscarbon(ranged_ability_user) || ranged_ability_user.lying || ranged_ability_user.stat)
remove_ranged_ability(ranged_ability_user)
remove_ranged_ability()
return
var/mob/living/carbon/user = ranged_ability_user
@@ -219,8 +223,7 @@ Doesn't work on other aliens/AI.*/
return TRUE
/obj/effect/proc_holder/alien/neurotoxin/on_lose(mob/living/carbon/user)
if(user.ranged_ability == src)
user.ranged_ability = null
remove_ranged_ability()
/obj/effect/proc_holder/alien/neurotoxin/add_ranged_ability(mob/living/user, msg)
..()
@@ -328,7 +331,3 @@ Doesn't work on other aliens/AI.*/
return 1
return 0
/proc/cmp_abilities_cost(obj/effect/proc_holder/alien/a, obj/effect/proc_holder/alien/b)
return b.plasma_cost - a.plasma_cost
@@ -1,124 +1,126 @@
/mob/living/carbon/alien/humanoid
name = "alien"
icon_state = "alien"
pass_flags = PASSTABLE
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
limb_destroyer = 1
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
var/leap_on_click = 0
var/pounce_cooldown = 0
var/pounce_cooldown_time = 30
var/custom_pixel_x_offset = 0 //for admin fuckery.
var/custom_pixel_y_offset = 0
var/sneaking = 0 //For sneaky-sneaky mode and appropriate slowdown
var/drooling = 0 //For Neruotoxic spit overlays
bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien,
/obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien)
devourable = TRUE
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
. = ..()
/mob/living/carbon/alien/humanoid/movement_delay()
. = ..()
. += move_delay_add + config.alien_delay + sneaking //move_delay_add is used to slow aliens with stun
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
. = handcuffed
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
user.set_machine(src)
var/list/dat = list()
dat += {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><A href='?src=\ref[src];pouches=1'>Empty Pouches</A>"
if(handcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_handcuffed]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_legcuffed]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
user << browse(dat.Join(), "window=mob\ref[src];size=325x500")
onclose(user, "mob\ref[src]")
/mob/living/carbon/alien/humanoid/Topic(href, href_list)
..()
//strip panel
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["pouches"])
visible_message("<span class='danger'>[usr] tries to empty [src]'s pouches.</span>", \
"<span class='userdanger'>[usr] tries to empty [src]'s pouches.</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY * 0.5))
dropItemToGround(r_store)
dropItemToGround(l_store)
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
..(I, cuff_break = INSTANT_CUFFBREAK)
/mob/living/carbon/alien/humanoid/resist_grab(moving_resist)
if(pulledby.grab_state)
visible_message("<span class='danger'>[src] has broken free of [pulledby]'s grip!</span>")
pulledby.stop_pulling()
. = 0
/mob/living/carbon/alien/humanoid/get_standard_pixel_y_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_y_offset)
return custom_pixel_y_offset
else
return initial(pixel_y)
/mob/living/carbon/alien/humanoid/get_standard_pixel_x_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_x_offset)
return custom_pixel_x_offset
else
return initial(pixel_x)
/mob/living/carbon/alien/humanoid/get_permeability_protection()
return 0.8
/mob/living/carbon/alien/humanoid/alien_evolve(mob/living/carbon/alien/humanoid/new_xeno)
drop_all_held_items()
for(var/atom/movable/A in stomach_contents)
stomach_contents.Remove(A)
new_xeno.stomach_contents.Add(A)
A.loc = new_xeno
..()
//For alien evolution/promotion/queen finder procs. Checks for an active alien of that type
/proc/get_alien_type(var/alienpath)
for(var/mob/living/carbon/alien/humanoid/A in GLOB.living_mob_list)
if(!istype(A, alienpath))
continue
if(!A.key || A.stat == DEAD) //Only living aliens with a ckey are valid.
continue
return A
return FALSE
/mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath)
if(breath && breath.total_moles() > 0 && !sneaking)
playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5)
..()
/mob/living/carbon/alien/humanoid
name = "alien"
icon_state = "alien"
pass_flags = PASSTABLE
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
limb_destroyer = 1
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
var/alt_icon = 'icons/mob/alienleap.dmi' //used to switch between the two alien icon files.
var/leap_on_click = 0
var/pounce_cooldown = 0
var/pounce_cooldown_time = 30
var/custom_pixel_x_offset = 0 //for admin fuckery.
var/custom_pixel_y_offset = 0
var/sneaking = 0 //For sneaky-sneaky mode and appropriate slowdown
var/drooling = 0 //For Neruotoxic spit overlays
bodyparts = list(/obj/item/bodypart/chest/alien, /obj/item/bodypart/head/alien, /obj/item/bodypart/l_arm/alien,
/obj/item/bodypart/r_arm/alien, /obj/item/bodypart/r_leg/alien, /obj/item/bodypart/l_leg/alien)
//This is fine right now, if we're adding organ specific damage this needs to be updated
/mob/living/carbon/alien/humanoid/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
. = ..()
/mob/living/carbon/alien/humanoid/movement_delay()
. = ..()
var/static/config_alien_delay
if(isnull(config_alien_delay))
config_alien_delay = CONFIG_GET(number/alien_delay)
. += move_delay_add + config_alien_delay + sneaking //move_delay_add is used to slow aliens with stun
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
. = handcuffed
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
user.set_machine(src)
var/list/dat = list()
dat += {"
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><A href='?src=\ref[src];pouches=1'>Empty Pouches</A>"
if(handcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_handcuffed]'>Handcuffed</A>"
if(legcuffed)
dat += "<BR><A href='?src=\ref[src];item=[slot_legcuffed]'>Legcuffed</A>"
dat += {"
<BR>
<BR><A href='?src=\ref[user];mach_close=mob\ref[src]'>Close</A>
"}
user << browse(dat.Join(), "window=mob\ref[src];size=325x500")
onclose(user, "mob\ref[src]")
/mob/living/carbon/alien/humanoid/Topic(href, href_list)
..()
//strip panel
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
if(href_list["pouches"])
visible_message("<span class='danger'>[usr] tries to empty [src]'s pouches.</span>", \
"<span class='userdanger'>[usr] tries to empty [src]'s pouches.</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY * 0.5))
dropItemToGround(r_store)
dropItemToGround(l_store)
/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I)
playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free
..(I, cuff_break = INSTANT_CUFFBREAK)
/mob/living/carbon/alien/humanoid/resist_grab(moving_resist)
if(pulledby.grab_state)
visible_message("<span class='danger'>[src] has broken free of [pulledby]'s grip!</span>")
pulledby.stop_pulling()
. = 0
/mob/living/carbon/alien/humanoid/get_standard_pixel_y_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_y_offset)
return custom_pixel_y_offset
else
return initial(pixel_y)
/mob/living/carbon/alien/humanoid/get_standard_pixel_x_offset(lying = 0)
if(leaping)
return -32
else if(custom_pixel_x_offset)
return custom_pixel_x_offset
else
return initial(pixel_x)
/mob/living/carbon/alien/humanoid/get_permeability_protection()
return 0.8
/mob/living/carbon/alien/humanoid/alien_evolve(mob/living/carbon/alien/humanoid/new_xeno)
drop_all_held_items()
for(var/atom/movable/A in stomach_contents)
stomach_contents.Remove(A)
new_xeno.stomach_contents.Add(A)
A.loc = new_xeno
..()
//For alien evolution/promotion/queen finder procs. Checks for an active alien of that type
/proc/get_alien_type(var/alienpath)
for(var/mob/living/carbon/alien/humanoid/A in GLOB.living_mob_list)
if(!istype(A, alienpath))
continue
if(!A.key || A.stat == DEAD) //Only living aliens with a ckey are valid.
continue
return A
return FALSE
/mob/living/carbon/alien/humanoid/check_breath(datum/gas_mixture/breath)
if(breath && breath.total_moles() > 0 && !sneaking)
playsound(get_turf(src), pick('sound/voice/lowHiss2.ogg', 'sound/voice/lowHiss3.ogg', 'sound/voice/lowHiss4.ogg'), 50, 0, -5)
..()
@@ -34,6 +34,7 @@
if(L.handcuffed || L.legcuffed) // Cuffing larvas ? Eh ?
to_chat(user, "<span class='danger'>You cannot evolve when you are cuffed.</span>")
return
if(L.amount_grown >= L.max_grown) //TODO ~Carn
to_chat(L, "<span class='name'>You are growing into a beautiful alien! It is time to choose a caste.</span>")
-17
View File
@@ -425,23 +425,6 @@
var/turf/target = get_turf(loc)
I.throw_at(target,I.throw_range,I.throw_speed,src)
/mob/living/carbon/proc/AddAbility(obj/effect/proc_holder/alien/A)
abilities.Add(A)
A.on_gain(src)
if(A.has_action)
A.action.Grant(src)
sortInsert(abilities, /proc/cmp_abilities_cost, 0)
/mob/living/carbon/proc/RemoveAbility(obj/effect/proc_holder/alien/A)
abilities.Remove(A)
A.on_lose(src)
if(A.action)
A.action.Remove(src)
/mob/living/carbon/proc/add_abilities_to_panel()
for(var/obj/effect/proc_holder/alien/A in abilities)
statpanel("[A.panel]",A.plasma_cost > 0?"([A.plasma_cost])":"",A)
/mob/living/carbon/Stat()
..()
if(statpanel("Status"))
@@ -35,7 +35,6 @@
has_limbs = 1
var/obj/item/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab
var/list/obj/effect/proc_holder/alien/abilities = list()
var/gib_type = /obj/effect/decal/cleanable/blood/gibs
var/rotate_on_lying = 1
@@ -311,7 +311,7 @@
if(istype(H.glasses, /obj/item/clothing/glasses/hud/health) || istype(CIH, /obj/item/organ/cyberimp/eyes/hud/medical))
var/cyberimp_detect
for(var/obj/item/organ/cyberimp/CI in internal_organs)
if(CI.status == ORGAN_ROBOTIC)
if(CI.status == ORGAN_ROBOTIC && !CI.syndicate_implant)
cyberimp_detect += "[name] is modified with a [CI.name].<br>"
if(cyberimp_detect)
msg += "Detected cybernetic modifications:<br>"
@@ -941,3 +941,124 @@
riding_datum.unequip_buckle_inhands(M)
riding_datum.restore_position(M)
. = ..(M, force)
/mob/living/carbon/human/species
var/race = null
/mob/living/carbon/human/species/Initialize()
. = ..()
set_species(race)
/mob/living/carbon/human/species/abductor
race = /datum/species/abductor
/mob/living/carbon/human/species/android
race = /datum/species/android
/mob/living/carbon/human/species/angel
race = /datum/species/angel
/mob/living/carbon/human/species/corporate
race = /datum/species/corporate
/mob/living/carbon/human/species/fly
race = /datum/species/fly
/mob/living/carbon/human/species/golem
race = /datum/species/golem
/mob/living/carbon/human/species/golem/random
race = /datum/species/golem/random
/mob/living/carbon/human/species/golem/adamantine
race = /datum/species/golem/adamantine
/mob/living/carbon/human/species/golem/plasma
race = /datum/species/golem/plasma
/mob/living/carbon/human/species/golem/diamond
race = /datum/species/golem/diamond
/mob/living/carbon/human/species/golem/gold
race = /datum/species/golem/gold
/mob/living/carbon/human/species/golem/silver
race = /datum/species/golem/silver
/mob/living/carbon/human/species/golem/plasteel
race = /datum/species/golem/plasteel
/mob/living/carbon/human/species/golem/titanium
race = /datum/species/golem/titanium
/mob/living/carbon/human/species/golem/plastitanium
race = /datum/species/golem/plastitanium
/mob/living/carbon/human/species/golem/alien_alloy
race = /datum/species/golem/alloy
/mob/living/carbon/human/species/golem/wood
race = /datum/species/golem/wood
/mob/living/carbon/human/species/golem/uranium
race = /datum/species/golem/uranium
/mob/living/carbon/human/species/golem/sand
race = /datum/species/golem/sand
/mob/living/carbon/human/species/golem/glass
race = /datum/species/golem/glass
/mob/living/carbon/human/species/golem/bluespace
race = /datum/species/golem/bluespace
/mob/living/carbon/human/species/golem/bananium
race = /datum/species/golem/bananium
/mob/living/carbon/human/species/golem/blood_cult
race = /datum/species/golem/runic
/mob/living/carbon/human/species/golem/cloth
race = /datum/species/golem/cloth
/mob/living/carbon/human/species/golem/plastic
race = /datum/species/golem/plastic
/mob/living/carbon/human/species/jelly
race = /datum/species/jelly
/mob/living/carbon/human/species/jelly/slime
race = /datum/species/jelly/slime
/mob/living/carbon/human/species/lizard
race = /datum/species/lizard
/mob/living/carbon/human/species/lizard/ashwalker
race = /datum/species/lizard/ashwalker
/mob/living/carbon/human/species/plasma
race = /datum/species/plasmaman
/mob/living/carbon/human/species/pod
race = /datum/species/pod
/mob/living/carbon/human/species/shadow
race = /datum/species/shadow
/mob/living/carbon/human/species/skeleton
race = /datum/species/skeleton
/mob/living/carbon/human/species/synth
race = /datum/species/synth
/mob/living/carbon/human/species/synth/military
race = /datum/species/synth/military
/mob/living/carbon/human/species/zombie
race = /datum/species/zombie
/mob/living/carbon/human/species/zombie/infectious
race = /datum/species/zombie/infectious
/mob/living/carbon/human/species/zombie/krokodil_addict
race = /datum/species/krokodil_addict
@@ -1,8 +1,9 @@
/mob/living/carbon/human/movement_delay()
. = 0
. += ..()
. += config.human_delay
. += dna.species.movement_delay(src)
var/static/config_human_delay
if(isnull(config_human_delay))
config_human_delay = CONFIG_GET(number/human_delay)
. += ..() + config_human_delay + dna.species.movement_delay(src)
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(isobj(shoes) && (shoes.flags_1&NOSLIP_1) && !(lube&GALOSHES_DONT_HELP))
@@ -667,7 +667,7 @@
equip_to_appropriate_slot(MYID)
//THIEVING SKILLS END
//-------------TOUCH ME
if(istype(TARGET, /obj/structure))
if(isstructure(TARGET))
var/obj/structure/STR = TARGET
if(main_hand)
var/obj/item/W = main_hand
@@ -586,6 +586,57 @@
H.adjustFireLoss(-4)
H.reagents.remove_reagent(chem.id, REAGENTS_METABOLISM)
/datum/species/golem/clockwork
name = "Clockwork Golem"
id = "clockwork golem"
say_mod = "clicks"
limbs_id = "clockgolem"
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>clockwork golem</span><span class='bold alloy'>, you are faster than \
other types of golem (being a machine), and are immune to electric shocks.</span>"
species_traits = list(NO_UNDERWEAR, NOTRANSSTING, NOBREATH, NOZOMBIE, VIRUSIMMUNE, RADIMMUNE, NOBLOOD, RESISTCOLD, RESISTPRESSURE)
armor = 40 //Reinforced, but also slim to allow for fast movement
attack_verb = "smash"
attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
sexes = FALSE
speedmod = 0
siemens_coeff = 0
damage_overlay_type = "synth"
prefix = "Clockwork"
var/has_corpse
/datum/species/golem/clockwork/on_species_gain(mob/living/carbon/human/H)
. = ..()
H.faction |= "ratvar"
/datum/species/golem/clockwork/on_species_loss(mob/living/carbon/human/H)
if(!is_servant_of_ratvar(H))
H.faction -= "ratvar"
. = ..()
/datum/species/golem/clockwork/get_spans()
return SPAN_ROBOT //beep
/datum/species/golem/clockwork/spec_death(gibbed, mob/living/carbon/human/H)
gibbed = !has_corpse ? FALSE : gibbed
. = ..()
if(!has_corpse)
var/turf/T = get_turf(H)
H.visible_message("<span class='warning'>[H]'s exoskeleton shatters, collapsing into a heap of scrap!</span>")
playsound(H, 'sound/magic/clockwork/anima_fragment_death.ogg', 50, TRUE)
for(var/i in 1 to rand(3, 5))
new/obj/item/clockwork/alloy_shards/small(T)
new/obj/item/clockwork/alloy_shards/clockgolem_remains(T)
qdel(H)
/datum/species/golem/clockwork/no_scrap //These golems are created through the herald's beacon and leave normal corpses on death.
id = "clockwork golem servant"
armor = 15 //Balance reasons make this armor weak
no_equip = list()
nojumpsuit = FALSE
has_corpse = TRUE
blacklisted = TRUE
dangerous_existence = TRUE
/datum/species/golem/cloth
name = "Cloth Golem"
id = "cloth golem"
+3 -2
View File
@@ -412,8 +412,9 @@
liver_failure()
else
liver.failing = FALSE
if(((!(NOLIVER in dna.species.species_traits)) && (!liver)))
else
if((dna && dna.species && (NOLIVER in dna.species.species_traits)))
return
liver_failure()
/mob/living/carbon/proc/undergoing_liver_failure()
@@ -62,7 +62,11 @@
if (bodytemperature < 283.222)
. += (283.222 - bodytemperature) / 10 * 1.75
return . + config.monkey_delay
var/static/config_monkey_delay
if(isnull(config_monkey_delay))
config_monkey_delay = CONFIG_GET(number/monkey_delay)
. += config_monkey_delay
/mob/living/carbon/monkey/Stat()
..()
+6 -6
View File
@@ -157,7 +157,7 @@
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
bruteloss = Clamp((bruteloss + (amount * config.damage_multiplier)), 0, maxHealth*2)
bruteloss = Clamp((bruteloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -168,7 +168,7 @@
/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
oxyloss = Clamp((oxyloss + (amount * config.damage_multiplier)), 0, maxHealth*2)
oxyloss = Clamp((oxyloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -187,7 +187,7 @@
/mob/living/proc/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
toxloss = Clamp((toxloss + (amount * config.damage_multiplier)), 0, maxHealth*2)
toxloss = Clamp((toxloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -206,7 +206,7 @@
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
fireloss = Clamp((fireloss + (amount * config.damage_multiplier)), 0, maxHealth*2)
fireloss = Clamp((fireloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -217,7 +217,7 @@
/mob/living/proc/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
cloneloss = Clamp((cloneloss + (amount * config.damage_multiplier)), 0, maxHealth*2)
cloneloss = Clamp((cloneloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
if(updating_health)
updatehealth()
return amount
@@ -236,7 +236,7 @@
/mob/living/proc/adjustBrainLoss(amount)
if(status_flags & GODMODE)
return 0
brainloss = Clamp((brainloss + (amount * config.damage_multiplier)), 0, maxHealth*2)
brainloss = Clamp((brainloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
/mob/living/proc/setBrainLoss(amount)
if(status_flags & GODMODE)
+26 -5
View File
@@ -412,7 +412,7 @@
set category = "OOC"
set src in view()
if(config.allow_Metadata)
if(CONFIG_GET(flag/allow_metadata))
if(client)
to_chat(src, "[src]'s Metainfo:<br>[client.prefs.metadata]")
else
@@ -460,20 +460,25 @@
makeTrail(newloc, T, old_direction)
/mob/living/movement_delay(ignorewalk = 0)
. = ..()
. = 0
if(isopenturf(loc) && !is_flying())
var/turf/open/T = loc
. += T.slowdown
var/static/config_run_delay
var/static/config_walk_delay
if(isnull(config_run_delay))
config_run_delay = CONFIG_GET(number/run_delay)
config_walk_delay = CONFIG_GET(number/walk_delay)
if(ignorewalk)
. += config.run_speed
. += config_run_delay
else
switch(m_intent)
if(MOVE_INTENT_RUN)
if(drowsyness > 0)
. += 6
. += config.run_speed
. += config_run_delay
if(MOVE_INTENT_WALK)
. += config.walk_speed
. += config_walk_delay
/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction)
if(!has_gravity())
@@ -982,3 +987,19 @@
client.move_delay = world.time + movement_delay()
lying_prev = lying
return canmove
/mob/living/proc/AddAbility(obj/effect/proc_holder/A)
abilities.Add(A)
A.on_gain(src)
if(A.has_action)
A.action.Grant(src)
/mob/living/proc/RemoveAbility(obj/effect/proc_holder/A)
abilities.Remove(A)
A.on_lose(src)
if(A.action)
A.action.Remove(src)
/mob/living/proc/add_abilities_to_panel()
for(var/obj/effect/proc_holder/A in abilities)
statpanel("[A.panel]",A.get_panel_text(),A)
@@ -77,3 +77,5 @@
var/datum/language/selected_default_language
var/last_words //used for database logging
var/list/obj/effect/proc_holder/abilities = list()
+1 -1
View File
@@ -15,7 +15,7 @@
return "[radio_freq ? " (" + speaker.GetJob() + ")" : ""]" + "[speaker.GetSource() ? "</a>" : ""]"
/mob/living/silicon/ai/IsVocal()
return !config.silent_ai
return !CONFIG_GET(flag/silent_ai)
/mob/living/silicon/ai/radio(message, message_mode, list/spans, language)
if(incapacitated())
+37 -9
View File
@@ -211,9 +211,9 @@
"MediHound" = /obj/item/robot_module/medihound, \
"Security K9" = /obj/item/robot_module/k9, \
"Scrub Puppy" = /obj/item/robot_module/scrubpup)
if(!config.forbid_peaceborg)
if(!CONFIG_GET(flag/disable_peaceborg))
modulelist["Peacekeeper"] = /obj/item/robot_module/peacekeeper
if(!config.forbid_secborg)
if(!CONFIG_GET(flag/disable_secborg))
modulelist["Security"] = /obj/item/robot_module/security
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in modulelist
@@ -810,7 +810,35 @@
cell = null
qdel(src)
/mob/living/silicon/robot/syndicate
/mob/living/silicon/robot/modules
var/set_module = null
/mob/living/silicon/robot/modules/Initialize()
. = ..()
module.transform_to(set_module)
/mob/living/silicon/robot/modules/standard
set_module = /obj/item/robot_module/standard
/mob/living/silicon/robot/modules/medical
set_module = /obj/item/robot_module/medical
/mob/living/silicon/robot/modules/engineering
set_module = /obj/item/robot_module/engineering
/mob/living/silicon/robot/modules/security
set_module = /obj/item/robot_module/security
/mob/living/silicon/robot/modules/peacekeeper
set_module = /obj/item/robot_module/peacekeeper
/mob/living/silicon/robot/modules/miner
set_module = /obj/item/robot_module/miner
/mob/living/silicon/robot/modules/janitor
set_module = /obj/item/robot_module/janitor
/mob/living/silicon/robot/modules/syndicate
icon_state = "syndie_bloodhound"
faction = list("syndicate")
bubble_icon = "syndibot"
@@ -822,25 +850,24 @@
<b>You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
Your cyborg LMG will slowly produce ammunition from your power supply, and your operative pinpointer will find and locate fellow nuclear operatives. \
<i>Help the operatives secure the disk at all costs!</i></b>"
var/set_module = /obj/item/robot_module/syndicate
set_module = /obj/item/robot_module/syndicate
/mob/living/silicon/robot/syndicate/Initialize()
/mob/living/silicon/robot/modules/syndicate/Initialize()
. = ..()
cell.maxcharge = 25000
cell.charge = 25000
radio = new /obj/item/device/radio/borg/syndicate(src)
module.transform_to(set_module)
laws = new /datum/ai_laws/syndicate_override()
addtimer(CALLBACK(src, .proc/show_playstyle), 5)
/mob/living/silicon/robot/syndicate/proc/show_playstyle()
/mob/living/silicon/robot/modules/syndicate/proc/show_playstyle()
if(playstyle_string)
to_chat(src, playstyle_string)
/mob/living/silicon/robot/syndicate/ResetModule()
/mob/living/silicon/robot/modules/syndicate/ResetModule()
return
/mob/living/silicon/robot/syndicate/medical
/mob/living/silicon/robot/modules/syndicate/medical
icon_state = "syndi-medi"
playstyle_string = "<span class='userdanger'>You are a Syndicate medical cyborg!</span><br>\
<b>You are armed with powerful medical tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
@@ -896,6 +923,7 @@
see_invisible = initial(see_invisible)
see_in_dark = initial(see_in_dark)
sight = initial(sight)
lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
if(client.eye != src)
var/atom/A = client.eye
File diff suppressed because it is too large Load Diff
@@ -5,8 +5,10 @@
/mob/living/silicon/robot/movement_delay()
. = ..()
. += speed
. += config.robot_delay
var/static/config_robot_delay
if(isnull(config_robot_delay))
config_robot_delay = CONFIG_GET(number/robot_delay)
. += speed + config_robot_delay
/mob/living/silicon/robot/mob_negates_gravity()
return magpulse
+1 -1
View File
@@ -1,2 +1,2 @@
/mob/living/silicon/robot/IsVocal()
return !config.silent_borg
return !CONFIG_GET(flag/silent_borg)
@@ -4,7 +4,9 @@
/mob/living/silicon/forceMove(atom/destination)
. = ..()
update_camera_location(destination)
//Only bother updating the camera if we actually managed to move
if(.)
update_camera_location(destination)
/mob/living/silicon/proc/do_camera_update(oldLoc)
if(!QDELETED(builtInCamera) && oldLoc != get_turf(src))
@@ -543,4 +543,4 @@
declare_cooldown = world.time + 200
/obj/machinery/bot_core/medbot
req_one_access =list(ACCESS_MEDICAL, ACCESS_ROBOTICS)
req_one_access = list(ACCESS_MEDICAL, ACCESS_ROBOTICS)
@@ -9,33 +9,33 @@
/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
if(forced)
. = adjustHealth(amount * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[BRUTE])
. = adjustHealth(amount * damage_coeff[BRUTE] * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * damage_coeff[BRUTE] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
if(forced)
. = adjustHealth(amount * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[BURN])
. = adjustHealth(amount * damage_coeff[BURN] * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * damage_coeff[BURN] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustOxyLoss(amount, updating_health = TRUE, forced = FALSE)
if(forced)
. = adjustHealth(amount * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[OXY])
. = adjustHealth(amount * damage_coeff[OXY] * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * damage_coeff[OXY] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE)
if(forced)
. = adjustHealth(amount * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[TOX])
. = adjustHealth(amount * damage_coeff[TOX] * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * damage_coeff[TOX] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustCloneLoss(amount, updating_health = TRUE, forced = FALSE)
if(forced)
. = adjustHealth(amount * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[CLONE])
. = adjustHealth(amount * damage_coeff[CLONE] * config.damage_multiplier, updating_health, forced)
. = adjustHealth(amount * damage_coeff[CLONE] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustStaminaLoss(amount)
return
@@ -27,7 +27,7 @@
del_on_death = 1
/mob/living/simple_animal/cockroach/death(gibbed)
if(SSticker.cinematic) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
if(SSticker.mode && SSticker.mode.station_was_nuked) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
return
..()
@@ -42,7 +42,7 @@
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
else
if(istype(AM, /obj/structure))
if(isstructure(AM))
if(prob(squish_chance))
AM.visible_message("<span class='notice'>[src] was crushed under [AM].</span>")
adjustBruteLoss(1)
@@ -424,6 +424,41 @@
setDir(i)
sleep(1)
/mob/living/simple_animal/pet/dog/corgi/Ian/narsie_act()
playsound(src, 'sound/magic/demon_dies.ogg', 75, TRUE)
var/mob/living/simple_animal/pet/dog/corgi/narsie/N = new(loc)
N.setDir(dir)
gib()
/mob/living/simple_animal/pet/dog/corgi/narsie
name = "Nars-Ian"
desc = "Ia! Ia!"
icon_state = "narsian"
icon_living = "narsian"
icon_dead = "narsian_dead"
faction = list("dog", "cult")
gold_core_spawnable = FALSE
nofur = TRUE
/mob/living/simple_animal/pet/dog/corgi/narsie/Life()
..()
for(var/mob/living/simple_animal/pet/P in range(1, src))
if(P != src && prob(5))
visible_message("<span class='warning'>[src] devours [P]!</span>", \
"<span class='cult big bold'>DELICIOUS SOULS</span>")
playsound(src, 'sound/magic/demon_attack1.ogg', 75, TRUE)
narsie_act()
P.gib()
/mob/living/simple_animal/pet/dog/corgi/narsie/update_corgi_fluff()
..()
speak = list("Tari'karat-pasnar!", "IA! IA!", "BRRUUURGHGHRHR")
speak_emote = list("growls", "barks ominously")
emote_hear = list("barks echoingly!", "woofs hauntingly!", "yaps in an eldritch manner.", "mutters something unspeakable.")
emote_see = list("communes with the unnameable.", "ponders devouring some souls.", "shakes.")
/mob/living/simple_animal/pet/dog/corgi/narsie/narsie_act()
adjustBruteLoss(-maxHealth)
/mob/living/simple_animal/pet/dog/corgi/regenerate_icons()
@@ -30,7 +30,7 @@
/obj/item/drone_shell/attack_ghost(mob/user)
if(jobban_isbanned(user,"drone"))
return
if(config.use_age_restriction_for_jobs)
if(CONFIG_GET(flag/use_age_restriction_for_jobs))
if(!isnum(user.client.player_age)) //apparently what happens when there's no DB connected. just don't let anybody be a drone without admin intervention
return
if(user.client.player_age < DRONE_MINIMUM_AGE)
@@ -130,9 +130,9 @@
hacked = TRUE
visualAppearence = CLOCKDRONE
can_be_held = FALSE
flavortext = "<span class='heavy_brass'>You are a cogscarab</span><b>, a clockwork creation of Ratvar. As a cogscarab, you have low health, an inbuilt fabricator that can convert brass \
to power, a set of relatively fast tools, </b><span class='heavy_brass'>can communicate over the Hierophant Network with :b</span><b>, and are immune to extreme \
temperatures and pressures. \nYour goal is to serve the Justiciar and his servants by repairing and defending all they create.</b>"
flavortext = "<b><span class='nezbere'>You are a cogscarab,</span> a tiny building construct of Ratvar. While you're weak and can't recite scripture, \
you have a set of quick tools, as well as a replica fabricator that can create brass and convert objects.<br><br>Work with the servants of Ratvar \
to construct and maintain defenses at the City of Cogs. If there are no servants, use this time to experiment with base designs!"
/mob/living/simple_animal/drone/cogscarab/ratvar //a subtype for spawning when ratvar is alive, has a slab that it can use and a normal fabricator
default_storage = /obj/item/storage/toolbox/brass/prefilled/ratvar
@@ -237,3 +237,8 @@
. = ..()
if(.)
update_icons()
/mob/living/simple_animal/drone/cogscarab/update_canmove()
. = ..()
if(.)
update_icons()
@@ -49,6 +49,17 @@
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
var/playable_spider = FALSE
devourable = TRUE
var/datum/action/innate/spider/lay_web/lay_web
var/directive = "" //Message passed down to children, to relay the creator's orders
/mob/living/simple_animal/hostile/poison/giant_spider/Initialize()
. = ..()
lay_web = new
lay_web.Grant(src)
/mob/living/simple_animal/hostile/poison/giant_spider/Destroy()
QDEL_NULL(lay_web)
return ..()
/mob/living/simple_animal/hostile/poison/giant_spider/Topic(href, href_list)
if(href_list["activate"])
@@ -56,6 +67,12 @@
if(istype(ghost) && playable_spider)
humanize_spider(ghost)
/mob/living/simple_animal/hostile/poison/giant_spider/Login()
..()
if(directive)
to_chat(src, "<span class='notice'>Your mother left you a directive! Follow it at all costs.</span>")
to_chat(src, "<span class='spider'><b>[directive]</b></span>")
/mob/living/simple_animal/hostile/poison/giant_spider/attack_ghost(mob/user)
if(!humanize_spider(user))
return ..()
@@ -87,8 +104,26 @@
poison_per_bite = 3
var/atom/movable/cocoon_target
var/fed = 0
var/obj/effect/proc_holder/wrap/wrap
var/datum/action/innate/spider/lay_eggs/lay_eggs
var/datum/action/innate/spider/set_directive/set_directive
var/static/list/consumed_mobs = list() //the tags of mobs that have been consumed by nurse spiders to lay eggs
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/Initialize()
. = ..()
wrap = new
AddAbility(wrap)
lay_eggs = new
lay_eggs.Grant(src)
set_directive = new
set_directive.Grant(src)
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/Destroy()
RemoveAbility(wrap)
QDEL_NULL(lay_eggs)
QDEL_NULL(set_directive)
return ..()
//hunters have the most poison and move the fastest, so they can find prey
/mob/living/simple_animal/hostile/poison/giant_spider/hunter
desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes."
@@ -117,6 +152,7 @@
move_to_delay = 4
poison_type = "venom" //all in venom, glass cannon. you bite 5 times and they are DEFINITELY dead, but 40 health and you are extremely obvious. Ambush, maybe?
speed = 1
gold_core_spawnable = 0
//tarantulas are really tanky, regenerating (maybe), hulky monster but are also extremely slow, so.
/mob/living/simple_animal/hostile/poison/giant_spider/tarantula
@@ -134,6 +170,7 @@
speed = 7
status_flags = NONE
mob_size = MOB_SIZE_LARGE
gold_core_spawnable = 0
/mob/living/simple_animal/hostile/poison/giant_spider/tarantula/movement_delay()
var/turf/T = get_turf(src)
@@ -153,12 +190,16 @@
maxHealth = 40
health = 40
var/datum/action/innate/spider/comm/letmetalkpls
gold_core_spawnable = 0
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife/Initialize()
. = ..()
letmetalkpls = new
letmetalkpls.Grant(src)
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife/Destroy()
QDEL_NULL(letmetalkpls)
return ..()
/mob/living/simple_animal/hostile/poison/giant_spider/ice //spiders dont usually like tempatures of 140 kelvin who knew
name = "giant ice spider"
@@ -222,11 +263,11 @@
//second, spin a sticky spiderweb on this tile
var/obj/structure/spider/stickyweb/W = locate() in get_turf(src)
if(!W)
Web()
lay_web.Activate()
else
//third, lay an egg cluster there
if(fed)
LayEggs()
lay_eggs.Activate()
else
//fourthly, cocoon any nearby items so those pesky pinkskins can't use them
for(var/obj/O in can_see)
@@ -234,7 +275,7 @@
if(O.anchored)
continue
if(isitem(O) || istype(O, /obj/structure) || istype(O, /obj/machinery))
if(isitem(O) || isstructure(O) || istype(O, /obj/machinery))
cocoon_target = O
busy = MOVING_TO_TARGET
stop_automated_movement = 1
@@ -244,62 +285,28 @@
else if(busy == MOVING_TO_TARGET && cocoon_target)
if(get_dist(src, cocoon_target) <= 1)
Wrap()
cocoon()
else
busy = SPIDER_IDLE
stop_automated_movement = FALSE
/mob/living/simple_animal/hostile/poison/giant_spider/verb/Web()
set name = "Lay Web"
set category = "Spider"
set desc = "Spread a sticky web to slow down prey."
var/T = src.loc
if(stat == DEAD)
return
if(busy != SPINNING_WEB)
busy = SPINNING_WEB
src.visible_message("<span class='notice'>\the [src] begins to secrete a sticky substance.</span>")
stop_automated_movement = 1
if(do_after(src, 40, target = T))
if(busy == SPINNING_WEB && src.loc == T)
new /obj/structure/spider/stickyweb(T)
busy = SPIDER_IDLE
stop_automated_movement = FALSE
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/verb/Wrap()
set name = "Wrap"
set category = "Spider"
set desc = "Wrap up prey to feast upon and objects for safe keeping."
if(stat == DEAD)
return
if(!cocoon_target)
var/list/choices = list()
for(var/mob/living/L in view(1,src))
if(L == src || L.anchored)
continue
if(istype(L, /mob/living/simple_animal/hostile/poison/giant_spider))
continue
if(Adjacent(L))
choices += L
for(var/obj/O in src.loc)
if(O.anchored)
continue
if(Adjacent(O))
choices += O
var/temp_input = input(src,"What do you wish to cocoon?") in null|choices
if(temp_input && !cocoon_target)
cocoon_target = temp_input
if(stat != DEAD && cocoon_target && Adjacent(cocoon_target) && !cocoon_target.anchored)
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/proc/cocoon()
if(stat != DEAD && cocoon_target && !cocoon_target.anchored)
if(cocoon_target == src)
to_chat(src, "<span class='warning'>You can't wrap yourself!</span>")
return
if(istype(cocoon_target, /mob/living/simple_animal/hostile/poison/giant_spider))
to_chat(src, "<span class='warning'>You can't wrap other spiders!</span>")
return
if(!Adjacent(cocoon_target))
to_chat(src, "<span class='warning'>You can't reach [cocoon_target]!</span>")
return
if(busy == SPINNING_COCOON)
to_chat(src, "<span class='warning'>You're already spinning a cocoon!</span>")
return //we're already doing this, don't cancel out or anything
busy = SPINNING_COCOON
visible_message("<span class='notice'>\the [src] begins to secrete a sticky substance around \the [cocoon_target].</span>")
visible_message("<span class='notice'>[src] begins to secrete a sticky substance around [cocoon_target].</span>","<span class='notice'>You begin wrapping [cocoon_target] into a cocoon.</span>")
stop_automated_movement = TRUE
walk(src,0)
if(do_after(src, 50, target = cocoon_target))
@@ -310,7 +317,8 @@
if(L.blood_volume && (L.stat != DEAD || !consumed_mobs[L.tag])) //if they're not dead, you can consume them anyway
consumed_mobs[L.tag] = TRUE
fed++
visible_message("<span class='danger'>\the [src] sticks a proboscis into \the [L] and sucks a viscous substance out.</span>")
lay_eggs.UpdateButtonIcon(TRUE)
visible_message("<span class='danger'>[src] sticks a proboscis into [L] and sucks a viscous substance out.</span>","<span class='notice'>You suck the nutriment out of [L], feeding you enough to lay a cluster of eggs.</span>")
L.death() //you just ate them, they're dead.
else
to_chat(src, "<span class='warning'>[L] cannot sate your hunger!</span>")
@@ -322,35 +330,155 @@
busy = SPIDER_IDLE
stop_automated_movement = FALSE
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/verb/LayEggs()
set name = "Lay Eggs"
set category = "Spider"
set desc = "Lay a clutch of eggs, but you must wrap a creature for feeding first."
/datum/action/innate/spider
icon_icon = 'icons/mob/actions/actions_animal.dmi'
background_icon_state = "bg_alien"
var/obj/structure/spider/eggcluster/E = locate() in get_turf(src)
if(stat == DEAD)
/datum/action/innate/spider/lay_web
name = "Spin Web"
desc = "Spin a web to slow down potential prey."
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "lay_web"
/datum/action/innate/spider/lay_web/Activate()
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
return
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner
if(!isturf(S.loc))
return
var/turf/T = get_turf(S)
var/obj/structure/spider/stickyweb/W = locate() in T
if(W)
to_chat(S, "<span class='warning'>There's already a web here!</span>")
return
if(S.busy != SPINNING_WEB)
S.busy = SPINNING_WEB
S.visible_message("<span class='notice'>[S] begins to secrete a sticky substance.</span>","<span class='notice'>You begin to lay a web.</span>")
S.stop_automated_movement = TRUE
if(do_after(S, 40, target = T))
if(S.busy == SPINNING_WEB && S.loc == T)
new /obj/structure/spider/stickyweb(T)
S.busy = SPIDER_IDLE
S.stop_automated_movement = FALSE
else
to_chat(S, "<span class='warning'>You're already spinning a web!</span>")
/obj/effect/proc_holder/wrap
name = "Wrap"
panel = "Spider"
active = FALSE
datum/action/spell_action/action = null
desc = "Wrap something or someone in a cocoon. If it's a living being, you'll also consume them, allowing you to lay eggs."
ranged_mousepointer = 'icons/effects/wrap_target.dmi'
action_icon = 'icons/mob/actions/actions_animal.dmi'
action_icon_state = "wrap_0"
action_background_icon_state = "bg_alien"
/obj/effect/proc_holder/wrap/Initialize()
. = ..()
action = new(src)
/obj/effect/proc_holder/wrap/update_icon()
action.button_icon_state = "wrap_[active]"
action.UpdateButtonIcon()
/obj/effect/proc_holder/wrap/Click()
if(!istype(usr, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
return TRUE
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/user = usr
activate(user)
return TRUE
/obj/effect/proc_holder/wrap/proc/activate(mob/living/user)
var/message
if(active)
message = "<span class='notice'>You no longer prepare to wrap something in a cocoon.</span>"
remove_ranged_ability(message)
else
message = "<span class='notice'>You prepare to wrap something in a cocoon. <B>Left-click your target to start wrapping!</B></span>"
add_ranged_ability(user, message, TRUE)
return 1
/obj/effect/proc_holder/wrap/InterceptClickOn(mob/living/caller, params, atom/target)
if(..())
return
if(ranged_ability_user.incapacitated() || !istype(ranged_ability_user, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
remove_ranged_ability()
return
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/user = ranged_ability_user
if(user.Adjacent(target) && (ismob(target) || isobj(target)))
var/atom/movable/target_atom = target
if(target_atom.anchored)
return
user.cocoon_target = target_atom
INVOKE_ASYNC(user, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/.proc/cocoon)
remove_ranged_ability()
return TRUE
/obj/effect/proc_holder/wrap/on_lose(mob/living/carbon/user)
remove_ranged_ability()
/datum/action/innate/spider/lay_eggs
name = "Lay Eggs"
desc = "Lay a cluster of eggs, which will soon grow into more spiders. You must wrap a living being to do this."
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "lay_eggs"
/datum/action/innate/spider/lay_eggs/IsAvailable()
if(..())
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
return 0
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner
if(S.fed)
return 1
return 0
/datum/action/innate/spider/lay_eggs/Activate()
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
return
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner
var/obj/structure/spider/eggcluster/E = locate() in get_turf(S)
if(E)
to_chat(src, "<span class='warning'>There is already a cluster of eggs here!</span>")
else if(!fed)
to_chat(src, "<span class='warning'>You are too hungry to do this!</span>")
else if(busy != LAYING_EGGS)
busy = LAYING_EGGS
src.visible_message("<span class='notice'>\the [src] begins to lay a cluster of eggs.</span>")
stop_automated_movement = 1
if(do_after(src, 50, target = src.loc))
if(busy == LAYING_EGGS)
E = locate() in get_turf(src)
if(!E)
var/obj/structure/spider/eggcluster/C = new /obj/structure/spider/eggcluster(src.loc)
if(ckey)
C.player_spiders = 1
C.poison_type = poison_type
C.poison_per_bite = poison_per_bite
C.faction = faction.Copy()
fed--
busy = SPIDER_IDLE
stop_automated_movement = FALSE
to_chat(S, "<span class='warning'>There is already a cluster of eggs here!</span>")
else if(!S.fed)
to_chat(S, "<span class='warning'>You are too hungry to do this!</span>")
else if(S.busy != LAYING_EGGS)
S.busy = LAYING_EGGS
S.visible_message("<span class='notice'>[S] begins to lay a cluster of eggs.</span>","<span class='notice'>You begin to lay a cluster of eggs.</span>")
S.stop_automated_movement = TRUE
if(do_after(S, 50, target = get_turf(S)))
if(S.busy == LAYING_EGGS)
E = locate() in get_turf(S)
if(!E || !isturf(S.loc))
var/obj/structure/spider/eggcluster/C = new /obj/structure/spider/eggcluster(get_turf(S))
if(S.ckey)
C.player_spiders = TRUE
C.directive = S.directive
C.poison_type = S.poison_type
C.poison_per_bite = S.poison_per_bite
C.faction = S.faction.Copy()
S.fed--
UpdateButtonIcon(TRUE)
S.busy = SPIDER_IDLE
S.stop_automated_movement = FALSE
/datum/action/innate/spider/set_directive
name = "Set Directive"
desc = "Set a directive for your children to follow."
check_flags = AB_CHECK_CONSCIOUS
button_icon_state = "directive"
/datum/action/innate/spider/set_directive/Activate()
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse))
return
var/mob/living/simple_animal/hostile/poison/giant_spider/nurse/S = owner
S.directive = stripped_input(S, "Enter the new directive", "Create directive", "[S.directive]", MAX_MESSAGE_LEN)
/mob/living/simple_animal/hostile/poison/giant_spider/Login()
. = ..()
@@ -362,7 +490,8 @@
/datum/action/innate/spider/comm
name = "Command"
button_icon_state = "cult_comms"
desc = "Send a command to all living spiders."
button_icon_state = "command"
/datum/action/innate/spider/comm/IsAvailable()
if(!istype(owner, /mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife))
@@ -370,19 +499,22 @@
return TRUE
/datum/action/innate/spider/comm/Trigger()
var/input = stripped_input(usr, "Input a message for your legions to follow.", "Command", "")
var/input = stripped_input(owner, "Input a command for your legions to follow.", "Command", "")
if(QDELETED(src) || !input || !IsAvailable())
return FALSE
spider_command(usr, input)
spider_command(owner, input)
return TRUE
/datum/action/innate/spider/comm/proc/spider_command(mob/living/user, message)
if(!message)
return
var/my_message
my_message = "<FONT size = 3><b>COMMAND FROM SPIDER QUEEN:</b> [message]</FONT>"
my_message = "<span class='spider'><b>Command from [user]:</b> [message]</span>"
for(var/mob/living/simple_animal/hostile/poison/giant_spider/M in GLOB.spidermobs)
to_chat(M, my_message)
for(var/M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, user)
to_chat(M, "[link] [my_message]")
log_talk(user, "SPIDERCOMMAND: [key_name(user)] : [message]",LOGSAY)
/mob/living/simple_animal/hostile/poison/giant_spider/handle_temperature_damage()
@@ -46,9 +46,9 @@
var/search_objects_timer_id //Timer for regaining our old search_objects value after being attacked
var/search_objects_regain_time = 30 //the delay between being attacked and gaining our old search_objects value back
var/list/wanted_objects = list() //A typecache of objects types that will be checked against to attack, should we have search_objects enabled
var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead.
var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction
var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead.
var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such
var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects.
@@ -164,56 +164,55 @@
var/chosen_target = pick(Targets)//Pick the remaining targets (if any) at random
return chosen_target
/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(!the_target)
return 0
// Please do not add one-off mob AIs here, but override this function for your mob
/mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
return FALSE
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
return 0
return FALSE
if(search_objects < 2)
if(isliving(the_target))
var/mob/living/L = the_target
var/faction_check = faction_check_mob(L)
if(robust_searching)
if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive)
return 0
if(faction_check && !attack_same || !faction_check && attack_same == 2)
return 0
if(L in friends)
return 0
else
if(L.stat)
return 0
if(faction_check && !attack_same)
return 0
return 1
return FALSE
if(L.stat > stat_attack)
return FALSE
if(L in friends)
return FALSE
else
if((faction_check && !attack_same) || L.stat)
return FALSE
return TRUE
if(istype(the_target, /obj/mecha))
var/obj/mecha/M = the_target
if(M.occupant)//Just so we don't attack empty mechs
if(CanAttack(M.occupant))
return 1
return TRUE
if(istype(the_target, /obj/machinery/porta_turret))
var/obj/machinery/porta_turret/P = the_target
if(P.faction in faction)
return 0
return FALSE
if(P.has_cover &&!P.raised) //Don't attack invincible turrets
return 0
return FALSE
if(P.stat & BROKEN) //Or turrets that are already broken
return 0
return 1
return FALSE
return TRUE
if(istype(the_target, /obj/structure/destructible/clockwork/ocular_warden))
var/obj/structure/destructible/clockwork/ocular_warden/OW = the_target
if(OW.target != src)
return FALSE
return TRUE
if(isobj(the_target))
if(attack_all_objects || is_type_in_typecache(the_target, wanted_objects))
return 1
return 0
return TRUE
return FALSE
/mob/living/simple_animal/hostile/proc/GiveTarget(new_target)//Step 4, give us our selected target
target = new_target
@@ -164,6 +164,7 @@ Difficulty: Medium
hitsound = 'sound/weapons/sear.ogg'
var/storm_type = /datum/weather/ash_storm
var/storm_cooldown = 0
var/static/list/excluded_areas = list(/area/reebe/city_of_cogs)
/obj/item/staff/storm/attack_self(mob/user)
if(storm_cooldown > world.time)
@@ -171,6 +172,9 @@ Difficulty: Medium
return
var/area/user_area = get_area(user)
if(user_area.type in excluded_areas)
to_chat(user, "<span class='warning'>Something is preventing you from using the staff here.</span>")
return
var/datum/weather/A
for(var/V in SSweather.existing_weather)
var/datum/weather/W = V
@@ -130,7 +130,7 @@
if(admin_spawned)
return FALSE
if(global.medal_hub && global.medal_pass && global.medals_enabled)
if(MedalsAvailable())
for(var/mob/living/L in view(7,src))
if(L.stat)
continue
@@ -144,55 +144,52 @@
return TRUE
/proc/UnlockMedal(medal,client/player)
set waitfor = FALSE
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
spawn()
var/result = world.SetMedal(medal, player, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to award medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to award [medal] medal to [player.ckey]!")
else if (result)
to_chat(player, "<span class='greenannounce'><B>Achievement unlocked: [medal]!</B></span>")
if(MedalsAvailable())
var/result = world.SetMedal(medal, player, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
if(isnull(result))
GLOB.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to award medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to award [medal] medal to [player.ckey]!")
else if (result)
to_chat(player, "<span class='greenannounce'><B>Achievement unlocked: [medal]!</B></span>")
/proc/SetScore(score,client/player,increment,force)
set waitfor = FALSE
if(!score || !player)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
spawn()
var/list/oldscore = GetScore(score,player,1)
if(increment)
if(!oldscore[score])
oldscore[score] = 1
else
oldscore[score] = (text2num(oldscore[score]) + 1)
if(MedalsAvailable())
var/list/oldscore = GetScore(score,player,1)
if(increment)
if(!oldscore[score])
oldscore[score] = 1
else
oldscore[score] = force
oldscore[score] = (text2num(oldscore[score]) + 1)
else
oldscore[score] = force
var/newscoreparam = list2params(oldscore)
var/newscoreparam = list2params(oldscore)
var/result = world.SetScores(player.ckey, newscoreparam, global.medal_hub, global.medal_pass)
var/result = world.SetScores(player.ckey, newscoreparam, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
if(isnull(result))
global.medals_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to set score. Score:[score] player:[player.ckey]")
message_admins("Error! Failed to contact hub to set [score] score for [player.ckey]!")
if(isnull(result))
GLOB.medals_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to set score. Score:[score] player:[player.ckey]")
message_admins("Error! Failed to contact hub to set [score] score for [player.ckey]!")
/proc/GetScore(score,client/player,returnlist)
if(!score || !player)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
if(MedalsAvailable())
var/scoreget = world.GetScores(player.ckey, score, global.medal_hub, global.medal_pass)
var/scoreget = world.GetScores(player.ckey, score, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
if(isnull(scoreget))
global.medals_enabled = FALSE
GLOB.medals_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to get score. Score:[score] player:[player.ckey]")
message_admins("Error! Failed to contact hub to get score: [score] for [player.ckey]!")
return
@@ -209,12 +206,12 @@
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
if(MedalsAvailable())
var/result = world.GetMedal(medal, player, global.medal_hub, global.medal_pass)
var/result = world.GetMedal(medal, player, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
if(isnull(result))
global.medals_enabled = FALSE
GLOB.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to get medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to get [medal] medal for [player.ckey]!")
else if (result)
@@ -224,12 +221,12 @@
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
if(MedalsAvailable())
var/result = world.ClearMedal(medal, player, global.medal_hub, global.medal_pass)
var/result = world.ClearMedal(medal, player, CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
if(isnull(result))
global.medals_enabled = FALSE
GLOB.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to clear medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to clear [medal] medal for [player.ckey]!")
else if (result)
@@ -239,6 +236,9 @@
/proc/ClearScore(client/player)
world.SetScores(player.ckey, "", global.medal_hub, global.medal_pass)
world.SetScores(player.ckey, "", CONFIG_GET(string/medal_hub_address), CONFIG_GET(string/medal_hub_password))
/proc/MedalsAvailable()
return CONFIG_GET(string/medal_hub_address) && CONFIG_GET(string/medal_hub_password) && GLOB.medals_enabled
#undef MEDAL_PREFIX
@@ -130,7 +130,7 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
faction |= "\ref[owner]"
/mob/living/simple_animal/hostile/mimic/copy/proc/CheckObject(obj/O)
if((isitem(O) || istype(O, /obj/structure)) && !is_type_in_list(O, GLOB.protected_objects))
if((isitem(O) || isstructure(O)) && !is_type_in_list(O, GLOB.protected_objects))
return 1
return 0
@@ -144,7 +144,7 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
icon_living = icon_state
copy_overlays(O)
add_overlay(googly_eyes)
if(istype(O, /obj/structure) || istype(O, /obj/machinery))
if(isstructure(O) || istype(O, /obj/machinery))
health = (anchored * 50) + 50
destroy_objects = 1
if(O.density && O.anchored)
@@ -45,6 +45,25 @@
udder = new()
. = ..()
/mob/living/simple_animal/hostile/asteroid/gutlunch/CanAttack(atom/the_target) // Gutlunch-specific version of CanAttack to handle stupid stat_exclusive = true crap so we don't have to do it for literally every single simple_animal/hostile except the two that spawn in lavaland
if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids
return FALSE
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
return FALSE
if(isliving(the_target))
var/mob/living/L = the_target
if(faction_check_mob(L) && !attack_same)
return FALSE
if(L.stat > stat_attack || L.stat != stat_attack && stat_exclusive)
return FALSE
return TRUE
return FALSE
/mob/living/simple_animal/hostile/asteroid/gutlunch/Destroy()
QDEL_NULL(udder)
return ..()
@@ -55,7 +55,7 @@
last_tendril = FALSE
break
if(last_tendril && !admin_spawned)
if(global.medal_hub && global.medal_pass && global.medals_enabled)
if(MedalsAvailable())
for(var/mob/living/L in view(7,src))
if(L.stat)
continue
@@ -62,6 +62,25 @@
health = maxHealth
. = ..()
/mob/living/simple_animal/hostile/mushroom/CanAttack(atom/the_target) // Mushroom-specific version of CanAttack to handle stupid attack_same = 2 crap so we don't have to do it for literally every single simple_animal/hostile because this shit never gets spawned
if(!the_target || isturf(the_target) || istype(the_target, /atom/movable/lighting_object))
return FALSE
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
return FALSE
if(isliving(the_target))
var/mob/living/L = the_target
if (!faction_check_mob(L) && attack_same == 2)
return FALSE
if(L.stat > stat_attack)
return FALSE
return TRUE
return FALSE
/mob/living/simple_animal/hostile/mushroom/adjustHealth(amount, updating_health = TRUE, forced = FALSE) //Possibility to flee from a fight just to make it more visually interesting
if(!retreat_distance && prob(33))
retreat_distance = 5
+43 -17
View File
@@ -33,6 +33,7 @@
icon_state = "parrot_fly"
icon_living = "parrot_fly"
icon_dead = "parrot_dead"
var/icon_sit = "parrot_sit"
density = FALSE
health = 80
maxHealth = 80
@@ -284,7 +285,7 @@
return
if(!stat && M.a_intent == INTENT_HARM)
icon_state = "parrot_fly" //It is going to be flying regardless of whether it flees or attacks
icon_state = icon_living //It is going to be flying regardless of whether it flees or attacks
if(parrot_state == PARROT_PERCH)
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
@@ -320,7 +321,7 @@
if(M.melee_damage_upper > 0 && !stat)
parrot_interest = M
parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless
icon_state = "parrot_fly"
icon_state = icon_living
//Mobs with objects
/mob/living/simple_animal/parrot/attackby(obj/item/O, mob/living/user, params)
@@ -335,7 +336,7 @@
parrot_state |= PARROT_ATTACK
else
parrot_state |= PARROT_FLEE
icon_state = "parrot_fly"
icon_state = icon_living
drop_held_item(0)
else if(istype(O, /obj/item/reagent_containers/food/snacks/cracker)) //Poly wants a cracker.
qdel(O)
@@ -358,7 +359,7 @@
parrot_interest = null
parrot_state = PARROT_WANDER | PARROT_FLEE //Been shot and survived! RUN LIKE HELL!
//parrot_been_shot += 5
icon_state = "parrot_fly"
icon_state = icon_living
drop_held_item(0)
return
@@ -371,7 +372,7 @@
//Sprite update for when a parrot gets pulled
if(pulledby && stat == CONSCIOUS)
icon_state = "parrot_fly"
icon_state = icon_living
if(!client)
parrot_state = PARROT_WANDER
return
@@ -400,11 +401,11 @@
if(parrot_perch && parrot_perch.loc != src.loc) //Make sure someone hasnt moved our perch on us
if(parrot_perch in view(src))
parrot_state = PARROT_SWOOP | PARROT_RETURN
icon_state = "parrot_fly"
icon_state = icon_living
return
else
parrot_state = PARROT_WANDER
icon_state = "parrot_fly"
icon_state = icon_living
return
if(--parrot_sleep_dur) //Zzz
@@ -445,7 +446,7 @@
if(parrot_interest)
emote("me", 1, "looks in [parrot_interest]'s direction and takes flight.")
parrot_state = PARROT_SWOOP | PARROT_STEAL
icon_state = "parrot_fly"
icon_state = icon_living
return
//-----WANDERING - This is basically a 'I dont know what to do yet' state
@@ -530,7 +531,7 @@
src.loc = parrot_perch.loc
drop_held_item()
parrot_state = PARROT_PERCH
icon_state = "parrot_sit"
icon_state = icon_sit
return
walk_to(src, parrot_perch, 1, parrot_speed)
@@ -603,8 +604,8 @@
*/
/mob/living/simple_animal/parrot/movement_delay()
if(client && stat == CONSCIOUS && parrot_state != "parrot_fly")
icon_state = "parrot_fly"
if(client && stat == CONSCIOUS && parrot_state != icon_living)
icon_state = icon_living
//Because the most appropriate place to set icon_state is movement_delay(), clearly
return ..()
@@ -797,12 +798,12 @@
if(stat || !client)
return
if(icon_state == "parrot_fly")
if(icon_state == icon_living)
for(var/atom/movable/AM in view(src,1))
for(var/perch_path in desired_perches)
if(istype(AM, perch_path))
src.loc = AM.loc
icon_state = "parrot_sit"
icon_state = icon_sit
return
to_chat(src, "<span class='warning'>There is no perch nearby to sit on!</span>")
return
@@ -816,7 +817,7 @@
if(stat || !client)
return
if(icon_state == "parrot_fly")
if(icon_state == icon_living)
for(var/mob/living/carbon/human/H in view(src,1))
if(H.has_buckled_mobs() && H.buckled_mobs.len >= H.max_buckled_mobs) //Already has a parrot, or is being eaten by a slime
continue
@@ -824,7 +825,7 @@
return
to_chat(src, "<span class='warning'>There is nobody nearby that you can sit on!</span>")
else
icon_state = "parrot_fly"
icon_state = icon_living
parrot_state = PARROT_WANDER
if(buckled)
to_chat(src, "<span class='notice'>You are no longer sitting on [buckled]'s shoulder.</span>")
@@ -842,7 +843,7 @@
H.buckle_mob(src, force=1)
pixel_y = 9
pixel_x = pick(-8,8) //pick left or right shoulder
icon_state = "parrot_sit"
icon_state = icon_sit
parrot_state = PARROT_PERCH
to_chat(src, "<span class='notice'>You sit on [H]'s shoulder.</span>")
@@ -961,6 +962,12 @@
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
/mob/living/simple_animal/parrot/Poly/ratvar_act()
playsound(src, 'sound/magic/clockwork/fellowship_armory.ogg', 75, TRUE)
var/mob/living/simple_animal/parrot/clock_hawk/H = new(loc)
H.setDir(dir)
dust()
/mob/living/simple_animal/parrot/Poly/ghost
name = "The Ghost of Poly"
desc = "Doomed to squawk the earth."
@@ -996,4 +1003,23 @@
loc = H
H.ContractDisease(P)
parrot_interest = null
H.visible_message("<span class='danger'>[src] dive bombs into [H]'s chest and vanishes!</span>", "<span class='userdanger'>[src] dive bombs into your chest, vanishing! This can't be good!</span>")
H.visible_message("<span class='danger'>[src] dive bombs into [H]'s chest and vanishes!</span>", "<span class='userdanger'>[src] dive bombs into your chest, vanishing! This can't be good!</span>")
/mob/living/simple_animal/parrot/clock_hawk
name = "clock hawk"
desc = "Cbyl jnaan penpxre! Fdhnnnjx!"
icon_state = "clock_hawk_fly"
icon_living = "clock_hawk_fly"
icon_sit = "clock_hawk_sit"
speak = list("Penpxre!", "Ratvar vf n qhzo anzr naljnl!")
speak_emote = list("squawks rustily", "says crassly", "yells brassly")
emote_hear = list("squawks rustily.", "bawks metallically!")
emote_see = list("flutters its metal wings.")
faction = list("ratvar")
gold_core_spawnable = FALSE
del_on_death = TRUE
death_sound = 'sound/magic/clockwork/anima_fragment_death.ogg'
/mob/living/simple_animal/parrot/clock_hawk/ratvar_act()
return
+66 -66
View File
@@ -1,66 +1,66 @@
/mob/living/simple_animal/shade
name = "Shade"
real_name = "Shade"
desc = "A bound spirit"
gender = PLURAL
icon = 'icons/mob/mob.dmi'
icon_state = "shade"
icon_living = "shade"
maxHealth = 50
health = 50
healable = 0
speak_emote = list("hisses")
emote_hear = list("wails.","screeches.")
response_help = "puts their hand through"
response_disarm = "flails at"
response_harm = "punches"
speak_chance = 1
melee_damage_lower = 5
melee_damage_upper = 15
attacktext = "metaphysically strikes"
minbodytemp = 0
maxbodytemp = INFINITY
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
speed = -1
stop_automated_movement = 1
status_flags = 0
faction = list("cult")
status_flags = CANPUSH
movement_type = FLYING
loot = list(/obj/item/ectoplasm)
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
/mob/living/simple_animal/shade/death()
deathmessage = "lets out a contented sigh as [p_their()] form unwinds."
..()
/mob/living/simple_animal/shade/canSuicide()
if(istype(loc, /obj/item/device/soulstone)) //do not suicide inside the soulstone
return 0
return ..()
/mob/living/simple_animal/shade/Process_Spacemove(movement_dir = 0)
return TRUE //this doesn't make much sense; you'd thing TRUE would mean it'd process spacemove but it means it doesn't
/mob/living/simple_animal/shade/attack_animal(mob/living/simple_animal/M)
if(isconstruct(M))
var/mob/living/simple_animal/hostile/construct/C = M
if(!C.can_repair_constructs)
return
if(health < maxHealth)
adjustHealth(-25)
Beam(M,icon_state="sendbeam",time=4)
M.visible_message("<span class='danger'>[M] heals \the <b>[src]</b>.</span>", \
"<span class='cult'>You heal <b>[src]</b>, leaving <b>[src]</b> at <b>[health]/[maxHealth]</b> health.</span>")
else
to_chat(M, "<span class='cult'>You cannot heal <b>[src]</b>, as [p_they()] [p_are()] unharmed!</span>")
else if(src != M)
return ..()
/mob/living/simple_animal/shade/attackby(obj/item/O, mob/user, params) //Marker -Agouri
if(istype(O, /obj/item/device/soulstone))
var/obj/item/device/soulstone/SS = O
SS.transfer_soul("SHADE", src, user)
else
..()
/mob/living/simple_animal/shade
name = "Shade"
real_name = "Shade"
desc = "A bound spirit"
gender = PLURAL
icon = 'icons/mob/mob.dmi'
icon_state = "shade"
icon_living = "shade"
maxHealth = 50
health = 50
healable = 0
speak_emote = list("hisses")
emote_hear = list("wails.","screeches.")
response_help = "puts their hand through"
response_disarm = "flails at"
response_harm = "punches"
speak_chance = 1
melee_damage_lower = 5
melee_damage_upper = 15
attacktext = "metaphysically strikes"
minbodytemp = 0
maxbodytemp = INFINITY
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
speed = -1
stop_automated_movement = 1
status_flags = 0
faction = list("cult")
status_flags = CANPUSH
movement_type = FLYING
loot = list(/obj/item/ectoplasm)
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
/mob/living/simple_animal/shade/death()
deathmessage = "lets out a contented sigh as [p_their()] form unwinds."
..()
/mob/living/simple_animal/shade/canSuicide()
if(istype(loc, /obj/item/device/soulstone)) //do not suicide inside the soulstone
return 0
return ..()
/mob/living/simple_animal/shade/Process_Spacemove(movement_dir = 0)
return TRUE //this doesn't make much sense; you'd thing TRUE would mean it'd process spacemove but it means it doesn't
/mob/living/simple_animal/shade/attack_animal(mob/living/simple_animal/M)
if(isconstruct(M))
var/mob/living/simple_animal/hostile/construct/C = M
if(!C.can_repair_constructs)
return
if(health < maxHealth)
adjustHealth(-25)
Beam(M,icon_state="sendbeam",time=4)
M.visible_message("<span class='danger'>[M] heals \the <b>[src]</b>.</span>", \
"<span class='cult'>You heal <b>[src]</b>, leaving <b>[src]</b> at <b>[health]/[maxHealth]</b> health.</span>")
else
to_chat(M, "<span class='cult'>You cannot heal <b>[src]</b>, as [p_they()] [p_are()] unharmed!</span>")
else if(src != M)
return ..()
/mob/living/simple_animal/shade/attackby(obj/item/O, mob/user, params) //Marker -Agouri
if(istype(O, /obj/item/device/soulstone))
var/obj/item/device/soulstone/SS = O
SS.transfer_soul("SHADE", src, user)
else
. = ..()

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