This commit is contained in:
Arkatos1
2019-05-13 22:21:48 +02:00
586 changed files with 12352 additions and 10897 deletions
+32 -27
View File
@@ -572,7 +572,7 @@ var/global/nologevent = 0
delay = delay * 10
message_admins("[key_name_admin(usr)] has initiated a server restart with a delay of [delay/10] seconds")
log_admin("[key_name(usr)] has initiated a server restart with a delay of [delay/10] seconds")
ticker.delay_end = 0
SSticker.delay_end = 0
feedback_add_details("admin_verb","R") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
world.Reboot("Initiated by [usr.client.holder.fakekey ? "Admin" : usr.key].", "end_error", "admin reboot - by [usr.key] [usr.client.holder.fakekey ? "(stealth)" : ""]", delay)
@@ -672,21 +672,26 @@ var/global/nologevent = 0
if(!check_rights(R_SERVER))
return
if(!ticker)
if(!SSticker)
alert("Unable to start the game as it is not set up.")
return
if(ticker.current_state == GAME_STATE_PREGAME)
if(config.start_now_confirmation)
if(alert(usr, "This is a live server. Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
return
ticker.current_state = GAME_STATE_SETTING_UP
log_admin("[key_name(usr)] has started the game.")
message_admins("[key_name_admin(usr)] has started the game.")
if(config.start_now_confirmation)
if(alert(usr, "This is a live server. Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
return
if(SSticker.current_state == GAME_STATE_PREGAME || SSticker.current_state == GAME_STATE_STARTUP)
SSticker.force_start = TRUE
log_admin("[usr.key] has started the game.")
var/msg = ""
if(SSticker.current_state == GAME_STATE_STARTUP)
msg = " (The server is still setting up, but the round will be started as soon as possible.)"
message_admins("<font color='blue'>[usr.key] has started the game.[msg]</font>")
feedback_add_details("admin_verb","SN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return 1
else
to_chat(usr, "<font color='red'>Error: Start Now: Game has already started.</font>")
return 0
return
/datum/admins/proc/toggleenter()
set category = "Server"
@@ -763,10 +768,10 @@ var/global/nologevent = 0
if(!check_rights(R_SERVER))
return
if(!ticker || ticker.current_state != GAME_STATE_PREGAME)
ticker.delay_end = !ticker.delay_end
log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
message_admins("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1)
if(!SSticker || SSticker.current_state != GAME_STATE_PREGAME)
SSticker.delay_end = !SSticker.delay_end
log_admin("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
message_admins("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].", 1)
return //alert("Round end delayed", null, null, null, null, null)
going = !( going )
if(!( going ))
@@ -780,32 +785,32 @@ var/global/nologevent = 0
////////////////////////////////////////////////////////////////////////////////////////////////ADMIN HELPER PROCS
/proc/is_special_character(mob/M as mob) // returns 1 for specail characters and 2 for heroes of gamemode
if(!ticker || !ticker.mode)
if(!SSticker || !SSticker.mode)
return 0
if(!istype(M))
return 0
if((M.mind in ticker.mode.head_revolutionaries) || (M.mind in ticker.mode.revolutionaries))
if(ticker.mode.config_tag == "revolution")
if((M.mind in SSticker.mode.head_revolutionaries) || (M.mind in SSticker.mode.revolutionaries))
if(SSticker.mode.config_tag == "revolution")
return 2
return 1
if(M.mind in ticker.mode.cult)
if(ticker.mode.config_tag == "cult")
if(M.mind in SSticker.mode.cult)
if(SSticker.mode.config_tag == "cult")
return 2
return 1
if(M.mind in ticker.mode.syndicates)
if(ticker.mode.config_tag == "nuclear")
if(M.mind in SSticker.mode.syndicates)
if(SSticker.mode.config_tag == "nuclear")
return 2
return 1
if(M.mind in ticker.mode.wizards)
if(ticker.mode.config_tag == "wizard")
if(M.mind in SSticker.mode.wizards)
if(SSticker.mode.config_tag == "wizard")
return 2
return 1
if(M.mind in ticker.mode.changelings)
if(ticker.mode.config_tag == "changeling")
if(M.mind in SSticker.mode.changelings)
if(SSticker.mode.config_tag == "changeling")
return 2
return 1
if(M.mind in ticker.mode.abductors)
if(ticker.mode.config_tag == "abduction")
if(M.mind in SSticker.mode.abductors)
if(SSticker.mode.config_tag == "abduction")
return 2
return 1
if(isrobot(M))
-30
View File
@@ -72,7 +72,6 @@ var/list/admin_verbs_admin = list(
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
/client/proc/debug_variables,
/client/proc/show_snpc_verbs,
/client/proc/reset_all_tcs, /*resets all telecomms scripts*/
/client/proc/toggle_mentor_chat,
/client/proc/toggle_advanced_interaction, /*toggle admin ability to interact with not only machines, but also atoms such as buttons and doors*/
@@ -216,11 +215,6 @@ var/list/admin_verbs_proccall = list(
/client/proc/callproc_datum,
/client/proc/SDQL2_query
)
var/list/admin_verbs_snpc = list(
/client/proc/resetSNPC,
/client/proc/customiseSNPC,
/client/proc/hide_snpc_verbs
)
var/list/admin_verbs_ticket = list(
/client/proc/openAdminTicketUI,
/client/proc/toggleticketlogs,
@@ -291,8 +285,6 @@ var/list/admin_verbs_ticket = list(
admin_verbs_proccall,
admin_verbs_show_debug_verbs,
/client/proc/readmin,
admin_verbs_snpc,
/client/proc/hide_snpc_verbs,
admin_verbs_ticket
)
@@ -1013,28 +1005,6 @@ var/list/admin_verbs_ticket = list(
log_admin("[key_name(usr)] told everyone to man up and deal with it.")
message_admins("[key_name_admin(usr)] told everyone to man up and deal with it.")
/client/proc/show_snpc_verbs()
set name = "Show SNPC Verbs"
set category = "Admin"
if(!check_rights(R_ADMIN))
return
verbs += admin_verbs_snpc
verbs -= /client/proc/show_snpc_verbs
to_chat(src, "<span class='interface'>SNPC verbs have been toggled on.</span>")
/client/proc/hide_snpc_verbs()
set name = "Hide SNPC Verbs"
set category = "Admin"
if(!check_rights(R_ADMIN))
return
verbs -= admin_verbs_snpc
verbs += /client/proc/show_snpc_verbs
to_chat(src, "<span class='interface'>SNPC verbs have been toggled off.</span>")
/client/proc/toggle_advanced_interaction()
set name = "Toggle Advanced Admin Interaction"
set category = "Admin"
+50 -53
View File
@@ -390,10 +390,7 @@
/datum/admins/proc/check_antagonists_line(mob/M, caption = "", close = 1)
var/logout_status
if(istype(M, /mob/living/carbon/human/interactive))
logout_status = " <i>(snpc)</i>"
else
logout_status = M.client ? "" : " <i>(logged out)</i>"
logout_status = M.client ? "" : " <i>(logged out)</i>"
var/dname = M.real_name
if(!dname)
dname = M
@@ -403,9 +400,9 @@
/datum/admins/proc/check_antagonists()
if(!check_rights(R_ADMIN)) return
if(ticker && ticker.current_state >= GAME_STATE_PLAYING)
if(SSticker && SSticker.current_state >= GAME_STATE_PLAYING)
var/dat = "<html><head><title>Round Status</title></head><body><h1><B>Round Status</B></h1>"
dat += "Current Game Mode: <B>[ticker.mode.name]</B><BR>"
dat += "Current Game Mode: <B>[SSticker.mode.name]</B><BR>"
dat += "Round Duration: <B>[round(ROUND_TIME / 36000)]:[add_zero(num2text(ROUND_TIME / 600 % 60), 2)]:[add_zero(num2text(ROUND_TIME / 10 % 60), 2)]</B><BR>"
dat += "<B>Emergency shuttle</B><BR>"
if(SSshuttle.emergency.mode < SHUTTLE_CALL)
@@ -418,10 +415,10 @@
else
dat += "ETA: <a href='?_src_=holder;edit_shuttle_time=1'>[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</a><BR>"
dat += "<a href='?src=[UID()];delay_round_end=1'>[ticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
if(ticker.mode.syndicates.len)
dat += "<a href='?src=[UID()];delay_round_end=1'>[SSticker.delay_end ? "End Round Normally" : "Delay Round End"]</a><br>"
if(SSticker.mode.syndicates.len)
dat += "<br><table cellspacing=5><tr><td><B>Syndicates</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.syndicates)
for(var/datum/mind/N in SSticker.mode.syndicates)
var/mob/M = N.current
if(M)
dat += check_antagonists_line(M)
@@ -442,20 +439,20 @@
dat += "in [disk_loc.loc] at ([disk_loc.x], [disk_loc.y], [disk_loc.z])</td></tr>"
dat += "</table>"
if(ticker.mode.head_revolutionaries.len || ticker.mode.revolutionaries.len)
if(SSticker.mode.head_revolutionaries.len || SSticker.mode.revolutionaries.len)
dat += "<br><table cellspacing=5><tr><td><B>Revolutionaries</B></td><td></td></tr>"
for(var/datum/mind/N in ticker.mode.head_revolutionaries)
for(var/datum/mind/N in SSticker.mode.head_revolutionaries)
var/mob/M = N.current
if(!M)
dat += "<tr><td><i>Head Revolutionary not found!</i></td></tr>"
else
dat += check_antagonists_line(M, "(leader)")
for(var/datum/mind/N in ticker.mode.revolutionaries)
for(var/datum/mind/N in SSticker.mode.revolutionaries)
var/mob/M = N.current
if(M)
dat += check_antagonists_line(M)
dat += "</table><table cellspacing=5><tr><td><B>Target(s)</B></td><td></td><td><B>Location</B></td></tr>"
for(var/datum/mind/N in ticker.mode.get_living_heads())
for(var/datum/mind/N in SSticker.mode.get_living_heads())
var/mob/M = N.current
if(M)
dat += check_antagonists_line(M)
@@ -466,7 +463,7 @@
dat += "</table>"
if(GAMEMODE_IS_BLOB)
var/datum/game_mode/blob/mode = ticker.mode
var/datum/game_mode/blob/mode = SSticker.mode
dat += "<br><table cellspacing=5><tr><td><B>Blob</B></td><td></td><td></td></tr>"
dat += "<tr><td><i>Progress: [blobs.len]/[mode.blobwincount]</i></td></tr>"
@@ -479,67 +476,67 @@
dat += "<tr><td><i>Blob not found!</i></td></tr>"
dat += "</table>"
if(ticker.mode.blob_overminds.len)
dat += check_role_table("Blob Overminds", ticker.mode.blob_overminds)
if(SSticker.mode.blob_overminds.len)
dat += check_role_table("Blob Overminds", SSticker.mode.blob_overminds)
if(ticker.mode.changelings.len)
dat += check_role_table("Changelings", ticker.mode.changelings)
if(SSticker.mode.changelings.len)
dat += check_role_table("Changelings", SSticker.mode.changelings)
if(ticker.mode.wizards.len)
dat += check_role_table("Wizards", ticker.mode.wizards)
if(SSticker.mode.wizards.len)
dat += check_role_table("Wizards", SSticker.mode.wizards)
if(ticker.mode.raiders.len)
dat += check_role_table("Raiders", ticker.mode.raiders)
if(SSticker.mode.raiders.len)
dat += check_role_table("Raiders", SSticker.mode.raiders)
/*if(ticker.mode.ninjas.len)
dat += check_role_table("Ninjas", ticker.mode.ninjas)*/
if(ticker.mode.cult.len)
dat += check_role_table("Cultists", ticker.mode.cult, 0)
if(SSticker.mode.cult.len)
dat += check_role_table("Cultists", SSticker.mode.cult, 0)
dat += "<br> use <a href='?src=[UID()];cult_mindspeak=[UID()]'>Cult Mindspeak</a>"
if(GAMEMODE_IS_CULT)
var/datum/game_mode/cult/cult_round = ticker.mode
var/datum/game_mode/cult/cult_round = SSticker.mode
if(!cult_round.narsie_condition_cleared)
dat += "<br><a href='?src=[UID()];cult_nextobj=[UID()]'>complete objective (debug)</a>"
if(ticker.mode.traitors.len)
dat += check_role_table("Traitors", ticker.mode.traitors)
if(SSticker.mode.traitors.len)
dat += check_role_table("Traitors", SSticker.mode.traitors)
if(ticker.mode.shadows.len)
dat += check_role_table("Shadowlings", ticker.mode.shadows)
if(SSticker.mode.shadows.len)
dat += check_role_table("Shadowlings", SSticker.mode.shadows)
if(ticker.mode.shadowling_thralls.len)
dat += check_role_table("Shadowling Thralls", ticker.mode.shadowling_thralls)
if(SSticker.mode.shadowling_thralls.len)
dat += check_role_table("Shadowling Thralls", SSticker.mode.shadowling_thralls)
if(ticker.mode.abductors.len)
dat += check_role_table("Abductors", ticker.mode.abductors)
if(SSticker.mode.abductors.len)
dat += check_role_table("Abductors", SSticker.mode.abductors)
if(ticker.mode.abductees.len)
dat += check_role_table("Abductees", ticker.mode.abductees)
if(SSticker.mode.abductees.len)
dat += check_role_table("Abductees", SSticker.mode.abductees)
if(ticker.mode.vampires.len)
dat += check_role_table("Vampires", ticker.mode.vampires)
if(SSticker.mode.vampires.len)
dat += check_role_table("Vampires", SSticker.mode.vampires)
if(ticker.mode.vampire_enthralled.len)
dat += check_role_table("Vampire Thralls", ticker.mode.vampire_enthralled)
if(SSticker.mode.vampire_enthralled.len)
dat += check_role_table("Vampire Thralls", SSticker.mode.vampire_enthralled)
if(ticker.mode.devils.len)
dat += check_role_table("Devils", ticker.mode.devils)
if(SSticker.mode.devils.len)
dat += check_role_table("Devils", SSticker.mode.devils)
if(ticker.mode.xenos.len)
dat += check_role_table("Xenos", ticker.mode.xenos)
if(SSticker.mode.xenos.len)
dat += check_role_table("Xenos", SSticker.mode.xenos)
if(ticker.mode.superheroes.len)
dat += check_role_table("Superheroes", ticker.mode.superheroes)
if(SSticker.mode.superheroes.len)
dat += check_role_table("Superheroes", SSticker.mode.superheroes)
if(ticker.mode.supervillains.len)
dat += check_role_table("Supervillains", ticker.mode.supervillains)
if(SSticker.mode.supervillains.len)
dat += check_role_table("Supervillains", SSticker.mode.supervillains)
if(ticker.mode.greyshirts.len)
dat += check_role_table("Greyshirts", ticker.mode.greyshirts)
if(SSticker.mode.greyshirts.len)
dat += check_role_table("Greyshirts", SSticker.mode.greyshirts)
if(ticker.mode.eventmiscs.len)
dat += check_role_table("Event Roles", ticker.mode.eventmiscs)
if(SSticker.mode.eventmiscs.len)
dat += check_role_table("Event Roles", SSticker.mode.eventmiscs)
if(ts_spiderlist.len)
var/list/spider_minds = list()
@@ -559,8 +556,8 @@
count_spiderlings += 1
dat += "<table cellspacing=5><TR><TD>Growing TS on-station: [count_eggs] egg[count_eggs != 1 ? "s" : ""], [count_spiderlings] spiderling[count_spiderlings != 1 ? "s" : ""]. </TD></TR></TABLE>"
if(ticker.mode.ert.len)
dat += check_role_table("ERT", ticker.mode.ert)
if(SSticker.mode.ert.len)
dat += check_role_table("ERT", SSticker.mode.ert)
dat += "</body></html>"
usr << browse(dat, "window=roundstatus;size=400x500")
+33 -33
View File
@@ -6,7 +6,7 @@
message_admins("[key_name_admin(usr)] has attempted to override the admin panel!")
return
if(ticker.mode && ticker.mode.check_antagonists_topic(href, href_list))
if(SSticker.mode && SSticker.mode.check_antagonists_topic(href, href_list))
check_antagonists()
return
@@ -315,9 +315,9 @@
else if(href_list["delay_round_end"])
if(!check_rights(R_SERVER)) return
ticker.delay_end = !ticker.delay_end
log_admin("[key_name(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
message_admins("<span class='notice'>[key_name_admin(usr)] [ticker.delay_end ? "delayed the round end" : "has made the round end normally"].</span>", 1)
SSticker.delay_end = !SSticker.delay_end
log_admin("[key_name(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].")
message_admins("<span class='notice'>[key_name_admin(usr)] [SSticker.delay_end ? "delayed the round end" : "has made the round end normally"].</span>", 1)
href_list["secretsadmin"] = "check_antagonist"
else if(href_list["simplemake"])
@@ -1085,7 +1085,7 @@
else if(href_list["c_mode"])
if(!check_rights(R_ADMIN)) return
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
return alert(usr, "The game has already started.", null, null, null, null)
var/dat = {"<B>What mode do you wish to play?</B><HR>"}
for(var/mode in config.modes)
@@ -1098,7 +1098,7 @@
else if(href_list["f_secret"])
if(!check_rights(R_ADMIN)) return
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
return alert(usr, "The game has already started.", null, null, null, null)
if(master_mode != "secret")
return alert(usr, "The game mode has to be secret!", null, null, null, null)
@@ -1112,7 +1112,7 @@
else if(href_list["c_mode2"])
if(!check_rights(R_ADMIN|R_SERVER)) return
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
return alert(usr, "The game has already started.", null, null, null, null)
master_mode = href_list["c_mode2"]
log_admin("[key_name(usr)] set the mode as [master_mode].")
@@ -1125,7 +1125,7 @@
else if(href_list["f_secret2"])
if(!check_rights(R_ADMIN|R_SERVER)) return
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
return alert(usr, "The game has already started.", null, null, null, null)
if(master_mode != "secret")
return alert(usr, "The game mode has to be secret!", null, null, null, null)
@@ -1559,25 +1559,25 @@
alert("Couldn't locate cult mode datum! This shouldn't ever happen, tell a coder!")
return
var/datum/game_mode/cult/cult_round = ticker.mode
var/datum/game_mode/cult/cult_round = SSticker.mode
cult_round.bypass_phase()
message_admins("Admin [key_name_admin(usr)] has unlocked the Cult's next objective.")
log_admin("Admin [key_name_admin(usr)] has unlocked the Cult's next objective.")
else if(href_list["cult_mindspeak"])
var/input = stripped_input(usr, "Communicate to all the cultists with the voice of [ticker.cultdat.entity_name]", "Voice of [ticker.cultdat.entity_name]", "")
var/input = stripped_input(usr, "Communicate to all the cultists with the voice of [SSticker.cultdat.entity_name]", "Voice of [SSticker.cultdat.entity_name]", "")
if(!input)
return
for(var/datum/mind/H in ticker.mode.cult)
for(var/datum/mind/H in SSticker.mode.cult)
if (H.current)
to_chat(H.current, "<span class='danger'>[ticker.cultdat.entity_name]</span> murmurs, <span class='cultlarge'>[input]</span></span>")
to_chat(H.current, "<span class='danger'>[SSticker.cultdat.entity_name]</span> murmurs, <span class='cultlarge'>[input]</span></span>")
for(var/mob/dead/observer/O in GLOB.player_list)
to_chat(O, "<span class='danger'>[ticker.cultdat.entity_name]</span> murmurs, <span class='cultlarge'>[input]</span></span>")
to_chat(O, "<span class='danger'>[SSticker.cultdat.entity_name]</span> murmurs, <span class='cultlarge'>[input]</span></span>")
message_admins("Admin [key_name_admin(usr)] has talked with the Voice of [ticker.cultdat.entity_name].")
log_admin("[key_name(usr)] Voice of [ticker.cultdat.entity_name]: [input]")
message_admins("Admin [key_name_admin(usr)] has talked with the Voice of [SSticker.cultdat.entity_name].")
log_admin("[key_name(usr)] Voice of [SSticker.cultdat.entity_name]: [input]")
else if(href_list["adminplayerobservecoodjump"])
if(!check_rights(R_ADMIN)) return
@@ -1958,8 +1958,8 @@
kill_objective.target = H.mind
kill_objective.explanation_text = "Assassinate [H.real_name], the [H.mind.assigned_role]."
newtraitormind.objectives += kill_objective
ticker.mode.equip_traitor(newtraitor)
ticker.mode.traitors |= newtraitor.mind
SSticker.mode.equip_traitor(newtraitor)
SSticker.mode.traitors |= newtraitor.mind
to_chat(newtraitor, "<span class='danger'>ATTENTION:</span> It is time to pay your debt to the Syndicate...")
to_chat(newtraitor, "<B>You are now a traitor.</B>")
to_chat(newtraitor, "<B>Goal: <span class='danger'>KILL [H.real_name]</span>, currently in [get_area(H.loc)]</B>");
@@ -2341,7 +2341,7 @@
else if(href_list["traitor"])
if(!check_rights(R_ADMIN|R_MOD)) return
if(!ticker || !ticker.mode)
if(!SSticker || !SSticker.mode)
alert("The game hasn't started yet!")
return
@@ -2484,7 +2484,7 @@
else if(href_list["kick_all_from_lobby"])
if(!check_rights(R_ADMIN))
return
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
if(SSticker && SSticker.current_state == GAME_STATE_PLAYING)
var/afkonly = text2num(href_list["afkonly"])
if(alert("Are you sure you want to kick all [afkonly ? "AFK" : ""] clients from the lobby?","Confirmation","Yes","Cancel") != "Yes")
return
@@ -2573,7 +2573,7 @@
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","TriAI")
if("gravity")
if(!(ticker && ticker.mode))
if(!(SSticker && SSticker.mode))
to_chat(usr, "Please wait until the game starts! Not sure how it will work otherwise.")
return
gravity_is_on = !gravity_is_on
@@ -2609,7 +2609,7 @@
message_admins("<span class='notice'>[key_name_admin(usr)] made all SMESs powered</span>", 1)
power_restore_quick()
if("prisonwarp")
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!", null, null, null, null, null)
return
feedback_inc("admin_secrets_fun_used",1)
@@ -2651,7 +2651,7 @@
H.loc = pick(prisonsecuritywarp)
prisonwarped += H
if("traitor_all")
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
return
var/objective = sanitize(copytext(input("Enter an objective"),1,MAX_MESSAGE_LEN))
@@ -2663,24 +2663,24 @@
if(H.stat == 2 || !H.client || !H.mind) continue
if(is_special_character(H)) continue
//traitorize(H, objective, 0)
ticker.mode.traitors += H.mind
SSticker.mode.traitors += H.mind
H.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/objective/new_objective = new
new_objective.owner = H
new_objective.explanation_text = objective
H.mind.objectives += new_objective
ticker.mode.greet_traitor(H.mind)
SSticker.mode.greet_traitor(H.mind)
//ticker.mode.forge_traitor_objectives(H.mind)
ticker.mode.finalize_traitor(H.mind)
SSticker.mode.finalize_traitor(H.mind)
for(var/mob/living/silicon/A in GLOB.player_list)
ticker.mode.traitors += A.mind
SSticker.mode.traitors += A.mind
A.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/objective/new_objective = new
new_objective.owner = A
new_objective.explanation_text = objective
A.mind.objectives += new_objective
ticker.mode.greet_traitor(A.mind)
ticker.mode.finalize_traitor(A.mind)
SSticker.mode.greet_traitor(A.mind)
SSticker.mode.finalize_traitor(A.mind)
message_admins("<span class='notice'>[key_name_admin(usr)] used everyone is a traitor secret. Objective is [objective]</span>", 1)
log_admin("[key_name(usr)] used everyone is a traitor secret. Objective is [objective]")
@@ -2946,10 +2946,10 @@
if("showailaws")
output_ai_laws()
if("showgm")
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
else if(ticker.mode)
alert("The game mode is [ticker.mode.name]")
else if(SSticker.mode)
alert("The game mode is [SSticker.mode.name]")
else alert("For some reason there's a ticker, but not a game mode")
if("manifest")
var/dat = "<B>Showing Crew Manifest.</B><HR>"
@@ -3284,7 +3284,7 @@
return
G.report_message = description
message_admins("[key_name_admin(usr)] created \"[G.name]\" station goal.")
ticker.mode.station_goals += G
SSticker.mode.station_goals += G
modify_goals()
else if(href_list["showdetails"])
@@ -3408,7 +3408,7 @@
protect_objective.target = H.mind
protect_objective.explanation_text = "Protect [H.real_name], the [H.mind.assigned_role]."
hunter_mind.objectives += protect_objective
ticker.mode.traitors |= hunter_mob.mind
SSticker.mode.traitors |= hunter_mob.mind
to_chat(hunter_mob, "<span class='danger'>ATTENTION:</span> You are now on a mission!")
to_chat(hunter_mob, "<B>Goal: <span class='danger'>[killthem ? "MURDER" : "PROTECT"] [H.real_name]</span>, currently in [get_area(H.loc)]. </B>");
if(killthem)
+2 -2
View File
@@ -3,7 +3,7 @@
set category = "Debug"
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(!ticker)
if(!SSticker)
return
switch(cinematic)
if("explosion")
@@ -14,4 +14,4 @@
override = input(src, "mode = ?","Enter Parameter", null) as anything in list("nuclear emergency", "fake", "no override")
if(0)
override = input(src, "mode = ?","Enter Parameter", null) as anything in list("blob", "nuclear emergency", "AI malfunction", "no override")
ticker.station_explosion_cinematic(parameter, override)
SSticker.station_explosion_cinematic(parameter, override)
+7 -7
View File
@@ -215,7 +215,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
if(!ticker)
if(!SSticker)
alert("Wait until the game starts")
return
if(istype(M, /mob/living/carbon/human))
@@ -233,7 +233,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
if(!ticker)
if(!SSticker)
alert("Wait until the game starts")
return
@@ -293,7 +293,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
if(!ticker)
if(!SSticker)
alert("Wait until the game starts")
return
if(ishuman(M))
@@ -313,7 +313,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
if(!ticker)
if(!SSticker)
alert("Wait until the game starts")
return
if(ishuman(M))
@@ -333,7 +333,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
if(!ticker)
if(!SSticker)
alert("Wait until the game starts")
return
if(ishuman(M))
@@ -405,7 +405,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_EVENT))
return
if(!ticker)
if(!SSticker)
alert("Wait until the game starts")
return
if(istype(M, /mob/living/carbon/human))
@@ -818,7 +818,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!check_rights(R_SPAWN))
return
if(!ticker)
if(!SSticker)
alert("Wait until the game starts")
return
if(istype(M, /mob/living/carbon))
+2 -2
View File
@@ -7,7 +7,7 @@
set desc = "Spawns a group of players in the specified outfit."
if(!check_rights(R_EVENT))
return
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
return
if(alert("Do you want to spawn a Gimmick Team at YOUR CURRENT LOCATION?",,"Yes","No")=="No")
@@ -82,7 +82,7 @@
H.mind.store_memory("<B>[themission]</B><BR><BR>")
if(is_syndicate)
ticker.mode.traitors |= H.mind //Adds them to extra antag list
SSticker.mode.traitors |= H.mind //Adds them to extra antag list
players_spawned++
if(players_spawned >= teamsize)
+2 -2
View File
@@ -4,7 +4,7 @@ var/const/honksquad_possible = 6 //if more Commandos are needed in the future
var/global/sent_honksquad = 0
/client/proc/honksquad()
if(!ticker)
if(!SSticker)
to_chat(usr, "<font color='red'>The game hasn't started yet!</font>")
return
if(world.time < 6000)
@@ -95,7 +95,7 @@ var/global/sent_honksquad = 0
new_honksquad.mind.special_role = SPECIAL_ROLE_HONKSQUAD
new_honksquad.mind.offstation_role = TRUE
new_honksquad.add_language("Clownish")
ticker.mode.traitors |= new_honksquad.mind//Adds them to current traitor list. Which is really the extra antagonist list.
SSticker.mode.traitors |= new_honksquad.mind//Adds them to current traitor list. Which is really the extra antagonist list.
new_honksquad.equip_honksquad(honk_leader_selected)
return new_honksquad
@@ -10,7 +10,7 @@ var/global/sent_syndicate_infiltration_team = 0
if(!check_rights(R_ADMIN))
to_chat(src, "Only administrators may use this command.")
return
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
return
if(alert("Do you want to send in the Syndicate Infiltration Team?",,"Yes","No")=="No")
@@ -132,7 +132,7 @@ var/global/sent_syndicate_infiltration_team = 0
new_syndicate_infiltrator.mind.assigned_role = "Syndicate Infiltrator"
new_syndicate_infiltrator.mind.special_role = "Syndicate Infiltrator"
new_syndicate_infiltrator.mind.offstation_role = TRUE //they can flee to z2 so make them inelligible as antag targets
ticker.mode.traitors |= new_syndicate_infiltrator.mind //Adds them to extra antag list
SSticker.mode.traitors |= new_syndicate_infiltrator.mind //Adds them to extra antag list
new_syndicate_infiltrator.equip_syndicate_infiltrator(syndicate_leader_selected, uplink_tc, is_mgmt)
return new_syndicate_infiltrator
@@ -170,7 +170,7 @@ var/global/sent_syndicate_infiltration_team = 0
equip_or_collect(new /obj/item/pda(src), slot_in_backpack)
// Other gear
equip_to_slot_or_del(new /obj/item/clothing/shoes/syndigaloshes(src), slot_shoes)
equip_to_slot_or_del(new /obj/item/clothing/shoes/chameleon/noslip(src), slot_shoes)
var/obj/item/card/id/syndicate/W = new(src)
if (flag_mgmt)
+6 -17
View File
@@ -175,7 +175,7 @@ client/proc/one_click_antag()
for(var/i = 0, i<numCultists, i++)
H = pick(candidates)
ticker.mode.add_cultist(H.mind)
SSticker.mode.add_cultist(H.mind)
candidates.Remove(H)
return 1
@@ -247,28 +247,17 @@ client/proc/one_click_antag()
if(closet_spawn)
new /obj/structure/closet/syndicate/nuclear(closet_spawn.loc)
for(var/obj/effect/landmark/A in /area/syndicate_station/start)//Because that's the only place it can BE -Sieve
if(A.name == "Syndicate-Gear-Closet")
new /obj/structure/closet/syndicate/personal(A.loc)
qdel(A)
continue
if(A.name == "Syndicate-Bomb")
new /obj/effect/spawner/newbomb/timer/syndicate(A.loc)
qdel(A)
continue
for(var/datum/mind/synd_mind in ticker.mode.syndicates)
for(var/datum/mind/synd_mind in SSticker.mode.syndicates)
if(synd_mind.current)
if(synd_mind.current.client)
for(var/image/I in synd_mind.current.client.images)
if(I.icon_state == "synd")
qdel(I)
for(var/datum/mind/synd_mind in ticker.mode.syndicates)
for(var/datum/mind/synd_mind in SSticker.mode.syndicates)
if(synd_mind.current)
if(synd_mind.current.client)
for(var/datum/mind/synd_mind_1 in ticker.mode.syndicates)
for(var/datum/mind/synd_mind_1 in SSticker.mode.syndicates)
if(synd_mind_1.current)
var/I = image('icons/mob/mob.dmi', loc = synd_mind_1.current, icon_state = "synd")
synd_mind.current.client.images += I
@@ -417,7 +406,7 @@ client/proc/one_click_antag()
new_syndicate_commando.mind.special_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD
new_syndicate_commando.mind.offstation_role = TRUE
//Adds them to current traitor list. Which is really the extra antagonist list.
ticker.mode.traitors += new_syndicate_commando.mind
SSticker.mode.traitors += new_syndicate_commando.mind
new_syndicate_commando.equip_syndicate_commando(syndicate_leader_selected)
return new_syndicate_commando
@@ -477,7 +466,7 @@ client/proc/one_click_antag()
break
new_vox.key = theghost.key
ticker.mode.traitors += new_vox.mind
SSticker.mode.traitors += new_vox.mind
to_chat(new_vox, "<span class='notice'>You are a Vox Primalis, fresh out of the Shoal. Your ship has arrived at the Tau Ceti system hosting the NSV Exodus... or was it the Luna? NSS? Utopia? Nobody is really sure, but everyong is raring to start pillaging! Your current goal is: <span class='danger'> [input]</span></span>")
to_chat(new_vox, "<span class='warning'>Don't forget to turn on your nitrogen internals!</span>")
+4 -4
View File
@@ -1,5 +1,5 @@
/client/proc/only_one()
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
return
@@ -14,7 +14,7 @@
var/datum/preferences/A = new() // Randomize appearance
A.copy_to(H)
ticker.mode.traitors += H.mind
SSticker.mode.traitors += H.mind
H.mind.special_role = SPECIAL_ROLE_TRAITOR
var/datum/objective/hijack/hijack_objective = new
@@ -58,7 +58,7 @@
world << sound('sound/music/thunderdome.ogg')
/client/proc/only_me()
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
return
@@ -66,7 +66,7 @@
if(H.stat == 2 || !(H.client)) continue
if(is_special_character(H)) continue
ticker.mode.traitors += H.mind
SSticker.mode.traitors += H.mind
H.mind.special_role = "[H.real_name] Prime"
var/datum/objective/hijackclone/hijack_objective = new /datum/objective/hijackclone
+1 -1
View File
@@ -1,5 +1,5 @@
/client/proc/only_one_team()
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
return
+3 -3
View File
@@ -18,8 +18,8 @@
var/prayer_type = "PRAYER"
var/deity
if(usr.job == "Chaplain")
if(ticker && ticker.Bible_deity_name)
deity = ticker.Bible_deity_name
if(SSticker && SSticker.Bible_deity_name)
deity = SSticker.Bible_deity_name
cross = image('icons/obj/storage.dmi',"kingyellow")
font_color = "blue"
prayer_type = "CHAPLAIN PRAYER"
@@ -27,7 +27,7 @@
cross = image('icons/obj/storage.dmi',"tome")
font_color = "red"
prayer_type = "CULTIST PRAYER"
deity = ticker.cultdat.entity_name
deity = SSticker.cultdat.entity_name
log_say("(PRAYER) [msg]", usr)
msg = "<span class='notice'>[bicon(cross)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""][mind && mind.isholy ? " (blessings: [mind.num_blessed])" : ""]:</font> [key_name(src, 1)] ([ADMIN_QUE(src,"?")]) ([ADMIN_PP(src,"PP")]) ([ADMIN_VV(src,"VV")]) ([ADMIN_SM(src,"SM")]) ([admin_jump_link(src)]) (<A HREF='?_src_=holder;secretsadmin=check_antagonist'>CA</A>) ([ADMIN_SC(src,"SC")]) (<A HREF='?_src_=holder;Bless=[UID()]'>BLESS</A>) (<A HREF='?_src_=holder;Smite=[UID()]'>SMITE</A>):</b> [msg]</span>"
+16 -16
View File
@@ -437,11 +437,11 @@ Traitors and the like can also be revived with the previous role mostly intact.
if("traitor")
SSjobs.AssignRank(new_character, new_character.mind.assigned_role, 0)
SSjobs.EquipRank(new_character, new_character.mind.assigned_role, 1)
ticker.mode.equip_traitor(new_character)
SSticker.mode.equip_traitor(new_character)
if("Wizard")
new_character.loc = pick(wizardstart)
//ticker.mode.learn_basic_spells(new_character)
ticker.mode.equip_wizard(new_character)
SSticker.mode.equip_wizard(new_character)
if("Syndicate")
var/obj/effect/landmark/synd_spawn = locate("landmark*Syndicate-Spawn")
if(synd_spawn)
@@ -858,7 +858,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
set category = "Admin"
set name = "Toggle Deny Shuttle"
if(!ticker)
if(!SSticker)
return
if(!check_rights(R_ADMIN))
@@ -891,12 +891,12 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_SERVER|R_EVENT))
return
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
to_chat(usr, "Nope you can't do this, the game's already started. This only works before rounds!")
return
if(ticker.random_players)
ticker.random_players = 0
if(SSticker.random_players)
SSticker.random_players = 0
message_admins("Admin [key_name_admin(usr)] has disabled \"Everyone is Special\" mode.", 1)
to_chat(usr, "Disabled.")
return
@@ -914,7 +914,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
to_chat(usr, "<i>Remember: you can always disable the randomness by using the verb again, assuming the round hasn't started yet</i>.")
ticker.random_players = 1
SSticker.random_players = 1
feedback_add_details("admin_verb","MER") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/toggle_random_events()
@@ -1009,13 +1009,13 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_EVENT))
return
if(ticker.mode.ert_disabled)
ticker.mode.ert_disabled = 0
if(SSticker.mode.ert_disabled)
SSticker.mode.ert_disabled = 0
to_chat(usr, "<span class='notice'>ERT has been <b>Enabled</b>.</span>")
log_admin("Admin [key_name(src)] has enabled ERT calling.")
message_admins("Admin [key_name_admin(usr)] has enabled ERT calling.", 1)
else
ticker.mode.ert_disabled = 1
SSticker.mode.ert_disabled = 1
to_chat(usr, "<span class='warning'>ERT has been <b>Disabled</b>.</span>")
log_admin("Admin [key_name(src)] has disabled ERT calling.")
message_admins("Admin [key_name_admin(usr)] has disabled ERT calling.", 1)
@@ -1033,14 +1033,14 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!input)
return
if(!ticker)
if(!SSticker)
return
ticker.selected_tip = input
SSticker.selected_tip = input
// If we've already tipped, then send it straight away.
if(ticker.tipped)
ticker.send_tip_of_the_round()
if(SSticker.tipped)
SSticker.send_tip_of_the_round()
message_admins("[key_name_admin(usr)] sent a Tip of the round.")
log_admin("[key_name(usr)] sent \"[input]\" as the Tip of the Round.")
@@ -1055,12 +1055,12 @@ Traitors and the like can also be revived with the previous role mostly intact.
holder.modify_goals()
/datum/admins/proc/modify_goals()
if(!ticker || !ticker.mode)
if(!SSticker || !SSticker.mode)
to_chat(usr, "<span class='warning'>This verb can only be used if the round has started.</span>")
return
var/dat = ""
for(var/datum/station_goal/S in ticker.mode.station_goals)
for(var/datum/station_goal/S in SSticker.mode.station_goals)
dat += "[S.name] - <a href='?src=[S.UID()];announce=1'>Announce</a> | <a href='?src=[S.UID()];remove=1'>Remove</a><br>"
dat += "<br><a href='?src=[UID()];add_station_goal=1'>Add New Goal</a>"
usr << browse(dat, "window=goals;size=400x400")
+5 -5
View File
@@ -4,7 +4,7 @@ var/const/commandos_possible = 6 //if more Commandos are needed in the future
var/global/sent_strike_team = 0
/client/proc/strike_team()
if(!ticker)
if(!SSticker)
to_chat(usr, "<span class='userdanger'>The game hasn't started yet!</span>")
return
if(sent_strike_team == 1)
@@ -86,9 +86,9 @@ var/global/sent_strike_team = 0
R.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD
R.mind.special_role = SPECIAL_ROLE_DEATHSQUAD
R.mind.offstation_role = TRUE
if(!(R.mind in ticker.minds))
ticker.minds += R.mind
ticker.mode.traitors += R.mind
if(!(R.mind in SSticker.minds))
SSticker.minds += R.mind
SSticker.mode.traitors += R.mind
R.key = ghost_mob.key
if(nuke_code)
R.mind.store_memory("<B>Nuke Code:</B> <span class='warning'>[nuke_code].</span>")
@@ -150,7 +150,7 @@ var/global/sent_strike_team = 0
new_commando.mind_initialize()
new_commando.mind.assigned_role = SPECIAL_ROLE_DEATHSQUAD
new_commando.mind.special_role = SPECIAL_ROLE_DEATHSQUAD
ticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list.
SSticker.mode.traitors |= new_commando.mind//Adds them to current traitor list. Which is really the extra antagonist list.
new_commando.equip_death_commando(is_leader)
return new_commando
@@ -9,7 +9,7 @@ var/global/sent_syndicate_strike_team = 0
if(!src.holder)
to_chat(src, "Only administrators may use this command.")
return
if(!ticker)
if(!SSticker)
alert("The game hasn't started yet!")
return
if(sent_syndicate_strike_team == 1)
@@ -117,7 +117,7 @@ var/global/sent_syndicate_strike_team = 0
new_syndicate_commando.mind.assigned_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD
new_syndicate_commando.mind.special_role = SPECIAL_ROLE_SYNDICATE_DEATHSQUAD
new_syndicate_commando.mind.offstation_role = TRUE
ticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list.
SSticker.mode.traitors |= new_syndicate_commando.mind //Adds them to current traitor list. Which is really the extra antagonist list.
new_syndicate_commando.equip_syndicate_commando(is_leader)
qdel(spawn_location)
return new_syndicate_commando
+5 -5
View File
@@ -2,21 +2,21 @@
set category = "Event"
set name = "Create AI Triumvirate"
if(ticker.current_state > GAME_STATE_PREGAME)
if(SSticker.current_state > GAME_STATE_PREGAME)
to_chat(usr, "This option is currently only usable during pregame. This may change at a later date.")
return
if(SSjobs && ticker)
if(SSjobs && SSticker)
var/datum/job/job = SSjobs.GetJob("AI")
if(!job)
to_chat(usr, "Unable to locate the AI job")
return
if(ticker.triai)
ticker.triai = 0
if(SSticker.triai)
SSticker.triai = 0
to_chat(usr, "Only one AI will be spawned at round start.")
message_admins("<span class='notice'>[key_name_admin(usr)] has toggled off triple AIs at round start.</span>", 1)
else
ticker.triai = 1
SSticker.triai = 1
to_chat(usr, "There will be an AI Triumvirate at round start.")
message_admins("<span class='notice'>[key_name_admin(usr)] has toggled on triple AIs at round start.</span>", 1)
return
@@ -18,6 +18,7 @@
icon_state = "locator"
var/borg_to_spawn
var/checking = FALSE
var/rolename = "Syndicate Operative"
/obj/item/antag_spawner/nuke_ops/proc/before_candidate_search(user)
return TRUE
@@ -26,7 +27,7 @@
if(used)
to_chat(user, "<span class='warning'>[src] is out of power!</span>")
return FALSE
if(!(user.mind in ticker.mode.syndicates))
if(!(user.mind in SSticker.mode.syndicates))
to_chat(user, "<span class='danger'>AUTHENTICATION FAILURE. ACCESS DENIED.</span>")
return FALSE
if(checking)
@@ -45,7 +46,7 @@
checking = TRUE
to_chat(user, "<span class='notice'>You activate [src] and wait for confirmation.</span>")
var/list/nuke_candidates = pollCandidates("Do you want to play as a syndicate [borg_to_spawn ? "[lowertext(borg_to_spawn)] cyborg" : "operative"]?", ROLE_OPERATIVE, TRUE, 150)
var/list/nuke_candidates = pollCandidates("Do you want to play as a [rolename]?", ROLE_OPERATIVE, TRUE, 150)
if(LAZYLEN(nuke_candidates))
checking = FALSE
if(QDELETED(src) || !check_usability(user))
@@ -62,27 +63,27 @@
/obj/item/antag_spawner/nuke_ops/spawn_antag(client/C, turf/T, kind, datum/mind/user)
var/mob/living/carbon/human/M = new/mob/living/carbon/human(T)
var/agent_number = LAZYLEN(ticker.mode.syndicates)
var/agent_number = LAZYLEN(SSticker.mode.syndicates) - 1
M.real_name = "[syndicate_name()] Operative #[agent_number]"
set_syndicate_values(C, M)
ticker.mode.create_syndicate(M.mind)
ticker.mode.equip_syndicate(M, 0)
ticker.mode.update_syndicate_id(M.mind, FALSE)
SSticker.mode.create_syndicate(M.mind)
SSticker.mode.equip_syndicate(M, 0)
SSticker.mode.update_syndicate_id(M.mind, FALSE)
/obj/item/antag_spawner/nuke_ops/proc/set_syndicate_values(client/C, mob/living/M)
M.key = C.key
ticker.mode.syndicates += M.mind
ticker.mode.update_synd_icons_added(M.mind)
SSticker.mode.syndicates += M.mind
SSticker.mode.update_synd_icons_added(M.mind)
M.mind.assigned_role = SPECIAL_ROLE_NUKEOPS
M.mind.special_role = SPECIAL_ROLE_NUKEOPS
M.mind.offstation_role = TRUE
M.faction = list("syndicate")
ticker.mode.forge_syndicate_objectives(M.mind)
ticker.mode.greet_syndicate(M.mind)
SSticker.mode.forge_syndicate_objectives(M.mind)
SSticker.mode.greet_syndicate(M.mind)
//////SYNDICATE BORG
/obj/item/antag_spawner/nuke_ops/borg_tele
@@ -109,13 +110,15 @@
if(switch_roles_choice == "Syndicate Cyborg")
switch_roles = TRUE
rolename = initial(rolename)
else
switch_roles = FALSE
rolename = "Syndicate [borg_to_spawn] Cyborg"
return TRUE
/obj/item/antag_spawner/nuke_ops/borg_tele/spawn_antag(client/C, turf/T, datum/mind/user)
if(!(user in ticker.mode.syndicates))
if(!(user in SSticker.mode.syndicates))
used = FALSE
return
@@ -147,7 +150,7 @@
set_syndicate_values(user.current.client, R)
L.key = C.key
ticker.mode.greet_syndicate(L.mind)
SSticker.mode.greet_syndicate(L.mind)
///////////SLAUGHTER DEMON
@@ -198,7 +201,7 @@
S.key = C.key
S.mind.assigned_role = S.name
S.mind.special_role = S.name
ticker.mode.traitors += S.mind
SSticker.mode.traitors += S.mind
var/datum/objective/assassinate/KillDaWiz = new /datum/objective/assassinate
KillDaWiz.owner = S.mind
KillDaWiz.target = user.mind
@@ -266,7 +269,7 @@
M.mind.assigned_role = SPECIAL_ROLE_MORPH
M.mind.special_role = SPECIAL_ROLE_MORPH
to_chat(M, M.playstyle_string)
ticker.mode.traitors += M.mind
SSticker.mode.traitors += M.mind
var/datum/objective/assassinate/KillDaWiz = new /datum/objective/assassinate
KillDaWiz.owner = M.mind
KillDaWiz.target = user.mind
+2 -2
View File
@@ -42,8 +42,8 @@
possible_contents = list(/obj/random/carp_plushie)
/obj/item/toy/prizeball/plushie
name = "animal plushie capsule"
desc = "Contains one cuddly animal plushie!"
name = "plushie capsule"
desc = "Contains one cuddly plushie!"
possible_contents = list(/obj/random/plushie)
/obj/item/toy/prizeball/figure
+2 -2
View File
@@ -157,8 +157,8 @@ var/global/datum/prizes/global_prizes = new
cost = 65
/datum/prize_item/plushie
name = "Random Animal Plushie"
desc = "A colorful animal-shaped plush toy."
name = "Random Plushie"
desc = "A colorful plush toy."
typepath = /obj/item/toy/prizeball/plushie
cost = 75
+1 -1
View File
@@ -34,7 +34,7 @@
/obj/effect/mob_spawn/attack_ghost(mob/user)
var/mob/dead/observer/O = user
if(ticker.current_state != GAME_STATE_PLAYING || !loc || !ghost_usable)
if(SSticker.current_state != GAME_STATE_PLAYING || !loc || !ghost_usable)
return
if(!uses)
to_chat(user, "<span class='warning'>This spawner is out of charges!</span>")
@@ -1,44 +1,44 @@
/area/awaymission/UO71
name = "UO71"
icon_state = "away"
report_alerts = 0
tele_proof = 1
report_alerts = FALSE
tele_proof = TRUE
/area/awaymission/UO71/plaza
name = "UO71 Plaza"
icon_state = "awaycontent1"
fire = 1
fire = TRUE
/area/awaymission/UO71/centralhall
name = "UO71 Central"
icon_state = "awaycontent2"
fire = 1
fire = TRUE
/area/awaymission/UO71/eng
name = "UO71 Engineering"
icon_state = "awaycontent3"
fire = 1
fire = TRUE
/area/awaymission/UO71/mining
name = "UO71 Mining"
icon_state = "awaycontent4"
fire = 1
fire = TRUE
/area/awaymission/UO71/science
name = "UO71 Science"
icon_state = "awaycontent5"
fire = 1
fire = TRUE
/area/awaymission/UO71/medical
name = "UO71 Medical"
icon_state = "awaycontent6"
fire = 1
fire = TRUE
/area/awaymission/UO71/gateway
name = "UO71 Gateway"
icon_state = "awaycontent7"
fire = 1
fire = TRUE
/area/awaymission/UO71/outside
name = "UO71 Outside"
@@ -47,36 +47,41 @@
/area/awaymission/UO71/bridge
name = "UO71 Bridge"
icon_state = "awaycontent21"
fire = 1
requires_power = 0
tele_proof = 1
fire = TRUE
requires_power = FALSE
tele_proof = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/UO71/queen
name = "UO71 Queen Lair"
icon_state = "awaycontent9"
fire = 1
requires_power = 0
tele_proof = 1
fire = TRUE
requires_power = FALSE
tele_proof = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/UO71/prince
name = "UO71 Prince Containment"
icon_state = "awaycontent10"
fire = 1
requires_power = 0
tele_proof = 1
fire = TRUE
requires_power = FALSE
tele_proof = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/UO71/mother
name = "UO71 Mother Containment"
icon_state = "awaycontent10"
fire = 1
requires_power = 0
tele_proof = 1
fire = TRUE
requires_power = FALSE
tele_proof = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/UO71/loot
name = "UO71 Loot Vault"
icon_state = "awaycontent11"
requires_power = 0
tele_proof = 1
requires_power = FALSE
tele_proof = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/obj/item/paper/terrorspiders1
name = "paper - 'Sealed Facility'"
@@ -3,25 +3,24 @@
/area/awaymission/BMPship
name = "\improper BMP Asteroids"
icon_state = "away"
luminosity = 0
report_alerts = 0
report_alerts = FALSE
/area/awaymission/BMPship/Aft
name = "\improper Aft Block"
icon_state = "away1"
requires_power = 1
requires_power = TRUE
/area/awaymission/BMPship/Midship
name = "\improper Midship Block"
icon_state = "away2"
requires_power = 1
requires_power = TRUE
/area/awaymission/BMPship/Fore
name = "\improper Fore Block"
icon_state = "away3"
requires_power = 1
requires_power = TRUE
/area/awaymission/BMPship/Gate
name = "\improper Gateway Block"
icon_state = "away4"
requires_power = 1
requires_power = TRUE
@@ -3,7 +3,7 @@
/area/awaymission/challenge
name = "Challenge"
icon_state = "away"
report_alerts = 0
report_alerts = FALSE
/area/awaymission/challenge/start
name = "Where Am I?"
@@ -12,12 +12,14 @@
/area/awaymission/challenge/main
name = "\improper Danger Room"
icon_state = "away1"
requires_power = 0
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
/area/awaymission/challenge/end
name = "Administration"
icon_state = "away2"
requires_power = 0
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
/obj/machinery/power/emitter/energycannon
@@ -1,21 +0,0 @@
//Clown Planet Areas
/area/planet/clown
name = "\improper Clown Planet"
icon_state = "honk"
luminosity = 1
dynamic_lighting = 0
requires_power = 0
report_alerts = 0
/area/awaymission/clownplanet/miningtown
name = "\improper Clown Planet - Bananium-o-Rama"
icon_state = "away1"
luminosity = 1
requires_power = 0
/area/awaymission/clownplanet/mine
name = "\improper Clown Planet - Bananium-o-Rama Mines"
icon_state = "away2"
luminosity = 1
requires_power = 0
@@ -307,6 +307,7 @@
name = "Powered Tile"
icon_state = "teleporter"
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/ruin/space/ancientstation/space
name = "Exposed To Space"
@@ -3,8 +3,9 @@
/area/awaymission/spacebattle
name = "\improper Space Battle"
icon_state = "away"
requires_power = 0
report_alerts = 0
requires_power = FALSE
report_alerts = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
/area/awaymission/spacebattle/cruiser
name = "\improper Nanotrasen Cruiser"
@@ -2,7 +2,8 @@
/area/awaymission/spacehotel
name = "Deep Space Hotel 419"
requires_power = 0
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/spacehotel/kitchen
name = "Hotel Kitchen"
@@ -152,14 +153,6 @@
/obj/machinery/door/unpowered/hotel_door/autoclose()
if(!density && !operating && autoclose)
close()
/obj/machinery/door/unpowered/hotel_door/emag_act(mob/user)
if(isliving(user) && density)
var/obj/effect/hotel_controller/H
if(H.controller)
H.controller.deploy_sec(user)
..()
/obj/item/card/hotel_card
name = "Key Card"
icon_state = "guest"
@@ -283,20 +276,4 @@
spawn(300)
if(D.occupant == deadbeat)
// they still haven't checked out...
deploy_sec(deadbeat)
checkout(roomid)
/obj/effect/hotel_controller/proc/deploy_sec(mob/living/target)
if(!istype(target) || !istype(get_area(target), /area/awaymission/spacehotel))
return
var/list/secs[0]
for(var/mob/living/carbon/human/interactive/away/hotel/guard/M in get_area(src))
if(!M.retal)
secs += M
var/mob/living/carbon/human/interactive/away/hotel/guard/S = safepick(secs)
if(!S)
return
S.retal_target = target
S.retal = 1
checkout(roomid)
@@ -1,132 +0,0 @@
/mob/living/carbon/human/interactive/away/hotel
away_area = /area/awaymission/spacehotel
override_under = /obj/item/clothing/under/mafia
chattyness = SNPC_CHANCE_TALK / 4
/mob/living/carbon/human/interactive/away/hotel/Initialize(mapload)
. = ..(mapload, /datum/species/skrell)
/mob/living/carbon/human/interactive/away/hotel/doSetup()
..()
MYID.access = list(access_syndicate)
RPID.access = list(access_syndicate)
/mob/living/carbon/human/interactive/away/hotel/guard
default_job = /datum/job/officer
/mob/living/carbon/human/interactive/away/hotel/guard/doSetup()
..("Guard")
// anti-pinata cheese
var/obj/item/implant/dust/D = new /obj/item/implant/dust(src)
D.implant(src)
for(var/obj/item/I in get_all_slots())
I.flags |= NODROP
/mob/living/carbon/human/interactive/away/hotel/guard/KnockOut()
// you'll never take me alive (this triggers the implant)
emote("deathgasp")
if(stat != DEAD)
// mission failed. we'll get em next time
..()
/mob/living/carbon/human/interactive/away/hotel/chef
default_job = /datum/job/chef
away_area = /area/awaymission/spacehotel/kitchen
override_under = /obj/item/clothing/under/mafia/vest
/mob/living/carbon/human/interactive/away/hotel/bartender
default_job = /datum/job/bartender
override_under = /obj/item/clothing/under/mafia/vest
/mob/living/carbon/human/interactive/away/hotel/concierge
override_under = /obj/item/clothing/under/mafia/white
away_area = /area/awaymission/spacehotel/reception
var/list/known_guests[0]
var/obj/effect/hotel_controller/hotel
var/obj/item/card/id/last_seen_id = null
/mob/living/carbon/human/interactive/away/hotel/concierge/random()
..()
equip_or_collect(new /obj/item/clipboard(src), slot_l_hand)
/mob/living/carbon/human/interactive/away/hotel/concierge/doSetup()
..("Concierge")
/mob/living/carbon/human/interactive/away/hotel/concierge/setup_job()
favoured_types = list(/obj/item/paper, /obj/item/clipboard)
functions += list("stamping", "concierge")
restrictedJob = 1
/mob/living/carbon/human/interactive/away/hotel/concierge/proc/concierge()
if(!hotel)
hotel = hotel.controller
if(!hotel)
return
var/verbs_use = pick_list(speak_file, "verbs_use")
var/verbs_touch = pick_list(speak_file, "verbs_touch")
var/verbs_move = pick_list(speak_file, "verbs_move")
var/nouns_generic = pick_list(speak_file, "nouns_generic")
var/adjective_insult = pick_list(speak_file, "adjective_insult")
var/adjective_objects = pick_list(speak_file, "adjective_objects")
var/adjective_generic = pick_list(speak_file, "adjective_generic")
var/curse_words = pick_list(speak_file, "curse_words")
var/found = 0
for(var/mob/living/carbon/human/H in nearby - known_guests)
pointed(H)
known_guests += H
found = 1
if(found)
say("Welcome to [hotel], [nouns_generic]! Please check in by [ing_verb(verbs_move)] and [ing_verb(verbs_use)] your [adjective_objects] ID onto the table.")
return
var/obj/item/card/id
var/id_seen = 0
for(var/obj/item/card/id/I in get_area(src))
id_seen = 1
if(I != last_seen_id)
id = I
if(!id_seen)
last_seen_id = null
return
if(!id)
return
var/turf/idloc = get_turf(id)
if(!Adjacent(idloc))
tryWalk(idloc)
else
// is the last jerk that touched it over here?
var/mob/id_owner
for(var/mob/living/carbon/human/H in nearby)
if(H.ckey == id.fingerprintslast)
id_owner = H
break
if(!id_owner)
say("Whose card is this?")
pointed(id)
return
last_seen_id = id
// Checking in or out?
if(id_owner in hotel.guests)
// Check out
say ("Hope you enjoyed your [adjective_objects] stay at our [adjective_generic] hotel!")
hotel.checkout(hotel.guests[id_owner])
else
// pick a room
var/obj/machinery/door/unpowered/hotel_door/D = safepick(hotel.vacant_rooms)
if(!D)
say("Sorry, all the [adjective_objects] are occupied currently.")
else
// Check in
say("$100 per 10 minutes. The cost will be automatically [past_verb(verbs_touch)] while you're checked in.")
var/obj/item/card/hotel_card/K = hotel.checkin(D.id, id_owner, id)
if(K)
K.forceMove(idloc)
else
say("Your [adjective_insult] [curse_words] card was rejected.")
@@ -161,7 +161,7 @@ var/sc_safecode5 = "[rand(0,9)]"
desc = "Your body becomes weak and your feel your mind slipping away as you try to comprehend what you know can't be possible."
move_self = 0 //Contianed narsie does not move!
grav_pull = 0 //Contained narsie does not pull stuff in!
var/uneatable = list(/turf/space, /obj/effect/overlay, /atom/movable/lighting_overlay, /mob/living/simple_animal/hostile/construct)
var/uneatable = list(/turf/space, /obj/effect/overlay, /atom/movable/lighting_object, /mob/living/simple_animal/hostile/construct)
//Override this to prevent no adminlog runtimes and admin warnings about a singularity without containment
/obj/singularity/narsie/sc_Narsie/admin_investigate_setup()
@@ -9,31 +9,30 @@
/area/awaymission/wwmines
name = "\improper Wild West Mines"
icon_state = "away1"
luminosity = 1
requires_power = 0
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/wwgov
name = "\improper Wild West Mansion"
icon_state = "away2"
luminosity = 1
requires_power = 0
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/wwrefine
name = "\improper Wild West Refinery"
icon_state = "away3"
luminosity = 1
requires_power = 0
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/area/awaymission/wwvault
name = "\improper Wild West Vault"
icon_state = "away3"
luminosity = 0
/area/awaymission/wwvaultdoors
name = "\improper Wild West Vault Doors" // this is to keep the vault area being entirely lit because of requires_power
icon_state = "away2"
requires_power = 0
luminosity = 0
requires_power = FALSE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/*
* Wish Granter
-85
View File
@@ -1,85 +0,0 @@
/mob/living/carbon/human/interactive/away
var/away_area = /area/awaymission // their overriden job area
var/override_under = null // optional type for uniform, else default for job
var/squad_member = 0 // was spawned by squad
var/home_z
/mob/living/carbon/human/interactive/away/Initialize(mapload)
. = ..()
TRAITS |= TRAIT_ROBUST
faction += "away"
/mob/living/carbon/human/interactive/away/random()
..()
// a little hacky but it should prevent doubled uniforms
if(ispath(override_under, /obj/item/clothing/under))
var/old_under = w_uniform
w_uniform = null
equip_to_slot(new override_under(src), slot_w_uniform)
qdel(old_under)
/mob/living/carbon/human/interactive/away/doSetup()
..()
var/datum/data/pda/app/messenger/M = MYPDA.find_program(/datum/data/pda/app/messenger)
M.toff = 1
/mob/living/carbon/human/interactive/away/job2area()
return away_area
/mob/living/carbon/human/interactive/away/doProcess()
if(!home_z)
home_z = get_turf(z)
if(home_z != get_turf(z))
gib()
..()
/obj/effect/spawner/snpc_squad
name = "squad spawner"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x"
density = 0
opacity = 0
invisibility = 101
var/squad_type = /mob/living/carbon/human/interactive/away
var/squad_size = 3
var/global/list/squads[0]
var/list/squad
/obj/effect/spawner/snpc_squad/New()
START_PROCESSING(SSobj, src)
squad = squads[squad_type]
if(!squad)
squad = list()
squads[squad_type] = squad
squad += src
/obj/effect/spawner/snpc_squad/Destroy()
squad = null
STOP_PROCESSING(SSobj, src)
return ..()
/obj/effect/spawner/snpc_squad/process()
// check squad memebers
var/living = 0
for(var/mob/living/carbon/human/interactive/away/A in squad)
if(!A.stat)
living++
else
// see if anyone's looking, if not, despawn
var/can_despawn = 1
for(var/mob/living/M in viewers(A, world.view + 1))
if(M.client)
living++ // dead guy that can be seen still takes up a slot
can_despawn = 0
break
if(can_despawn)
squad -= A
qdel(A)
// spawn new ones
if(living < squad_size && !length(viewers(src, world.view)))
var/mob/living/carbon/human/interactive/away/A = new squad_type(loc)
squad += A
A.squad_member = 1
+11 -6
View File
@@ -1,8 +1,8 @@
/area/awaymission/upperlevel
name = "Open Space"
color = "#888"
dynamic_lighting = 0
requires_power = 0
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
requires_power = FALSE
// Used by /turf/unsimulated/floor/upperlevel as a reference for where the other floor is
/obj/effect/levelref
@@ -84,9 +84,14 @@
/obj/effect/portal_sensor/proc/check_light()
var/turf/T = loc
if(istype(T) && T.lighting_overlay && !T.lighting_overlay.needs_update)
var/atom/movable/lighting_overlay/O = T.lighting_overlay
var/hash = O.lum_r + O.lum_g + O.lum_b
if(istype(T) && T.lighting_object && !T.lighting_object.needs_update)
var/atom/movable/lighting_object/O = T.lighting_object
var/hash = 0
for(var/lighting_corner in O)
var/datum/lighting_corner/C = lighting_corner
hash = hash + C.lum_r + C.lum_g + C.lum_b
if(hash != light_hash)
light_hash = hash
trigger()
@@ -365,4 +370,4 @@
screen_loc = "CENTER[ox >= 0 ? "+" : ""][ox],CENTER[oy >= 0 ? "+" : ""][oy]"
/obj/effect/view_portal_dummy/attack_ghost(mob/user)
owner.attack_ghost(user)
owner.attack_ghost(user)
+1 -1
View File
@@ -81,7 +81,7 @@
var/datum/chatOutput/chatOutput
// Donator stuff.
var/donator_level = DONATOR_LEVEL_NONE
var/donator_level = 0
// If set to true, this client can interact with atoms such as buttons and doors on top of regular machinery interaction
var/advanced_admin_interaction = FALSE
+32 -14
View File
@@ -74,7 +74,7 @@
//Admin PM
if(href_list["priv_msg"])
var/client/C = locate(href_list["priv_msg"])
if(!C) // Might be a stealthmin ID, so pass it in straight
C = href_list["priv_msg"]
else if(C.UID() != href_list["priv_msg"])
@@ -328,13 +328,13 @@
GLOB.admins += src
holder.owner = src
donator_check()
//preferences datum - also holds some persistant data for the client (because we may as well keep these datums to a minimum)
prefs = preferences_datums[ckey]
if(!prefs)
prefs = new /datum/preferences(src)
preferences_datums[ckey] = prefs
else
prefs.parent = src
prefs.last_ip = address //these are gonna be used for banning
prefs.last_id = computer_id //these are gonna be used for banning
if(world.byond_version >= 511 && byond_version >= 511 && prefs.clientfps)
@@ -343,12 +343,6 @@
spawn() // Goonchat does some non-instant checks in start()
chatOutput.start()
if(custom_event_msg && custom_event_msg != "")
to_chat(src, "<h1 class='alert'>Custom Event</h1>")
to_chat(src, "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>")
to_chat(src, "<span class='alert'>[html_encode(custom_event_msg)]</span>")
to_chat(src, "<br>")
if( (world.address == address || !address) && !host )
host = key
world.update_status()
@@ -376,6 +370,7 @@
to_chat(src, message)
clientmessages.Remove(ckey)
donator_check()
send_resources()
@@ -395,10 +390,14 @@
if(establish_db_connection())
to_chat(src,"<span class='notice'>You have enabled karma gains.")
if(!void)
void = new()
generate_clickcatcher()
apply_clickcatcher()
screen += void
if(custom_event_msg && custom_event_msg != "")
to_chat(src, "<h1 class='alert'>Custom Event</h1>")
to_chat(src, "<h2 class='alert'>A custom event is taking place. OOC Info:</h2>")
to_chat(src, "<span class='alert'>[html_encode(custom_event_msg)]</span>")
to_chat(src, "<br>")
if(!winexists(src, "asset_cache_browser")) // The client is using a custom skin, tell them.
to_chat(src, "<span class='warning'>Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.</span>")
@@ -431,17 +430,27 @@
if(!dbcon.IsConnected())
return
if(check_rights(R_ADMIN, 0, mob)) // Yes, the mob is required, regardless of other examples in this file, it won't work otherwise
donator_level = DONATOR_LEVEL_MAX
donor_loadout_points()
return
//Donator stuff.
var/DBQuery/query_donor_select = dbcon.NewQuery("SELECT ckey, tier, active FROM `[format_table_name("donators")]` WHERE ckey = '[ckey]'")
query_donor_select.Execute()
while(query_donor_select.NextRow())
if(!text2num(query_donor_select.item[3]))
// Inactive donator.
donator_level = DONATOR_LEVEL_NONE
donator_level = 0
return
donator_level = text2num(query_donor_select.item[2])
donor_loadout_points()
break
/client/proc/donor_loadout_points()
if(donator_level > 0 && prefs)
prefs.max_gear_slots = config.max_loadout_points + 5
/client/proc/log_client_to_db(connectiontopic)
if(IsGuestKey(key))
return
@@ -775,6 +784,15 @@
else
winset(src, "rpane.changelog", "background-color=none;text-color=#000000")
/client/proc/generate_clickcatcher()
if(!void)
void = new()
screen += void
/client/proc/apply_clickcatcher()
generate_clickcatcher()
var/list/actualview = getviewsize(view)
void.UpdateGreed(actualview[1],actualview[2])
/client/proc/send_ssd_warning(mob/M)
if(!config.ssd_warning)
@@ -786,4 +804,4 @@
to_chat(src, "Interacting with SSD players is against server rules unless you've ahelped first for permission. If you have, <a href='byond://?src=[UID()];ssdwarning=accepted'>confirm that</A> and proceed.")
return TRUE
#undef SSD_WARNING_TIMER
#undef SSD_WARNING_TIMER
@@ -4,7 +4,6 @@ var/list/gear_datums = list()
/datum/loadout_category
var/category = ""
var/list/gear = list()
var/donor_only = FALSE
/datum/loadout_category/New(cat)
category = cat
@@ -34,8 +33,6 @@ var/list/gear_datums = list()
if(!loadout_categories[use_category])
loadout_categories[use_category] = new /datum/loadout_category(use_category)
var/datum/loadout_category/LC = loadout_categories[use_category]
if(initial(G.donor_only))
LC.donor_only = TRUE
gear_datums[use_name] = new geartype
LC.gear[use_name] = gear_datums[use_name]
@@ -57,7 +54,7 @@ var/list/gear_datums = list()
var/list/gear_tweaks = list() //List of datums which will alter the item after it has been spawned.
var/subtype_path = /datum/gear //for skipping organizational subtypes (optional)
var/subtype_cost_overlap = TRUE //if subtypes can take points at the same time
var/donor_only = FALSE // if it's only available to donors
var/donator_tier = 0
/datum/gear/New()
..()
@@ -1,5 +1,5 @@
/datum/gear/donor
donor_only = TRUE
donator_tier = 2
sort_category = "Donor"
subtype_path = /datum/gear/donor
@@ -77,6 +77,26 @@
display_name = "Guy Fawkes mask"
path = /obj/item/clothing/mask/fawkes
/datum/gear/donor/noble_clothes
display_name = "Noble Clothes"
path = /obj/item/clothing/under/noble_clothes
/datum/gear/donor/id_decal_silver
display_name = "Silver ID Decal"
path = /obj/item/id_decal/silver
donator_tier = 3
cost = 2
/datum/gear/donor/id_decal_prisoner
display_name = "Prisoner ID Decal"
path = /obj/item/id_decal/prisoner
donator_tier = 3
cost = 2
/datum/gear/donor/id_decal_emag
display_name = "Emag ID Decal"
path = /obj/item/id_decal/emag
donator_tier = 3
cost = 2
/datum/gear/donor/id_decal_gold
display_name = "Gold ID Decal"
path = /obj/item/id_decal/gold
donator_tier = 4
cost = 4
+19 -30
View File
@@ -183,7 +183,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
// 0 = character settings, 1 = game preferences
var/current_tab = TAB_CHAR
// OOC Metadata:
// OOC Metadata:
var/metadata = ""
var/slot_name = ""
@@ -211,8 +211,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
unlock_content = C.IsByondMember()
if(unlock_content)
max_save_slots = MAX_SAVE_SLOTS_MEMBER
if(C.donator_level >= DONATOR_LEVEL_ONE)
max_gear_slots += 5
loaded_preferences_successfully = load_preferences(C) // Do not call this with no client/C, it generates a runtime / SQL error
if(loaded_preferences_successfully)
@@ -448,10 +446,11 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
dat += " - <b>Color:</b> <a href='?_src_=prefs;preference=UIcolor'><b>[UI_style_color]</b></a> <span style='border: 1px solid #161616; background-color: [UI_style_color];'>&nbsp;&nbsp;&nbsp;</span><br>"
dat += " - <b>UI Style:</b> <a href='?_src_=prefs;preference=ui'><b>[UI_style]</b></a><br>"
dat += "<b>Deadchat Anonymity:</b> <a href='?_src_=prefs;preference=ghost_anonsay'><b>[ghost_anonsay ? "Anonymous" : "Not Anonymous"]</b></a><br>"
if(user.client.donator_level >= DONATOR_LEVEL_ONE)
if(user.client.donator_level > 0)
dat += "<b>Donator Publicity:</b> <a href='?_src_=prefs;preference=donor_public'><b>[(toggles & DONATOR_PUBLIC) ? "Public" : "Hidden"]</b></a><br>"
dat += "<b>Fancy NanoUI:</b> <a href='?_src_=prefs;preference=nanoui'>[(nanoui_fancy) ? "Yes" : "No"]</a><br>"
dat += "<b>FPS:</b> <a href='?_src_=prefs;preference=clientfps;task=input'>[clientfps]</a><br>"
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'><b>[toggles & AMBIENT_OCCLUSION ? "Enabled" : "Disabled"]</b></a><br>"
dat += "<b>Ghost Ears:</b> <a href='?_src_=prefs;preference=ghost_ears'><b>[(toggles & CHAT_GHOSTEARS) ? "All Speech" : "Nearest Creatures"]</b></a><br>"
dat += "<b>Ghost Sight:</b> <a href='?_src_=prefs;preference=ghost_sight'><b>[(toggles & CHAT_GHOSTSIGHT) ? "All Emotes" : "Nearest Creatures"]</b></a><br>"
dat += "<b>Ghost Radio:</b> <a href='?_src_=prefs;preference=ghost_radio'><b>[(toggles & CHAT_GHOSTRADIO) ? "All Chatter" : "Nearest Speakers"]</b></a><br>"
@@ -508,10 +507,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
var/firstcat = 1
for(var/category in loadout_categories)
var/datum/loadout_category/LC = loadout_categories[category]
if(LC.donor_only)
if(user.client.donator_level < DONATOR_LEVEL_TWO) // level two donators get the donator loadout, so don't show it to anyone with less than that
continue
if(firstcat)
firstcat = 0
else
@@ -529,7 +524,10 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
for(var/gear_name in LC.gear)
var/datum/gear/G = LC.gear[gear_name]
var/ticked = (G.display_name in gear)
dat += "<tr style='vertical-align:top;'><td width=15%><a style='white-space:normal;' [ticked ? "class='linkOn' " : ""]href='?_src_=prefs;preference=gear;toggle_gear=[G.display_name]'>[G.display_name]</a></td>"
if(G.donator_tier > user.client.donator_level)
dat += "<tr style='vertical-align:top;'><td width=15%><B>[G.display_name]</B></td>"
else
dat += "<tr style='vertical-align:top;'><td width=15%><a style='white-space:normal;' [ticked ? "class='linkOn' " : ""]href='?_src_=prefs;preference=gear;toggle_gear=[G.display_name]'>[G.display_name]</a></td>"
dat += "<td width = 5% style='vertical-align:top'>[G.cost]</td><td>"
if(G.allowed_roles)
dat += "<font size=2>Restrictions: "
@@ -1147,10 +1145,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if(TG.display_name in gear)
gear -= TG.display_name
else
if(TG.donor_only)
if(user.client.donator_level < DONATOR_LEVEL_TWO) // donator items are locked to > tier 2
//they normally can't even get this far- but just in case of href exploits, we check them here
return
if(TG.donator_tier && user.client.donator_level < TG.donator_tier)
to_chat(user, "<span class='warning'>That gear is only available at a higher donation tier than you are on.</span>")
return
var/total_cost = 0
var/list/type_blacklist = list()
for(var/gear_name in gear)
@@ -1921,22 +1918,6 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if(world.byond_version >= 511 && user.client && user.client.byond_version >= 511)
parent.fps = clientfps
/*
if("skin_style")
var/skin_style_name = input(user, "Select a new skin style") as null|anything in list("default1", "default2", "default3")
if(!skin_style_name) return
*/
/* if("spawnpoint")
var/list/spawnkeys = list()
for(var/S in spawntypes)
spawnkeys += S
var/choice = input(user, "Where would you like to spawn when latejoining?") as null|anything in spawnkeys
if(!choice || !spawntypes[choice])
spawnpoint = "Arrivals Shuttle"
return
spawnpoint = choice */
else
switch(href_list["preference"])
if("publicity")
@@ -1944,7 +1925,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
toggles ^= MEMBER_PUBLIC
if("donor_public")
if(user.client.donator_level >= DONATOR_LEVEL_ONE)
if(user.client.donator_level > 0)
toggles ^= DONATOR_PUBLIC
if("gender")
@@ -2081,6 +2062,14 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if(href_list["tab"])
current_tab = text2num(href_list["tab"])
if("ambientocclusion")
toggles ^= AMBIENT_OCCLUSION
if(parent && parent.screen && parent.screen.len)
var/obj/screen/plane_master/game_world/PM = locate(/obj/screen/plane_master/game_world) in parent.screen
PM.filters -= FILTER_AMBIENT_OCCLUSION
if(toggles & AMBIENT_OCCLUSION)
PM.filters += FILTER_AMBIENT_OCCLUSION
ShowChoices(user)
return 1
@@ -55,7 +55,7 @@
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
UI_style = sanitize_inlist(UI_style, list("White", "Midnight"), initial(UI_style))
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
toggles = sanitize_integer(toggles, 0, 2097151, initial(toggles))
toggles = sanitize_integer(toggles, 0, TOGGLES_TOTAL, initial(toggles))
sound = sanitize_integer(sound, 0, 65535, initial(sound))
UI_style_color = sanitize_hexcolor(UI_style_color, initial(UI_style_color))
UI_style_alpha = sanitize_integer(UI_style_alpha, 0, 255, initial(UI_style_alpha))
@@ -87,7 +87,7 @@
UI_style_alpha='[UI_style_alpha]',
be_role='[sanitizeSQL(list2params(be_special))]',
default_slot='[default_slot]',
toggles='[toggles]',
toggles='[num2text(toggles, 7)]',
atklog='[atklog]',
sound='[sound]',
randomslot='[randomslot]',
@@ -230,7 +230,6 @@
to_chat(usr, "<span class='notice'>You have disabled karma gains.")
else
to_chat(usr, "<span class='notice'>You have enabled karma gains.")
return
/client/verb/toggle_popup_limiter()
set name = "Toggle Text Popup Limiter"
@@ -242,4 +241,4 @@
to_chat(usr, "<span class='notice'>You have enabled text popup limiting.")
else
to_chat(usr, "<span class='notice'>You have disabled text popup limiting.")
return
+34 -6
View File
@@ -151,14 +151,16 @@
slot_flags = SLOT_EYES
materials = list(MAT_GLASS = 250)
var/vision_flags = 0
var/darkness_view = 0 //Base human is 2
var/see_in_dark = 0 //Base human is 2
var/invis_view = SEE_INVISIBLE_LIVING
var/invis_override = 0
var/lighting_alpha
var/emagged = 0
var/list/color_view = null//overrides client.color while worn
var/prescription = 0
var/prescription_upgradable = 0
var/over_mask = FALSE //Whether or not the eyewear is rendered above the mask. Purely cosmetic.
strip_delay = 20 // but seperated to allow items to protect but not impair vision, like space helmets
put_on_delay = 25
burn_state = FIRE_PROOF
@@ -173,6 +175,28 @@ SEE_PIXELS// if an object is located on an unlit area, but some of its pixels ar
BLIND // can't see anything
*/
/obj/item/clothing/glasses/verb/adjust_eyewear() //Adjust eyewear to be worn above or below the mask.
set name = "Adjust Eyewear"
set category = "Object"
set desc = "Adjust your eyewear to be worn over or under a mask."
set src in usr
var/mob/living/carbon/human/user = usr
if(!istype(user))
return
if(user.incapacitated()) //Dead spessmen adjust no glasses. Resting/buckled ones do, though
return
var/action_fluff = "You adjust \the [src]"
if(user.glasses == src)
if(!user.canUnEquip(src))
to_chat(usr, "[src] is stuck to you!")
return
if(attack_hand(user)) //Remove the glasses for this action. Prevents logic-defying instances where glasses phase through your mask as it ascends/descends to another plane of existence.
action_fluff = "You remove \the [src] and adjust it"
over_mask = !over_mask
to_chat(user, "<span class='notice'>[action_fluff] to be worn [over_mask ? "over" : "under"] a mask.</span>")
//Gloves
/obj/item/clothing/gloves
@@ -281,9 +305,11 @@ BLIND // can't see anything
slot_flags = SLOT_HEAD
var/blockTracking // Do we block AI tracking?
var/HUDType = null
var/darkness_view = 0
var/helmet_goggles_invis_view = 0
var/vision_flags = 0
var/see_in_dark = 0
var/lighting_alpha
var/can_toggle = null
//Mask
@@ -574,8 +600,9 @@ BLIND // can't see anything
"Drask" = 'icons/mob/species/drask/uniform.dmi',
"Grey" = 'icons/mob/species/grey/uniform.dmi'
)
var/has_sensor = 1//For the crew computer 2 = unable to change mode
var/sensor_mode = 0
var/has_sensor = TRUE//For the crew computer 2 = unable to change mode
var/sensor_mode = SENSOR_OFF
var/random_sensor = TRUE
/*
1 = Report living/dead
2 = Report detailed damages
@@ -587,7 +614,8 @@ BLIND // can't see anything
var/basecolor
/obj/item/clothing/under/rank/New()
sensor_mode = pick(0,1,2,3)
if(random_sensor)
sensor_mode = pick(SENSOR_OFF, SENSOR_LIVING, SENSOR_VITALS, SENSOR_COORDS)
..()
/obj/item/clothing/under/Destroy()
+34 -23
View File
@@ -37,7 +37,7 @@
item_state = "glasses"
origin_tech = "magnets=1;engineering=2"
vision_flags = SEE_TURFS
invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
prescription_upgradable = 1
species_fit = list("Vox")
sprite_sheets = list(
@@ -52,7 +52,8 @@
icon_state = "nvgmeson"
item_state = "glasses"
origin_tech = "magnets=4;engineering=5;plasmatech=4"
darkness_view = 8
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
prescription_upgradable = 0
/obj/item/clothing/glasses/meson/prescription
@@ -103,8 +104,8 @@
desc = "Now you can science in darkness."
icon_state = "nvpurple"
item_state = "glasses"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE //don't render darkness while wearing these
/obj/item/clothing/glasses/janitor
name = "Janitorial Goggles"
@@ -122,8 +123,8 @@
icon_state = "night"
item_state = "glasses"
origin_tech = "materials=4;magnets=4;plasmatech=4;engineering=4"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE //don't render darkness while wearing these
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
@@ -177,6 +178,15 @@
flags = NODROP
flags_cover = null
/obj/item/clothing/glasses/material/lighting
name = "Neutron Goggles"
desc = "These odd glasses use a form of neutron-based imaging to completely negate the effects of light and darkness."
origin_tech = null
vision_flags = 0
flags = NODROP
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
/obj/item/clothing/glasses/regular
name = "prescription glasses"
desc = "Made by Nerd. Co."
@@ -223,7 +233,7 @@
name = "sunglasses"
icon_state = "sun"
item_state = "sunglasses"
darkness_view = 1
see_in_dark = 1
flash_protect = 1
tint = 1
prescription_upgradable = 1
@@ -237,7 +247,7 @@
/obj/item/clothing/glasses/sunglasses/fake
desc = "Cheap, plastic sunglasses. They don't even have UV protection."
name = "cheap sunglasses"
darkness_view = 0
see_in_dark = 0
flash_protect = 0
tint = 0
@@ -285,7 +295,7 @@
name = "sunglasses"
icon_state = "sun"
item_state = "sunglasses"
darkness_view = 1
see_in_dark = 1
flash_protect = 1
tint = 1
species_fit = list("Vox")
@@ -382,6 +392,7 @@
item_state = "glasses"
origin_tech = "magnets=3"
vision_flags = SEE_MOBS
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
flash_protect = -1
species_fit = list("Vox")
sprite_sheets = list(
@@ -389,18 +400,18 @@
"Grey" = 'icons/mob/species/grey/eyes.dmi'
)
emp_act(severity)
if(istype(src.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/M = src.loc
to_chat(M, "<span class='warning'>The Optical Thermal Scanner overloads and blinds you!</span>")
if(M.glasses == src)
M.EyeBlind(3)
M.EyeBlurry(5)
if(!(M.disabilities & NEARSIGHTED))
M.BecomeNearsighted()
spawn(100)
M.CureNearsighted()
..()
/obj/item/clothing/glasses/thermal/emp_act(severity)
if(istype(src.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/M = src.loc
to_chat(M, "<span class='warning'>The Optical Thermal Scanner overloads and blinds you!</span>")
if(M.glasses == src)
M.EyeBlind(3)
M.EyeBlurry(5)
if(!(M.disabilities & NEARSIGHTED))
M.BecomeNearsighted()
spawn(100)
M.CureNearsighted()
..()
/obj/item/clothing/glasses/thermal/syndi //These are now a traitor item, concealed as mesons. -Pete
name = "Optical Meson Scanner"
@@ -503,11 +514,11 @@
icon_state = "godeye"
item_state = "godeye"
vision_flags = SEE_TURFS|SEE_MOBS|SEE_OBJS
darkness_view = 8
see_in_dark = 8
scan_reagents = 1
flags = NODROP
flags_cover = null
invis_view = SEE_INVISIBLE_MINIMUM
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
/obj/item/clothing/glasses/godeye/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, src) && W != src && W.loc == user)
+10 -9
View File
@@ -50,8 +50,8 @@
icon_state = "healthhudnight"
item_state = "glasses"
origin_tech = "magnets=4;biotech=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
prescription_upgradable = 0
/obj/item/clothing/glasses/hud/diagnostic
@@ -72,8 +72,8 @@
icon_state = "diagnostichudnight"
item_state = "glasses"
origin_tech = "magnets=4;powerstorage=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
prescription_upgradable = 0
/obj/item/clothing/glasses/hud/security
@@ -105,14 +105,15 @@
icon_state = "jensenshades"
item_state = "jensenshades"
vision_flags = SEE_MOBS
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
/obj/item/clothing/glasses/hud/security/night
name = "\improper Night Vision Security HUD"
desc = "An advanced heads-up display which provides id data and vision in complete darkness."
icon_state = "securityhudnight"
origin_tech = "magnets=4;combat=4;plasmatech=4;engineering=5"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE //don't render darkness while wearing these
prescription_upgradable = 0
/obj/item/clothing/glasses/hud/security/sunglasses/read_only
@@ -123,7 +124,7 @@
desc = "Sunglasses with a HUD."
icon_state = "sunhud"
origin_tech = "magnets=3;combat=3;engineering=3"
darkness_view = 1
see_in_dark = 1
flash_protect = 1
tint = 1
prescription_upgradable = 1
@@ -153,8 +154,8 @@
desc = "A hydroponic HUD fitted with a light amplifier."
icon_state = "hydroponichudnight"
item_state = "glasses"
darkness_view = 8
invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
prescription_upgradable = 0
/obj/item/clothing/glasses/hud/security/tajblind
+2 -1
View File
@@ -50,6 +50,7 @@
desc = "A helmet with a built-in thermal scanning visor."
icon_state = "helmetthermals"
vision_flags = SEE_MOBS
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
/obj/item/clothing/head/helmet/meson
name = "meson visor helmet"
@@ -67,7 +68,7 @@
name = "night-vision helmet"
desc = "A helmet with a built-in pair of night vision goggles."
icon_state = "helmetNVG"
helmet_goggles_invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE //don't render darkness while wearing these
/obj/item/clothing/head/helmet/alt
name = "bulletproof helmet"
-5
View File
@@ -162,11 +162,6 @@
item_state = "sexymime"
burn_state = FLAMMABLE
/obj/item/clothing/mask/gas/death_commando
name = "Death Commando Mask"
icon_state = "death_commando_mask"
item_state = "death_commando_mask"
/obj/item/clothing/mask/gas/cyborg
name = "cyborg visor"
desc = "Beep boop"
-38
View File
@@ -1,38 +0,0 @@
/obj/item/voice_changer
name = "voice changer"
desc = "A voice scrambling module. If you can see this, report it as a bug on the tracker."
var/voice //If set and item is present in mask/suit, this name will be used for the wearer's speech.
var/active
/obj/item/clothing/mask/gas/voice
name = "gas mask"
// desc = "A face-covering mask that can be connected to an air supply. It seems to house some odd electronics."
var/obj/item/voice_changer/changer
burn_state = FIRE_PROOF
/obj/item/clothing/mask/gas/voice/verb/Toggle_Voice_Changer()
set category = "Object"
set src in usr
changer.active = !changer.active
to_chat(usr, "<span class='notice'>You [changer.active ? "enable" : "disable"] the voice-changing module in \the [src].</span>")
/obj/item/clothing/mask/gas/voice/verb/Set_Voice(name as text)
set category = "Object"
set src in usr
var/voice = sanitize(copytext(name,1,MAX_MESSAGE_LEN))
if(!voice || !length(voice)) return
changer.voice = voice
to_chat(usr, "<span class='notice'>You are now mimicking <B>[changer.voice]</B>.</span>")
/obj/item/clothing/mask/gas/voice/New()
..()
changer = new(src)
/obj/item/clothing/mask/gas/voice/clown
name = "clown wig and mask"
desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
icon_state = "clown"
item_state = "clown_hat"
flags = BLOCK_GAS_SMOKE_EFFECT | AIRTIGHT | BLOCKHAIR
+1 -1
View File
@@ -83,7 +83,7 @@ obj/item/clothing/shoes/magboots/syndie/advance //For the Syndicate Strike Team
/obj/item/clothing/shoes/magboots/wizard/attack_self(mob/user)
if(user)
if(user.mind in ticker.mode.wizards)
if(user.mind in SSticker.mode.wizards)
if(magpulse) //faint blue light when shoes are turned on gives a reason to turn them off when not needed in maint
set_light(0)
else
@@ -1,21 +1,3 @@
/obj/item/clothing/shoes/syndigaloshes
desc = "A pair of brown shoes. They seem to have extra grip."
name = "brown shoes"
icon_state = "brown"
item_state = "brown"
permeability_coefficient = 0.05
flags = NOSLIP
origin_tech = "syndicate=2"
burn_state = FIRE_PROOF
var/list/clothing_choices = list()
silence_steps = 1
/obj/item/clothing/shoes/syndigaloshes/black
name = "black shoes"
icon_state = "black"
item_color = "black"
desc = "A pair of black shoes. They seem to have extra grip."
/obj/item/clothing/shoes/mime
name = "mime shoes"
icon_state = "mime"
@@ -47,7 +47,8 @@
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
unacidable = 1
vision_flags = SEE_MOBS
helmet_goggles_invis_view = SEE_INVISIBLE_MINIMUM //don't render darkness while wearing these
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE //don't render darkness while wearing these
see_in_dark = 8
HUDType = MEDHUD
strip_delay = 130
@@ -269,14 +269,13 @@
/obj/item/rig_module/voice/New()
..()
voice_holder = new(src)
voice_holder.active = 0
voice_holder.active = FALSE
/obj/item/rig_module/voice/installed()
..()
holder.speech = src
/obj/item/rig_module/voice/engage()
if(!..())
return 0
@@ -287,17 +286,17 @@
switch(choice)
if("Enable")
active = 1
voice_holder.active = 1
active = TRUE
voice_holder.active = TRUE
to_chat(usr, "<font color='blue'>You enable the speech synthesiser.</font>")
if("Disable")
active = 0
voice_holder.active = 0
active = FALSE
voice_holder.active = FALSE
to_chat(usr, "<font color='blue'>You disable the speech synthesiser.</font>")
if("Set Name")
var/raw_choice = sanitize(input(usr, "Please enter a new name.") as text|null, MAX_NAME_LEN)
if(!raw_choice)
return 0
return FALSE
voice_holder.voice = raw_choice
to_chat(usr, "<font color='blue'>You are now mimicking <B>[voice_holder.voice]</B>.</font>")
return 1
+10 -1
View File
@@ -345,7 +345,7 @@
name = "winter coat"
desc = "A heavy jacket made from 'synthetic' animal furs."
icon_state = "wintercoat"
item_state = "labcoat"
item_state = "coatwinter"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|ARMS
cold_protection = UPPER_TORSO|LOWER_TORSO|ARMS
min_cold_protection_temperature = FIRE_SUIT_MIN_TEMP_PROTECT
@@ -369,6 +369,7 @@
/obj/item/clothing/suit/hooded/wintercoat/captain
name = "captain's winter coat"
icon_state = "wintercoat_captain"
item_state = "coatcaptain"
armor = list(melee = 25, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
allowed = list(/obj/item/gun/energy, /obj/item/reagent_containers/spray/pepper, /obj/item/gun/projectile, /obj/item/ammo_box,/obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/flashlight/seclite, /obj/item/melee/classic_baton/telescopic)
hoodtype = /obj/item/clothing/head/winterhood/captain
@@ -379,6 +380,7 @@
/obj/item/clothing/suit/hooded/wintercoat/security
name = "security winter coat"
icon_state = "wintercoat_sec"
item_state = "coatsecurity"
armor = list(melee = 10, bullet = 10, laser = 10, energy = 5, bomb = 15, bio = 0, rad = 0)
allowed = list(/obj/item/gun/energy, /obj/item/reagent_containers/spray/pepper, /obj/item/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/flashlight/seclite, /obj/item/melee/classic_baton/telescopic)
hoodtype = /obj/item/clothing/head/winterhood/security
@@ -389,6 +391,7 @@
/obj/item/clothing/suit/hooded/wintercoat/medical
name = "medical winter coat"
icon_state = "wintercoat_med"
item_state = "coatmedical"
allowed = list(/obj/item/analyzer, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 50, rad = 0)
hoodtype = /obj/item/clothing/head/winterhood/medical
@@ -399,6 +402,7 @@
/obj/item/clothing/suit/hooded/wintercoat/science
name = "science winter coat"
icon_state = "wintercoat_sci"
item_state = "coatscience"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer,/obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 0, rad = 0)
hoodtype = /obj/item/clothing/head/winterhood/science
@@ -409,6 +413,7 @@
/obj/item/clothing/suit/hooded/wintercoat/engineering
name = "engineering winter coat"
icon_state = "wintercoat_engi"
item_state = "coatengineer"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 20)
allowed = list(/obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/t_scanner, /obj/item/rcd)
hoodtype = /obj/item/clothing/head/winterhood/engineering
@@ -419,6 +424,7 @@
/obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
name = "atmospherics winter coat"
icon_state = "wintercoat_atmos"
item_state = "coatatmos"
hoodtype = /obj/item/clothing/head/winterhood/engineering/atmos
/obj/item/clothing/head/winterhood/engineering/atmos
@@ -427,6 +433,7 @@
/obj/item/clothing/suit/hooded/wintercoat/hydro
name = "hydroponics winter coat"
icon_state = "wintercoat_hydro"
item_state = "coathydro"
allowed = list(/obj/item/reagent_containers/spray, /obj/item/plant_analyzer, /obj/item/seeds, /obj/item/reagent_containers/glass/bottle, /obj/item/hatchet, /obj/item/storage/bag/plants)
hoodtype = /obj/item/clothing/head/winterhood/hydro
@@ -436,6 +443,7 @@
/obj/item/clothing/suit/hooded/wintercoat/cargo
name = "cargo winter coat"
icon_state = "wintercoat_cargo"
item_state = "coatcargo"
hoodtype = /obj/item/clothing/head/winterhood/cargo
/obj/item/clothing/head/winterhood/cargo
@@ -444,6 +452,7 @@
/obj/item/clothing/suit/hooded/wintercoat/miner
name = "mining winter coat"
icon_state = "wintercoat_miner"
item_state = "coatminer"
allowed = list(/obj/item/pickaxe, /obj/item/flashlight, /obj/item/tank/emergency_oxygen, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
armor = list(melee = 10, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0)
hoodtype = /obj/item/clothing/head/winterhood/miner
@@ -630,7 +630,7 @@
var/area/t = get_area(M)
var/obj/item/radio/headset/a = new /obj/item/radio/headset(src)
if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) )
if(istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite))
//give the syndicats a bit of stealth
a.autosay("[M] has been vandalized in Space!", "[M]'s Death Alarm")
else
+457 -65
View File
@@ -1,86 +1,478 @@
#define EMP_RANDOMISE_TIME 300
/datum/action/chameleon_outfit
name = "Select Chameleon Outfit"
button_icon_state = "chameleon_outfit"
var/list/outfit_options //By default, this list is shared between all instances. It is not static because if it were, subtypes would not be able to have their own. If you ever want to edit it, copy it first.
/datum/action/chameleon_outfit/New()
..()
initialize_outfits()
/datum/action/chameleon_outfit/proc/initialize_outfits()
var/static/list/standard_outfit_options
if(!standard_outfit_options)
standard_outfit_options = list()
for(var/path in subtypesof(/datum/outfit/job))
var/datum/outfit/O = path
standard_outfit_options[initial(O.name)] = path
sortTim(standard_outfit_options, /proc/cmp_text_asc)
outfit_options = standard_outfit_options
/datum/action/chameleon_outfit/Trigger()
return select_outfit(owner)
/datum/action/chameleon_outfit/proc/select_outfit(mob/user)
if(!user || !IsAvailable())
return FALSE
var/selected = input("Select outfit to change into", "Chameleon Outfit") as null|anything in outfit_options
if(!IsAvailable() || QDELETED(src) || QDELETED(user))
return FALSE
var/outfit_type = outfit_options[selected]
if(!outfit_type)
return FALSE
var/datum/outfit/O = new outfit_type()
var/list/outfit_types = O.get_chameleon_disguise_info()
for(var/V in user.chameleon_item_actions)
var/datum/action/item_action/chameleon/change/A = V
var/done = FALSE
for(var/T in outfit_types)
for(var/name in A.chameleon_list)
if(A.chameleon_list[name] == T)
A.update_look(user, T)
outfit_types -= T
done = TRUE
break
if(done)
break
//hardsuit helmets/suit hoods
if(ispath(O.suit, /obj/item/clothing/suit/hooded) && ishuman(user))
var/mob/living/carbon/human/H = user
//make sure they are actually wearing the suit, not just holding it, and that they have a chameleon hat
if(istype(H.wear_suit, /obj/item/clothing/suit/chameleon) && istype(H.head, /obj/item/clothing/head/chameleon))
var/helmet_type
var/obj/item/clothing/suit/hooded/hooded = O.suit
helmet_type = initial(hooded.hoodtype)
if(helmet_type)
var/obj/item/clothing/head/chameleon/hat = H.head
hat.chameleon_action.update_look(user, helmet_type)
qdel(O)
return TRUE
/datum/action/item_action/chameleon/change
name = "Chameleon Change"
var/list/chameleon_blacklist = list() //This is a typecache
var/list/chameleon_list = list()
var/chameleon_type = null
var/chameleon_name = "Item"
var/emp_timer
/datum/action/item_action/chameleon/change/Grant(mob/M)
if(M && (owner != M))
if(!M.chameleon_item_actions)
M.chameleon_item_actions = list(src)
var/datum/action/chameleon_outfit/O = new /datum/action/chameleon_outfit()
O.Grant(M)
else
M.chameleon_item_actions |= src
..()
/datum/action/item_action/chameleon/change/Remove(mob/M)
if(M && (M == owner))
LAZYREMOVE(M.chameleon_item_actions, src)
if(!LAZYLEN(M.chameleon_item_actions))
var/datum/action/chameleon_outfit/O = locate(/datum/action/chameleon_outfit) in M.actions
qdel(O)
..()
/datum/action/item_action/chameleon/change/proc/initialize_disguises()
if(button)
button.name = "Change [chameleon_name] Appearance"
chameleon_blacklist |= typecacheof(target.type)
for(var/V in typesof(chameleon_type))
if(ispath(V) && ispath(V, /obj/item))
var/obj/item/I = V
if(chameleon_blacklist[V] || (initial(I.flags) & ABSTRACT) || !initial(I.icon_state))
continue
var/chameleon_item_name = "[initial(I.name)] ([initial(I.icon_state)])"
chameleon_list[chameleon_item_name] = I
/datum/action/item_action/chameleon/change/proc/select_look(mob/user)
var/obj/item/picked_item
var/picked_name
picked_name = input("Select [chameleon_name] to change into", "Chameleon [chameleon_name]", picked_name) as null|anything in chameleon_list
if(!picked_name)
return
picked_item = chameleon_list[picked_name]
if(!picked_item)
return
update_look(user, picked_item)
/datum/action/item_action/chameleon/change/proc/random_look(mob/user)
var/picked_name = pick(chameleon_list)
// If a user is provided, then this item is in use, and we
// need to update our icons and stuff
if(user)
update_look(user, chameleon_list[picked_name])
// Otherwise, it's likely a random initialisation, so we
// don't have to worry
else
update_item(chameleon_list[picked_name])
/datum/action/item_action/chameleon/change/proc/update_look(mob/user, obj/item/picked_item)
if(isliving(user))
var/mob/living/C = user
if(C.stat != CONSCIOUS)
return
update_item(picked_item)
var/obj/item/thing = target
thing.update_slot_icon()
UpdateButtonIcon()
/datum/action/item_action/chameleon/change/proc/update_item(obj/item/picked_item)
target.name = initial(picked_item.name)
target.desc = initial(picked_item.desc)
target.icon_state = initial(picked_item.icon_state)
if(isitem(target))
var/obj/item/I = target
I.item_state = initial(picked_item.item_state)
I.item_color = initial(picked_item.item_color)
if(istype(I, /obj/item/clothing) && istype(initial(picked_item), /obj/item/clothing))
var/obj/item/clothing/CL = I
var/obj/item/clothing/PCL = picked_item
CL.flags_cover = initial(PCL.flags_cover)
target.icon = initial(picked_item.icon)
/datum/action/item_action/chameleon/change/Trigger()
if(!IsAvailable())
return
select_look(owner)
return 1
/datum/action/item_action/chameleon/change/proc/emp_randomise(var/amount = EMP_RANDOMISE_TIME)
START_PROCESSING(SSprocessing, src)
random_look(owner)
var/new_value = world.time + amount
if(new_value > emp_timer)
emp_timer = new_value
/datum/action/item_action/chameleon/change/process()
if(world.time > emp_timer)
STOP_PROCESSING(SSprocessing, src)
return
random_look(owner)
/obj/item/clothing/under/chameleon
//starts off as black
name = "black jumpsuit"
icon_state = "black"
item_state = "bl_suit"
item_color = "black"
desc = "It's a plain jumpsuit. It seems to have a small dial on the wrist."
origin_tech = "syndicate=2"
var/list/clothing_choices = list()
burn_state = FIRE_PROOF
armor = list(melee = 10, bullet = 10, laser = 10, energy = 0, bomb = 0, bio = 0, rad = 0)
desc = "It's a plain jumpsuit. It has a small dial on the wrist."
sensor_mode = SENSOR_OFF //Hey who's this guy on the Syndicate Shuttle??
random_sensor = FALSE
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
New()
..()
var/blocked = list(/obj/item/clothing/under/color/random, /obj/item/clothing/under/rank/centcom) // Stops random coloured jumpsuit and undefined centcomm suit appearing in the list.
for(var/U in subtypesof(/obj/item/clothing/under/color) - blocked)
var/obj/item/clothing/under/V = new U
src.clothing_choices += V
var/datum/action/item_action/chameleon/change/chameleon_action
for(var/U in subtypesof(/obj/item/clothing/under/rank) - blocked)
var/obj/item/clothing/under/V = new U
src.clothing_choices += V
return
/obj/item/clothing/under/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/under
chameleon_action.chameleon_name = "Jumpsuit"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/under, /obj/item/clothing/under/color, /obj/item/clothing/under/rank), only_root_path = TRUE)
chameleon_action.initialize_disguises()
/obj/item/clothing/under/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
attackby(obj/item/clothing/under/U as obj, mob/user as mob, params)
..()
if(istype(U, /obj/item/clothing/under/chameleon))
to_chat(user, "<span class='warning'>Nothing happens.</span>")
return
if(istype(U, /obj/item/clothing/under))
if(src.clothing_choices.Find(U))
to_chat(user, "<span class='warning'>Pattern is already recognised by the suit.</span>")
return
src.clothing_choices += U
to_chat(user, "<span class='warning'>Pattern absorbed by the suit.</span>")
/obj/item/clothing/under/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/suit/chameleon
name = "armor"
desc = "A slim armored vest that protects against most types of damage."
icon_state = "armor"
item_state = "armor"
blood_overlay_type = "armor"
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
emp_act(severity)
name = "psychedelic"
desc = "Groovy!"
icon_state = "psyche"
item_color = "psyche"
usr.update_inv_w_uniform()
spawn(200)
name = initial(name)
icon_state = initial(icon_state)
item_color = initial(item_color)
desc = initial(desc)
usr.update_inv_w_uniform()
..()
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/suit/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/suit
chameleon_action.chameleon_name = "Suit"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/suit/armor/abductor), only_root_path = TRUE)
chameleon_action.initialize_disguises()
verb/change()
set name = "Change Color"
set category = "Object"
set src in usr
/obj/item/clothing/suit/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
if(icon_state == "psyche")
to_chat(usr, "<span class='warning'>Your suit is malfunctioning</span>")
return
/obj/item/clothing/suit/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
var/obj/item/clothing/under/A
A = input("Select Colour to change it to", "BOOYEA", A) in clothing_choices
if(!A)
return
/obj/item/clothing/glasses/chameleon
name = "Optical Meson Scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition."
icon_state = "meson"
item_state = "meson"
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
desc = null
permeability_coefficient = 0.90
var/datum/action/item_action/chameleon/change/chameleon_action
desc = A.desc
name = A.name
icon_state = A.icon_state
item_state = A.item_state
item_color = A.item_color
usr.update_inv_w_uniform() //so our overlays update.
/obj/item/clothing/glasses/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/glasses
chameleon_action.chameleon_name = "Glasses"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
/obj/item/clothing/glasses/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/glasses/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/under/chameleon/all/New()
..()
var/blocked = list(/obj/item/clothing/under/chameleon, /obj/item/clothing/under/chameleon/all)
//to prevent an infinite loop
for(var/U in typesof(/obj/item/clothing/under)-blocked)
var/obj/item/clothing/under/V = new U
src.clothing_choices += V
/obj/item/clothing/gloves/chameleon
desc = "These gloves will protect the wearer from electric shock."
name = "insulated gloves"
icon_state = "yellow"
item_state = "ygloves"
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/gloves/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/gloves
chameleon_action.chameleon_name = "Gloves"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/clothing/gloves, /obj/item/clothing/gloves/color), only_root_path = TRUE)
chameleon_action.initialize_disguises()
/obj/item/clothing/gloves/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/gloves/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/head/chameleon
name = "grey cap"
desc = "It's a baseball hat in a tasteful grey colour."
icon_state = "greysoft"
item_color = "grey"
resistance_flags = NONE
armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/head/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/head
chameleon_action.chameleon_name = "Hat"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
/obj/item/clothing/head/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/head/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/mask/chameleon
name = "gas mask"
desc = "A face-covering mask that can be connected to an air supply. While good for concealing your identity, it isn't good for blocking gas flow." //More accurate
icon_state = "gas_alt"
item_state = "gas_alt"
resistance_flags = NONE
armor = list("melee" = 5, "bullet" = 5, "laser" = 5, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
flags = AIRTIGHT | BLOCK_GAS_SMOKE_EFFECT
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE
gas_transfer_coefficient = 0.01
permeability_coefficient = 0.01
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
var/obj/item/voice_changer/voice_changer
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/mask/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/mask
chameleon_action.chameleon_name = "Mask"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
voice_changer = new(src)
/obj/item/clothing/mask/chameleon/Destroy()
QDEL_NULL(voice_changer)
return ..()
/obj/item/clothing/mask/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/mask/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/clothing/shoes/chameleon
name = "black shoes"
icon_state = "black"
item_color = "black"
desc = "A pair of black shoes."
permeability_coefficient = 0.05
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/clothing/shoes/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/clothing/shoes
chameleon_action.chameleon_name = "Shoes"
chameleon_action.chameleon_blacklist = list()
chameleon_action.initialize_disguises()
/obj/item/clothing/shoes/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/clothing/shoes/chameleon/noslip
name = "black shoes"
icon_state = "black"
item_color = "black"
desc = "A pair of black shoes."
flags = NOSLIP
/obj/item/clothing/shoes/chameleon/noslip/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/storage/backpack/chameleon
name = "backpack"
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/storage/backpack/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/storage/backpack
chameleon_action.chameleon_name = "Backpack"
chameleon_action.initialize_disguises()
/obj/item/storage/backpack/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/storage/backpack/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/storage/belt/chameleon
name = "toolbelt"
desc = "Holds tools."
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/storage/belt/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/storage/belt
chameleon_action.chameleon_name = "Belt"
chameleon_action.initialize_disguises()
/obj/item/storage/belt/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/storage/belt/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/radio/headset/chameleon
name = "radio headset"
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/radio/headset/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/radio/headset
chameleon_action.chameleon_name = "Headset"
chameleon_action.initialize_disguises()
/obj/item/radio/headset/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/radio/headset/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/pda/chameleon
name = "PDA"
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/pda/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/pda
chameleon_action.chameleon_name = "PDA"
chameleon_action.chameleon_blacklist = typecacheof(list(/obj/item/pda/heads), only_root_path = TRUE)
chameleon_action.initialize_disguises()
/obj/item/pda/chameleon/emp_act(severity)
. = ..()
chameleon_action.emp_randomise()
/obj/item/pda/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
/obj/item/stamp/chameleon
var/datum/action/item_action/chameleon/change/chameleon_action
/obj/item/stamp/chameleon/Initialize()
. = ..()
chameleon_action = new(src)
chameleon_action.chameleon_type = /obj/item/stamp
chameleon_action.chameleon_name = "Stamp"
chameleon_action.initialize_disguises()
/obj/item/stamp/chameleon/broken/Initialize()
. = ..()
chameleon_action.emp_randomise(INFINITY)
@@ -802,6 +802,7 @@
lefthand_file = 'icons/goonstation/mob/inhands/clothing_lefthand.dmi'
righthand_file = 'icons/goonstation/mob/inhands/clothing_righthand.dmi'
flags = NODROP
flags_size = ONESIZEFITSALL
has_sensor = 0 // HUNKE
/obj/item/clothing/under/victdress
+1 -1
View File
@@ -1785,4 +1785,4 @@
item_state = "voxbodysuit"
item_color = "voxbodysuit"
body_parts_covered = HEAD|UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
species_fit = list("Vox")
species_fit = list("Vox")
-1
View File
@@ -154,7 +154,6 @@ var/global/current_date_string
if("toggle_suspension")
if(detailed_account_view)
detailed_account_view.suspended = !detailed_account_view.suspended
callHook("change_account_status", list(detailed_account_view))
if("finalise_create_account")
var/account_name = href_list["holder_name"]
+6 -6
View File
@@ -13,11 +13,11 @@
if(candidates.len >= 2)
//Oh god why we can't have static functions
var/number = ticker.mode.abductor_teams + 1
var/number = SSticker.mode.abductor_teams + 1
var/datum/game_mode/abduction/temp
if(ticker.mode.config_tag == "abduction")
temp = ticker.mode
if(SSticker.mode.config_tag == "abduction")
temp = SSticker.mode
else
temp = new
@@ -42,10 +42,10 @@
temp.make_abductor_team(number,preset_scientist=scientist_mind,preset_agent=agent_mind)
temp.post_setup_team(number)
ticker.mode.abductor_teams++
SSticker.mode.abductor_teams++
if(ticker.mode.config_tag != "abduction")
ticker.mode.abductors |= temp.abductors
if(SSticker.mode.config_tag != "abduction")
SSticker.mode.abductors |= temp.abductors
processing = 1 //So it will get gc'd
return 1
else
+2 -2
View File
@@ -27,8 +27,8 @@
GLOB.respawnable_list -= C.client
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
new_xeno.key = C.key
if(ticker && ticker.mode)
ticker.mode.xenos += new_xeno.mind
if(SSticker && SSticker.mode)
SSticker.mode.xenos += new_xeno.mind
spawncount--
successSpawn = 1
+2 -1
View File
@@ -58,7 +58,8 @@
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
blueeffect.icon = 'icons/effects/effects.dmi'
blueeffect.icon_state = "shieldsparkles"
blueeffect.layer = 17
blueeffect.layer = FLASH_LAYER
blueeffect.plane = FULLSCREEN_PLANE
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
M.client.screen += blueeffect
sleep(20)
+15 -11
View File
@@ -17,10 +17,11 @@ We hope you enjoy the lights.", "Harmless ions approaching", new_sound = 'sound/
M.playsound_local(null, 'sound/ambience/aurora_caelus.ogg', 20, FALSE, pressure_affected = FALSE)
/datum/event/aurora_caelus/start()
for(var/s in GLOB.station_level_space_turfs)
var/turf/space/S = s
S.set_light(S.light_range * 3, S.light_power * 0.5, aurora_colors[1])
CHECK_TICK
for(var/area in GLOB.all_areas)
var/area/A = area
if(initial(A.dynamic_lighting) == DYNAMIC_LIGHTING_IFSTARLIGHT)
for(var/turf/space/S in A)
S.set_light(S.light_range * 3, S.light_power * 0.5)
/datum/event/aurora_caelus/tick()
if(aurora_progress >= aurora_colors.len)
@@ -28,15 +29,18 @@ We hope you enjoy the lights.", "Harmless ions approaching", new_sound = 'sound/
if(activeFor % 5 == 0)
aurora_progress++
var/aurora_color = aurora_colors[aurora_progress]
for(var/s in GLOB.station_level_space_turfs)
var/turf/space/S = s
S.set_light(l_color = aurora_color)
CHECK_TICK
for(var/area in GLOB.all_areas)
var/area/A = area
if(initial(A.dynamic_lighting) == DYNAMIC_LIGHTING_IFSTARLIGHT)
for(var/turf/space/S in A)
S.set_light(l_color = aurora_color)
/datum/event/aurora_caelus/end()
for(var/s in GLOB.station_level_space_turfs)
var/turf/space/S = s
fade_to_black(S)
for(var/area in GLOB.all_areas)
var/area/A = area
if(initial(A.dynamic_lighting) == DYNAMIC_LIGHTING_IFSTARLIGHT)
for(var/turf/space/S in A)
fade_to_black(S)
event_announcement.Announce("The Aurora Caelus event is now ending. Starlight conditions will slowly return to normal. \
When this has concluded, please return to your workplace and continue work as normal. \
Have a pleasant shift, [station_name()], and thank you for watching with us.",
+1 -1
View File
@@ -23,7 +23,7 @@
"atrazine","banana","charcoal","space_drugs","methamphetamine","holywater","ethanol","hot_coco","facid",
"blood","morphine","ether","fluorine","mutadone","mutagen","hydrocodone","fuel",
"haloperidol","lsd","syndicate_nanites","lipolicide","frostoil","salglu_solution","beepskysmash",
"omnizine", "amanitin", "neurotoxin", "synaptizine")
"omnizine", "amanitin", "neurotoxin", "synaptizine", "rotatium")
var/datum/reagents/R = new/datum/reagents(50)
R.my_atom = vent
R.add_reagent(pick(gunk), 50)
+2 -2
View File
@@ -671,8 +671,8 @@ var/list/non_fakeattack_weapons = list(/obj/item/gun/projectile, /obj/item/ammo_
/obj/item/gun/energy/kinetic_accelerator/crossbow,\
/obj/item/storage/box/syndicate, /obj/item/storage/box/emps,\
/obj/item/cartridge/syndicate, /obj/item/clothing/under/chameleon,\
/obj/item/clothing/shoes/syndigaloshes, /obj/item/card/id/syndicate,\
/obj/item/clothing/mask/gas/voice, /obj/item/clothing/glasses/thermal,\
/obj/item/clothing/shoes/chameleon/noslip, /obj/item/card/id/syndicate,\
/obj/item/clothing/mask/chameleon, /obj/item/clothing/glasses/thermal,\
/obj/item/chameleon, /obj/item/card/emag,\
/obj/item/storage/toolbox/syndicate, /obj/item/aiModule,\
/obj/item/radio/headset/syndicate, /obj/item/grenade/plastic/c4,\
+1 -1
View File
@@ -59,7 +59,7 @@ var/list/karma_spenders = list()
if(config.disable_karma)
to_chat(src, "<span class='warning'>Karma is disabled.</span>")
return FALSE
if(!ticker || !GLOB.player_list.len || (ticker.current_state == GAME_STATE_PREGAME))
if(!SSticker || !GLOB.player_list.len || (SSticker.current_state == GAME_STATE_PREGAME))
to_chat(src, "<span class='warning'>You can't award karma until the game has started.</span>")
return FALSE
if(client.karma_spent || (ckey in karma_spenders))
+5 -5
View File
@@ -320,11 +320,11 @@
if(!bibledelay)
var/obj/item/storage/bible/B = new /obj/item/storage/bible(src.loc)
if(ticker && ( ticker.Bible_icon_state && ticker.Bible_item_state) )
B.icon_state = ticker.Bible_icon_state
B.item_state = ticker.Bible_item_state
B.name = ticker.Bible_name
B.deity_name = ticker.Bible_deity_name
if(SSticker && ( SSticker.Bible_icon_state && SSticker.Bible_item_state) )
B.icon_state = SSticker.Bible_icon_state
B.item_state = SSticker.Bible_item_state
B.name = SSticker.Bible_name
B.deity_name = SSticker.Bible_deity_name
bibledelay = 1
spawn(60)
+1 -1
View File
@@ -54,7 +54,7 @@ turf: (lighting_turf.dm)
- Create lighting overlays for this turf
atom/movable/lighting_overlay: (lighting_overlay.dm)
atom/movable/lighting_object: (lighting_object.dm)
- var/lum_r, var/lum_g, var/lum_b; lumcounts of each colour
- var/needs_update; set on update_lumcount, checked by lighting process
+26 -5
View File
@@ -1,9 +1,30 @@
/area
luminosity = TRUE
var/dynamic_lighting = TRUE
var/dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
/area/New()
. = ..()
/area/proc/set_dynamic_lighting(var/new_dynamic_lighting = DYNAMIC_LIGHTING_ENABLED)
if(new_dynamic_lighting == dynamic_lighting)
return FALSE
if(dynamic_lighting)
luminosity = FALSE
dynamic_lighting = new_dynamic_lighting
if(IS_DYNAMIC_LIGHTING(src))
cut_overlay(/obj/effect/fullbright)
for (var/turf/T in src)
if(IS_DYNAMIC_LIGHTING(T))
T.lighting_build_overlay()
else
add_overlay(/obj/effect/fullbright)
for (var/turf/T in src)
if(T.lighting_object)
T.lighting_clear_overlay()
return TRUE
/area/vv_edit_var(var_name, var_value)
switch(var_name)
if("dynamic_lighting")
set_dynamic_lighting(var_value)
return TRUE
return ..()
+79 -46
View File
@@ -1,14 +1,18 @@
/atom
var/light_power = 1 // intensity of the light
var/light_range = 0 // range in tiles of the light
var/light_color // Hexadecimal RGB string representing the colour of the light
var/light_power = 1 // Intensity of the light.
var/light_range = 0 // Range in tiles of the light.
var/light_color // Hexadecimal RGB string representing the colour of the light.
var/datum/light_source/light
var/list/light_sources
var/tmp/datum/light_source/light // Our light source. Don't fuck with this directly unless you have a good reason!
var/tmp/list/light_sources // Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list.
// Nonsensical value for l_color default, so we can detect if it gets set to null.
// The proc you should always use to set the light of this atom.
// Nonesensical value for l_color default, so we can detect if it gets set to null.
#define NONSENSICAL_VALUE -99999
/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE)
/atom/proc/set_light(var/l_range, var/l_power, var/l_color = NONSENSICAL_VALUE)
if(l_range > 0 && l_range < MINIMUM_USEFUL_LIGHT_RANGE)
l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players.
if(l_power != null)
light_power = l_power
@@ -18,59 +22,48 @@
if(l_color != NONSENSICAL_VALUE)
light_color = l_color
SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT, l_range, l_power, l_color)
update_light()
#undef NONSENSICAL_VALUE
// Will update the light (duh).
// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf...
/atom/proc/update_light()
set waitfor = FALSE
if(QDELETED(src))
return
if(!light_power || !light_range)
if(light)
light.destroy()
light = null
if(!light_power || !light_range) // We won't emit light anyways, destroy the light source.
QDEL_NULL(light)
else
if(!istype(loc, /atom/movable))
if(!ismovableatom(loc)) // We choose what atom should be the top atom of the light here.
. = src
else
. = loc
if(light)
if(light) // Update the light or create it if it does not exist.
light.update(.)
else
light = new /datum/light_source(src, .)
light = new/datum/light_source(src, .)
/atom/proc/extinguish_light()
return
/atom/Destroy()
if(light)
light.destroy()
light = null
return ..()
// If we have opacity, make sure to tell (potentially) affected light sources.
/atom/movable/Destroy()
var/turf/T = loc
if(opacity && istype(T))
T.reconsider_lights()
return ..()
/atom/movable/Move()
var/turf/old_loc = loc
. = ..()
if(opacity && istype(T))
var/old_has_opaque_atom = T.has_opaque_atom
T.recalc_atom_opacity()
if(old_has_opaque_atom != T.has_opaque_atom)
T.reconsider_lights()
if(loc != old_loc)
for(var/datum/light_source/L in light_sources)
L.source_atom.update_light()
var/turf/new_loc = loc
if(istype(old_loc) && opacity)
old_loc.reconsider_lights()
if(istype(new_loc) && opacity)
new_loc.reconsider_lights()
/atom/proc/set_opacity(new_opacity)
// Should always be used to change the opacity of an atom.
// It notifies (potentially) affected light sources so they can update (if needed).
/atom/proc/set_opacity(var/new_opacity)
if(new_opacity == opacity)
return
@@ -88,14 +81,54 @@
if(old_has_opaque_atom != T.has_opaque_atom)
T.reconsider_lights()
/obj/item/equipped()
. = ..()
update_light()
/obj/item/pickup()
/atom/movable/Moved(atom/OldLoc, Dir)
. = ..()
update_light()
var/datum/light_source/L
var/thing
for (thing in light_sources) // Cycle through the light sources on this atom and tell them to update.
L = thing
L.source_atom.update_light()
/obj/item/dropped()
. = ..()
update_light()
/atom/vv_edit_var(var_name, var_value)
switch (var_name)
if("light_range")
set_light(l_range=var_value)
return TRUE
if("light_power")
set_light(l_power=var_value)
return TRUE
if("light_color")
set_light(l_color=var_value)
return TRUE
return ..()
/atom/proc/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
return
/turf/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
if(!_duration)
stack_trace("Lighting FX obj created on a turf without a duration")
new /obj/effect/dummy/lighting_obj (src, _color, _range, _power, _duration)
/obj/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
var/temp_color
var/temp_power
var/temp_range
if(!_reset_lighting) //incase the obj already has a lighting color that you don't want cleared out after, ie computer monitors.
temp_color = light_color
temp_power = light_power
temp_range = light_range
set_light(_range, _power, _color)
addtimer(CALLBACK(src, /atom/proc/set_light, _reset_lighting ? initial(light_range) : temp_range, _reset_lighting ? initial(light_power) : temp_power, _reset_lighting ? initial(light_color) : temp_color), _duration, TIMER_OVERRIDE|TIMER_UNIQUE)
/mob/living/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
mob_light(_color, _range, _power, _duration)
/mob/living/proc/mob_light(_color, _range, _power, _duration)
var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _color, _range, _power, _duration)
return mob_light_obj
+56 -38
View File
@@ -1,15 +1,13 @@
/var/total_lighting_corners = 0
/var/datum/lighting_corner/dummy/dummy_lighting_corner = new
// Because we can control each corner of every lighting overlay.
// Because we can control each corner of every lighting object.
// And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't).
// For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting.
// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list.
/var/list/LIGHTING_CORNER_DIAGONAL = list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)
GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST))
/datum/lighting_corner
var/list/turf/masters = list()
var/list/datum/light_source/affecting = list() // Light sources affecting us.
var/list/turf/masters
var/list/datum/light_source/affecting // Light sources affecting us.
var/active = FALSE // TRUE if one of our masters has dynamic lighting.
var/x = 0
@@ -27,13 +25,9 @@
var/cache_b = LIGHTING_SOFT_THRESHOLD
var/cache_mx = 0
var/update_gen = 0
/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
. = ..()
total_lighting_corners++
masters = list()
masters[new_turf] = turn(diagonal, 180)
z = new_turf.z
@@ -51,75 +45,99 @@
// Diagonal one is easy.
T = get_step(new_turf, diagonal)
if (T) // In case we're on the map's border.
if (!T.corners)
if(T) // In case we're on the map's border.
if(!T.corners)
T.corners = list(null, null, null, null)
masters[T] = diagonal
i = LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180))
i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180))
T.corners[i] = src
// Now the horizontal one.
T = get_step(new_turf, horizontal)
if (T) // Ditto.
if (!T.corners)
if(T) // Ditto.
if(!T.corners)
T.corners = list(null, null, null, null)
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
T.corners[i] = src
// And finally the vertical one.
T = get_step(new_turf, vertical)
if (T)
if (!T.corners)
if(T)
if(!T.corners)
T.corners = list(null, null, null, null)
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
T.corners[i] = src
update_active()
/datum/lighting_corner/proc/update_active()
active = FALSE
for (var/turf/T in masters)
if (T.lighting_overlay)
var/turf/T
var/thing
for (thing in masters)
T = thing
if(T.lighting_object)
active = TRUE
// God that was a mess, now to do the rest of the corner code! Hooray!
/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b)
if((abs(delta_r)+abs(delta_g)+abs(delta_b)) == 0)
return
lum_r += delta_r
lum_g += delta_g
lum_b += delta_b
if (!needs_update)
if(!needs_update)
needs_update = TRUE
lighting_update_corners += src
GLOB.lighting_update_corners += src
/datum/lighting_corner/proc/update_overlays()
// Cache these values a head of time so 4 individual lighting overlays don't all calculate them individually.
var/mx = max(lum_r, lum_g, lum_b) // Scale it so 1 is the strongest lum, if it is above 1.
/datum/lighting_corner/proc/update_objects()
// Cache these values a head of time so 4 individual lighting objects don't all calculate them individually.
var/lum_r = src.lum_r
var/lum_g = src.lum_g
var/lum_b = src.lum_b
var/mx = max(lum_r, lum_g, lum_b) // Scale it so one of them is the strongest lum, if it is above 1.
. = 1 // factor
if (mx > 1)
if(mx > 1)
. = 1 / mx
else if (mx < LIGHTING_SOFT_THRESHOLD)
#if LIGHTING_SOFT_THRESHOLD != 0
else if(mx < LIGHTING_SOFT_THRESHOLD)
. = 0 // 0 means soft lighting.
cache_r = lum_r * . || LIGHTING_SOFT_THRESHOLD
cache_g = lum_g * . || LIGHTING_SOFT_THRESHOLD
cache_b = lum_b * . || LIGHTING_SOFT_THRESHOLD
cache_mx = mx
cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
#else
cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE)
cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE)
cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE)
#endif
cache_mx = round(mx, LIGHTING_ROUND_VALUE)
for (var/TT in masters)
var/turf/T = TT
if (T.lighting_overlay)
if (!T.lighting_overlay.needs_update)
T.lighting_overlay.needs_update = TRUE
lighting_update_overlays += T.lighting_overlay
if(T.lighting_object)
if(!T.lighting_object.needs_update)
T.lighting_object.needs_update = TRUE
GLOB.lighting_update_objects += T.lighting_object
/datum/lighting_corner/dummy/New()
return
/datum/lighting_corner/Destroy(var/force)
if(!force)
return QDEL_HINT_LETMELIVE
stack_trace("Attempted qdel of a lighting corner.")
return ..()
+148
View File
@@ -0,0 +1,148 @@
/atom/movable/lighting_object
name = ""
anchored = TRUE
icon = LIGHTING_ICON
icon_state = "transparent"
color = LIGHTING_BASE_MATRIX
plane = LIGHTING_PLANE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
layer = LIGHTING_LAYER
invisibility = INVISIBILITY_LIGHTING
simulated = FALSE
var/needs_update = FALSE
var/turf/myturf
/atom/movable/lighting_object/Initialize(mapload)
. = ..()
verbs.Cut()
myturf = loc
if(myturf.lighting_object)
qdel(myturf.lighting_object, force = TRUE)
myturf.lighting_object = src
myturf.luminosity = 0
for(var/turf/space/S in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm
S.update_starlight()
needs_update = TRUE
GLOB.lighting_update_objects += src
/atom/movable/lighting_object/Destroy(var/force)
if(force)
GLOB.lighting_update_objects -= src
if(loc != myturf)
var/turf/oldturf = get_turf(myturf)
var/turf/newturf = get_turf(loc)
stack_trace("A lighting object was qdeleted with a different loc then it is suppose to have ([COORD(oldturf)] -> [COORD(newturf)])")
if(isturf(myturf))
myturf.lighting_object = null
myturf.luminosity = 1
myturf = null
return ..()
else
return QDEL_HINT_LETMELIVE
/atom/movable/lighting_object/proc/update()
if(loc != myturf)
if(loc)
var/turf/oldturf = get_turf(myturf)
var/turf/newturf = get_turf(loc)
warning("A lighting object realised it's loc had changed in update() ([myturf]\[[myturf ? myturf.type : "null"]]([COORD(oldturf)]) -> [loc]\[[ loc ? loc.type : "null"]]([COORD(newturf)]))!")
qdel(src, TRUE)
return
// To the future coder who sees this and thinks
// "Why didn't he just use a loop?"
// Well my man, it's because the loop performed like shit.
// And there's no way to improve it because
// without a loop you can make the list all at once which is the fastest you're gonna get.
// Oh it's also shorter line wise.
// Including with these comments.
// See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are.
var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new
var/list/corners = myturf.corners
var/datum/lighting_corner/cr = dummy_lighting_corner
var/datum/lighting_corner/cg = dummy_lighting_corner
var/datum/lighting_corner/cb = dummy_lighting_corner
var/datum/lighting_corner/ca = dummy_lighting_corner
if(corners) //done this way for speed
cr = corners[3] || dummy_lighting_corner
cg = corners[2] || dummy_lighting_corner
cb = corners[4] || dummy_lighting_corner
ca = corners[1] || dummy_lighting_corner
var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
var/rr = cr.cache_r
var/rg = cr.cache_g
var/rb = cr.cache_b
var/gr = cg.cache_r
var/gg = cg.cache_g
var/gb = cg.cache_b
var/br = cb.cache_r
var/bg = cb.cache_g
var/bb = cb.cache_b
var/ar = ca.cache_r
var/ag = ca.cache_g
var/ab = ca.cache_b
#if LIGHTING_SOFT_THRESHOLD != 0
var/set_luminosity = max > LIGHTING_SOFT_THRESHOLD
#else
// Because of floating points™?, it won't even be a flat 0.
// This number is mostly arbitrary.
var/set_luminosity = max > 1e-6
#endif
if((rr & gr & br & ar) && (rg + gg + bg + ag + rb + gb + bb + ab == 8))
//anything that passes the first case is very likely to pass the second, and addition is a little faster in this case
icon_state = "transparent"
color = null
else if(!set_luminosity)
icon_state = "dark"
color = null
else
icon_state = null
color = list(
rr, rg, rb, 00,
gr, gg, gb, 00,
br, bg, bb, 00,
ar, ag, ab, 00,
00, 00, 00, 01
)
luminosity = set_luminosity
// Variety of overrides so the overlays don't get affected by weird things.
/atom/movable/lighting_object/ex_act(severity)
return 0
/atom/movable/lighting_object/singularity_act()
return
/atom/movable/lighting_object/singularity_pull()
return
/atom/movable/lighting_object/blob_act()
return
/atom/movable/lighting_object/onTransitZ()
return
// Override here to prevent things accidentally moving around overlays.
/atom/movable/lighting_object/forceMove(atom/destination, var/no_tp=FALSE, var/harderforce = FALSE)
if(harderforce)
. = ..()
-89
View File
@@ -1,89 +0,0 @@
/var/total_lighting_overlays = 0
/atom/movable/lighting_overlay
name = ""
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
simulated = 0
anchored = 1
icon = LIGHTING_ICON
layer = LIGHTING_LAYER
plane = LIGHTING_PLANE
invisibility = INVISIBILITY_LIGHTING
color = LIGHTING_BASE_MATRIX
icon_state = "light1"
blend_mode = BLEND_MULTIPLY
var/lum_r = 0
var/lum_g = 0
var/lum_b = 0
var/needs_update = FALSE
/atom/movable/lighting_overlay/New(var/atom/loc, var/no_update = FALSE)
. = ..()
verbs.Cut()
total_lighting_overlays++
var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays outside of turfs.
T.lighting_overlay = src
T.luminosity = 0
if(no_update)
return
update_overlay()
/atom/movable/lighting_overlay/proc/update_overlay()
set waitfor = FALSE
var/turf/T = loc
if(!istype(T))
if(loc)
log_debug("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : "null"]) in update_overlay() and got qdel'ed!")
else
log_debug("A lighting overlay realised it was in nullspace in update_overlay() and got pooled!")
qdel(src)
return
// To the future coder who sees this and thinks
// "Why didn't he just use a loop?"
// Well my man, it's because the loop performed like shit.
// And there's no way to improve it because
// without a loop you can make the list all at once which is the fastest you're gonna get.
// Oh it's also shorter line wise.
// Including with these comments.
// See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are.
// No I seriously cannot think of a more efficient method, fuck off Comic.
var/datum/lighting_corner/cr = T.corners[3] || dummy_lighting_corner
var/datum/lighting_corner/cg = T.corners[2] || dummy_lighting_corner
var/datum/lighting_corner/cb = T.corners[4] || dummy_lighting_corner
var/datum/lighting_corner/ca = T.corners[1] || dummy_lighting_corner
var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
color = list(
cr.cache_r, cr.cache_g, cr.cache_b, 0,
cg.cache_r, cg.cache_g, cg.cache_b, 0,
cb.cache_r, cb.cache_g, cb.cache_b, 0,
ca.cache_r, ca.cache_g, ca.cache_b, 0,
0, 0, 0, 1
)
luminosity = max > LIGHTING_SOFT_THRESHOLD
/atom/movable/lighting_overlay/singularity_act()
return
/atom/movable/lighting_overlay/singularity_pull()
return
/atom/movable/lighting_overlay/Destroy()
total_lighting_overlays--
global.lighting_update_overlays -= src
global.lighting_update_overlays_old -= src
var/turf/T = loc
if(istype(T))
T.lighting_overlay = null
T.luminosity = 1
return ..()
+9 -13
View File
@@ -1,16 +1,12 @@
/proc/create_all_lighting_overlays()
for(var/zlevel = 1 to world.maxz)
create_lighting_overlays_zlevel(zlevel)
/proc/create_lighting_overlays_zlevel(var/zlevel)
ASSERT(zlevel)
for(var/turf/T in block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel)))
if(!T.dynamic_lighting)
/proc/create_all_lighting_objects()
for(var/area/A in GLOB.all_areas)
if(!IS_DYNAMIC_LIGHTING(A))
continue
var/area/A = T.loc
if(!A.dynamic_lighting)
continue
for(var/turf/T in A)
if(!IS_DYNAMIC_LIGHTING(T))
continue
new /atom/movable/lighting_overlay(T, TRUE)
new/atom/movable/lighting_object(T)
CHECK_TICK
CHECK_TICK
+206 -198
View File
@@ -1,12 +1,12 @@
/var/total_lighting_sources = 0
// This is where the fun begins.
// These are the main datums that emit light.
/datum/light_source
var/atom/top_atom // The atom we're emitting light from(for example a mob if we're from a flashlight that's being held).
var/atom/top_atom // The atom we're emitting light from (for example a mob if we're from a flashlight that's being held).
var/atom/source_atom // The atom that we belong to.
var/turf/source_turf // The turf under the above.
var/turf/pixel_turf // The turf the top_atom appears to over.
var/light_power // Intensity of the emitter light.
var/light_range // The range of the emitted light.
var/light_color // The colour of the light, string, decomposed by parse_light_color()
@@ -26,133 +26,80 @@
var/applied = FALSE // Whether we have applied our light yet or not.
var/vis_update // Whether we should smartly recalculate visibility. and then only update tiles that became(in)visible to us.
var/needs_update // Whether we are queued for an update.
var/destroyed // Whether we are destroyed and need to stop emitting light.
var/force_update
var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update.
/datum/light_source/New(var/atom/owner, var/atom/top)
total_lighting_sources++
source_atom = owner // Set our new owner.
if(!source_atom.light_sources)
source_atom.light_sources = list()
source_atom.light_sources += src // Add us to the lights of our owner.
LAZYADD(source_atom.light_sources, src)
top_atom = top
if(top_atom != source_atom)
if(!top.light_sources)
top.light_sources = list()
top_atom.light_sources += src
LAZYADD(top_atom.light_sources, src)
source_turf = top_atom
pixel_turf = get_turf_pixel(top_atom) || source_turf
light_power = source_atom.light_power
light_range = source_atom.light_range
light_color = source_atom.light_color
parse_light_color()
effect_str = list()
affecting_turfs = list()
update()
return ..()
// Kill ourselves.
/datum/light_source/proc/destroy()
total_lighting_sources--
destroyed = TRUE
force_update()
/datum/light_source/Destroy(force)
remove_lum()
if(source_atom)
if(!source_atom.light_sources)
log_runtime(EXCEPTION("Atom [source_atom] was a light source, but lacked a light source list!\n"), source_atom)
else
source_atom.light_sources -= src
LAZYREMOVE(source_atom.light_sources, src)
if(top_atom)
top_atom.light_sources -= src
LAZYREMOVE(top_atom.light_sources, src)
if(needs_update)
GLOB.lighting_update_lights -= src
. = ..()
// Yes this doesn't align correctly on anything other than 4 width tabs.
// If you want it to go switch everybody to elastic tab stops.
// Actually that'd be great if you could!
#define EFFECT_UPDATE(level) \
if(needs_update == LIGHTING_NO_UPDATE) \
GLOB.lighting_update_lights += src; \
if(needs_update < level) \
needs_update = level; \
// Call it dirty, I don't care.
// This is here so there's no performance loss on non-instant updates from the fact that the engine can also do instant updates.
// If you're wondering what's with the "BYOND" argument: BYOND won't let me have a() macro that has no arguments :|.
#define effect_update(BYOND) \
if(!needs_update) \
{ \
lighting_update_lights += src; \
needs_update = TRUE; \
}
// This proc will cause the light source to update the top atom, and add itself to the update queue.
/datum/light_source/proc/update(var/atom/new_top_atom)
// This top atom is different.
if(new_top_atom && new_top_atom != top_atom)
if(top_atom != source_atom) // Remove ourselves from the light sources of that top atom.
top_atom.light_sources -= src
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
LAZYREMOVE(top_atom.light_sources, src)
top_atom = new_top_atom
if(top_atom != source_atom)
if(!top_atom.light_sources)
top_atom.light_sources = list()
LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom.
top_atom.light_sources += src // Add ourselves to the light sources of our new top atom.
effect_update(null)
EFFECT_UPDATE(LIGHTING_CHECK_UPDATE)
// Will force an update without checking if it's actually needed.
/datum/light_source/proc/force_update()
force_update = 1
effect_update(null)
EFFECT_UPDATE(LIGHTING_FORCE_UPDATE)
// Will cause the light source to recalculate turfs that were removed or added to visibility only.
/datum/light_source/proc/vis_update()
vis_update = 1
effect_update(null)
// Will check if we actually need to update, and update any variables that may need to be updated.
/datum/light_source/proc/check()
if(!source_atom || !light_range || !light_power)
destroy()
return 1
if(!top_atom)
top_atom = source_atom
. = 1
if(isturf(top_atom))
if(source_turf != top_atom)
source_turf = top_atom
. = 1
else if(top_atom.loc != source_turf)
source_turf = top_atom.loc
. = 1
if(source_atom.light_power != light_power)
light_power = source_atom.light_power
. = 1
if(source_atom.light_range != light_range)
light_range = source_atom.light_range
. = 1
if(light_range && light_power && !applied)
. = 1
if(source_atom.light_color != light_color)
light_color = source_atom.light_color
parse_light_color()
. = 1
EFFECT_UPDATE(LIGHTING_VIS_UPDATE)
// Decompile the hexadecimal colour into lumcounts of each perspective.
/datum/light_source/proc/parse_light_color()
if(light_color)
lum_r = GetRedPart (light_color) / 255
lum_g = GetGreenPart(light_color) / 255
lum_b = GetBluePart (light_color) / 255
lum_r = GetRedPart (light_color) / 255
lum_g = GetGreenPart (light_color) / 255
lum_b = GetBluePart (light_color) / 255
else
lum_r = 1
lum_g = 1
@@ -163,128 +110,189 @@
// If you're wondering what's with the backslashes, the backslashes cause BYOND to not automatically end the line.
// As such this all gets counted as a single line.
// The braces and semicolons are there to be able to do this on a single line.
#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
#define APPLY_CORNER(C) \
. = LUM_FALLOFF(C, source_turf); \
\
. *= light_power; \
\
effect_str[C] = .; \
\
C.update_lumcount \
( \
. * applied_lum_r, \
. * applied_lum_g, \
. * applied_lum_b \
#define APPLY_CORNER(C) \
. = LUM_FALLOFF(C, pixel_turf); \
. *= light_power; \
var/OLD = effect_str[C]; \
effect_str[C] = .; \
\
C.update_lumcount \
( \
(. * lum_r) - (OLD * applied_lum_r), \
(. * lum_g) - (OLD * applied_lum_g), \
(. * lum_b) - (OLD * applied_lum_b) \
);
// I don't need to explain what this does, do I?
#define REMOVE_CORNER(C) \
. = -effect_str[C]; \
C.update_lumcount \
( \
. * applied_lum_r, \
. * applied_lum_g, \
. * applied_lum_b \
#define REMOVE_CORNER(C) \
. = -effect_str[C]; \
C.update_lumcount \
( \
. * applied_lum_r, \
. * applied_lum_g, \
. * applied_lum_b \
);
// This is the define used to calculate falloff.
#define LUM_FALLOFF(C, T)(1 - CLAMP01(sqrt((C.x - T.x) ** 2 +(C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
/datum/light_source/proc/apply_lum()
var/static/update_gen = 1
applied = 1
/datum/light_source/proc/remove_lum()
applied = FALSE
var/thing
for (thing in affecting_turfs)
var/turf/T = thing
LAZYREMOVE(T.affecting_lights, src)
affecting_turfs = null
var/datum/lighting_corner/C
for (thing in effect_str)
C = thing
REMOVE_CORNER(C)
LAZYREMOVE(C.affecting, src)
effect_str = null
/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
LAZYINITLIST(effect_str)
if(effect_str[C]) // Already have one.
REMOVE_CORNER(C)
effect_str[C] = 0
APPLY_CORNER(C)
UNSETEMPTY(effect_str)
/datum/light_source/proc/update_corners()
var/update = FALSE
var/atom/source_atom = src.source_atom
if(QDELETED(source_atom))
qdel(src)
return
if(source_atom.light_power != light_power)
light_power = source_atom.light_power
update = TRUE
if(source_atom.light_range != light_range)
light_range = source_atom.light_range
update = TRUE
if(!top_atom)
top_atom = source_atom
update = TRUE
if(!light_range || !light_power)
qdel(src)
return
if(isturf(top_atom))
if(source_turf != top_atom)
source_turf = top_atom
pixel_turf = source_turf
update = TRUE
else if(top_atom.loc != source_turf)
source_turf = top_atom.loc
pixel_turf = get_turf_pixel(top_atom)
update = TRUE
else
var/P = get_turf_pixel(top_atom)
if(P != pixel_turf)
pixel_turf = P
update = TRUE
if(!isturf(source_turf))
if(applied)
remove_lum()
return
if(light_range && light_power && !applied)
update = TRUE
if(source_atom.light_color != light_color)
light_color = source_atom.light_color
parse_light_color()
update = TRUE
else if(applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b)
update = TRUE
if(update)
needs_update = LIGHTING_CHECK_UPDATE
applied = TRUE
else if(needs_update == LIGHTING_CHECK_UPDATE)
return //nothing's changed
var/list/datum/lighting_corner/corners = list()
var/list/turf/turfs = list()
var/thing
var/datum/lighting_corner/C
var/turf/T
if(source_turf)
var/oldlum = source_turf.luminosity
source_turf.luminosity = CEILING(light_range, 1)
for(T in view(CEILING(light_range, 1), source_turf))
for (thing in T.get_corners(source_turf))
C = thing
corners[C] = 0
turfs += T
source_turf.luminosity = oldlum
LAZYINITLIST(affecting_turfs)
var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them.
affecting_turfs += L
for (thing in L)
T = thing
LAZYADD(T.affecting_lights, src)
L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights.
affecting_turfs -= L
for (thing in L)
T = thing
LAZYREMOVE(T.affecting_lights, src)
LAZYINITLIST(effect_str)
if(needs_update == LIGHTING_VIS_UPDATE)
for (thing in corners - effect_str) // New corners
C = thing
LAZYADD(C.affecting, src)
if(!C.active)
effect_str[C] = 0
continue
APPLY_CORNER(C)
else
L = corners - effect_str
for (thing in L) // New corners
C = thing
LAZYADD(C.affecting, src)
if(!C.active)
effect_str[C] = 0
continue
APPLY_CORNER(C)
for (thing in corners - L) // Existing corners
C = thing
if(!C.active)
effect_str[C] = 0
continue
APPLY_CORNER(C)
L = effect_str - corners
for (thing in L) // Old, now gone, corners.
C = thing
REMOVE_CORNER(C)
LAZYREMOVE(C.affecting, src)
effect_str -= L
// Keep track of the last applied lum values so that the lighting can be reversed
applied_lum_r = lum_r
applied_lum_g = lum_g
applied_lum_b = lum_b
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
if(!T.lighting_corners_initialised)
T.generate_missing_corners()
UNSETEMPTY(effect_str)
UNSETEMPTY(affecting_turfs)
for(var/datum/lighting_corner/C in T.get_corners())
if(C.update_gen == update_gen)
continue
C.update_gen = update_gen
C.affecting += src
if(!C.active)
effect_str[C] = 0
continue
APPLY_CORNER(C)
if(!T.affecting_lights)
T.affecting_lights = list()
T.affecting_lights += src
affecting_turfs += T
update_gen++
/datum/light_source/proc/remove_lum()
applied = FALSE
for(var/turf/T in affecting_turfs)
if(!T.affecting_lights)
T.affecting_lights = list()
else
T.affecting_lights -= src
affecting_turfs.Cut()
for(var/datum/lighting_corner/C in effect_str)
REMOVE_CORNER(C)
C.affecting -= src
effect_str.Cut()
/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
if(effect_str.Find(C)) // Already have one.
REMOVE_CORNER(C)
APPLY_CORNER(C)
/datum/light_source/proc/smart_vis_update()
var/list/datum/lighting_corner/corners = list()
var/list/turf/turfs = list()
FOR_DVIEW(var/turf/T, light_range, source_turf, 0)
if(!T.lighting_corners_initialised)
T.generate_missing_corners()
corners |= T.get_corners()
turfs += T
var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them.
affecting_turfs += L
for(var/turf/T in L)
if(!T.affecting_lights)
T.affecting_lights = list(src)
else
T.affecting_lights += src
L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights.
affecting_turfs -= L
for(var/turf/T in L)
T.affecting_lights -= src
for(var/datum/lighting_corner/C in corners - effect_str) // New corners
C.affecting += src
if(!C.active)
effect_str[C] = 0
continue
APPLY_CORNER(C)
for(var/datum/lighting_corner/C in effect_str - corners) // Old, now gone, corners.
REMOVE_CORNER(C)
C.affecting -= src
effect_str -= C
#undef effect_update
#undef EFFECT_UPDATE
#undef LUM_FALLOFF
#undef REMOVE_CORNER
#undef APPLY_CORNER
#undef APPLY_CORNER
+77 -44
View File
@@ -5,98 +5,131 @@
var/tmp/lighting_corners_initialised = FALSE
var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf.
var/tmp/atom/movable/lighting_overlay/lighting_overlay // Our lighting overlay.
var/tmp/atom/movable/lighting_object/lighting_object // Our lighting object.
var/tmp/list/datum/lighting_corner/corners
var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile.
/turf/New()
. = ..()
if(opacity)
has_opaque_atom = TRUE
// Causes any affecting light sources to be queued for a visibility update, for example a door got opened.
/turf/proc/reconsider_lights()
for(var/datum/light_source/L in affecting_lights)
var/datum/light_source/L
var/thing
for (thing in affecting_lights)
L = thing
L.vis_update()
/turf/proc/lighting_clear_overlay()
if(lighting_overlay)
qdel(lighting_overlay)
if(lighting_object)
qdel(lighting_object, TRUE)
for(var/datum/lighting_corner/C in corners)
var/datum/lighting_corner/C
var/thing
for (thing in corners)
if(!thing)
continue
C = thing
C.update_active()
// Builds a lighting overlay for us, but only if our area is dynamic.
// Builds a lighting object for us, but only if our area is dynamic.
/turf/proc/lighting_build_overlay()
if(lighting_overlay)
return
if(lighting_object)
qdel(lighting_object,force=TRUE) //Shitty fix for lighting objects persisting after death
var/area/A = loc
if(A.dynamic_lighting)
if(!lighting_corners_initialised)
generate_missing_corners()
if(!IS_DYNAMIC_LIGHTING(A) && !light_sources)
return
new /atom/movable/lighting_overlay(src)
if(!lighting_corners_initialised)
generate_missing_corners()
for(var/datum/lighting_corner/C in corners)
if(!C.active) // We would activate the corner, calculate the lighting for it.
for(var/L in C.affecting)
var/datum/light_source/S = L
S.recalc_corner(C)
new/atom/movable/lighting_object(src)
C.active = TRUE
var/thing
var/datum/lighting_corner/C
var/datum/light_source/S
for (thing in corners)
if(!thing)
continue
C = thing
if(!C.active) // We would activate the corner, calculate the lighting for it.
for (thing in C.affecting)
S = thing
S.recalc_corner(C)
C.active = TRUE
// Used to get a scaled lumcount.
/turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1)
if(!lighting_overlay)
if(!lighting_object)
return 1
var/totallums = 0
for(var/datum/lighting_corner/L in corners)
totallums += max(L.lum_r, L.lum_g, L.lum_b)
var/thing
var/datum/lighting_corner/L
for (thing in corners)
if(!thing)
continue
L = thing
totallums += L.lum_r + L.lum_b + L.lum_g
totallums /= 4 // 4 corners, max channel selected, return the average
totallums /= 12 // 4 corners, each with 3 channels, get the average.
totallums =(totallums - minlum) /(maxlum - minlum)
totallums = (totallums - minlum) / (maxlum - minlum)
return CLAMP01(totallums)
// Returns a boolean whether the turf is on soft lighting.
// Soft lighting being the threshold at which point the overlay considers
// itself as too dark to allow sight and see_in_dark becomes useful.
// So basically if this returns true the tile is unlit black.
/turf/proc/is_softly_lit()
if(!lighting_object)
return FALSE
return !lighting_object.luminosity
// Can't think of a good name, this proc will recalculate the has_opaque_atom variable.
/turf/proc/recalc_atom_opacity()
has_opaque_atom = FALSE
for(var/atom/A in src.contents + src) // Loop through every movable atom on our tile PLUS ourselves (we matter too...)
if(A.opacity)
has_opaque_atom = TRUE
has_opaque_atom = opacity
if(!has_opaque_atom)
for (var/atom/A in src.contents) // Loop through every movable atom on our tile PLUS ourselves (we matter too...)
if(A.opacity)
has_opaque_atom = TRUE
break
// If an opaque movable atom moves around we need to potentially update visibility.
/turf/Entered(var/atom/movable/Obj, var/atom/OldLoc)
. = ..()
if(Obj && Obj.opacity)
has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
reconsider_lights()
/turf/Exited(var/atom/movable/Obj, var/atom/newloc)
/turf/Exited(atom/movable/Obj, atom/newloc)
. = ..()
if(Obj && Obj.opacity)
recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates.
reconsider_lights()
/turf/proc/change_area(var/area/old_area, var/area/new_area)
if(SSlighting.initialized)
if(new_area.dynamic_lighting != old_area.dynamic_lighting)
if(new_area.dynamic_lighting)
lighting_build_overlay()
else
lighting_clear_overlay()
/turf/proc/get_corners()
if(!IS_DYNAMIC_LIGHTING(src) && !light_sources)
return null
if(!lighting_corners_initialised)
generate_missing_corners()
if(has_opaque_atom)
return null // Since this proc gets used in a for loop, null won't be looped though.
return corners
/turf/proc/generate_missing_corners()
if(!IS_DYNAMIC_LIGHTING(src) && !light_sources)
return
lighting_corners_initialised = TRUE
if(!corners)
corners = list(null, null, null, null)
for(var/i = 1 to 4)
for (var/i = 1 to 4)
if(corners[i]) // Already have a corner on this direction.
continue
corners[i] = new /datum/lighting_corner(src, LIGHTING_CORNER_DIAGONAL[i])
corners[i] = new/datum/lighting_corner(src, GLOB.LIGHTING_CORNER_DIAGONAL[i])
@@ -1,7 +0,0 @@
#undef LIGHTING_FALLOFF
#undef LIGHTING_LAMBERTIAN
#undef LIGHTING_HEIGHT
#undef LIGHTING_ICON
#undef LIGHTING_BASE_MATRIX
@@ -38,7 +38,7 @@
/obj/machinery/smartfridge/black_box/process()
..()
if(!memory_saved && ticker.current_state == GAME_STATE_FINISHED)
if(!memory_saved && SSticker.current_state == GAME_STATE_FINISHED)
WriteMemory()
/obj/machinery/smartfridge/black_box/proc/WriteMemory()
@@ -184,42 +184,52 @@
generic_pixel_x = 1
vehicle_move_delay = 1
// Wisp Lantern
//Wisp Lantern
/obj/item/wisp_lantern
name = "spooky lantern"
desc = "This lantern gives off no light, but is home to a friendly wisp."
icon = 'icons/obj/lighting.dmi'
icon_state = "lantern-blue"
item_state = "lantern"
light_range = 7
var/obj/effect/wisp/wisp
var/sight_flags = SEE_MOBS
var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
/obj/item/wisp_lantern/attack_self(mob/user)
if(!wisp)
to_chat(user, "<span class='warning'>The wisp has gone missing!</span>")
return
if(wisp.loc == src)
to_chat(user, "<span class='notice'>You release the wisp. It begins to bob around your head.</span>")
user.sight |= SEE_MOBS
icon_state = "lantern"
wisp.orbit(user, 20, forceMove = TRUE)
return
if(wisp.loc == src)
RegisterSignal(user, COMSIG_MOB_UPDATE_SIGHT, .proc/update_user_sight)
to_chat(user, "<span class='notice'>You release the wisp. It begins to bob around your head.</span>")
icon_state = "lantern"
wisp.orbit(user, 20)
set_light(0)
user.update_sight()
to_chat(user, "<span class='notice'>The wisp enhances your vision.</span>")
feedback_add_details("wisp_lantern","F") // freed
else
UnregisterSignal(user, COMSIG_MOB_UPDATE_SIGHT)
to_chat(user, "<span class='notice'>You return the wisp to the lantern.</span>")
if(wisp.orbiting)
var/atom/A = wisp.orbiting
if(isliving(A))
var/mob/living/M = A
M.sight &= ~SEE_MOBS
to_chat(M, "<span class='notice'>Your vision returns to normal.</span>")
wisp.stop_orbit()
wisp.loc = src
wisp.forceMove(src)
set_light(initial(light_range))
user.update_sight()
to_chat(user, "<span class='notice'>Your vision returns to normal.</span>")
icon_state = "lantern-blue"
feedback_add_details("wisp_lantern","R") // returned
/obj/item/wisp_lantern/New()
..()
/obj/item/wisp_lantern/Initialize(mapload)
. = ..()
wisp = new(src)
/obj/item/wisp_lantern/Destroy()
@@ -230,17 +240,20 @@
wisp.visible_message("<span class='notice'>[wisp] has a sad feeling for a moment, then it passes.</span>")
return ..()
/obj/item/wisp_lantern/proc/update_user_sight(mob/user)
user.sight |= sight_flags
if(!isnull(lighting_alpha))
user.lighting_alpha = min(user.lighting_alpha, lighting_alpha)
/obj/effect/wisp
name = "friendly wisp"
desc = "Happy to light your way."
icon = 'icons/obj/lighting.dmi'
icon_state = "orb"
layer = ABOVE_ALL_MOB_LAYER
light_power = 1
light_range = 7
layer = ABOVE_ALL_MOB_LAYER
//Red/Blue Cubes
/obj/item/warp_cube
name = "blue cube"
desc = "A mysterious blue cube."
+3 -2
View File
@@ -273,8 +273,9 @@
/area/survivalpod
name = "\improper Emergency Shelter"
icon_state = "away"
requires_power = 0
has_gravity = 1
requires_power = FALSE
has_gravity = TRUE
dynamic_lighting = DYNAMIC_LIGHTING_FORCED
/obj/item/survivalcapsule
name = "bluespace shelter capsule"
+10 -26
View File
@@ -69,7 +69,7 @@
visible_message("<span class='warning'>[src] crackles and buzzes violently!</span>")
/mob/living/simple_animal/hostile/mining_drone/sentience_act()
AIStatus = AI_OFF
..()
check_friendly_fire = 0
/mob/living/simple_animal/hostile/mining_drone/attackby(obj/item/I, mob/user, params)
@@ -184,28 +184,6 @@
mode = MINEDRONE_COLLECT
SetCollectBehavior()
/mob/living/simple_animal/hostile/mining_drone/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
if(mesons_active)
sight |= SEE_TURFS
see_invisible = SEE_INVISIBLE_MINIMUM
else
sight &= ~SEE_TURFS
see_invisible = SEE_INVISIBLE_LIVING
see_in_dark = initial(see_in_dark)
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
//Actions for sentient minebots
/datum/action/innate/minedrone
@@ -232,10 +210,16 @@
/datum/action/innate/minedrone/toggle_meson_vision/Activate()
var/mob/living/simple_animal/hostile/mining_drone/user = owner
user.mesons_active = !user.mesons_active
user.update_sight()
if(user.sight & SEE_TURFS)
user.sight &= ~SEE_TURFS
user.lighting_alpha = initial(user.lighting_alpha)
else
user.sight |= SEE_TURFS
user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.mesons_active) ? "on" : "off"].</span>")
user.sync_lighting_plane_alpha()
to_chat(user, "<span class='notice'>You toggle your meson vision [(user.sight & SEE_TURFS) ? "on" : "off"].</span>")
/datum/action/innate/minedrone/toggle_mode
name = "Toggle Mode"
+3
View File
@@ -83,6 +83,9 @@ obj/structure/ore_box/ex_act(severity, target)
O.forceMove(loc)
CHECK_TICK
/obj/structure/ore_box/onTransitZ()
return
/obj/structure/ore_box/verb/empty_box()
set name = "Empty Ore Box"
set category = "Object"
+1 -1
View File
@@ -7,7 +7,7 @@
move_resist = INFINITY
status_flags = GODMODE // You can't damage it.
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
see_in_dark = 7
see_in_dark = 8
invisibility = 101 // No one can see us
sight = SEE_SELF
move_on_shuttle = 0
+2 -21
View File
@@ -1,23 +1,4 @@
/mob/dead/forceMove(atom/destination)
// Overriden from code/game/atoms_movable.dm#141 to prevent things like mice squeaking when ghosts walk on them.
// Same as parent, except that it does not include Uncrossed or Crossed calls.
var/turf/old_loc = loc
var/oldloc = loc
loc = destination
if(old_loc)
old_loc.Exited(src, destination)
if(destination)
destination.Entered(src)
if(isturf(destination) && opacity)
var/turf/new_loc = destination
new_loc.reconsider_lights()
if(isturf(old_loc) && opacity)
old_loc.reconsider_lights()
for(var/datum/light_source/L in light_sources)
L.source_atom.update_light()
return 1
Moved(oldloc, NONE, TRUE)
+1 -1
View File
@@ -1,6 +1,6 @@
/mob/dead/observer/Logout()
if(client)
client.images -= ghost_darkness_images
client.images -= ghost_images
..()
spawn(0)
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
+51 -32
View File
@@ -1,7 +1,7 @@
#define GHOST_CAN_REENTER 1
#define GHOST_IS_OBSERVER 2
var/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness
var/list/image/ghost_images = list()
GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
@@ -10,7 +10,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
icon = 'icons/mob/mob.dmi'
icon_state = "ghost"
layer = 4
layer = GHOST_LAYER
stat = DEAD
density = 0
canmove = 0
@@ -74,7 +74,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
ghostimage.appearance_flags |= KEEP_TOGETHER
ghostimage.alpha = alpha
appearance_flags |= KEEP_TOGETHER
ghost_darkness_images |= ghostimage
ghost_images |= ghostimage
updateallghostimages()
if(!T) T = pick(latejoin) //Safety in case we cannot find the body's position
forceMove(T)
@@ -90,7 +90,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
M.following_mobs -= src
following = null
if(ghostimage)
ghost_darkness_images -= ghostimage
ghost_images -= ghostimage
QDEL_NULL(ghostimage)
updateallghostimages()
return ..()
@@ -231,31 +231,31 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
P.despawn_occupant()
return
// Ghosts have no momentum, being massless ectoplasm
/mob/dead/observer/Process_Spacemove(movement_dir)
return 1
/mob/dead/observer/Move(NewLoc, direct)
following = null
dir = direct
ghostimage.dir = dir
setDir(direct)
ghostimage.setDir(dir)
var/oldloc = loc
if(NewLoc)
forceMove(NewLoc)
return
forceMove(get_turf(src)) //Get out of closets and such as a ghost
if((direct & NORTH) && y < world.maxy)
y++
else if((direct & SOUTH) && y > 1)
y--
if((direct & EAST) && x < world.maxx)
x++
else if((direct & WEST) && x > 1)
x--
else
forceMove(get_turf(src)) //Get out of closets and such as a ghost
if((direct & NORTH) && y < world.maxy)
y++
else if((direct & SOUTH) && y > 1)
y--
if((direct & EAST) && x < world.maxx)
x++
else if((direct & WEST) && x > 1)
x--
for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb
S.Crossed(src)
var/area/A = get_area(src)
if(A)
A.Entered(src)
..()
Moved(oldloc, direct)
/mob/dead/observer/can_use_hands() return 0
@@ -404,7 +404,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/area/A = input("Area to jump to", "BOOYEA") as null|anything in ghostteleportlocs
var/area/thearea = ghostteleportlocs[A]
if(!thearea)
return
@@ -681,14 +681,32 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set desc = "Toggles your ability to see things only ghosts can see, like other ghosts"
set category = "Ghost"
ghostvision = !(ghostvision)
updateghostsight()
update_sight()
to_chat(usr, "You [(ghostvision?"now":"no longer")] have ghost vision.")
/mob/dead/observer/verb/toggle_darkness()
set name = "Toggle Darkness"
set category = "Ghost"
seedarkness = !(seedarkness)
updateghostsight()
switch(lighting_alpha)
if (LIGHTING_PLANE_ALPHA_VISIBLE)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
if (LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE)
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
if (LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE)
lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE
else
lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
update_sight()
/mob/dead/observer/update_sight()
if (!ghostvision)
see_invisible = SEE_INVISIBLE_LIVING
else
see_invisible = SEE_INVISIBLE_OBSERVER
updateghostimages()
. = ..()
/mob/dead/observer/proc/updateghostsight()
if(!seedarkness)
@@ -696,7 +714,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
else
see_invisible = SEE_INVISIBLE_OBSERVER
if(!ghostvision)
see_invisible = SEE_INVISIBLE_LIVING;
see_invisible = SEE_INVISIBLE_LIVING
updateghostimages()
/proc/updateallghostimages()
@@ -706,11 +725,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/updateghostimages()
if(!client)
return
if(seedarkness || !ghostvision)
client.images -= ghost_darkness_images
if(!ghostvision)
client.images -= ghost_images
else
//add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now
client.images |= ghost_darkness_images
client.images |= ghost_images
if(ghostimage)
client.images -= ghostimage //remove ourself
+4 -4
View File
@@ -38,8 +38,8 @@
if(!l_hand && has_left_hand())
W.forceMove(src) //TODO: move to equipped?
l_hand = W
W.layer = 20 //TODO: move to equipped?
W.plane = HUD_PLANE //TODO: move to equipped?
W.layer = ABOVE_HUD_LAYER //TODO: move to equipped?
W.plane = ABOVE_HUD_PLANE //TODO: move to equipped?
W.equipped(src,slot_l_hand)
if(pulling == W)
stop_pulling()
@@ -54,8 +54,8 @@
if(!r_hand && has_right_hand())
W.forceMove(src)
r_hand = W
W.layer = 20
W.plane = HUD_PLANE
W.layer = ABOVE_HUD_LAYER
W.plane = ABOVE_HUD_PLANE
W.equipped(src,slot_r_hand)
if(pulling == W)
stop_pulling()
+50 -12
View File
@@ -5,18 +5,21 @@
icon = 'icons/mob/alien.dmi'
gender = NEUTER
dna = null
alien_talk_understand = 1
nightvision = 1
alien_talk_understand = TRUE
var/nightvision = FALSE
see_in_dark = 4
var/obj/item/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
var/move_delay_add = 0 // movement delay to add
var/has_fine_manipulation = FALSE
var/move_delay_add = FALSE // movement delay to add
status_flags = CANPARALYSE|CANPUSH
var/heal_rate = 5
var/large = 0
var/large = FALSE
var/heat_protection = 0.5
var/leaping = 0
var/leaping = FALSE
ventcrawler = 2
var/list/alien_organs = list()
var/death_message = "lets out a waning guttural screech, green blood bubbling from its maw..."
@@ -149,15 +152,17 @@
if(!nightvision)
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
nightvision = 1
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
nightvision = TRUE
usr.hud_used.nightvisionicon.icon_state = "nightvision1"
else if(nightvision == 1)
see_in_dark = 4
see_invisible = 45
nightvision = 0
else if(nightvision)
see_in_dark = initial(see_in_dark)
lighting_alpha = initial(lighting_alpha)
nightvision = FALSE
usr.hud_used.nightvisionicon.icon_state = "nightvision0"
update_sight()
/mob/living/carbon/alien/assess_threat(var/mob/living/simple_animal/bot/secbot/judgebot, var/lasercolor)
if(judgebot.emagged == 2)
@@ -264,3 +269,36 @@ Des: Removes all infected images from the alien.
return pick("xltrails_1", "xltrails_2")
else
return pick("xttrails_1", "xttrails_2")
/mob/living/carbon/alien/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
see_invisible = initial(see_invisible)
sight = SEE_MOBS
if(nightvision)
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
else
see_in_dark = initial(see_in_dark)
lighting_alpha = initial(lighting_alpha)
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
for(var/obj/item/organ/internal/cyberimp/eyes/E in internal_organs)
sight |= E.vision_flags
if(E.see_in_dark)
see_in_dark = max(see_in_dark, E.see_in_dark)
if(E.see_invisible)
see_invisible = min(see_invisible, E.see_invisible)
if(!isnull(E.lighting_alpha))
lighting_alpha = min(lighting_alpha, E.lighting_alpha)
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -6,7 +6,7 @@ As such, they can either help or harm other aliens. Help works like the human he
In all, this is a lot like the monkey code. /N
*/
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
if(!ticker)
if(!SSticker)
to_chat(M, "You cannot attack people before the game has started.")
return
@@ -159,7 +159,7 @@ Doesn't work on other aliens/AI.*/
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.loc = loc
M.forceMove(loc)
//Paralyse(10)
src.visible_message("<span class='alertalien'><B>[src] hurls out the contents of [p_their()] stomach!</span>")
return
@@ -7,8 +7,8 @@
if(stat != CONSCIOUS)
return
if(layer != TURF_LAYER+0.2)
layer = TURF_LAYER+0.2
if(layer != ABOVE_NORMAL_TURF_LAYER)
layer = ABOVE_NORMAL_TURF_LAYER
visible_message("<B>[src] scurries to the ground!</B>", "<span class='noticealien'>You are now hiding.</span>")
else
layer = MOB_LAYER
@@ -28,33 +28,3 @@
//BREATH TEMPERATURE
handle_breath_temperature(breath)
/mob/living/carbon/alien/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
sight = SEE_MOBS
if(nightvision)
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
else
see_in_dark = 4
see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
for(var/obj/item/organ/internal/cyberimp/eyes/E in internal_organs)
sight |= E.vision_flags
if(E.dark_view)
see_in_dark = max(see_in_dark, E.dark_view)
if(E.see_invisible)
see_invisible = min(see_invisible, E.see_invisible)
if(see_override)
see_invisible = see_override
@@ -93,8 +93,8 @@
spawn(6)
var/mob/living/carbon/alien/larva/new_xeno = new(owner.drop_location())
new_xeno.key = C.key
if(ticker && ticker.mode)
ticker.mode.xenos += new_xeno.mind
if(SSticker && SSticker.mode)
SSticker.mode.xenos += new_xeno.mind
new_xeno.mind.name = new_xeno.name
new_xeno.mind.assigned_role = SPECIAL_ROLE_XENOMORPH
new_xeno.mind.special_role = SPECIAL_ROLE_XENOMORPH
+2 -2
View File
@@ -44,7 +44,7 @@
visible_message("<span class='notice'>[user] sticks \a [O] into \the [src].</span>")
brainmob = B.brainmob
B.brainmob = null
brainmob.loc = src
brainmob.forceMove(src)
brainmob.container = src
brainmob.stat = CONSCIOUS
GLOB.respawnable_list -= brainmob
@@ -152,7 +152,7 @@
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
brainmob.container = null//Reset brainmob mmi var.
brainmob.loc = held_brain//Throw mob into brain.
brainmob.forceMove(held_brain) //Throw mob into brain.
GLOB.respawnable_list += brainmob
GLOB.living_mob_list -= brainmob//Get outta here
held_brain.brainmob = brainmob//Set the brain to use the brainmob
@@ -67,10 +67,10 @@
/mob/living/carbon/brain/on_forcemove(atom/newloc)
if(container)
container.loc = newloc
container.forceMove(newloc)
else //something went very wrong.
CRASH("Brainmob without container.")
loc = container
forceMove(container)
/*
This will return true if the brain has a container that leaves it less helpless than a naked brain
@@ -48,7 +48,6 @@
H.mind.transfer_to(brainmob)
to_chat(brainmob, "<span class='notice'>You feel slightly disoriented. That's normal when you're just a [initial(src.name)].</span>")
callHook("debrain", list(brainmob))
/obj/item/organ/internal/brain/examine(mob/user) // -- TLE
..(user)
+43 -8
View File
@@ -72,7 +72,7 @@
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
A.loc = loc
A.forceMove(drop_location())
stomach_contents.Remove(A)
src.gib()
@@ -323,8 +323,8 @@
return
var/extra_darkview = 0
if(E.dark_view)
extra_darkview = max(E.dark_view - 2, 0)
if(E.see_in_dark)
extra_darkview = max(E.see_in_dark - 2, 0)
extra_damage = extra_darkview
var/light_amount = 10 // assume full brightness
@@ -833,7 +833,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
to_chat(src, "<span class='notice'>You successfully remove [I].</span>")
if(I == handcuffed)
handcuffed.loc = loc
handcuffed.forceMove(drop_location())
handcuffed.dropped(src)
handcuffed = null
if(buckled && buckled.buckle_requires_restraints)
@@ -841,7 +841,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
update_handcuffed()
return
if(I == legcuffed)
legcuffed.loc = loc
legcuffed.forceMove(drop_location())
legcuffed.dropped()
legcuffed = null
update_inv_legcuffed()
@@ -935,7 +935,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
if(client)
client.screen -= W
if(W)
W.loc = loc
W.forceMove(drop_location())
W.dropped(src)
if(W)
W.layer = initial(W.layer)
@@ -947,7 +947,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
if(client)
client.screen -= W
if(W)
W.loc = loc
W.forceMove(drop_location())
W.dropped(src)
if(W)
W.layer = initial(W.layer)
@@ -1129,4 +1129,39 @@ so that different stomachs can handle things in different ways VB*/
/mob/living/carbon/proc/shock_internal_organs(intensity)
for(var/obj/item/organ/O in internal_organs)
O.shock_organ(intensity)
O.shock_organ(intensity)
/mob/living/carbon/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
see_invisible = initial(see_invisible)
see_in_dark = initial(see_in_dark)
sight = initial(sight)
lighting_alpha = initial(lighting_alpha)
for(var/obj/item/organ/internal/cyberimp/eyes/E in internal_organs)
sight |= E.vision_flags
if(E.see_in_dark)
see_in_dark = max(see_in_dark, E.see_in_dark)
if(E.see_invisible)
see_invisible = min(see_invisible, E.see_invisible)
if(!isnull(E.lighting_alpha))
lighting_alpha = min(lighting_alpha, E.lighting_alpha)
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
if(XRAY in mutations)
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -112,7 +112,7 @@
if(H.mind)
H.mind.kills += "[key_name(src)]"
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
// log_world("k")
sql_report_death(src)
@@ -30,6 +30,7 @@
msg += "<EM>[name]</EM>"
var/displayed_species = dna.species.name
var/examine_color = dna.species.flesh_color
for(var/obj/item/clothing/C in src) //Disguise checks
if(C == src.head || C == src.wear_suit || C == src.wear_mask || C == src.w_uniform || C == src.belt || C == src.back)
if(C.species_disguise)
@@ -37,11 +38,11 @@
if(skipjumpsuit && skipface || (NO_EXAMINE in dna.species.species_traits)) //either obscured or on the nospecies list
msg += "!\n" //omit the species when examining
else if(displayed_species == "Slime People") //snowflakey because Slime People are defined as a plural
msg += ", a slime person!\n"
msg += ", a<b><font color='[examine_color]'> slime person</font></b>!\n"
else if(displayed_species == "Unathi") //DAMN YOU, VOWELS
msg += ", a unathi!\n"
msg += ", a<b><font color='[examine_color]'> unathi</font></b>!\n"
else
msg += ", \a [lowertext(displayed_species)]!\n"
msg += ", a<b><font color='[examine_color]'> [lowertext(displayed_species)]</font></b>!\n"
//uniform
if(w_uniform && !skipjumpsuit && !(w_uniform.flags & ABSTRACT))
@@ -315,15 +316,7 @@
msg += "[p_they(TRUE)] [p_have()] a stupid expression on [p_their()] face.\n"
if(get_int_organ(/obj/item/organ/internal/brain))
if(istype(src, /mob/living/carbon/human/interactive))
var/mob/living/carbon/human/interactive/auto = src
if(auto.showexaminetext)
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] appears to be some sort of sick automaton, [p_their()] eyes are glazed over and [p_their()] mouth is slightly agape.</span>\n"
if(auto.debugexamine)
var/dodebug = auto.doing2string(auto.doing)
var/interestdebug = auto.interest2string(auto.interest)
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] appears to be [interestdebug] and [dodebug].</span>\n"
else if(dna.species.show_ssd)
if(dna.species.show_ssd)
if(!key)
msg += "<span class='deadsay'>[p_they(TRUE)] [p_are()] totally catatonic. The stresses of life in deep-space must have been too much for [p_them()]. Any recovery is unlikely.</span>\n"
else if(!client)
+26 -10
View File
@@ -414,8 +414,22 @@
if(has_breathable_mask && istype(belt, /obj/item/tank))
dat += "&nbsp;<A href='?src=[UID()];internal=[slot_belt]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Pockets:</B></td><td><A href='?src=[UID()];pockets=left'>[(l_store && !(l_store.flags&ABSTRACT)) ? "Left (Full)" : "<font color=grey>Left (Empty)</font>"]</A>"
dat += "&nbsp;<A href='?src=[UID()];pockets=right'>[(r_store && !(r_store.flags&ABSTRACT)) ? "Right (Full)" : "<font color=grey>Right (Empty)</font>"]</A></td></tr>"
// Pockets
dat += "<tr><td>&nbsp;&#8627;<B>Pockets:</B></td><td><A href='?src=[UID()];pockets=left'>"
if(l_store && internal && l_store == internal)
dat += "[l_store]"
else if(l_store && !(l_store.flags&ABSTRACT))
dat += "Left (Full)"
else
dat += "<font color=grey>Left (Empty)</font>"
dat += "</A>&nbsp;<A href='?src=[UID()];pockets=right'>"
if(r_store && internal && r_store == internal)
dat += "[r_store]"
else if(r_store && !(r_store.flags&ABSTRACT))
dat += "Right (Full)"
else
dat += "<font color=grey>Right (Empty)</font>"
dat += "</A></td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>ID:</B></td><td><A href='?src=[UID()];item=[slot_wear_id]'>[(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>PDA:</B></td><td><A href='?src=[UID()];item=[slot_wear_pda]'>[(wear_pda && !(wear_pda.flags&ABSTRACT)) ? wear_pda : "<font color=grey>Empty</font>"]</A></td></tr>"
@@ -545,11 +559,14 @@
/mob/living/carbon/human/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
dna.species.update_sight(src)
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
@@ -1317,11 +1334,13 @@
var/list/thing_to_check = list(slot_wear_mask, slot_head, slot_shoes, slot_gloves, slot_l_ear, slot_r_ear, slot_glasses, slot_l_hand, slot_r_hand)
var/list/kept_items[0]
var/list/item_flags[0]
for(var/thing in thing_to_check)
var/obj/item/I = get_item_by_slot(thing)
if(I)
kept_items[I] = thing
item_flags[I] = I.flags
I.flags = 0 // Temporary set the flags to 0
if(retain_damage)
//Create a list of body parts which are damaged by burn or brute and save them to apply after new organs are generated. First we just handle external organs.
@@ -1387,8 +1406,9 @@
else
dna.species.create_organs(src)
for(var/thing in kept_items)
for(var/obj/item/thing in kept_items)
equip_to_slot_if_possible(thing, kept_items[thing], redraw_mob = 0)
thing.flags = item_flags[thing] // Reset the flags to the origional ones
//Handle default hair/head accessories for created mobs.
var/obj/item/organ/external/head/H = get_organ("head")
@@ -1427,11 +1447,7 @@
dna.species.on_species_gain(src)
see_in_dark = dna.species.get_resultant_darksight(src)
if(see_in_dark > 2)
see_invisible = SEE_INVISIBLE_LEVEL_ONE
else
see_invisible = SEE_INVISIBLE_LIVING
update_sight()
dna.species.handle_dna(src) //Give them whatever special dna business they got.
@@ -1961,7 +1977,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
if(7) // Pride
log_game("[src] was influenced by the sin of pride.")
O = new /datum/objective/sintouched/pride
ticker.mode.sintouched += src.mind
SSticker.mode.sintouched += src.mind
src.mind.objectives += O
var/obj_count = 1
to_chat(src, "<span class='notice> Your current objectives:")
@@ -362,7 +362,7 @@ This function restores all organs.
if(LAssailant && ishuman(LAssailant)) //superheros still get the comical hit markers
var/mob/living/carbon/human/H = LAssailant
if(H.mind && H.mind in (ticker.mode.superheroes || ticker.mode.supervillains || ticker.mode.greyshirts))
if(H.mind && H.mind in (SSticker.mode.superheroes || SSticker.mode.supervillains || SSticker.mode.greyshirts))
var/list/attack_bubble_recipients = list()
var/mob/living/user
for(var/mob/O in viewers(user, src))
@@ -267,7 +267,7 @@ emp_act
apply_effect(5, WEAKEN, armor)
AdjustConfused(15)
if(prob(I.force + ((100 - health)/2)) && src != user && I.damtype == BRUTE)
ticker.mode.remove_revolutionary(mind)
SSticker.mode.remove_revolutionary(mind)
if(bloody)//Apply blood
if(wear_mask)
@@ -1,874 +0,0 @@
/mob/living/carbon/human/interactive/proc/chatter(obj)
var/verbs_use = pick_list(speak_file, "verbs_use")
var/verbs_touch = pick_list(speak_file, "verbs_touch")
var/verbs_move = pick_list(speak_file, "verbs_move")
var/nouns_insult = pick_list(speak_file, "nouns_insult")
var/nouns_generic = pick_list(speak_file, "nouns_generic")
var/nouns_objects = pick_list(speak_file, "nouns_objects")
var/nouns_body = pick_list(speak_file, "nouns_body")
var/adjective_insult = pick_list(speak_file, "adjective_insult")
var/adjective_objects = pick_list(speak_file, "adjective_objects")
var/adjective_generic = pick_list(speak_file, "adjective_generic")
var/curse_words = pick_list(speak_file, "curse_words")
var/chatmsg = ""
if(prob(10)) // 10% chance to broadcast it over the radio
chatmsg = ";"
if(prob(chattyness) || knownStrings.len < 10) // say a generic phrase, otherwise draw from our strings.
if(doing & SNPC_INTERACTING)
if(prob(chattyness))
chatmsg += pick("This [nouns_objects] is a little [adjective_objects].",
"Well [verbs_use] my [nouns_body], this [nouns_insult] is pretty [adjective_insult].",
"[capitalize(curse_words)], what am I meant to do with this [adjective_insult] [nouns_objects].")
else if(doing & SNPC_TRAVEL)
if(prob(chattyness))
chatmsg += pick("Oh [curse_words], [verbs_move]!",
"Time to get my [adjective_generic] [adjective_insult] [nouns_body] elsewhere.",
"I wonder if there is anything to [verbs_use] and [verbs_touch] somewhere else..")
else if(doing & SNPC_FIGHTING)
if(prob(chattyness))
chatmsg += pick("I'm going to [verbs_use] you, you [adjective_insult] [nouns_insult]!",
"Rend and [verbs_touch], Rend and [verbs_use]!",
"You [nouns_insult], I'm going to [verbs_use] you right in the [nouns_body]. JUST YOU WAIT!")
if(prob(chattyness/2))
chatmsg = ";"
var/what = pick(1,2,3,4,5)
switch(what)
if(1)
chatmsg += "Well [curse_words], this is a [adjective_generic] situation."
if(2)
chatmsg += "Oh [curse_words], that [nouns_insult] was one hell of an [adjective_insult] [nouns_body]."
if(3)
chatmsg += "I want to [verbs_use] that [nouns_insult] when I find them."
if(4)
chatmsg += "[pick("Innocent","Guilty","Traitorous","Honk")] until proven [adjective_generic]!"
if(5)
var/toSay = ""
for(var/i = 0; i < 5; i++)
curse_words = pick_list(speak_file, "curse_words")
toSay += "[curse_words] "
chatmsg += "Hey [nouns_generic], why don't you go [copytext(toSay, 1, length(toSay))], you [nouns_insult]!"
else if(prob(chattyness))
chatmsg += pick(knownStrings)
if(prob(25)) // cut out some phrases now and then to make sure we're fresh and new
knownStrings -= pick(chatmsg)
if(chatmsg != ";" && chatmsg != "")
say(chatmsg)
/mob/living/carbon/human/interactive/proc/traitor(obj)
if(traitorType == SNPC_PSYCHO && nearby.len)
traitorTarget = pick(nearby)
if(prob(traitorScale))
if(!Adjacent(traitorTarget) && !(traitorType == SNPC_PSYCHO))
tryWalk(get_turf(traitorTarget))
else
switch(traitorType)
if(SNPC_BRUTE)
retal = 1
retal_target = traitorTarget
if(SNPC_STEALTH)
if(istype(traitorTarget,/mob)) // it's inside something, lets kick their shit in
var/mob/M = traitorTarget
if(!M.stat)
retal = 1
retal_target = traitorTarget
else
var/obj/item/I = traitorTarget
I.loc = get_turf(traitorTarget) // pull it outta them
else
take_to_slot(traitorTarget)
if(SNPC_MARTYR)
custom_emote(1, "[src]'s chest opens up, revealing a large mass of explosives and tangled wires!")
if(inactivity_period <= 0)
inactivity_period = 9999 // technically infinite
if(do_after(src, 60, target = traitorTarget))
custom_emote(1, "A fire bursts from [src]'s eyes, igniting white hot and consuming [p_their()] body in a flaming explosion!")
explosion(src, 6, 6, 6)
else
inactivity_period = 0
custom_emote(1, "[src]'s chest closes, hiding [p_their()] insides.")
if(SNPC_PSYCHO)
var/choice = pick(typesof(/obj/item/grenade/chem_grenade) - /obj/item/grenade/chem_grenade)
new choice(src)
retal = 1
retal_target = traitorTarget
/mob/living/carbon/human/interactive/proc/botany(obj)
if(shouldModulePass())
return
if(enforceHome())
return
var/list/allContents = getAllContents()
var/obj/item/reagent_containers/glass/beaker/bluespace/internalBeaker = locate(/obj/item/reagent_containers/glass/beaker/bluespace) in allContents
var/obj/item/storage/bag/plants/internalBag = locate(/obj/item/storage/bag/plants) in allContents
if(!internalBag)
internalBag = new/obj/item/storage/bag/plants(src)
if(!internalBeaker)
internalBeaker = new/obj/item/reagent_containers/glass/beaker/bluespace(src)
internalBeaker.name = "Grow-U-All Super Spray"
if(internalBeaker && internalBag)
var/obj/machinery/hydroponics/HP
//consider the appropriate target
var/list/considered = list()
for(var/obj/machinery/hydroponics/tester in view(12,src))
considered[tester] = 1
if(!tester.myseed)
considered[tester] += 50
if(tester.weedlevel > 0)
considered[tester] += 5
if(tester.pestlevel > 0)
considered[tester] += 5
if(tester.nutrilevel < tester.maxnutri)
considered[tester] += 15
if(tester.waterlevel < tester.maxwater)
considered[tester] += 15
if(tester.harvest || tester.dead)
considered[tester] += 100
considered[tester] = max(1, considered[tester] - get_dist(src,tester))
var/index = 0
for(var/A in considered)
++index
if(considered[A] > considered[HP] || !HP)
HP = considered[index]
if(HP)
TARGET = HP
if(!Adjacent(HP))
tryWalk(get_turf(HP))
else
if(HP.harvest || HP.dead)
HP.attack_hand(src)
else if(!HP.myseed)
var/obj/item/seeds/SEED = new /obj/item/seeds/random(src)
custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")] towards [TARGET], producing a [SEED]!")
HP.attackby(SEED, src)
else
var/change = 0
if(HP.weedlevel > 0)
change = 1
if(!internalBeaker.reagents.has_reagent("atrazine", 10))
internalBeaker.reagents.add_reagent("atrazine", 10)
if(HP.pestlevel > 0)
change = 1
if(!internalBeaker.reagents.has_reagent("diethylamine", 10))
internalBeaker.reagents.add_reagent("diethylamine", 10)
if(HP.nutrilevel < HP.maxnutri)
change = 1
if(!internalBeaker.reagents.has_reagent("eznutriment", 15))
internalBeaker.reagents.add_reagent("eznutriment", 15)
if(!internalBeaker.reagents.has_reagent("diethylamine", 15))
internalBeaker.reagents.add_reagent("diethylamine", 15)
if(HP.waterlevel < HP.maxwater)
change = 1
if(!internalBeaker.reagents.has_reagent("holywater", 50))
internalBeaker.reagents.add_reagent("holywater", 50)
if(change)
HP.attackby(internalBeaker,src)
var/obj/item/reagent_containers/food/snacks/grown/GF = locate(/obj/item/reagent_containers/food/snacks/grown) in view(12,src)
if(GF)
if(!Adjacent(GF))
tryWalk(get_turf(GF))
else
GF.attackby(internalBag,src)
if(internalBag.contents.len)
var/obj/machinery/smartfridge/SF = locate(/obj/machinery/smartfridge) in range(12, src)
if(!Adjacent(SF))
tryWalk(get_turf(SF))
else
custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")], upending the [internalBag]'s contents all over the [SF]!")
//smartfridges call updateUsrDialog when you call attackby, so we're going to have to cheese-magic-space this
for(var/obj/toLoad in internalBag.contents)
if(contents.len >= SF.max_n_of_items)
break
if(SF.accept_check(toLoad))
SF.load(toLoad, src)
else
qdel(toLoad) // destroy everything we dont need
/mob/living/carbon/human/interactive/proc/bartend(obj)
if(shouldModulePass())
return
if(enforceHome())
return
var/list/rangeCheck = oview(6,src)
var/obj/structure/table/RT
var/mob/living/carbon/human/serveTarget
for(var/mob/living/carbon/human/H in rangeCheck)
if(!locate(/obj/item/reagent_containers/food/drinks) in orange(1, H))
serveTarget = H
if(serveTarget)
RT = locate(/obj/structure/table) in orange(1, serveTarget)
if(RT && serveTarget)
if(!Adjacent(RT))
tryWalk(get_turf(RT))
else
var/drinkChoice = pick(typesof(/obj/item/reagent_containers/food/drinks) - /obj/item/reagent_containers/food/drinks)
if(drinkChoice)
var/obj/item/reagent_containers/food/drinks/D = new drinkChoice(get_turf(src))
RT.attackby(D,src)
say("[pick("Something to wet your whistle!","Down the hatch, a tasty beverage!","One drink, coming right up!","Tasty liquid for your oral intake!","Enjoy!")]")
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")], serving up a [D]!")
/mob/living/carbon/human/interactive/proc/shitcurity(obj)
var/list/allContents = getAllContents()
if(retal && TARGET)
if(Adjacent(TARGET))
var/obj/item/restraints/R = locate() in allContents
if(R)
R.attack(TARGET, src) // go go bluespace restraint launcher!
else if(TARGET in oview(7, src))
var/obj/item/gun/G = locate() in allContents
if(G)
G.afterattack(TARGET, src)
/mob/living/carbon/human/interactive/proc/clowning(obj)
if(shouldModulePass())
return
var/list/allContents = getAllContents()
var/list/rangeCheck = oview(12, src)
var/mob/living/carbon/human/clownTarget
var/list/clownPriority = list()
var/obj/item/reagent_containers/spray/S
if(!locate(/obj/item/reagent_containers/spray) in allContents)
new/obj/item/reagent_containers/spray(src)
else
S = locate(/obj/item/reagent_containers/spray) in allContents
for(var/mob/living/carbon/human/C in rangeCheck)
var/pranksNearby = 100
for(var/turf/simulated/T in orange(1, C))
for(var/obj/item/A in T)
if(istype(A,/obj/item/soap) || istype(A,/obj/item/reagent_containers/food/snacks/grown/banana) || istype(A,/obj/item/grown/bananapeel))
pranksNearby--
if(T.wet)
pranksNearby -= 10
clownPriority[C] = pranksNearby
for(var/A in clownPriority)
if(!clownTarget)
clownTarget = A
else
if(clownPriority[A] > clownPriority[clownTarget])
clownTarget = clownPriority[A]
if(clownTarget)
if(!Adjacent(clownTarget))
tryWalk(clownTarget)
else
var/hasPranked = 0
for(var/A in allContents)
if(prob(smartness/2) && !hasPranked)
if(istype(A,/obj/item/soap))
npcDrop(A)
hasPranked = 1
if(istype(A,/obj/item/reagent_containers/food/snacks/grown/banana))
var/obj/item/reagent_containers/food/snacks/B = A
B.attack(src, src)
if(istype(A,/obj/item/grown/bananapeel))
npcDrop(A)
hasPranked = 1
if(!hasPranked)
if(S.reagents.total_volume <= 5)
S.reagents.add_reagent("water", 25)
S.afterattack(get_turf(pick(orange(1, clownTarget))),src)
/mob/living/carbon/human/interactive/proc/healpeople(obj)
var/shouldTryHeal = 0
var/obj/item/stack/medical/M
var/list/allContents = getAllContents()
for(var/A in allContents)
if(istype(A,/obj/item/stack/medical))
shouldTryHeal = 1
M = A
var/obj/item/reagent_containers/hypospray/HPS
if(!locate(/obj/item/reagent_containers/hypospray) in allContents)
new/obj/item/reagent_containers/hypospray(src)
else
HPS = locate(/obj/item/reagent_containers/hypospray) in allContents
if(!shouldTryHeal)
shouldTryHeal = 2 // we have no stackables to use, lets use our internal hypospray instead
if(shouldTryHeal == 1)
for(var/mob/living/carbon/human/C in nearby)
if(istype(C,/mob/living/carbon/human)) //I haven't the foggiest clue why this is turning up non-carbons but sure here whatever
if(C.health <= 75)
if(get_dist(src,C) <= 2)
src.say("Wait, [C], let me heal you!")
M.attack(C,src)
sleep(25)
else
tryWalk(get_turf(C))
else if(shouldTryHeal == 2)
if(HPS)
if(HPS.reagents.total_volume <= 0)
HPS.reagents.add_reagent("omnizine",30)
for(var/mob/living/carbon/human/C in nearby)
if(istype(C,/mob/living/carbon/human))
if(C.health <= 75 && C.reagents.get_reagent_amount("omnizine") <= 0) // make sure they wont be overdosing
if(get_dist(src,C) <= 2)
src.say("Wait, [C], let me heal you!")
HPS.attack(C,src)
sleep(25)
else
tryWalk(get_turf(C))
/mob/living/carbon/human/interactive/proc/dojanitor(obj)
if(shouldModulePass())
return
var/list/allContents = getAllContents()
//now with bluespace magic!
var/obj/item/reagent_containers/spray/SP = locate() in allContents
if(!SP)
SP = new /obj/item/reagent_containers/spray(src)
var/obj/item/soap/SO = locate() in allContents
if(!SO)
SO = new /obj/item/soap(src)
if(SP.reagents.total_volume <= 5)
SP.reagents.add_reagent("cleaner", 25) // bluespess water delivery for AI
var/obj/effect/decal/cleanable/TC
TC = locate(/obj/effect/decal/cleanable) in view(6, src)
if(TC)
if(!Adjacent(TC))
tryWalk(TC)
else
var/turf/T = get_turf(TC)
if(T && !T.density)
SP.afterattack(TC, src, 1)
else
SO.afterattack(TC, src, 1)
qdel(TC)
// START COOKING MODULE
/mob/living/carbon/human/interactive/proc/refundrecipe(list/ingredients)
for(var/obj/I in ingredients)
I.loc = contents
// Ingredients may be in the rangeCheck or inside the chef's inventory.
// As they are checked off, they are moved to a seperate list as to not be counted twice
// If the recipe fails (eg somebody else took an ingredient before it was picked up) the ingredients are dumped back to inventory
// That way, the chef has a better chance of making a recipe next ptick, if he has more stuff on him
/mob/living/carbon/human/interactive/proc/makerecipe(datum/recipe/R, allContents, rangeCheck)
set background = 1
var/list/ingredients[0]
for(var/P in R.items)
var/obj/item/I = locate(P) in allContents
if(I)
ingredients += I
I.forceMove(null)
continue
I = locate(P) in rangeCheck
TARGET = I
if(I && !Adjacent(I))
tryWalk(get_turf(I))
sleep(get_dist(src, I))
if(!I || !(I in rangeCheck))
refundrecipe(ingredients)
return 0
custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")], picking up [I].")
ingredients += I
I.forceMove(null)
// cheaply cook the ingredients into result
sleep(R.time)
for(var/obj/I in ingredients)
qdel(I)
ingredients.Cut()
var/result = new R.result(get_turf(src))
custom_emote(1, "[pick("gibbers","drools","slobbers","claps wildly","spits")] and, with a bang, \a [result] is cooked!")
return 1
/mob/living/carbon/human/interactive/proc/souschef(obj)
if(shouldModulePass() || enforceHome() || prob(SNPC_FUZZY_CHANCE_HIGH) || prob(SNPC_FUZZY_CHANCE_HIGH))
return
if(doing & SNPC_SPECIAL)
return
doing |= SNPC_SPECIAL
var/static/list/customableTypes = list(/obj/item/reagent_containers/food/snacks/customizable,/obj/item/reagent_containers/food/snacks/breadslice,/obj/item/reagent_containers/food/snacks/bun,/obj/item/reagent_containers/food/snacks/sliceable/flatdough,/obj/item/reagent_containers/food/snacks/boiledspaghetti,/obj/item/trash/plate,/obj/item/trash/bowl)
var/static/list/rawtypes = list(/obj/item/reagent_containers/food/snacks/grown, /obj/item/reagent_containers/food/snacks/rawcutlet, /obj/item/reagent_containers/food/snacks/rawsticks, /obj/item/reagent_containers/food/snacks/salmonmeat, /obj/item/reagent_containers/food/snacks/carpmeat, /obj/item/reagent_containers/food/snacks/catfishmeat, /obj/item/reagent_containers/food/snacks/spaghetti, /obj/item/reagent_containers/food/snacks/dough, /obj/item/reagent_containers/food/snacks/sliceable/flatdough, /obj/item/reagent_containers/food/snacks/doughslice, /obj/item/reagent_containers/food/snacks/meat, /obj/item/reagent_containers/food/snacks/boiledrice, /obj/item/reagent_containers/food/snacks/cheesewedge, /obj/item/reagent_containers/food/snacks/raw_bacon)
try
var/list/allContents = getAllContents()
var/list/rangeCheck = view(6, src)
//Bluespace in some inbuilt tools
var/obj/item/kitchen/rollingpin/RP = locate() in allContents
if(!RP)
RP = new /obj/item/kitchen/rollingpin(src)
var/obj/item/kitchen/knife/KK = locate() in allContents
if(!KK)
KK = new /obj/item/kitchen/knife(src)
var/global/list/available_recipes
if(!available_recipes)
available_recipes = list()
for(var/type in subtypesof(/datum/recipe))
var/datum/recipe/recipe = new type
if(recipe.result) // Ignore recipe subtypes that lack a result
available_recipes += recipe
else
qdel(recipe)
var/foundCookable = 0
//Make some basic custom food
var/foundCustom
for(var/customType in customableTypes)
var/A = locate(customType) in rangeCheck
var/obj/item/reagent_containers/food/snacks/customizable/I = A
if(A && (!istype(I) || I.ingredients.len <= 3))
foundCustom = A // this will eventually wittle down to 0
break
var/obj/machinery/smartfridge/SF = locate(/obj/machinery/smartfridge) in rangeCheck
if(SF)
if(SF.contents.len > 0)
if(!Adjacent(SF))
tryWalk(get_turf(SF))
else
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")], grabbing various foodstuffs from [SF] and sticking them in its mouth!")
for(var/obj/item/A in SF.contents)
if(prob(smartness/2))
var/count = SF.item_quants[A.name]
if(count)
SF.item_quants[A.name] = count - 1
A.forceMove(src)
if(foundCustom)
var/obj/item/reagent_containers/food/snacks/FC = foundCustom
for(var/obj/item/reagent_containers/food/snacks/toMake in allContents)
if(prob(smartness))
if(FC.reagents)
if(toMake.reagents)
var/raw = 0
for(var/type in rawtypes)
if(istype(toMake, type))
raw = 1
break
if(!raw)
npcDrop(toMake)
FC.attackby(toMake, src)
allContents -= toMake
break
else
qdel(FC) // this food is usless, toss it
// Process tool-based ingredients
var/obj/item/reagent_containers/food/snacks/dough/D = locate() in rangeCheck
var/obj/item/reagent_containers/food/snacks/sliceable/flatdough/FD = locate() in rangeCheck
var/obj/item/reagent_containers/food/snacks/rawcutlet/RC = locate() in rangeCheck
var/obj/item/reagent_containers/food/snacks/sliceable/cheesewheel/CW = locate() in rangeCheck
var/obj/item/reagent_containers/food/snacks/grown/potato/PO = locate() in rangeCheck
var/obj/item/reagent_containers/food/snacks/meat/ME = locate() in rangeCheck
var/obj/item/reagent_containers/food/snacks/raw_bacon/RB = locate() in rangeCheck
if(D)
TARGET = D
if(prob(50))
tryWalk(get_turf(D))
sleep(get_dist(src, D))
D.attackby(RP, src)
foundCookable = 1
else if(FD)
TARGET = FD
if(prob(50))
tryWalk(get_turf(FD))
sleep(get_dist(src, FD))
FD.attackby(KK, src)
foundCookable = 1
else if(RC)
TARGET = RC
if(prob(50))
tryWalk(get_turf(RC))
sleep(get_dist(src, RC))
RC.attackby(KK, src)
foundCookable = 1
else if(CW)
TARGET = CW
if(prob(50))
tryWalk(get_turf(CW))
sleep(get_dist(src, CW))
CW.attackby(KK, src)
foundCookable = 1
else if(PO)
TARGET = PO
if(prob(50))
tryWalk(get_turf(PO))
sleep(get_dist(src, PO))
PO.attackby(KK, src)
foundCookable = 1
else if(ME)
TARGET = ME
if(prob(50))
tryWalk(get_turf(ME))
sleep(get_dist(src, ME))
ME.attackby(KK, src)
foundCookable = 1
else if(RB)
TARGET = RB
if(prob(50))
tryWalk(get_turf(RB))
sleep(get_dist(src, RB))
RB.attackby(KK, src)
foundCookable = 1
// refresh
allContents = getAllContents()
rangeCheck = view(6, src)
// Find most complex recipe we can cook
var/ingredientZone = rangeCheck + allContents
var/highest_count = 0
var/datum/recipe/winner = null
for(var/datum/recipe/R in available_recipes)
if(R.check_items(ingredientZone) >= 0)
var/count = (R.items ? R.items.len : 0)
if(count > highest_count)
highest_count = count
winner = R
// make winner
if(winner)
if(makerecipe(winner, allContents, rangeCheck))
foundCookable = 1
// refresh
allContents = getAllContents()
rangeCheck = view(6, src)
// dont display our ingredients
var/list/finishedList = list()
for(var/obj/item/reagent_containers/food/snacks/toDisplay in allContents)
var/raw = 0
for(var/type in rawtypes)
if(istype(toDisplay, type))
raw = 1
break
if(!raw)
finishedList += toDisplay
for(var/obj/item/reagent_containers/food/snacks/toGrab in rangeCheck)
if(!(locate(/obj/structure/table/reinforced) in get_turf(toGrab))) //it's not being displayed
var/raw = 0
for(var/type in rawtypes)
if(istype(toGrab, type))
raw = 1
break
if(!raw)
foundCookable = 1
if(!Adjacent(toGrab))
tryWalk(toGrab)
else
finishedList += toGrab
toGrab.forceMove(src)
if(finishedList.len)
var/obj/structure/table/reinforced/RT
for(var/obj/structure/table/reinforced/toCheck in rangeCheck)
var/counted = 0
for(var/obj/item/reagent_containers/food/snacks/S in get_turf(toCheck))
++counted
if(counted < 12) // make sure theres not too much food here
RT = toCheck
break
if(RT)
foundCookable = 1
if(!Adjacent(RT))
tryWalk(get_turf(RT))
else
for(var/obj/item/reagent_containers/food/snacks/toPlop in finishedList)
RT.attackby(toPlop,src)
if(!foundCookable)
var/chosenType = pick(rawtypes)
var/obj/item/reagent_containers/food/snacks/newSnack = new chosenType(get_turf(src))
TARGET = newSnack
newSnack.reagents.remove_any((newSnack.reagents.total_volume/2)-1)
newSnack.name = "synthetic [newSnack.name]"
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as [p_they()] vomit[p_s()] [newSnack] from [p_their()] mouth!")
catch(var/exception/e)
log_runtime(e, src, "Caught in SNPC cooking module")
doing &= ~SNPC_SPECIAL
// END COOKING MODULE
/mob/living/carbon/human/interactive/proc/combat(obj)
set background = 1
enforce_hands()
if(canmove)
if((graytide || (TRAITS & TRAIT_MEAN)) || retal)
interest += targetInterestShift
a_intent = INTENT_HARM
zone_sel.selecting = pick("chest","r_leg","l_leg","r_arm","l_arm","head")
doing |= SNPC_FIGHTING
if(retal)
TARGET = retal_target
else
var/mob/living/M = locate(/mob/living) in oview(7, src)
if(!M)
doing = doing & ~SNPC_FIGHTING
else if(M != src && !compareFaction(M.faction))
TARGET = M
//no infighting
if(retal)
if(retal_target)
if(compareFaction(retal_target.faction))
retal = 0
retal_target = null
TARGET = null
doing = 0
//ensure we're using the best object possible
var/obj/item/best
var/foundFav = 0
var/list/allContents = getAllContents()
for(var/test in allContents)
for(var/a in favoured_types)
if(ispath(test,a) && !(doing & SNPC_FIGHTING)) // if we're not in combat and we find our favourite things, use them (for people like janitor and doctors)
best = test
foundFav = 1
return
if(!foundFav)
if(istype(test,/obj/item))
var/obj/item/R = test
if(R.force > 2) // make sure we don't equip any non-weaponlike items, ie bags and stuff
if(!best)
best = R
else
if(best.force < R.force)
best = R
if(istype(R, /obj/item/gun))
var/obj/item/gun/G = R
if(G.can_shoot())
best = R
break // gun with ammo? screw the rest
if(best && best != main_hand)
take_to_slot(best,1)
if(TARGET && (doing & SNPC_FIGHTING)) // this is a redundancy check
var/mob/living/M = TARGET
if(istype(M,/mob/living))
if(M.health > 1 && (M in oview(src, 6)))
//THROWING OBJECTS
for(var/A in allContents)
if(istype(A,/obj/item/gun)) // guns are for shooting, not throwing.
continue
if(prob(robustness))
if(istype(A,/obj/item))
var/obj/item/W = A
if(W.throwforce > 19) // Only throw worthwile stuff, no more lobbing wrenches at wenches
npcDrop(W, 1)
throw_item(TARGET)
if(istype(A,/obj/item/grenade)) // Allahu ackbar! ALLAHU ACKBARR!!
var/obj/item/grenade/G = A
G.attack_self(src)
if(prob(smartness))
npcDrop(G, 1)
sleep(15)
throw_item(TARGET)
if(!main_hand && other_hand)
swap_hands()
if(main_hand)
if(main_hand.force != 0)
if(istype(main_hand,/obj/item/gun))
var/obj/item/gun/G = main_hand
if(G.can_trigger_gun(src))
var/shouldFire = 1
if(istype(main_hand, /obj/item/gun/energy))
var/obj/item/gun/energy/P = main_hand
var/stunning = 0
for(var/A in P.ammo_type)
if(ispath(A,/obj/item/ammo_casing/energy/electrode))
stunning = 1
var/mob/stunCheck = TARGET
if(stunning && stunCheck.stunned)
shouldFire = 0
if(shouldFire)
if(!G.can_shoot())
G.shoot_with_empty_chamber(src)
npcDrop(G, 1)
else
G.process_fire(TARGET, src)
else
if(get_dist(src,TARGET) > 6)
if(!walk2derpless(TARGET))
timeout++
else
var/obj/item/W = main_hand
W.attack(TARGET, src)
else
npcDrop(G, 1)
else
if(targetRange(TARGET) > 2)
tryWalk(TARGET)
else
if(Adjacent(TARGET))
a_intent = pick(INTENT_DISARM, INTENT_HARM)
M.attack_hand(src)
timeout++
else if(timeout >= 10 || !(targetRange(M) > 14))
doing = doing & ~SNPC_FIGHTING
timeout = 0
TARGET = null
retal = 0
retal_target = null
else
timeout++
/mob/living/carbon/human/interactive/proc/past_verb(word)
if(copytext(word, length(word)) == "e")
return "[word]d"
else
return "[word]ed"
/mob/living/carbon/human/interactive/proc/ing_verb(word)
if(copytext(word, length(word)) == "e")
return "[copytext(word, 1, length(word))]ing"
else
return "[word]ing"
/mob/living/carbon/human/interactive/proc/paperwork_sentence()
var/verbs_use = pick_list(speak_file, "verbs_use")
var/verbs_touch = pick_list(speak_file, "verbs_touch")
var/verbs_move = pick_list(speak_file, "verbs_move")
var/nouns_insult = pick_list(speak_file, "nouns_insult")
var/nouns_generic = pick_list(speak_file, "nouns_generic")
var/nouns_objects = pick_list(speak_file, "nouns_objects")
var/nouns_body = pick_list(speak_file, "nouns_body")
var/adjective_insult = pick_list(speak_file, "adjective_insult")
var/adjective_objects = pick_list(speak_file, "adjective_objects")
var/adjective_generic = pick_list(speak_file, "adjective_generic")
var/curse_words = pick_list(speak_file, "curse_words")
var/result = pick("fired", "promoted", "demoted", "terminated", "incinerated", "sent to CentCom", "borged")
return pick(
"The [adjective_insult] [pick(command_positions)] [past_verb(verbs_touch)] the [adjective_objects] [nouns_objects] and was [result].",
"The [adjective_generic] [pick(engineering_positions)] [past_verb(verbs_touch)] the [adjective_insult] [nouns_objects]. [capitalize(curse_words)], the [nouns_insult] was [result].",
"The [adjective_insult] [pick(security_positions)] [past_verb(verbs_touch)] the [adjective_generic] [nouns_insult] [pick(support_positions)]'s [nouns_body] and had to be [result].",
"Medical had to [verbs_use] the [adjective_generic] [pick(command_positions)]'s [adjective_objects] [nouns_body] after the incident.",
"I demand that [nouns_generic] respond with a [adjective_generic] update ASAP.",
"Would like an update from [nouns_generic] regarding the [adjective_insult] [pick(command_positions)] being [result].",
"The [pick(medical_positions)] needs to [verbs_move] faster when the crew's [adjective_objects] [nouns_body]s are injured, or they will be [result].",
"[capitalize(curse_words)] [adjective_insult] [curse_words].",
"<br><br>")
/mob/living/carbon/human/interactive/proc/pickStamp(allContents)
var/list/stamps[0]
for(var/obj/item/stamp/S in allContents)
stamps += S
if(stamps.len)
return pick(stamps)
// just make one, maybe
if(prob(SNPC_FUZZY_CHANCE_LOW / 2))
for(var/p in favoured_types)
if(ispath(p, /obj/item/stamp))
return new p(src)
return null
/mob/living/carbon/human/interactive/proc/paperwork(obj)
set background = 1
if(shouldModulePass() || !prob(SNPC_FUZZY_CHANCE_LOW / 4))
return
var/list/allContents = getAllContents()
var/obj/item/paper/P = locate() in allContents
var/obj/item/stamp/S = pickStamp(allContents)
var/mob/living/carbon/human/H = locate() in nearby
if(!P)
P = new /obj/item/paper(src)
if(P && S && H)
if(!P.stamped || !P.stamped.len)
// generate form
P.name = pick("Inspection Report", "Re: Crew", "Complaint", "To: CentCom")
P.info = {"<center><img src=ntlogo.png><br><b><font size="1">[paperwork_sentence()]</font></b></center>"}
for(var/I in 1 to rand(10, 20))
P.info += "[paperwork_sentence()] "
P.info += {"<br><br>[pick("Signed", "Sincerely", "Regards")], <font face="Times New Roman"><i>[real_name]</i></font>"}
P.update_icon()
P.stamp(S)
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] and throws [P] on the ground!")
npcDrop(P)
P.throw_at(H, P.throw_range, P.throw_speed, src)
/mob/living/carbon/human/interactive/proc/stamping(obj)
if(shouldModulePass())
return
var/list/allContents = getAllContents()
var/list/rangeCheck = view(7, src)
var/obj/item/stamp/S = pickStamp(allContents)
if(!S)
return
// stamp a paper we're holding, and drop it
var/obj/item/paper/P = locate() in allContents
if(P)
if(!P.stamped || !P.stamped.len)
P.stamp(S)
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as they stamp \the [P] with \a [S]!")
npcDrop(P, 1)
return
// stamp a paper in the world
for(var/obj/item/paper/A in rangeCheck)
if(!A.stamped || !A.stamped.len)
if(!Adjacent(A))
tryWalk(A)
else
A.stamp(S)
custom_emote(2, "[pick("gibbers","drools","slobbers","claps wildly","spits")] as they stamp \the [A] with \a [S]!")
return

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