Merge branch 'master' into FERMICHEMCurTweaks

This commit is contained in:
Fermi
2019-11-23 00:10:33 +00:00
3018 changed files with 65365 additions and 157564 deletions
+2 -2
View File
@@ -17,7 +17,7 @@
/datum/ntnet_service/proc/connect(datum/ntnet/net)
if(!istype(net))
return FALSE
GET_COMPONENT(interface, /datum/component/ntnet_interface)
var/datum/component/ntnet_interface/interface = GetComponent(/datum/component/ntnet_interface)
if(!interface.register_connection(net))
return FALSE
if(!net.register_service(src))
@@ -29,7 +29,7 @@
/datum/ntnet_service/proc/disconnect(datum/ntnet/net, force = FALSE)
if(!istype(net) || (!net.unregister_service(src) && !force))
return FALSE
GET_COMPONENT(interface, /datum/component/ntnet_interface)
var/datum/component/ntnet_interface/interface = GetComponent(/datum/component/ntnet_interface)
interface.unregister_connection(net)
networks_by_id -= net.network_id
return TRUE
+15 -1
View File
@@ -682,10 +682,24 @@
log_admin("[key_name(usr)] delayed the round start.")
else
to_chat(world, "<b>The game will start in [DisplayTimeText(newtime)].</b>")
SEND_SOUND(world, sound('sound/ai/attention.ogg'))
SEND_SOUND(world, sound(get_announcer_sound("attention")))
log_admin("[key_name(usr)] set the pre-game delay to [DisplayTimeText(newtime)].")
SSblackbox.record_feedback("tally", "admin_verb", 1, "Delay Game Start") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/toggledynamicvote()
set category = "Server"
set desc="Switches between secret/extended and dynamic voting"
set name="Toggle Dynamic Vote"
var/prev_dynamic_voting = CONFIG_GET(flag/dynamic_voting)
CONFIG_SET(flag/dynamic_voting,!prev_dynamic_voting)
if (!prev_dynamic_voting)
to_chat(world, "<B>Vote is now between extended and dynamic chaos.</B>")
else
to_chat(world, "<B>Vote is now between extended and secret.</B>")
log_admin("[key_name(usr)] [prev_dynamic_voting ? "disabled" : "enabled"] dynamic voting.")
message_admins("<span class='adminnotice'>[key_name_admin(usr)] toggled dynamic voting.</span>")
SSblackbox.record_feedback("nested tally", "admin_toggle", 1, list("Toggle Dynamic Voting", "[prev_dynamic_voting ? "Disabled" : "Enabled"]")) //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/datum/admins/proc/unprison(mob/M in GLOB.mob_list)
set category = "Admin"
set name = "Unprison"
+13 -12
View File
@@ -1,7 +1,7 @@
//admin verb groups - They can overlap if you so wish. Only one of each verb will exist in the verbs list regardless
//the procs are cause you can't put the comments in the GLOB var define
GLOBAL_PROTECT(admin_verbs_default)
GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
GLOBAL_PROTECT(admin_verbs_default)
/world/proc/AVerbsDefault()
return list(
/client/proc/deadmin, /*destroys our own admin datum so we can play as a regular player*/
@@ -13,8 +13,8 @@ GLOBAL_LIST_INIT(admin_verbs_default, world.AVerbsDefault())
/client/proc/toggleprayers,
/client/proc/toggleadminhelpsound
)
GLOBAL_PROTECT(admin_verbs_admin)
GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
GLOBAL_PROTECT(admin_verbs_admin)
/world/proc/AVerbsAdmin()
return list(
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
@@ -78,11 +78,10 @@ GLOBAL_LIST_INIT(admin_verbs_admin, world.AVerbsAdmin())
/client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/
/datum/admins/proc/open_borgopanel
)
GLOBAL_PROTECT(admin_verbs_ban)
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/DB_ban_panel, /client/proc/stickybanpanel))
GLOBAL_PROTECT(admin_verbs_sounds)
GLOBAL_PROTECT(admin_verbs_ban)
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/set_round_end_sound))
GLOBAL_PROTECT(admin_verbs_fun)
GLOBAL_PROTECT(admin_verbs_sounds)
GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/cmd_admin_dress,
/client/proc/cmd_admin_gib_self,
@@ -108,9 +107,9 @@ GLOBAL_LIST_INIT(admin_verbs_fun, list(
/client/proc/admin_away,
/client/proc/roll_dices //CIT CHANGE - Adds dice verb
))
GLOBAL_PROTECT(admin_verbs_spawn)
GLOBAL_PROTECT(admin_verbs_fun)
GLOBAL_LIST_INIT(admin_verbs_spawn, list(/datum/admins/proc/spawn_atom, /datum/admins/proc/spawn_cargo, /datum/admins/proc/spawn_objasmob, /client/proc/respawn_character))
GLOBAL_PROTECT(admin_verbs_server)
GLOBAL_PROTECT(admin_verbs_spawn)
GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/world/proc/AVerbsServer()
return list(
@@ -122,6 +121,7 @@ GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/client/proc/everyone_random,
/datum/admins/proc/toggleAI,
/datum/admins/proc/toggleMulticam,
/datum/admins/proc/toggledynamicvote,
/client/proc/cmd_admin_delete, /*delete an instance/object/mob/etc*/
/client/proc/cmd_debug_del_all,
/client/proc/toggle_random_events,
@@ -129,7 +129,7 @@ GLOBAL_LIST_INIT(admin_verbs_server, world.AVerbsServer())
/client/proc/adminchangemap,
/client/proc/toggle_hub
)
GLOBAL_PROTECT(admin_verbs_debug)
GLOBAL_PROTECT(admin_verbs_server)
GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
/world/proc/AVerbsDebug()
return list(
@@ -171,15 +171,15 @@ GLOBAL_LIST_INIT(admin_verbs_debug, world.AVerbsDebug())
/datum/admins/proc/create_or_modify_area,
/client/proc/generate_wikichem_list //DO NOT PRESS UNLESS YOU WANT SUPERLAG
)
GLOBAL_PROTECT(admin_verbs_possess)
GLOBAL_PROTECT(admin_verbs_debug)
GLOBAL_LIST_INIT(admin_verbs_possess, list(/proc/possess, /proc/release))
GLOBAL_PROTECT(admin_verbs_permissions)
GLOBAL_PROTECT(admin_verbs_possess)
GLOBAL_LIST_INIT(admin_verbs_permissions, list(/client/proc/edit_admin_permissions))
GLOBAL_PROTECT(admin_verbs_poll)
GLOBAL_PROTECT(admin_verbs_permissions)
GLOBAL_LIST_INIT(admin_verbs_poll, list(/client/proc/create_poll))
//verbs which can be hidden - needs work
GLOBAL_PROTECT(admin_verbs_hideable)
GLOBAL_PROTECT(admin_verbs_poll)
GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/set_ooc,
/client/proc/reset_ooc,
@@ -247,6 +247,7 @@ GLOBAL_LIST_INIT(admin_verbs_hideable, list(
/client/proc/cmd_admin_man_up, //CIT CHANGE - adds man up verb
/client/proc/cmd_admin_man_up_global //CIT CHANGE - ditto
))
GLOBAL_PROTECT(admin_verbs_hideable)
/client/proc/add_admin_verbs()
if(holder)
+3
View File
@@ -25,6 +25,9 @@
H.facial_hair_color = H.hair_color
H.eye_color = random_eye_color()
H.dna.blood_type = random_blood_type()
H.saved_underwear = H.underwear
H.saved_undershirt = H.undershirt
H.saved_socks = H.socks
// Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant.
H.dna.features["mcolor"] = random_short_color()
+2 -2
View File
@@ -400,7 +400,7 @@
SSblackbox.record_feedback("nested tally", "admin_secrets_fun_used", 1, list("Chinese Cartoons"))
message_admins("[key_name_admin(usr)] made everything kawaii.")
for(var/mob/living/carbon/human/H in GLOB.carbon_list)
SEND_SOUND(H, sound('sound/ai/animes.ogg'))
SEND_SOUND(H, sound(get_announcer_sound("animes")))
if(H.dna.species.id == "human")
if(H.dna.features["tail_human"] == "None" || H.dna.features["ears"] == "None")
@@ -469,7 +469,7 @@
if(is_station_level(W.z) && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison))
W.req_access = list()
message_admins("[key_name_admin(usr)] activated Egalitarian Station mode")
priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, 'sound/ai/commandreport.ogg')
priority_announce("CentCom airlock control override activated. Please take this time to get acquainted with your coworkers.", null, "commandreport")
if("ak47s")
if(!check_rights(R_FUN))
+2 -2
View File
@@ -504,7 +504,7 @@
output += ruler
var/datum/browser/browser = new(usr, "Note panel", "Manage player notes", 1000, 500)
var/datum/asset/notes_assets = get_asset_datum(/datum/asset/simple/notes)
notes_assets.send(src)
notes_assets.send(usr.client)
browser.set_content(jointext(output, ""))
browser.open()
@@ -556,7 +556,7 @@
/proc/convert_notes_sql(ckey)
if(!fexists(NOTESFILE))
return
var/savefile/notesfile = new(NOTESFILE)
if(!notesfile)
log_game("Error: Cannot access [NOTESFILE]")
+9 -11
View File
@@ -1347,7 +1347,7 @@
else if(href_list["f_secret"])
return HandleFSecret()
else if(href_list["f_dynamic_roundstart"])
if(!check_rights(R_ADMIN))
return
@@ -1449,9 +1449,7 @@
if(GLOB.master_mode != "dynamic")
return alert(usr, "The game mode has to be dynamic mode!", null, null, null, null)
var/new_centre = input(usr,"Change the centre of the dynamic mode threat curve. A negative value will give a more peaceful round ; a positive value, a round with higher threat. Any number between -5 and +5 is allowed.", "Change curve centre", null) as num
if (new_centre < -5 || new_centre > 5)
return alert(usr, "Only values between -5 and +5 are allowed.", null, null, null, null)
var/new_centre = input(usr,"Change the centre of the dynamic mode threat curve. A negative value will give a more peaceful round ; a positive value, a round with higher threat. Any number is allowed. This is adjusted by dynamic voting.", "Change curve centre", null) as num
log_admin("[key_name(usr)] changed the distribution curve center to [new_centre].")
message_admins("[key_name(usr)] changed the distribution curve center to [new_centre]", 1)
@@ -1593,7 +1591,7 @@
GLOB.dynamic_stacking_limit = input(usr,"Change the threat limit at which round-endings rulesets will start to stack.", "Change stacking limit", null) as num
log_admin("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
message_admins("[key_name(usr)] set 'stacking_limit' to [GLOB.dynamic_stacking_limit].")
dynamic_mode_options(usr)
dynamic_mode_options(usr)
else if(href_list["f_dynamic_high_pop_limit"])
if(!check_rights(R_ADMIN))
@@ -1612,7 +1610,7 @@
log_admin("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
message_admins("[key_name(usr)] set 'high_pop_limit' to [GLOB.dynamic_high_pop_limit].")
dynamic_mode_options(usr)
dynamic_mode_options(usr)
else if(href_list["f_dynamic_forced_threat"])
if(!check_rights(R_ADMIN))
@@ -1631,7 +1629,7 @@
log_admin("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
message_admins("[key_name(usr)] set 'forced_threat_level' to [GLOB.dynamic_forced_threat_level].")
dynamic_mode_options(usr)
dynamic_mode_options(usr)
else if(href_list["c_mode2"])
if(!check_rights(R_ADMIN|R_SERVER))
@@ -2442,7 +2440,7 @@
return
src.admincaster_feed_channel.channel_name = stripped_input(usr, "Provide a Feed Channel Name.", "Network Channel Handler", "")
while (findtext(src.admincaster_feed_channel.channel_name," ") == 1)
src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,lentext(src.admincaster_feed_channel.channel_name)+1)
src.admincaster_feed_channel.channel_name = copytext(src.admincaster_feed_channel.channel_name,2,length(src.admincaster_feed_channel.channel_name)+1)
src.access_news_network()
else if(href_list["ac_set_channel_lock"])
@@ -2484,7 +2482,7 @@
return
src.admincaster_feed_message.body = adminscrub(input(usr, "Write your Feed story.", "Network Channel Handler", ""))
while (findtext(src.admincaster_feed_message.returnBody(-1)," ") == 1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,lentext(src.admincaster_feed_message.returnBody(-1))+1)
src.admincaster_feed_message.body = copytext(src.admincaster_feed_message.returnBody(-1),2,length(src.admincaster_feed_message.returnBody(-1))+1)
src.access_news_network()
else if(href_list["ac_submit_new_message"])
@@ -2545,7 +2543,7 @@
return
src.admincaster_wanted_message.criminal = adminscrub(input(usr, "Provide the name of the Wanted person.", "Network Security Handler", ""))
while(findtext(src.admincaster_wanted_message.criminal," ") == 1)
src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,lentext(admincaster_wanted_message.criminal)+1)
src.admincaster_wanted_message.criminal = copytext(admincaster_wanted_message.criminal,2,length(admincaster_wanted_message.criminal)+1)
src.access_news_network()
else if(href_list["ac_set_wanted_desc"])
@@ -2553,7 +2551,7 @@
return
src.admincaster_wanted_message.body = adminscrub(input(usr, "Provide the a description of the Wanted person and any other details you deem important.", "Network Security Handler", ""))
while (findtext(src.admincaster_wanted_message.body," ") == 1)
src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,lentext(src.admincaster_wanted_message.body)+1)
src.admincaster_wanted_message.body = copytext(src.admincaster_wanted_message.body,2,length(src.admincaster_wanted_message.body)+1)
src.access_news_network()
else if(href_list["ac_submit_wanted"])
+4 -3
View File
@@ -318,6 +318,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
RemoveActive()
state = AHELP_CLOSED
GLOB.ahelp_tickets.ListInsert(src)
to_chat(initiator, "<span class='adminhelp'>Ticket closed by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"].</span>")
AddInteraction("<font color='red'>Closed by [key_name].</font>")
if(!silent)
SSblackbox.record_feedback("tally", "ahelp_stats", 1, "closed")
@@ -336,7 +337,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
addtimer(CALLBACK(initiator, /client/proc/giveadminhelpverb), 50)
AddInteraction("<font color='green'>Resolved by [key_name].</font>")
to_chat(initiator, "<span class='adminhelp'>Your ticket has been resolved by an admin. The Adminhelp verb will be returned to you shortly.</span>")
to_chat(initiator, "<span class='adminhelp'>Your ticket has been resolved by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]. The Adminhelp verb will be returned to you shortly.</span>")
if(!silent)
SSblackbox.record_feedback("tally", "ahelp_stats", 1, "resolved")
var/msg = "Ticket [TicketHref("#[id]")] resolved by [key_name]"
@@ -353,7 +354,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
SEND_SOUND(initiator, sound('sound/effects/adminhelp.ogg'))
to_chat(initiator, "<font color='red' size='4'><b>- AdminHelp Rejected! -</b></font>")
to_chat(initiator, "<font color='red' size='4'><b>- AdminHelp Rejected by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]! -</b></font>")
to_chat(initiator, "<font color='red'><b>Your admin help was rejected.</b> The adminhelp verb has been returned to you so that you may try again.</font>")
to_chat(initiator, "Please try to be calm, clear, and descriptive in admin helps, do not assume the admin has seen any related events, and clearly state the names of anybody you are reporting.")
@@ -369,7 +370,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(state != AHELP_ACTIVE)
return
var/msg = "<font color='red' size='4'><b>- AdminHelp marked as IC issue! -</b></font><br>"
var/msg = "<font color='red' size='4'><b>- AdminHelp marked as IC issue by [usr?.client?.holder?.fakekey? usr.client.holder.fakekey : "an administrator"]! -</b></font><br>"
msg += "<font color='red'><b>Losing is part of the game!</b></font><br>"
msg += "<font color='red'>It is also possible that your ahelp is unable to be answered properly, due to events occurring in the round.</font>"
if(initiator)
+1 -1
View File
@@ -61,7 +61,7 @@
var/output = "<b>Radio Report</b><hr>"
for (var/fq in SSradio.frequencies)
output += "<b>Freq: [fq]</b><br>"
var/list/datum/radio_frequency/fqs = SSradio.frequencies[fq]
var/datum/radio_frequency/fqs = SSradio.frequencies[fq]
if (!fqs)
output += "&nbsp;&nbsp;<b>ERROR</b><br>"
continue
+1 -1
View File
@@ -19,7 +19,6 @@
//- Identify how hard it is to break into the area and where the weak points are
//- Check if the area has too much empty space. If so, make it smaller and replace the rest with maintenance tunnels.
GLOBAL_PROTECT(admin_verbs_debug_mapping)
GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/camera_view, //-errorage
/client/proc/sec_camera_report, //-errorage
@@ -50,6 +49,7 @@ GLOBAL_LIST_INIT(admin_verbs_debug_mapping, list(
/client/proc/debug_z_levels,
/client/proc/place_ruin
))
GLOBAL_PROTECT(admin_verbs_debug_mapping)
/obj/effect/debugging/mapfix_marker
name = "map fix marker"
+6 -6
View File
@@ -307,11 +307,11 @@ GLOBAL_PROTECT(VVpixelmovement)
// the type with the base type removed from the begaining
var/fancytype = types[D.type]
if (findtext(fancytype, types[type]))
fancytype = copytext(fancytype, lentext(types[type])+1)
var/shorttype = copytext("[D.type]", lentext("[type]")+1)
if (lentext(shorttype) > lentext(fancytype))
fancytype = copytext(fancytype, length(types[type])+1)
var/shorttype = copytext("[D.type]", length("[type]")+1)
if (length(shorttype) > length(fancytype))
shorttype = fancytype
if (!lentext(shorttype))
if (!length(shorttype))
shorttype = "/"
.["[D]([shorttype])[REF(D)]#[i]"] = D
@@ -534,7 +534,7 @@ GLOBAL_PROTECT(VVpixelmovement)
if (prompt != "Continue")
return FALSE
return TRUE
/client/proc/modify_variables(atom/O, param_var_name = null, autodetect_class = 0)
if(!check_rights(R_VAREDIT))
@@ -545,7 +545,7 @@ GLOBAL_PROTECT(VVpixelmovement)
var/var_value
if(param_var_name)
if(!param_var_name in O.vars)
if(!(param_var_name in O.vars))
to_chat(src, "A variable with this name ([param_var_name]) doesn't exist in this datum ([O])")
return
variable = param_var_name
+2 -2
View File
@@ -560,7 +560,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
var/announce_command_report = TRUE
switch(confirm)
if("Yes")
priority_announce(input, null, 'sound/ai/commandreport.ogg')
priority_announce(input, null, "commandreport")
announce_command_report = FALSE
if("Cancel")
return
@@ -949,7 +949,7 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits
<tr>
<th>Uniform:</th>
<td>
[uniform_select]
[uniform_select]
</td>
</tr>
<tr>
+4 -4
View File
@@ -16,10 +16,10 @@
var/obj/chosen_obj = text2path(chosen)
var/list/settings = list(
"mainsettings" = list(
"name" = list("desc" = "Name", "type" = "string", "value" = "Bob"),
"mainsettings" = list(
"name" = list("desc" = "Name", "type" = "string", "value" = "Bob"),
"maxhealth" = list("desc" = "Max. health", "type" = "number", "value" = 100),
"access" = list("desc" = "Access ID", "type" = "datum", "path" = "/obj/item/card/id", "value" = "Default"),
"access" = list("desc" = "Access ID", "type" = "datum", "path" = "/obj/item/card/id", "value" = "Default"),
"objtype" = list("desc" = "Base obj type", "type" = "datum", "path" = "/obj", "value" = "[chosen]"),
"googlyeyes" = list("desc" = "Googly eyes", "type" = "boolean", "value" = "No"),
"disableai" = list("desc" = "Disable AI", "type" = "boolean", "value" = "Yes"),
@@ -27,7 +27,7 @@
"dropitem" = list("desc" = "Drop obj on death", "type" = "boolean", "value" = "Yes"),
"mobtype" = list("desc" = "Base mob type", "type" = "datum", "path" = "/mob/living/simple_animal/hostile/mimic/copy", "value" = "/mob/living/simple_animal/hostile/mimic/copy"),
"ckey" = list("desc" = "ckey", "type" = "ckey", "value" = "none"),
)
)
)
var/list/prefreturn = presentpreflikepicker(usr,"Customize mob", "Customize mob", Button1="Ok", width = 450, StealFocus = 1,Timeout = 0, settings=settings)
@@ -96,7 +96,6 @@ GLOBAL_LIST_EMPTY(antagonists)
LAZYREMOVE(owner.antag_datums, src)
if(!silent && owner.current)
farewell()
owner.objectives -= objectives
var/datum/team/team = get_team()
if(team)
team.remove_member(owner)
@@ -132,14 +131,14 @@ GLOBAL_LIST_EMPTY(antagonists)
report += printplayer(owner)
var/objectives_complete = TRUE
if(owner.objectives.len)
report += printobjectives(owner)
for(var/datum/objective/objective in owner.objectives)
if(objectives.len)
report += printobjectives(objectives)
for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
if(owner.objectives.len == 0 || objectives_complete)
if(objectives.len == 0 || objectives_complete)
report += "<span class='greentext big'>The [name] was successful!</span>"
else
report += "<span class='redtext big'>The [name] has failed!</span>"
@@ -216,25 +215,6 @@ GLOBAL_LIST_EMPTY(antagonists)
return
antag_memory = new_memo
//This datum will autofill the name with special_role
//Used as placeholder for minor antagonists, please create proper datums for these
/datum/antagonist/auto_custom
show_in_antagpanel = FALSE
antagpanel_category = "Other"
show_name_in_check_antagonists = TRUE
/datum/antagonist/auto_custom/on_gain()
..()
name = owner.special_role
//Add all objectives not already owned by other datums to this one.
var/list/already_registered_objectives = list()
for(var/datum/antagonist/A in owner.antag_datums)
if(A == src)
continue
else
already_registered_objectives |= A.objectives
objectives = owner.objectives - already_registered_objectives
//This one is created by admin tools for custom objectives
/datum/antagonist/custom
antagpanel_category = "Custom"
@@ -182,6 +182,10 @@
name = "syndicate medical teleporter"
borg_to_spawn = "Medical"
/obj/item/antag_spawner/nuke_ops/borg_tele/saboteur
name = "syndicate saboteur teleporter"
borg_to_spawn = "Saboteur"
/obj/item/antag_spawner/nuke_ops/borg_tele/spawn_antag(client/C, turf/T, kind, datum/mind/user)
var/mob/living/silicon/robot/R
var/datum/antagonist/nukeop/creator_op = user.has_antag_datum(/datum/antagonist/nukeop,TRUE)
@@ -191,6 +195,8 @@
switch(borg_to_spawn)
if("Medical")
R = new /mob/living/silicon/robot/modules/syndicate/medical(T)
if("Saboteur")
R = new /mob/living/silicon/robot/modules/syndicate/saboteur(T)
else
R = new /mob/living/silicon/robot/modules/syndicate(T) //Assault borg by default
+20 -15
View File
@@ -26,7 +26,7 @@
sub_role = "Scientist"
outfit = /datum/outfit/abductor/scientist
landmark_type = /obj/effect/landmark/abductor/scientist
greet_text = "Use your stealth technology and equipment to incapacitate humans for your scientist to retrieve."
greet_text = "Use your experimental console and surgical equipment to monitor your agent and experiment upon abducted humans."
show_in_antagpanel = TRUE
/datum/antagonist/abductor/create_team(datum/team/abductor_team/new_team)
@@ -40,17 +40,18 @@
return team
/datum/antagonist/abductor/on_gain()
owner.special_role = "[name] [sub_role]"
owner.assigned_role = "[name] [sub_role]"
owner.objectives += team.objectives
owner.special_role = "[name]"
owner.assigned_role = "[name]"
objectives += team.objectives
finalize_abductor()
ADD_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
return ..()
/datum/antagonist/abductor/on_removal()
owner.objectives -= team.objectives
if(owner.current)
to_chat(owner.current,"<span class='userdanger'>You are no longer the [owner.special_role]!</span>")
owner.special_role = null
REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_TRAINING, ABDUCTOR_ANTAGONIST)
return ..()
/datum/antagonist/abductor/greet()
@@ -64,6 +65,7 @@
//Equip
var/mob/living/carbon/human/H = owner.current
H.set_species(/datum/species/abductor)
H.real_name = "[team.name] [sub_role]"
H.equipOutfit(outfit)
@@ -75,11 +77,15 @@
update_abductor_icons_added(owner,"abductor")
/datum/antagonist/abductor/scientist/finalize_abductor()
..()
var/mob/living/carbon/human/H = owner.current
var/datum/species/abductor/A = H.dna.species
A.scientist = TRUE
/datum/antagonist/abductor/scientist/on_gain()
ADD_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
ADD_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
. = ..()
/datum/antagonist/abductor/scientist/on_removal()
REMOVE_TRAIT(owner, TRAIT_ABDUCTOR_SCIENTIST_TRAINING, ABDUCTOR_ANTAGONIST)
REMOVE_TRAIT(owner, TRAIT_SURGEON, ABDUCTOR_ANTAGONIST)
. = ..()
/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
var/list/current_teams = list()
@@ -93,8 +99,8 @@
else
return
new_owner.add_antag_datum(src)
log_admin("[key_name(usr)] made [key_name(new_owner.current)] [name] on [choice]!")
message_admins("[key_name_admin(usr)] made [key_name_admin(new_owner.current)] [name] on [choice] !")
log_admin("[key_name(usr)] made [key_name(new_owner)] [name] on [choice]!")
message_admins("[key_name_admin(usr)] made [key_name_admin(new_owner)] [name] on [choice] !")
/datum/antagonist/abductor/get_admin_commands()
. = ..()
@@ -147,7 +153,7 @@
result += "<span class='header'>The abductors of [name] were:</span>"
for(var/datum/mind/abductor_mind in members)
result += printplayer(abductor_mind)
result += printobjectives(abductor_mind)
result += printobjectives(objectives)
return "<div class='panel redborder'>[result.Join("<br>")]</div>"
@@ -172,7 +178,6 @@
var/objtype = (prob(75) ? /datum/objective/abductee/random : pick(subtypesof(/datum/objective/abductee/) - /datum/objective/abductee/random))
var/datum/objective/abductee/O = new objtype()
objectives += O
owner.objectives += objectives
/datum/antagonist/abductee/apply_innate_effects(mob/living/mob_override)
update_abductor_icons_added(mob_override ? mob_override.mind : owner,"abductee")
@@ -214,4 +219,4 @@
/datum/antagonist/proc/update_abductor_icons_removed(datum/mind/alien_mind)
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_ABDUCTOR]
hud.leave_hud(alien_mind.current)
set_antag_hud(alien_mind.current, null)
set_antag_hud(alien_mind.current, null)
@@ -55,7 +55,7 @@
var/datum/action/A = X
A.UpdateButtonIcon()
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user)
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_WEAR_SUIT) //we only give the mob the ability to activate the vest if he's actually wearing it.
return 1
@@ -132,22 +132,26 @@
/obj/item/abductor
icon = 'icons/obj/abductor.dmi'
/obj/item/abductor/proc/AbductorCheck(user)
if(isabductor(user))
/obj/item/abductor/proc/AbductorCheck(mob/user)
if(HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING))
return TRUE
if (istype(user) && user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
return TRUE
to_chat(user, "<span class='warning'>You can't figure how this works!</span>")
return FALSE
/obj/item/abductor/proc/ScientistCheck(user)
if(!AbductorCheck(user))
return FALSE
/obj/item/abductor/proc/ScientistCheck(mob/user)
var/training = HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
var/sci_training = HAS_TRAIT(user, TRAIT_ABDUCTOR_SCIENTIST_TRAINING) || (user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING))
var/mob/living/carbon/human/H = user
var/datum/species/abductor/S = H.dna.species
if(S.scientist)
return TRUE
to_chat(user, "<span class='warning'>You're not trained to use this!</span>")
return FALSE
if(training && !sci_training)
to_chat(user, "<span class='warning'>You're not trained to use this!</span>")
. = FALSE
else if(!training && !sci_training)
to_chat(user, "<span class='warning'>You can't figure how this works!</span>")
. = FALSE
else
. = TRUE
/obj/item/abductor/gizmo
name = "science tool"
@@ -341,8 +345,8 @@
if(QDELETED(G))
return
if(istype(C.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>Your target seems to have some sort of protective headgear on, blocking the message from being sent!</span>")
if(C.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>Your target seems to have some sort of tinfoil protection on, blocking the message from being sent!</span>")
return
G.mind_control(command, user)
@@ -389,23 +393,22 @@
name = "Dissection Guide"
icon_state = "alienpaper_words"
info = {"<b>Dissection for Dummies</b><br>
<br>
1.Acquire fresh specimen.<br>
2.Put the specimen on operating table.<br>
3.Apply surgical drapes, preparing for experimental dissection.<br>
4.Apply scalpel to specimen's torso.<br>
5.Clamp bleeders on specimen's torso with a hemostat.<br>
6.Retract skin of specimen's torso with a retractor.<br>
7.Apply scalpel again to specimen's torso.<br>
8.Search through the specimen's torso with your hands to remove any superfluous organs.<br>
9.Insert replacement gland (Retrieve one from gland storage).<br>
10.Consider dressing the specimen back to not disturb the habitat. <br>
11.Put the specimen in the experiment machinery.<br>
12.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.<br>
13.You will receive one supply credit, and the subject will be counted towards your quota.<br>
<br>
Congratulations! You are now trained for invasive xenobiology research!"}
<br>
1.Acquire fresh specimen.<br>
2.Put the specimen on operating table.<br>
3.Apply surgical drapes, preparing for experimental dissection.<br>
4.Apply scalpel to specimen's torso.<br>
5.Clamp bleeders on specimen's torso with a hemostat.<br>
6.Retract skin of specimen's torso with a retractor.<br>
7.Apply scalpel again to specimen's torso.<br>
8.Search through the specimen's torso with your hands to remove any superfluous organs.<br>
9.Insert replacement gland (Retrieve one from gland storage).<br>
10.Consider dressing the specimen back to not disturb the habitat. <br>
11.Put the specimen in the experiment machinery.<br>
12.Choose one of the machine options. The target will be analyzed and teleported to the selected drop-off point.<br>
13.You will receive one supply credit, and the subject will be counted towards your quota.<br>
<br>
Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/paper/guides/antag/abductor/update_icon()
return
@@ -520,10 +523,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
/obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.incapacitated(TRUE, TRUE))
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>The specimen's protective headgear is interfering with the sleep inducement!</span>")
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] headgear protected [L.p_them()]!</span>", \
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your headgear deflects most of it!</span>")
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is interfering with the sleep inducement!</span>")
L.visible_message("<span class='danger'>[user] tried to induced sleep in [L] with [src], but [L.p_their()] tinfoil protected [L.p_them()]!</span>", \
"<span class='userdanger'>You feel a strange wave of heavy drowsiness wash over you, but your tinfoil protection deflects most of it!</span>")
L.drowsyness += 2
return
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
@@ -532,10 +535,10 @@ Congratulations! You are now trained for invasive xenobiology research!"}
L.Sleeping(1200)
log_combat(user, L, "put to sleep")
else
if(istype(L.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
to_chat(user, "<span class='warning'>The specimen's protective headgear is completely blocking our sleep inducement methods!</span>")
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] headgear completely protected [L.p_them()]!</span>", \
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your headgear deflects the effects!</span>")
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is completely blocking our sleep inducement methods!</span>")
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src], but [L.p_their()] tinfoil completely protected [L.p_them()]!</span>", \
"<span class='userdanger'>Any sense of drowsiness is quickly diminished as your tinfoil protection deflects the effects!</span>")
return
L.drowsyness += 1
to_chat(user, "<span class='warning'>Sleep inducement works fully only on stunned specimens! </span>")
@@ -683,7 +686,7 @@ Congratulations! You are now trained for invasive xenobiology research!"}
desc = "Abduct with style - spiky style. Prevents digital tracking."
icon_state = "alienhelmet"
item_state = "alienhelmet"
blockTracking = 1
blockTracking = TRUE
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
// Operating Table / Beds / Lockers
@@ -5,6 +5,7 @@
icon_state = "gland"
status = ORGAN_ROBOTIC
beating = TRUE
var/true_name = "baseline placebo referencer"
var/cooldown_low = 300
var/cooldown_high = 300
var/next_activation = 0
@@ -16,6 +17,11 @@
var/mind_control_duration = 1800
var/active_mind_control = FALSE
/obj/item/organ/heart/gland/examine(mob/user)
. = ..()
if((user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)) || isobserver(user))
to_chat(user, "<span class='notice'>It is \a [true_name].</span>")
/obj/item/organ/heart/gland/proc/ownerCheck()
if(ishuman(owner))
return TRUE
@@ -42,19 +48,19 @@
/obj/item/organ/heart/gland/proc/mind_control(command, mob/living/user)
if(!ownerCheck() || !mind_control_uses || active_mind_control)
return
return FALSE
mind_control_uses--
to_chat(owner, "<span class='userdanger'>You suddenly feel an irresistible compulsion to follow an order...</span>")
to_chat(owner, "<span class='mind_control'>[command]</span>")
active_mind_control = TRUE
log_admin("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
message_admins("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
update_gland_hud()
addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration)
/obj/item/organ/heart/gland/proc/clear_mind_control()
if(!ownerCheck() || !active_mind_control)
return
return FALSE
to_chat(owner, "<span class='userdanger'>You feel the compulsion fade, and you completely forget about your previous orders.</span>")
active_mind_control = FALSE
@@ -67,7 +73,7 @@
clear_mind_control()
..()
/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
if(special != 2 && uses) // Special 2 means abductor surgery
Start()
@@ -95,6 +101,7 @@
return
/obj/item/organ/heart/gland/heals
true_name = "coherency harmonizer"
cooldown_low = 200
cooldown_high = 400
uses = -1
@@ -109,6 +116,7 @@
owner.adjustOxyLoss(-20)
/obj/item/organ/heart/gland/slime
true_name = "gastric animation galvanizer"
cooldown_low = 600
cooldown_high = 1200
uses = -1
@@ -116,7 +124,7 @@
mind_control_uses = 1
mind_control_duration = 2400
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
owner.faction |= "slime"
owner.grant_language(/datum/language/slime)
@@ -130,6 +138,7 @@
Slime.Leader = owner
/obj/item/organ/heart/gland/mindshock
true_name = "neural crosstalk uninhibitor"
cooldown_low = 400
cooldown_high = 700
uses = -1
@@ -156,6 +165,7 @@
H.hallucination += 60
/obj/item/organ/heart/gland/pop
true_name = "anthropmorphic translocator"
cooldown_low = 900
cooldown_high = 1800
uses = -1
@@ -171,6 +181,7 @@
owner.set_species(species)
/obj/item/organ/heart/gland/ventcrawling
true_name = "pliant cartilage enabler"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
@@ -183,6 +194,7 @@
owner.ventcrawler = VENTCRAWLER_ALWAYS
/obj/item/organ/heart/gland/viral
true_name = "contamination incubator"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
@@ -217,6 +229,7 @@
return A
/obj/item/organ/heart/gland/trauma
true_name = "white matter randomiser"
cooldown_low = 800
cooldown_high = 1200
uses = 5
@@ -235,6 +248,7 @@
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
/obj/item/organ/heart/gland/spiderman
true_name = "araneae cloister accelerator"
cooldown_low = 450
cooldown_high = 900
uses = -1
@@ -249,6 +263,7 @@
S.directive = "Protect your nest inside [owner.real_name]."
/obj/item/organ/heart/gland/egg
true_name = "roe/enzymatic synthesizer"
cooldown_low = 300
cooldown_high = 400
uses = -1
@@ -264,13 +279,14 @@
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
/obj/item/organ/heart/gland/electric
true_name = "electron accumulator/discharger"
cooldown_low = 800
cooldown_high = 1200
uses = -1
mind_control_uses = 2
mind_control_duration = 900
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
@@ -289,6 +305,7 @@
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1)
/obj/item/organ/heart/gland/chem
true_name = "intrinsic pharma-provider"
cooldown_low = 50
cooldown_high = 50
uses = -1
@@ -315,6 +332,7 @@
..()
/obj/item/organ/heart/gland/plasma
true_name = "effluvium sanguine-synonym emitter"
cooldown_low = 1200
cooldown_high = 1800
uses = -1
@@ -17,9 +17,9 @@
/obj/machinery/computer/camera_advanced/abductor/CreateEye()
..()
eyeobj.visible_icon = 1
eyeobj.icon = 'icons/obj/abductor.dmi'
eyeobj.icon_state = "camera_target"
eyeobj.visible_icon = TRUE
eyeobj.icon = 'icons/mob/cameramob.dmi'
eyeobj.icon_state = "generic_camera"
/obj/machinery/computer/camera_advanced/abductor/GrantActions(mob/living/carbon/user)
..()
@@ -55,8 +55,7 @@
actions += set_droppoint_action
/obj/machinery/computer/camera_advanced/abductor/proc/IsScientist(mob/living/carbon/human/H)
var/datum/species/abductor/S = H.dna.species
return S.scientist
return HAS_TRAIT(H, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)
/datum/action/innate/teleport_in
name = "Send To"
@@ -28,7 +28,7 @@
. = ..()
if(.)
return
if(!isabductor(user))
if(!HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING) && !HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
to_chat(user, "<span class='warning'>You start mashing alien buttons at random!</span>")
if(do_after(user,100, target = src))
TeleporterSend()
@@ -178,8 +178,8 @@
c.console = src
/obj/machinery/abductor/console/proc/AddSnapshot(mob/living/carbon/human/target)
if(istype(target.get_item_by_slot(SLOT_HEAD), /obj/item/clothing/head/foilhat))
say("Subject wearing specialized protective headgear, unable to get a proper scan!")
if(target.anti_magic_check(FALSE, FALSE, TRUE, 0))
say("Subject wearing specialized protective tinfoil gear, unable to get a proper scan!")
return
var/datum/icon_snapshot/entry = new
entry.name = target.name
@@ -53,4 +53,4 @@
. = ..()
var/datum/effect_system/spark_spread/S = new
S.set_up(10,0,loc)
S.start()
S.start()
-1
View File
@@ -30,7 +30,6 @@
var/datum/objective/blob_takeover/main = new
main.owner = owner
objectives += main
owner.objectives |= objectives
/datum/antagonist/blob/apply_innate_effects(mob/living/mob_override)
if(!isovermind(owner.current))
@@ -27,7 +27,7 @@
. = ..()
/obj/structure/blob/core/proc/generate_announcement()
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/outbreak5.ogg')
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", "outbreak5")
/obj/structure/blob/core/scannerreport()
return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts."
@@ -9,7 +9,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
name = "Blob Overmind"
real_name = "Blob Overmind"
desc = "The overmind. It controls the blob."
icon = 'icons/mob/blob.dmi'
icon = 'icons/mob/cameramob.dmi'
icon_state = "marker"
mouse_opacity = MOUSE_OPACITY_ICON
move_on_shuttle = 1
@@ -0,0 +1,33 @@
/datum/antagonist/blood_contract
name = "Blood Contract Target"
show_in_roundend = FALSE
show_in_antagpanel = FALSE
/datum/antagonist/blood_contract/on_gain()
. = ..()
give_objective()
start_the_hunt()
/datum/antagonist/blood_contract/proc/give_objective()
var/datum/objective/survive/survive = new
survive.owner = owner
objectives += survive
/datum/antagonist/blood_contract/greet()
. = ..()
to_chat(owner, "<span class='userdanger'>You've been marked for death! Don't let the demons get you! KILL THEM ALL!</span>")
/datum/antagonist/blood_contract/proc/start_the_hunt()
var/mob/living/carbon/human/H = owner.current
if(!istype(H))
return
H.add_atom_colour("#FF0000", ADMIN_COLOUR_PRIORITY)
var/obj/effect/mine/pickup/bloodbath/B = new(H)
INVOKE_ASYNC(B, /obj/effect/mine/pickup/bloodbath/.proc/mineEffect, H) //could use moving out from the mine
for(var/mob/living/carbon/human/P in GLOB.player_list)
if(P == H)
continue
to_chat(P, "<span class='userdanger'>You have an overwhelming desire to kill [H]. [H.p_theyve(TRUE)] been marked red! Whoever [H.p_they()] [H.p_were()], friend or foe, go kill [H.p_them()]!</span>")
P.put_in_hands(new /obj/item/kitchen/knife/butcher(P), TRUE)
@@ -9,7 +9,6 @@
for(var/O in directives)
var/datum/objective/brainwashing/objective = new(O)
B.objectives += objective
M.objectives += objective
B.greet()
else
B = new()
@@ -32,10 +31,6 @@
antagpanel_category = "Other"
show_name_in_check_antagonists = TRUE
/datum/antagonist/brainwashed/on_gain()
owner.objectives |= objectives
. = ..()
/datum/antagonist/brainwashed/greet()
to_chat(owner, "<span class='warning'>Your mind reels as it begins focusing on a single purpose...</span>")
to_chat(owner, "<big><span class='warning'><b>Follow the Directives, at any cost!</b></span></big>")
@@ -20,7 +20,6 @@
/datum/antagonist/brother/on_gain()
SSticker.mode.brothers += owner
objectives += team.objectives
owner.objectives += objectives
owner.special_role = special_role
finalize_brother()
return ..()
@@ -459,8 +459,6 @@
objectives += identity_theft
escape_objective_possible = FALSE
owner.objectives |= objectives
/datum/antagonist/changeling/proc/update_changeling_icons_added()
var/datum/atom_hud/antag/hud = GLOB.huds[ANTAG_HUD_CHANGELING]
hud.join_hud(owner.current)
@@ -334,7 +334,7 @@
/obj/item/projectile/tentacle/proc/tentacle_stab(mob/living/carbon/human/H, mob/living/carbon/C)
if(H.Adjacent(C))
for(var/obj/item/I in H.held_items)
if(I.is_sharp())
if(I.get_sharpness())
C.visible_message("<span class='danger'>[H] impales [C] with [H.p_their()] [I.name]!</span>", "<span class='userdanger'>[H] impales you with [H.p_their()] [I.name]!</span>")
C.apply_damage(I.force, BRUTE, BODY_ZONE_CHEST)
H.do_item_attack_animation(C, used_item = I)
@@ -21,7 +21,7 @@
to_chat(user, "<span class='notice'>Our muscles tense and strengthen.</span>")
changeling.chem_recharge_slowdown += 0.5
else
REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
to_chat(user, "<span class='notice'>Our muscles relax.</span>")
changeling.chem_recharge_slowdown -= 0.5
if(stacks >= 20)
@@ -36,12 +36,12 @@
/obj/effect/proc_holder/changeling/strained_muscles/proc/muscle_loop(mob/living/carbon/user)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
while(active)
ADD_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
user.add_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
if(user.stat != CONSCIOUS || user.staminaloss >= 90)
active = !active
to_chat(user, "<span class='notice'>Our muscles relax without the energy to strengthen them.</span>")
user.Knockdown(40)
REMOVE_TRAIT(user, TRAIT_GOTTAGOFAST, "changeling_muscles")
user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES)
changeling.chem_recharge_slowdown -= 0.5
break
@@ -147,6 +147,11 @@
if(iscarbon(L))
var/mob/living/carbon/M = L
M.uncuff()
var/brutedamage = L.getBruteLoss()
var/burndamage = L.getFireLoss()
if(brutedamage || burndamage)
L.adjustBruteLoss(-(brutedamage * 0.25))
L.adjustFireLoss(-(burndamage * 0.25))
L.Knockdown(50) //Completely defenseless for five seconds - mainly to give them time to read over the information they've just been presented with
if(iscarbon(L))
var/mob/living/carbon/C = L
@@ -262,7 +267,7 @@
clockwork_desc = "A sigil that will drain non-Servants that remain on it. Servants that remain on it will be healed if it has any vitality drained."
icon_state = "sigilvitality"
layer = SIGIL_LAYER
alpha = 75
alpha = 125
color = "#123456"
affects_servants = TRUE
stat_affected = DEAD
@@ -366,6 +371,8 @@
break
if(!GLOB.ratvar_awakens)
if(GLOB.clockwork_vitality <= 0)
break
GLOB.clockwork_vitality -= vitality_used
sleep(2)
@@ -35,7 +35,7 @@
/obj/item/clockwork/weapon/ratvarian_spear/attack(mob/living/target, mob/living/carbon/human/user)
. = ..()
if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check() && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
if(!QDELETED(target) && target.stat != DEAD && !target.anti_magic_check(chargecost = 0) && !is_servant_of_ratvar(target)) //we do bonus damage on attacks unless they're a servant, have a null rod, or are dead
var/bonus_damage = bonus_burn //normally a total of 20 damage, 30 with ratvar
if(issilicon(target))
target.visible_message("<span class='warning'>[target] shudders violently at [src]'s touch!</span>", "<span class='userdanger'>ERROR: Temperature rising!</span>")
@@ -64,7 +64,7 @@
/obj/item/clockwork/slab/cyborg/janitor //six scriptures, plus a fabricator
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant, /datum/clockwork_scripture/create_object/sigil_of_transgression, \
/datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
/datum/clockwork_scripture/create_object/stargazer, /datum/clockwork_scripture/create_object/ocular_warden, /datum/clockwork_scripture/create_object/mania_motor)
/obj/item/clockwork/slab/cyborg/service //six scriptures, plus xray vision
quickbound = list(/datum/clockwork_scripture/abscond, /datum/clockwork_scripture/create_object/replicant,/datum/clockwork_scripture/create_object/stargazer, \
@@ -15,7 +15,7 @@
. = ..()
var/area/A = get_area(src)
if(A && construct_type)
notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_CONSTRUCT)
notify_ghosts("A [construct_name] chassis has been created in [A.name]!", 'sound/magic/clockwork/fellowship_armory.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_CONSTRUCT, ignore_dnr_observers = TRUE)
GLOB.poi_list += src
LAZYADD(GLOB.mob_spawners[name], src)
@@ -39,7 +39,9 @@
. = ..()
//ATTACK GHOST IGNORING PARENT RETURN VALUE
/obj/item/clockwork/construct_chassis/attack_ghost(mob/user)
/obj/item/clockwork/construct_chassis/attack_ghost(mob/dead/observer/user)
if(!user.can_reenter_round())
return FALSE
if(!SSticker.mode)
to_chat(user, "<span class='danger'>You cannot use that before the game has started.</span>")
return
@@ -27,7 +27,7 @@
qdel(blaster)
return ..()
/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user)
/obj/item/clothing/glasses/judicial_visor/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot != SLOT_GLASSES)
return 0
return ..()
@@ -190,8 +190,8 @@
for(var/mob/living/L in range(1, src))
if(is_servant_of_ratvar(L))
continue
if(L.anti_magic_check())
var/atom/I = L.anti_magic_check()
var/atom/I = L.anti_magic_check()
if(I)
if(isitem(I))
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
@@ -119,3 +119,33 @@
var/datum/clockwork_scripture/create_object/construct/clockwork_marauder/CM = new()
CM.recent_marauders--
qdel(CM)
//Summon Neovgre: Summon a very powerful combat mech that explodes when destroyed for massive damage.
/datum/clockwork_scripture/create_object/summon_arbiter
descname = "Powerful Assault Mech"
name = "Summon Neovgre, the Anima Bulwark"
desc = "Calls forth the mighty Anima Bulwark, a weapon of unmatched power,\
mech with superior defensive and offensive capabilities. It will \
steadily regenerate HP and triple its regeneration speed while standing \
on a clockwork tile. It will automatically draw power from nearby sigils of \
transmission should the need arise. Its Arbiter laser cannon can decimate foes \
from a range and is capable of smashing through any barrier presented to it. \
Be warned, choosing to pilot Neovgre is a lifetime commitment, once you are \
in you cannot leave and when it is destroyed it will explode catastrophically with you inside."
invocations = list("By the strength of the alloy...!!", "...call forth the Arbiter!!")
channel_time = 200 // This is a strong fucking weapon, 20 seconds channel time is getting off light I tell ya.
power_cost = 75000 //75 KW
usage_tip = "Neovgre is a powerful mech that will crush your enemies!"
invokers_required = 5
multiple_invokers_used = TRUE
object_path = /obj/mecha/combat/neovgre
tier = SCRIPTURE_APPLICATION
primary_component = BELLIGERENT_EYE
sort_priority = 2
creator_message = "<span class='brass'>Neovgre, the Anima Bulwark towers over you... your enemies reckoning has come.</span>"
/datum/clockwork_scripture/create_object/summon_arbiter/check_special_requirements()
if(GLOB.neovgre_exists)
to_chat(invoker, "<span class='brass'>\"You've already got one...\"</span>")
return FALSE
return ..()
@@ -80,7 +80,7 @@
power_cost = 125
whispered = TRUE
object_path = /obj/effect/clockwork/sigil/submission
creator_message = "<span class='brass'>A luminous sigil appears below you. Any non-Servants to cross it will be converted after 8 seconds if they do not move.</span>"
creator_message = "<span class='brass'>A luminous sigil appears below you. Any non-Servants to cross it will be converted and healed of some of their wounds after 8 seconds if they do not move.</span>"
usage_tip = "This is the primary conversion method, though it will not penetrate mindshield implants."
tier = SCRIPTURE_DRIVER
one_per_tile = TRUE
@@ -71,6 +71,7 @@
return TRUE
/obj/structure/destructible/clockwork/trap/proc/activate()
return
//These objects send signals to normal traps to activate
/obj/structure/destructible/clockwork/trap/trigger
@@ -79,6 +80,14 @@
break_message = "<span class='warning'>The trigger breaks apart!</span>"
density = FALSE
/obj/structure/destructible/clockwork/trap/trigger/Initialize()
. = ..()
for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
wired_to += T
T.wired_to += src
to_chat(usr, "<span class='alloy'>[src] automatically links with [T] beneath it.</span>")
/obj/structure/destructible/clockwork/trap/trigger/activate()
for(var/obj/structure/destructible/clockwork/trap/T in wired_to)
if(istype(T, /obj/structure/destructible/clockwork/trap/trigger)) //Triggers don't go off multiple times
@@ -78,7 +78,7 @@
return
voters += user.key
else
if(!user.key in voters)
if(!(user.key in voters))
return
voters -= user.key
var/votes_left = votes_needed - voters.len
@@ -60,7 +60,7 @@
else
if(isliving(target))
var/mob/living/L = target
if(!L.anti_magic_check())
if(!L.anti_magic_check(chargecost = 0))
if(isrevenant(L))
var/mob/living/simple_animal/revenant/R = L
if(R.revealed)
@@ -110,9 +110,7 @@
if(!(BI.resistance_flags & ON_FIRE))
BI.fire_act()
continue
if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE))
continue
if(L.stat || L.lying)
if(is_servant_of_ratvar(L) || (HAS_TRAIT(L, TRAIT_BLIND)) || L.anti_magic_check(TRUE, TRUE) || L.incapacitated(TRUE))
continue
if (iscarbon(L))
var/mob/living/carbon/c = L
@@ -53,7 +53,7 @@
/obj/structure/destructible/clockwork/taunting_trail/proc/affect_mob(mob/living/L)
if(istype(L) && !is_servant_of_ratvar(L))
if(!L.anti_magic_check())
if(!L.anti_magic_check(chargecost = 0))
L.confused = min(L.confused + 15, 50)
L.dizziness = min(L.dizziness + 15, 50)
if(L.confused >= 25)
@@ -7,18 +7,10 @@
icon_state = "pressure_sensor"
alpha = 50
/obj/structure/destructible/clockwork/trap/trigger/Initialize()
. = ..()
for(var/obj/structure/destructible/clockwork/trap/T in get_turf(src))
if(!istype(T, /obj/structure/destructible/clockwork/trap/trigger))
wired_to += T
T.wired_to += src
to_chat(usr, "<span class='alloy'>[src] automatically links with [T] beneath it.</span>")
/obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/Crossed(atom/movable/AM)
if(isliving(AM) && !is_servant_of_ratvar(AM))
var/mob/living/L = AM
if(L.stat || L.m_intent == MOVE_INTENT_WALK || L.lying)
if(L.stat || L.m_intent == MOVE_INTENT_WALK || L.movement_type & (FLYING|FLOATING))
return
audible_message("<i>*click*</i>")
playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE)
@@ -7,7 +7,6 @@
break_message = "<span class='warning'>The vent snaps and collapses!</span>"
max_integrity = 100
density = FALSE
layer = BELOW_OBJ_LAYER
/obj/structure/destructible/clockwork/trap/steam_vent/activate()
opacity = !opacity
@@ -5,7 +5,6 @@
unanchored_icon = "wall_gear"
climbable = TRUE
max_integrity = 100
layer = BELOW_OBJ_LAYER
construction_value = 3
desc = "A massive brass gear. You could probably secure or unsecure it with a wrench, or just climb over it."
break_message = "<span class='warning'>The gear breaks apart into shards of alloy!</span>"
-1
View File
@@ -35,7 +35,6 @@
/datum/antagonist/cult/proc/add_objectives()
objectives |= cult_team.objectives
owner.objectives |= objectives
/datum/antagonist/cult/Destroy()
QDEL_NULL(communion)
+4 -4
View File
@@ -275,7 +275,7 @@
desc = "A torn, dust-caked hood. Strange letters line the inside."
flags_inv = HIDEFACE|HIDEHAIR|HIDEEARS
flags_cover = HEADCOVERSEYES
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
cold_protection = HEAD
min_cold_protection_temperature = HELMET_MIN_TEMP_PROTECT
heat_protection = HEAD
@@ -288,7 +288,7 @@
item_state = "cultrobes"
body_parts_covered = CHEST|GROIN|LEGS|ARMS
allowed = list(/obj/item/tome, /obj/item/melee/cultblade)
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 25, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
armor = list("melee" = 40, "bullet" = 30, "laser" = 40,"energy" = 20, "bomb" = 65, "bio" = 10, "rad" = 0, "fire" = 10, "acid" = 10)
flags_inv = HIDEJUMPSUIT
cold_protection = CHEST|GROIN|LEGS|ARMS
min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT
@@ -493,7 +493,7 @@
desc = "You peer within this smokey orb and glimpse terrible fates befalling the escape shuttle."
icon = 'icons/obj/cult.dmi'
icon_state ="shuttlecurse"
var/global/curselimit = 0
var/static/curselimit = 0
/obj/item/shuttle_curse/attack_self(mob/living/user)
if(!iscultist(user))
@@ -530,7 +530,7 @@
playsound(user.loc, 'sound/effects/glassbr1.ogg', 50, 1)
qdel(src)
sleep(20)
var/global/list/curses
var/static/list/curses
if(!curses)
curses = list("A fuel technician just slit his own throat and begged for death.",
"The shuttle's navigation programming was replaced by a file containing just two words: IT COMES.",
+1 -1
View File
@@ -107,7 +107,7 @@ This file contains the cult dagger and rune list code
if(!(A in summon_objective.summon_spots)) // Check again to make sure they didn't move
to_chat(user, "<span class='cultlarge'>The Geometer can only be summoned where the veil is weak - in [english_list(summon_objective.summon_spots)]!</span>")
return
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/ai/spanomalies.ogg')
priority_announce("Figments from an eldritch god are being summoned by [user] into [A.map_name] from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", "spanomalies")
for(var/B in spiral_range_turfs(1, user, 1))
var/obj/structure/emergency_shield/sanguine/N = new(B)
shields += N
+6 -6
View File
@@ -237,7 +237,7 @@ structure_check() searches for nearby cultist structures required for the invoca
to_chat(M, "<span class='warning'>You need at least two invokers to convert [convertee]!</span>")
log_game("Offer rune failed - tried conversion with one invoker")
return 0
if(convertee.anti_magic_check(TRUE, TRUE, FALSE, 0)) //Not chargecost because it can be spammed
if(convertee.anti_magic_check(TRUE, TRUE, chargecost = 0)) //Not major because it can be spammed
for(var/M in invokers)
to_chat(M, "<span class='warning'>Something is shielding [convertee]'s mind!</span>")
log_game("Offer rune failed - convertee had anti-magic")
@@ -249,7 +249,7 @@ structure_check() searches for nearby cultist structures required for the invoca
convertee.adjustFireLoss(-(burndamage * 0.75))
convertee.visible_message("<span class='warning'>[convertee] writhes in pain \
[brutedamage || burndamage ? "even as [convertee.p_their()] wounds heal and close" : "as the markings below [convertee.p_them()] glow a bloody red"]!</span>", \
"<span class='cultlarge'><i>AAAAAAAAAAAAAA-</i></span>")
"<span class='cultlarge'><i>AAAAAAAAAAAAAA-</i></span>")
SSticker.mode.add_cultist(convertee.mind, 1)
new /obj/item/melee/cultblade/dagger(get_turf(src))
convertee.mind.special_role = ROLE_CULTIST
@@ -767,7 +767,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
var/atom/I = L.anti_magic_check()
var/atom/I = L.anti_magic_check(chargecost = 0)
if(I)
if(isitem(I))
to_chat(L, "<span class='userdanger'>[I] suddenly burns hotly before returning to normal!</span>")
@@ -797,7 +797,7 @@ structure_check() searches for nearby cultist structures required for the invoca
set_light(6, 1, color)
for(var/mob/living/L in viewers(T))
if(!iscultist(L) && L.blood_volume)
if(L.anti_magic_check())
if(L.anti_magic_check(chargecost = 0))
continue
L.take_overall_damage(tick_damage*multiplier, tick_damage*multiplier)
if(is_servant_of_ratvar(L))
@@ -848,10 +848,10 @@ structure_check() searches for nearby cultist structures required for the invoca
fail_invoke()
log_game("Manifest rune failed - too many summoned ghosts")
return list()
notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src)
notify_ghosts("Manifest rune invoked in [get_area(src)].", 'sound/effects/ghost2.ogg', source = src, ignore_dnr_observers = TRUE)
var/list/ghosts_on_rune = list()
for(var/mob/dead/observer/O in T)
if(O.client && !jobban_isbanned(O, ROLE_CULTIST) && !QDELETED(src) && !QDELETED(O))
if(!QDELETED(O) && O.client && !jobban_isbanned(O, ROLE_CULTIST) && !QDELETED(src) && O.can_reenter_round())
ghosts_on_rune += O
if(!ghosts_on_rune.len)
to_chat(user, "<span class='cultitalic'>There are no spirits near [src]!</span>")
+1 -1
View File
@@ -549,7 +549,7 @@ GLOBAL_LIST_INIT(devil_suffix, list(" the Red", " the Soulless", " the Master",
var/list/parts = list()
parts += printplayer(owner)
parts += printdevilinfo()
parts += printobjectives(owner)
parts += printobjectives(objectives)
return parts.Join("<br>")
//A simple super light weight datum for the codex gigas.
+15
View File
@@ -57,3 +57,18 @@
visible_message("<span class='danger'>[src] screams in agony as it sublimates into a sulfurous smoke.</span>")
ghostize()
qdel(src)
/datum/antagonist/imp
name = "Imp"
antagpanel_category = "Devil"
show_in_roundend = FALSE
/datum/antagonist/imp/on_gain()
. = ..()
give_objectives()
/datum/antagonist/imp/proc/give_objectives()
var/datum/objective/newobjective = new
newobjective.explanation_text = "Try to get a promotion to a higher devilic rank."
newobjective.owner = owner
objectives += newobjective
@@ -106,7 +106,7 @@
/mob/living/carbon/true_devil/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
return 666
/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0)
/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
if(mind && has_bane(BANE_LIGHT))
mind.disrupt_spells(-500)
return ..() //flashes don't stop devils UNLESS it's their bane.
@@ -147,13 +147,8 @@
if(ascended || user.mind.soulOwner == src.mind)
var/mob/living/simple_animal/imp/S = new(get_turf(loc))
user.transfer_ckey(S, FALSE)
S.mind.assigned_role = "Imp"
S.mind.special_role = "Imp"
var/datum/objective/newobjective = new
newobjective.explanation_text = "Try to get a promotion to a higher devilic rank."
S.mind.objectives += newobjective
to_chat(S, S.playstyle_string)
to_chat(S, "<B>Objective #[1]</B>: [newobjective.explanation_text]")
var/datum/antagonist/imp/A = new()
S.mind.add_antag_datum(A)
else
return ..()
@@ -10,12 +10,10 @@
var/datum/objective/O = new /datum/objective/disease_infect()
O.owner = owner
objectives += O
owner.objectives += O
O = new /datum/objective/disease_infect_centcom()
O.owner = owner
objectives += O
owner.objectives += O
. = ..()
@@ -3,6 +3,7 @@
name = "Spawn Sentient Disease"
typepath = /datum/round_event/ghost_role/sentient_disease
weight = 7
gamemode_blacklist = list("dynamic")
max_occurrences = 1
min_players = 5
@@ -9,7 +9,7 @@ the new instance inside the host to be updated to the template's stats.
name = "Sentient Disease"
real_name = "Sentient Disease"
desc = ""
icon = 'icons/mob/blob.dmi'
icon = 'icons/mob/cameramob.dmi'
icon_state = "marker"
mouse_opacity = MOUSE_OPACITY_ICON
move_on_shuttle = FALSE
@@ -31,7 +31,6 @@ the new instance inside the host to be updated to the template's stats.
var/browser_open = FALSE
var/mob/living/following_host
var/datum/component/redirect/move_listener
var/list/disease_instances
var/list/hosts //this list is associative, affected_mob -> disease_instance
var/datum/disease/advance/sentient_disease/disease_template
@@ -261,16 +260,10 @@ the new instance inside the host to be updated to the template's stats.
refresh_adaptation_menu()
/mob/camera/disease/proc/set_following(mob/living/L)
if(following_host)
UnregisterSignal(following_host, COMSIG_MOVABLE_MOVED)
RegisterSignal(L, COMSIG_MOVABLE_MOVED, .proc/follow_mob)
following_host = L
if(!move_listener)
move_listener = L.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/follow_mob)))
else
if(L)
L.TakeComponent(move_listener)
if(QDELING(move_listener))
move_listener = null
else
QDEL_NULL(move_listener)
follow_mob()
/mob/camera/disease/proc/follow_next(reverse = FALSE)
-1
View File
@@ -113,7 +113,6 @@
/datum/antagonist/ert/proc/forge_objectives()
if(ert_team)
objectives |= ert_team.objectives
owner.objectives |= objectives
/datum/antagonist/ert/proc/equipERT()
var/mob/living/carbon/human/H = owner.current
@@ -8,7 +8,6 @@
O.completed = TRUE //YES!
O.owner = owner
objectives += O
owner.objectives += objectives
/datum/antagonist/greentext/on_gain()
forge_objectives()
@@ -24,8 +24,6 @@
hijack_objective.owner = owner
objectives += hijack_objective
owner.objectives |= objectives
/datum/antagonist/highlander/on_gain()
forge_objectives()
owner.special_role = "highlander"
@@ -0,0 +1,9 @@
/datum/antagonist/magic_servant
name = "Magic Servant"
show_in_roundend = FALSE
show_in_antagpanel = FALSE
/datum/antagonist/magic_servant/proc/setup_master(mob/M)
var/datum/objective/O = new("Serve [M.real_name].")
O.owner = owner
objectives |= O
@@ -63,7 +63,6 @@
/datum/antagonist/monkey/proc/forge_objectives()
objectives |= monkey_team.objectives
owner.objectives |= objectives
/datum/antagonist/monkey/admin_remove(mob/admin)
var/mob/living/carbon/monkey/M = owner.current
-1
View File
@@ -96,7 +96,6 @@
var/datum/objective/O = new /datum/objective/survive()
O.owner = owner
objectives += O
owner.objectives |= objectives
/proc/remove_ninja(mob/living/L)
if(!L || !L.mind)
@@ -0,0 +1,181 @@
/obj/item/borg_chameleon
name = "cyborg chameleon projector"
icon = 'icons/obj/device.dmi'
icon_state = "shield0"
flags_1 = CONDUCT_1
item_flags = NOBLUDGEON
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
w_class = WEIGHT_CLASS_SMALL
var/friendlyName
var/savedName
var/active = FALSE
var/activationCost = 300
var/activationUpkeep = 50
var/disguise = null
var/disguise_icon_override = null
var/disguise_pixel_offset = null
var/mob/listeningTo
var/static/list/signalCache = list( // list here all signals that should break the camouflage
COMSIG_PARENT_ATTACKBY,
COMSIG_ATOM_ATTACK_HAND,
COMSIG_MOVABLE_IMPACT_ZONE,
COMSIG_ATOM_BULLET_ACT,
COMSIG_ATOM_EX_ACT,
COMSIG_ATOM_FIRE_ACT,
COMSIG_ATOM_EMP_ACT,
)
var/mob/living/silicon/robot/user // needed for process()
var/animation_playing = FALSE
var/list/engymodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Marina", "Can", "Spider", "Loader","Handy", "Pup Dozer", "Vale")
/obj/item/borg_chameleon/Initialize()
. = ..()
friendlyName = pick(GLOB.ai_names)
/obj/item/borg_chameleon/Destroy()
listeningTo = null
return ..()
/obj/item/borg_chameleon/dropped(mob/user)
. = ..()
disrupt(user)
/obj/item/borg_chameleon/equipped(mob/user)
. = ..()
disrupt(user)
/obj/item/borg_chameleon/attack_self(mob/living/silicon/robot/user)
if (user && user.cell && user.cell.charge > activationCost)
if (isturf(user.loc))
toggle(user)
else
to_chat(user, "<span class='warning'>You can't use [src] while inside something!</span>")
else
to_chat(user, "<span class='warning'>You need at least [activationCost] charge in your cell to use [src]!</span>")
/obj/item/borg_chameleon/proc/toggle(mob/living/silicon/robot/user)
if(active)
playsound(src, 'sound/effects/pop.ogg', 100, TRUE, -6)
to_chat(user, "<span class='notice'>You deactivate \the [src].</span>")
deactivate(user)
else
if(animation_playing)
to_chat(user, "<span class='notice'>\the [src] is recharging.</span>")
return
var/borg_icon = input(user, "Select an icon!", "Robot Icon", null) as null|anything in engymodels
if(!borg_icon)
return FALSE
switch(borg_icon)
if("Default")
disguise = "engineer"
disguise_icon_override = 'icons/mob/robots.dmi'
if("Default - Treads")
disguise = "engi-tread"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Loader")
disguise = "loaderborg"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Handy")
disguise = "handyeng"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Sleek")
disguise = "sleekeng"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Can")
disguise = "caneng"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Marina")
disguise = "marinaeng"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Spider")
disguise = "spidereng"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Heavy")
disguise = "heavyeng"
disguise_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Pup Dozer")
disguise = "pupdozer"
disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
disguise_pixel_offset = -16
if("Vale")
disguise = "valeeng"
disguise_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
disguise_pixel_offset = -16
animation_playing = TRUE
to_chat(user, "<span class='notice'>You activate \the [src].</span>")
playsound(src, 'sound/effects/seedling_chargeup.ogg', 100, TRUE, -6)
var/start = user.filters.len
var/X,Y,rsq,i,f
for(i=1, i<=7, ++i)
do
X = 60*rand() - 30
Y = 60*rand() - 30
rsq = X*X + Y*Y
while(rsq<100 || rsq>900)
user.filters += filter(type="wave", x=X, y=Y, size=rand()*2.5+0.5, offset=rand())
for(i=1, i<=7, ++i)
f = user.filters[start+i]
animate(f, offset=f:offset, time=0, loop=3, flags=ANIMATION_PARALLEL)
animate(offset=f:offset-1, time=rand()*20+10)
if (do_after(user, 50, target=user) && user.cell.use(activationCost))
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE, -6)
to_chat(user, "<span class='notice'>You are now disguised as the Nanotrasen engineering borg \"[friendlyName]\".</span>")
activate(user)
else
to_chat(user, "<span class='warning'>The chameleon field fizzles.</span>")
do_sparks(3, FALSE, user)
for(i=1, i<=min(7, user.filters.len), ++i) // removing filters that are animating does nothing, we gotta stop the animations first
f = user.filters[start+i]
animate(f)
user.filters = null
animation_playing = FALSE
/obj/item/borg_chameleon/process()
if (user)
if (!user.cell || !user.cell.use(activationUpkeep))
disrupt(user)
else
return PROCESS_KILL
/obj/item/borg_chameleon/proc/activate(mob/living/silicon/robot/user)
START_PROCESSING(SSobj, src)
src.user = user
savedName = user.name
user.name = friendlyName
user.module.cyborg_base_icon = disguise
user.module.cyborg_icon_override = disguise_icon_override
user.module.cyborg_pixel_offset = disguise_pixel_offset
user.bubble_icon = "robot"
active = TRUE
user.update_icons()
if(listeningTo == user)
return
if(listeningTo)
UnregisterSignal(listeningTo, signalCache)
RegisterSignal(user, signalCache, .proc/disrupt)
listeningTo = user
/obj/item/borg_chameleon/proc/deactivate(mob/living/silicon/robot/user)
STOP_PROCESSING(SSobj, src)
if(listeningTo)
UnregisterSignal(listeningTo, signalCache)
listeningTo = null
do_sparks(5, FALSE, user)
user.name = savedName
user.module.cyborg_base_icon = initial(user.module.cyborg_base_icon)
user.module.cyborg_icon_override = 'icons/mob/robots.dmi'
user.bubble_icon = "syndibot"
active = FALSE
user.update_icons()
user.pixel_x = 0 //this solely exists because of dogborgs. I want anyone who ever reads this code later on to know this. Don't ask me why it's here, doesn't work above update_icons()
src.user = user
/obj/item/borg_chameleon/proc/disrupt(mob/living/silicon/robot/user)
if(active)
to_chat(user, "<span class='danger'>Your chameleon field deactivates.</span>")
deactivate(user)
@@ -64,7 +64,7 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
for(var/obj/machinery/computer/camera_advanced/shuttle_docker/D in GLOB.jam_on_wardec)
D.jammed = TRUE
GLOB.war_declared = TRUE
GLOB.war_declared = TRUE
var/list/nukeops = get_antag_minds(/datum/antagonist/nukeop)
var/actual_players = GLOB.joined_player_list.len - nukeops.len
var/tc_malus = 0
@@ -74,6 +74,11 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
new uplink_type(get_turf(user), user.key, CHALLENGE_TELECRYSTALS - tc_malus + CEILING(PLAYER_SCALING * actual_players, 1))
CONFIG_SET(number/shuttle_refuel_delay, max(CONFIG_GET(number/shuttle_refuel_delay), CHALLENGE_SHUTTLE_DELAY))
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
var/threat_spent = CONFIG_GET(number/dynamic_warops_cost)
mode.spend_threat(threat_spent)
mode.log_threat("Nuke ops spent [threat_spent] on war ops.")
SSblackbox.record_feedback("amount", "nuclear_challenge_mode", 1)
qdel(src)
@@ -94,6 +99,14 @@ GLOBAL_VAR_INIT(war_declared, FALSE)
if(board.moved)
to_chat(user, "The shuttle has already been moved! You have forfeit the right to declare war.")
return FALSE
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
if(mode.threat_level < CONFIG_GET(number/dynamic_warops_requirement))
to_chat(user, "Due to the dynamic space in which the station resides, you are too deep into Nanotrasen territory to reasonably go loud.")
return FALSE
else if(mode.threat < CONFIG_GET(number/dynamic_warops_cost))
to_chat(user, "Due to recent threats on the station, Nanotrasen is looking too closely for a war declaration to be wise.")
return FALSE
return TRUE
/obj/item/nuclear_challenge/clownops
@@ -343,10 +343,10 @@
/obj/machinery/nuclearbomb/proc/set_anchor()
if(!isinspace())
anchored = !anchored
else
if(isinspace() && !anchored)
to_chat(usr, "<span class='warning'>There is nothing to anchor to!</span>")
else
anchored = !anchored
/obj/machinery/nuclearbomb/proc/set_safety()
safety = !safety
+1 -1
View File
@@ -87,7 +87,7 @@
/datum/antagonist/nukeop/proc/forge_objectives()
if(nuke_team)
owner.objectives |= nuke_team.objectives
objectives |= nuke_team.objectives
/datum/antagonist/nukeop/proc/move_to_spawnpoint()
var/team_number = 1
@@ -36,8 +36,6 @@
missionobj.completed = 1
mission = missionobj
objectives |= mission
owner.objectives |= objectives
/datum/antagonist/official/on_gain()
forge_objectives()
@@ -26,7 +26,6 @@
// Sets objectives, equips all antags with the storage implant.
/datum/antagonist/overthrow/on_gain()
objectives += team.objectives
owner.objectives += objectives
..()
owner.announce_objectives()
equip_overthrow()
@@ -34,7 +33,6 @@
/datum/antagonist/overthrow/on_removal()
owner.special_role = null
owner.objectives -= objectives
..()
// Creates the overthrow team, or sets it. The objectives are static for all the team members.
@@ -35,7 +35,9 @@
objectives += heads_obj
for(var/i in members)
var/datum/mind/M = i
M.objectives += heads_obj
var/datum/antagonist/overthrow/O = M.has_antag_datum(/datum/antagonist/overthrow)
if(O)
O.objectives += heads_obj
heads_obj.find_targets()
addtimer(CALLBACK(src,.proc/update_objectives),OBJECTIVE_UPDATING_TIME,TIMER_UNIQUE)
+4 -7
View File
@@ -31,12 +31,7 @@
/datum/antagonist/pirate/on_gain()
if(crew)
owner.objectives |= crew.objectives
. = ..()
/datum/antagonist/pirate/on_removal()
if(crew)
owner.objectives -= crew.objectives
objectives |= crew.objectives
. = ..()
/datum/team/pirate
@@ -53,7 +48,9 @@
getbooty.update_explanation_text()
objectives += getbooty
for(var/datum/mind/M in members)
M.objectives |= objectives
var/datum/antagonist/pirate/P = M.has_antag_datum(/datum/antagonist/pirate)
if(P)
P.objectives |= objectives
/datum/objective/loot
@@ -69,7 +69,7 @@
/mob/living/simple_animal/revenant/Initialize(mapload)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/targeted/night_vision/revenant(null))
AddSpell(new /obj/effect/proc_holder/spell/targeted/revenant_transmit(null))
AddSpell(new /obj/effect/proc_holder/spell/targeted/telepathy/revenant(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/defile(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/overload(null))
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/revenant/blight(null))
@@ -27,6 +27,7 @@
if(prob(10))
to_chat(target, "You feel as if you are being watched.")
return
face_atom(target)
draining = TRUE
essence_drained += rand(15, 20)
to_chat(src, "<span class='revennotice'>You search for the soul of [target].</span>")
@@ -65,7 +66,7 @@
if(target.anti_magic_check(FALSE, TRUE))
to_chat(src, "<span class='revenminor'>Something's wrong! [target] seems to be resisting the siphoning, leaving you vulnerable!</span>")
target.visible_message("<span class='warning'>[target] slumps onto the ground.</span>", \
"<span class='revenwarning'>Violets lights, dancing in your vision, receding--</span>")
"<span class='revenwarning'>Violet lights, dancing in your vision, receding--</span>")
draining = FALSE
return
var/datum/beam/B = Beam(target,icon_state="drain_life",time=INFINITY)
@@ -104,36 +105,16 @@
action_background_icon_state = "bg_revenant"
//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob
/obj/effect/proc_holder/spell/targeted/revenant_transmit
name = "Transmit"
desc = "Telepathically transmits a message to the target."
/obj/effect/proc_holder/spell/targeted/telepathy/revenant
name = "Revenant Transmit"
panel = "Revenant Abilities"
charge_max = 0
clothes_req = 0
range = 7
include_user = 0
action_icon = 'icons/mob/actions/actions_revenant.dmi'
action_icon_state = "r_transmit"
action_background_icon_state = "bg_revenant"
/obj/effect/proc_holder/spell/targeted/revenant_transmit/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
for(var/mob/living/M in targets)
var/msg = stripped_input(usr, "What do you wish to tell [M]?", null, "")
if(!msg)
charge_counter = charge_max
return
log_directed_talk(user, M, msg, LOG_SAY, "revenant whisper")
to_chat(user, "<span class='revenboldnotice'>You transmit to [M]:</span> <span class='revennotice'>[msg]</span>")
if(!M.anti_magic_check(FALSE, TRUE)) //hear no evil
to_chat(M, "<span class='revenboldnotice'>You hear something behind you talking...</span> <span class='revennotice'>[msg]</span>")
for(var/ded in GLOB.dead_mob_list)
if(!isobserver(ded))
continue
var/follow_rev = FOLLOW_LINK(ded, user)
var/follow_whispee = FOLLOW_LINK(ded, M)
to_chat(ded, "[follow_rev] <span class='revenboldnotice'>[user] Revenant Transmit:</span> <span class='revennotice'>\"[msg]\" to</span> [follow_whispee] <span class='name'>[M]</span>")
notice = "revennotice"
boldnotice = "revenboldnotice"
holy_check = TRUE
tinfoil_check = FALSE
/obj/effect/proc_holder/spell/aoe_turf/revenant
clothes_req = 0
@@ -14,8 +14,6 @@
objective2.owner = owner
objectives += objective2
owner.objectives |= objectives
/datum/antagonist/revenant/on_gain()
forge_objectives()
. = ..()
@@ -12,8 +12,8 @@
disease_flags = CURABLE
permeability_mod = 1
severity = DISEASE_SEVERITY_DANGEROUS
var/finalstage = 0 //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
var/datum/mood_event/revenant_blight/depression
var/finalstage = FALSE //Because we're spawning off the cure in the final stage, we need to check if we've done the final stage's effects.
var/depression = FALSE
/datum/disease/revblight/cure()
if(affected_mob)
@@ -44,12 +44,13 @@
affected_mob.emote("pale")
if(3)
if(!depression)
depression = SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.12, SANITY_CRAZY)
SEND_SIGNAL(affected_mob, COMSIG_ADD_MOOD_EVENT, "rev_blight", /datum/mood_event/revenant_blight)
depression = TRUE
SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.12, SANITY_CRAZY)
if(prob(10))
affected_mob.emote(pick("pale","shiver"))
if(4)
SEND_SIGNAL(affected_mob, COMSIG_DECREASE_SANITY, 0.18, SANITY_CRAZY)
SEND_SIGNAL(affected_mob, COMSIG_MODIFY_SANITY, -0.18, SANITY_CRAZY)
if(prob(15))
affected_mob.emote(pick("pale","shiver","cries"))
if(5)
@@ -4,6 +4,7 @@
name = "Spawn Revenant" // Did you mean 'griefghost'?
typepath = /datum/round_event/ghost_role/revenant
weight = 7
gamemode_blacklist = list("dynamic")
max_occurrences = 1
min_players = 5
@@ -66,10 +66,10 @@
return rev_team
/datum/antagonist/rev/proc/create_objectives()
owner.objectives |= rev_team.objectives
objectives |= rev_team.objectives
/datum/antagonist/rev/proc/remove_objectives()
owner.objectives -= rev_team.objectives
objectives -= rev_team.objectives
//Bump up to head_rev
/datum/antagonist/rev/proc/promote()
@@ -207,9 +207,20 @@
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.</span>", null, null, null, owner.current)
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and deletes your neural reprogramming! You remember nothing of your time spent reprogrammed, you can't even remember the names or identities of anyone involved...</span>")
/datum/antagonist/rev/head/farewell()
if((ishuman(owner.current) || ismonkey(owner.current)))
if(owner.current.stat != DEAD)
owner.current.visible_message("<span class='deconversion_message'>[owner.current] looks like [owner.current.p_theyve()] just remembered [owner.current.p_their()] real allegiance!</span>", null, null, null, owner.current)
to_chat(owner, "<span class ='deconversion_message bold'>You have given up your cause of overthrowing the command staff. You are no longer a Head Revolutionary.</span>")
else
to_chat(owner, "<span class ='deconversion_message bold'>The sweet release of death. You are no longer a Head Revolutionary.</span>")
else if(issilicon(owner.current))
owner.current.visible_message("<span class='deconversion_message'>The frame beeps contentedly, suppressing the disloyal personality traits from the MMI before initalizing it.</span>", null, null, null, owner.current)
to_chat(owner, "<span class='userdanger'>The frame's firmware detects and suppresses your unwanted personality traits! You feel more content with the leadership around these parts.</span>")
//blunt trauma deconversions call this through species.dm spec_attacked_by()
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
log_attack("[key_name(owner.current)] has been deconverted from the revolution by [key_name(deconverter)]!")
log_attack("[key_name(owner.current)] has been deconverted from the revolution by [ismob(deconverter) ? key_name(deconverter) : deconverter]!")
if(borged)
message_admins("[ADMIN_LOOKUPFLW(owner.current)] has been borged while being a [name]")
owner.special_role = null
@@ -219,9 +230,8 @@
owner.remove_antag_datum(type)
/datum/antagonist/rev/head/remove_revolutionary(borged,deconverter)
if(!borged)
return
. = ..()
if(borged || deconverter == "gamemode")
. = ..()
/datum/antagonist/rev/head/equip_rev()
var/mob/living/carbon/human/H = owner.current
@@ -253,6 +263,8 @@
/datum/team/revolution
name = "Revolution"
var/max_headrevs = 3
var/list/ex_headrevs = list() // Dynamic removes revs on loss, used to keep a list for the roundend report.
var/list/ex_revs = list()
/datum/team/revolution/proc/update_objectives(initial = FALSE)
var/untracked_heads = SSjob.get_all_heads()
@@ -265,7 +277,8 @@
new_target.update_explanation_text()
objectives += new_target
for(var/datum/mind/M in members)
M.objectives |= objectives
var/datum/antagonist/rev/R = M.has_antag_datum(/datum/antagonist/rev)
R.objectives |= objectives
addtimer(CALLBACK(src,.proc/update_objectives),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
@@ -295,9 +308,12 @@
addtimer(CALLBACK(src,.proc/update_heads),HEAD_UPDATE_PERIOD,TIMER_UNIQUE)
/datum/team/revolution/proc/save_members()
ex_headrevs = get_antag_minds(/datum/antagonist/rev/head, TRUE)
ex_revs = get_antag_minds(/datum/antagonist/rev, TRUE)
/datum/team/revolution/roundend_report()
if(!members.len)
if(!members.len && !ex_headrevs.len)
return
var/list/result = list()
@@ -317,8 +333,17 @@
var/list/targets = list()
var/list/datum/mind/headrevs = get_antag_minds(/datum/antagonist/rev/head)
var/list/datum/mind/revs = get_antag_minds(/datum/antagonist/rev,TRUE)
var/list/datum/mind/headrevs
var/list/datum/mind/revs
if(ex_headrevs.len)
headrevs = ex_headrevs
else
headrevs = get_antag_minds(/datum/antagonist/rev/head, TRUE)
if(ex_revs.len)
revs = ex_revs
else
revs = get_antag_minds(/datum/antagonist/rev, TRUE)
if(headrevs.len)
var/list/headrev_part = list()
headrev_part += "<span class='header'>The head revolutionaries were:</span>"
+29
View File
@@ -0,0 +1,29 @@
/datum/antagonist/santa
name = "Santa"
show_in_antagpanel = FALSE
/datum/antagonist/santa/on_gain()
. = ..()
give_equipment()
give_objective()
/datum/antagonist/santa/greet()
. = ..()
to_chat(owner, "<span class='boldannounce'>You are Santa! Your objective is to bring joy to the people on this station. You can conjure more presents using a spell, and there are several presents in your bag.</span>")
/datum/antagonist/santa/proc/give_equipment()
var/mob/living/carbon/human/H = owner.current
if(istype(H))
H.equipOutfit(/datum/outfit/santa)
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/presents)
var/obj/effect/proc_holder/spell/targeted/area_teleport/teleport/telespell = new
telespell.clothes_req = 0 //santa robes aren't actually magical.
owner.AddSpell(telespell) //does the station have chimneys? WHO KNOWS!
/datum/antagonist/santa/proc/give_objective()
var/datum/objective/santa_objective = new()
santa_objective.explanation_text = "Bring joy and presents to the station!"
santa_objective.completed = 1 //lets cut our santas some slack.
santa_objective.owner = owner
objectives |= santa_objective
@@ -34,7 +34,6 @@
melee_damage_upper = 30
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
var/boost = 0
bloodcrawl = BLOODCRAWL_EAT
var/playstyle_string = "<span class='big bold'>You are a slaughter demon,</span><B> a terrible creature from another realm. You have a single desire: To kill. \
You may use the \"Blood Crawl\" ability near blood pools to travel through them, appearing and disappearing from the station at will. \
@@ -54,24 +53,18 @@
if(istype(loc, /obj/effect/dummy/phased_mob/slaughter))
bloodspell.phased = TRUE
/mob/living/simple_animal/slaughter/Life()
..()
if(boost<world.time)
speed = 1
else
speed = 0
/obj/effect/decal/cleanable/blood/innards
icon = 'icons/obj/surgery.dmi'
name = "pile of viscera"
desc = "A repulsive pile of guts and gore."
gender = NEUTER
icon_state = "innards"
random_icon_states = null
/mob/living/simple_animal/slaughter/phasein()
. = ..()
speed = 0
boost = world.time + 60
add_movespeed_modifier(MOVESPEED_ID_SLAUGHTER, update=TRUE, priority=100, multiplicative_slowdown=-1)
addtimer(CALLBACK(src, .proc/remove_movespeed_modifier, MOVESPEED_ID_SLAUGHTER, TRUE), 6 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
//The loot from killing a slaughter demon - can be consumed to allow the user to blood crawl
@@ -101,7 +94,7 @@
user.temporarilyRemoveItemFromInventory(src, TRUE)
src.Insert(user) //Consuming the heart literally replaces your heart with a demon heart. H A R D C O R E
/obj/item/organ/heart/demon/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/demon/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
if(M.mind)
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
@@ -26,8 +26,6 @@
new_objective2.explanation_text = "[objective_verb] everyone[summoner ? " else while you're at it":""]."
objectives += new_objective2
owner.objectives |= objectives
/datum/antagonist/slaughter/laughter
name = "Laughter demon"
objective_verb = "Hug and Tickle"
@@ -3,6 +3,7 @@
typepath = /datum/round_event/ghost_role/slaughter
weight = 1 //Very rare
max_occurrences = 1
gamemode_blacklist = list("dynamic")
earliest_start = 1 HOURS
min_players = 20
@@ -8,7 +8,6 @@
var/datum/objective/survive/survive = new
survive.owner = owner
objectives += survive
owner.objectives |= objectives
/datum/antagonist/survivalist/on_gain()
owner.special_role = "survivalist"
+1 -1
View File
@@ -33,7 +33,7 @@
. = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user)
. = ..()
@@ -78,15 +78,14 @@
scan_target = null
if(owner)
if(owner.mind)
if(owner.mind.objectives)
for(var/datum/objective/objective_ in owner.mind.objectives)
if(!is_internal_objective(objective_))
continue
var/datum/objective/assassinate/internal/objective = objective_
var/mob/current = objective.target.current
if(current&&current.stat!=DEAD)
scan_target = current
break
for(var/datum/objective/objective_ in owner.mind.get_all_objectives())
if(!is_internal_objective(objective_))
continue
var/datum/objective/assassinate/internal/objective = objective_
var/mob/current = objective.target.current
if(current&&current.stat!=DEAD)
scan_target = current
break
/datum/status_effect/agent_pinpointer/tick()
if(!owner)
@@ -100,9 +99,9 @@
return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
/datum/antagonist/traitor/proc/replace_escape_objective()
if(!owner||!owner.objectives)
if(!owner || !objectives.len)
return
for (var/objective_ in owner.objectives)
for (var/objective_ in objectives)
if(!(istype(objective_, /datum/objective/escape)||istype(objective_, /datum/objective/survive)))
continue
remove_objective(objective_)
@@ -112,9 +111,9 @@
add_objective(martyr_objective)
/datum/antagonist/traitor/proc/reinstate_escape_objective()
if(!owner||!owner.objectives)
if(!owner||!objectives.len)
return
for (var/objective_ in owner.objectives)
for (var/objective_ in objectives)
if(!istype(objective_, /datum/objective/martyr))
continue
remove_objective(objective_)
@@ -131,7 +130,7 @@
return
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
LAZYINITLIST(targets_stolen)
for(var/objective_ in victim.objectives)
for(var/objective_ in victim.get_all_objectives())
if(istype(objective_, /datum/objective/assassinate/internal))
var/datum/objective/assassinate/internal/objective = objective_
if(objective.target==owner)
@@ -159,7 +158,7 @@
var/status_text = objective.check_completion() ? "neutralised" : "active"
to_chat(owner.current, "<span class='userdanger'> New target added to database: [objective.target.name] ([status_text]) </span>")
last_man_standing = TRUE
for(var/objective_ in owner.objectives)
for(var/objective_ in objectives)
if(!is_internal_objective(objective_))
continue
var/datum/objective/assassinate/internal/objective = objective_
@@ -175,7 +174,7 @@
/datum/antagonist/traitor/internal_affairs/proc/iaa_process()
if(owner&&owner.current&&owner.current.stat!=DEAD)
for(var/objective_ in owner.objectives)
for(var/objective_ in objectives)
if(!is_internal_objective(objective_))
continue
var/datum/objective/assassinate/internal/objective = objective_
@@ -224,8 +223,6 @@
special_role = TRAITOR_AGENT_ROLE
syndicate = TRUE
forge_single_objective()
else
..() // Give them standard objectives.
return
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
@@ -55,12 +55,10 @@
owner.special_role = null
..()
/datum/antagonist/traitor/proc/add_objective(var/datum/objective/O)
owner.objectives += O
/datum/antagonist/traitor/proc/add_objective(datum/objective/O)
objectives += O
/datum/antagonist/traitor/proc/remove_objective(var/datum/objective/O)
owner.objectives -= O
/datum/antagonist/traitor/proc/remove_objective(datum/objective/O)
objectives -= O
/datum/antagonist/traitor/proc/forge_traitor_objectives()
@@ -72,7 +70,17 @@
/datum/antagonist/traitor/proc/forge_human_objectives()
var/is_hijacker = FALSE
if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
var/datum/game_mode/dynamic/mode
var/is_dynamic = FALSE
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
if(GLOB.joined_player_list.len>=GLOB.dynamic_high_pop_limit)
is_hijacker = (prob(10) && mode.threat_level > CONFIG_GET(number/dynamic_hijack_high_population_requirement))
else
var/indice_pop = min(10,round(GLOB.joined_player_list.len/mode.pop_per_requirement)+1)
is_hijacker = (prob(10) && (mode.threat_level >= CONFIG_GET(number_list/dynamic_hijack_requirements)[indice_pop]))
else if (GLOB.joined_player_list.len >= 30) // Less murderboning on lowpop thanks
is_hijacker = prob(10)
var/martyr_chance = prob(20)
var/objective_count = is_hijacker //Hijacking counts towards number of objectives
@@ -89,15 +97,19 @@
forge_single_objective()
if(is_hijacker && objective_count <= toa) //Don't assign hijack if it would exceed the number of objectives set in config.traitor_objectives_amount
if (!(locate(/datum/objective/hijack) in owner.objectives))
if (!(locate(/datum/objective/hijack) in objectives))
var/datum/objective/hijack/hijack_objective = new
hijack_objective.owner = owner
add_objective(hijack_objective)
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on hijack.")
return
var/martyr_compatibility = 1 //You can't succeed in stealing if you're dead.
for(var/datum/objective/O in owner.objectives)
for(var/datum/objective/O in objectives)
if(!O.martyr_compatible)
martyr_compatibility = 0
break
@@ -106,10 +118,14 @@
var/datum/objective/martyr/martyr_objective = new
martyr_objective.owner = owner
add_objective(martyr_objective)
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_hijack_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on glorious death.")
return
else
if(!(locate(/datum/objective/escape) in owner.objectives))
if(!(locate(/datum/objective/escape) in objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
add_objective(escape_objective)
@@ -141,7 +157,18 @@
/datum/antagonist/traitor/proc/forge_single_human_objective() //Returns how many objectives are added
.=1
if(prob(50))
var/assassin_prob = 50
var/is_dynamic = FALSE
var/datum/game_mode/dynamic/mode
if(istype(SSticker.mode,/datum/game_mode/dynamic))
mode = SSticker.mode
is_dynamic = TRUE
assassin_prob = mode.threat_level*(2/3)
if(prob(assassin_prob))
if(is_dynamic)
var/threat_spent = CONFIG_GET(number/dynamic_assassinate_cost)
mode.spend_threat(threat_spent)
mode.log_threat("[owner.name] spent [threat_spent] on an assassination target.")
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/GLOB.joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
@@ -159,7 +186,7 @@
kill_objective.find_target()
add_objective(kill_objective)
else
if(prob(15) && !(locate(/datum/objective/download) in owner.objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
if(prob(15) && !(locate(/datum/objective/download) in objectives) && !(owner.assigned_role in list("Research Director", "Scientist", "Roboticist")))
var/datum/objective/download/download_objective = new
download_objective.owner = owner
download_objective.gen_amount_goal()
@@ -208,7 +208,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
var/unlock_text = "<span class='notice'>Hello World!</span>" //Text shown when an ability is unlocked
var/unlock_sound //Sound played when an ability is unlocked
/datum/AI_Module/proc/upgrade(mob/living/silicon/AI/AI) //Apply upgrades!
/datum/AI_Module/proc/upgrade(mob/living/silicon/ai/AI) //Apply upgrades!
return
/datum/AI_Module/large //Big, powerful stuff that can only be used once.
@@ -304,7 +304,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
sleep(30)
if(!owner || QDELETED(owner))
return
priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", 'sound/ai/aimalf.ogg')
priority_announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", "aimalf")
set_security_level("delta")
var/obj/machinery/doomsday_device/DOOM = new(owner_AI)
owner_AI.nuking = TRUE
@@ -397,7 +397,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
unlock_text = "<span class='notice'>You establish a power diversion to your turrets, upgrading their health and damage.</span>"
unlock_sound = 'sound/items/rped.ogg'
/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/AI/AI)
/datum/AI_Module/large/upgrade_turrets/upgrade(mob/living/silicon/ai/AI)
for(var/obj/machinery/porta_turret/ai/turret in GLOB.machines)
turret.obj_integrity += 30
turret.lethal_projectile = /obj/item/projectile/beam/laser/heavylaser //Once you see it, you will know what it means to FEAR.
@@ -9,7 +9,6 @@
var/datum/objective/martyr/normiesgetout = new
normiesgetout.owner = owner
objectives += normiesgetout
owner.objectives += objectives
/datum/antagonist/heartbreaker/on_gain()
forge_objectives()
@@ -12,7 +12,6 @@
protect_objective.human_check = FALSE
protect_objective.explanation_text = "Protect [date.name], your date."
objectives += protect_objective
owner.objectives += objectives
/datum/antagonist/valentine/on_gain()
forge_objectives()
@@ -34,8 +33,8 @@
//Squashed up a bit
/datum/antagonist/valentine/roundend_report()
var/objectives_complete = TRUE
if(owner.objectives.len)
for(var/datum/objective/objective in owner.objectives)
if(objectives.len)
for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
@@ -51,8 +50,8 @@
/datum/antagonist/valentine/chem/roundend_report()
var/objectives_complete = TRUE
if(owner.objectives.len)
for(var/datum/objective/objective in owner.objectives)
if(objectives.len)
for(var/datum/objective/objective in objectives)
if(!objective.check_completion())
objectives_complete = FALSE
break
@@ -8,7 +8,6 @@
var/datum/objective/hijack/hijack = new
hijack.owner = owner
objectives += hijack
owner.objectives |= objectives
/datum/antagonist/wishgranter/on_gain()
owner.special_role = "Avatar of the Wish Granter"
@@ -113,7 +113,7 @@
/obj/singularity/wizard/attack_tk(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
GET_COMPONENT_FROM(insaneinthemembrane, /datum/component/mood, C)
var/datum/component/mood/insaneinthemembrane = C.GetComponent(/datum/component/mood)
if(insaneinthemembrane.sanity < 15)
return //they've already seen it and are about to die, or are just too insane to care
to_chat(C, "<span class='userdanger'>OH GOD! NONE OF IT IS REAL! NONE OF IT IS REEEEEEEEEEEEEEEEEEEEEEEEAL!</span>")
@@ -255,7 +255,7 @@
/obj/item/voodoo/attackby(obj/item/I, mob/user, params)
if(target && cooldown < world.time)
if(I.is_hot())
if(I.get_temperature())
to_chat(target, "<span class='userdanger'>You suddenly feel very hot</span>")
target.adjust_bodytemperature(50)
GiveHint(target)
@@ -324,14 +324,11 @@
cooldown = world.time + cooldown_time
/obj/item/voodoo/proc/update_targets()
possible = list()
LAZYINITLIST(possible)
if(!voodoo_link)
return
var/list/prints = voodoo_link.return_fingerprints()
if(!length(prints))
return FALSE
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
if(prints[md5(H.dna.uni_identity)])
if(md5(H.dna.uni_identity) in voodoo_link.fingerprints)
possible |= H
/obj/item/voodoo/proc/GiveHint(mob/victim,force=0)
@@ -343,9 +340,9 @@
to_chat(victim, "<span class='notice'>You feel a dark presence from [A.name]</span>")
/obj/item/voodoo/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] links the voodoo doll to [user.p_them()]self and sits on it, infinitely crushing [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
user.gib()
return(BRUTELOSS)
user.visible_message("<span class='suicide'>[user] links the voodoo doll to [user.p_them()]self and sits on it, infinitely crushing [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
user.gib()
return(BRUTELOSS)
/obj/item/voodoo/fire_act(exposed_temperature, exposed_volume)
if(target)
@@ -386,7 +383,9 @@
if(!istype(user) || on_cooldown)
return
var/turf/T = get_turf(user)
if(!T)
var/area/A = get_area(user)
if(!T || !A || A.noteleport)
to_chat(user, "<span class='warning'>You play \the [src], yet no sound comes out of it... Looks like it won't work here.</span>")
return
on_cooldown = TRUE
last_user = user
@@ -238,6 +238,7 @@
T.stop_sound_channel(CHANNEL_HEARTBEAT)
T.invisibility = INVISIBILITY_ABSTRACT
T.dust_animation()
QDEL_IN(T, 5)
var/mob/living/simple_animal/shade/S = new /mob/living/simple_animal/shade(src)
S.status_flags |= GODMODE //So they won't die inside the stone somehow
S.canmove = FALSE//Can't move out of the soul stone
@@ -11,12 +11,18 @@
var/buy_word = "Learn"
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
var/list/no_coexistance_typecache //Used so you can't have specific spells together
var/dynamic_cost = 0 // How much threat the spell costs to purchase for dynamic.
var/dynamic_requirement = 0 // How high the threat level needs to be for purchasing in dynamic.
/datum/spellbook_entry/New()
..()
no_coexistance_typecache = typecacheof(no_coexistance_typecache)
/datum/spellbook_entry/proc/IsAvailible() // For config prefs / gamemode restrictions - these are round applied
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
if(dynamic_requirement > 0 && mode.threat_level < dynamic_requirement)
return 0
return 1
/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user,obj/item/spellbook/book) // Specific circumstances
@@ -25,6 +31,10 @@
for(var/spell in user.mind.spell_list)
if(is_type_in_typecache(spell, no_coexistance_typecache))
return 0
if(dynamic_cost>0 && istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
if(mode.threat < dynamic_cost)
return 0
return 1
/datum/spellbook_entry/proc/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) //return 1 on success
@@ -60,6 +70,10 @@
SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[aspell.spell_level]"))
return 1
//No same spell found - just learn it
if(dynamic_cost > 0 && istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
mode.spend_threat(dynamic_cost)
mode.log_threat("Wizard spent [dynamic_cost] on [name].")
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
user.mind.AddSpell(S)
to_chat(user, "<span class='notice'>You have learned [S.name].</span>")
@@ -83,6 +97,10 @@
if(!S)
S = new spell_type()
var/spell_levels = 0
if(dynamic_cost > 0 && istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
mode.refund_threat(dynamic_cost)
mode.log_threat("Wizard refunded [dynamic_cost] on [name].")
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
spell_levels = aspell.spell_level
@@ -285,6 +303,8 @@
name = "Staff of Change"
desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself."
item_path = /obj/item/gun/magic/staff/change
dynamic_requirement = 60
dynamic_cost = 20
/datum/spellbook_entry/item/staffanimation
name = "Staff of Animation"
@@ -369,6 +389,8 @@
desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side."
item_path = /obj/item/antag_spawner/contract
category = "Assistance"
dynamic_requirement = 50
dynamic_cost = 10
/datum/spellbook_entry/item/guardian
name = "Guardian Deck"
@@ -388,6 +410,11 @@
item_path = /obj/item/antag_spawner/slaughter_demon
limit = 3
category = "Assistance"
dynamic_requirement = 60
/datum/spellbook_entry/item/bloodbottle/New()
..()
dynamic_cost = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]
/datum/spellbook_entry/item/hugbottle
name = "Bottle of Tickles"
@@ -402,6 +429,11 @@
cost = 1 //non-destructive; it's just a jape, sibling!
limit = 3
category = "Assistance"
dynamic_requirement = 40
/datum/spellbook_entry/item/hugbottle/New()
..()
dynamic_cost = CONFIG_GET(keyed_list/dynamic_cost)["slaughter_demon"]/3
/datum/spellbook_entry/item/mjolnir
name = "Mjolnir"
@@ -465,7 +497,7 @@
if(!SSticker.mode)
return FALSE
else
return TRUE
return ..()
/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
@@ -478,11 +510,13 @@
/datum/spellbook_entry/summon/guns
name = "Summon Guns"
desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. Just be careful not to stand still too long!"
dynamic_cost = 10
dynamic_requirement = 60
/datum/spellbook_entry/summon/guns/IsAvailible()
if(!SSticker.mode) // In case spellbook is placed on map
return 0
return !CONFIG_GET(flag/no_summon_guns)
return (!CONFIG_GET(flag/no_summon_guns) && ..())
/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
@@ -490,16 +524,23 @@
active = 1
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon guns!</span>")
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
var/threat_spent = dynamic_cost
mode.spend_threat(threat_spent)
mode.log_threat("Wizard spent [threat_spent] on summon guns.")
return 1
/datum/spellbook_entry/summon/magic
name = "Summon Magic"
desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time."
dynamic_cost = 10
dynamic_requirement = 60
/datum/spellbook_entry/summon/magic/IsAvailible()
if(!SSticker.mode) // In case spellbook is placed on map
return 0
return !CONFIG_GET(flag/no_summon_magic)
return (!CONFIG_GET(flag/no_summon_guns) && ..())
/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
@@ -507,21 +548,33 @@
active = 1
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon magic!</span>")
if(istype(SSticker.mode,/datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
var/threat_spent = dynamic_cost
mode.spend_threat(threat_spent)
mode.log_threat("Wizard spent [threat_spent] on summon magic.")
return 1
/datum/spellbook_entry/summon/events
name = "Summon Events"
desc = "Give Murphy's law a little push and replace all events with special wizard ones that will confound and confuse everyone. Multiple castings increase the rate of these events."
dynamic_cost = 20
dynamic_requirement = 60
var/times = 0
/datum/spellbook_entry/summon/events/IsAvailible()
if(!SSticker.mode) // In case spellbook is placed on map
return 0
return !CONFIG_GET(flag/no_summon_events)
return (!CONFIG_GET(flag/no_summon_events) && ..())
/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user,obj/item/spellbook/book)
SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name)
summonevents()
if(istype(SSticker.mode,/datum/game_mode/dynamic) && times == 0)
var/datum/game_mode/dynamic/mode = SSticker.mode
var/threat_spent = dynamic_cost
mode.spend_threat(threat_spent)
mode.log_threat("Wizard spent [threat_spent] on summon events.")
times++
playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, 1)
to_chat(user, "<span class='notice'>You have cast summon events.</span>")
@@ -626,16 +679,16 @@
dat += {"
<head>
<style type="text/css">
body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
ul#tabs li { display: inline; }
ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
ul#tabs li a:hover { background-color: #f1f0ee; }
ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
div.tabContent.hide { display: none; }
</style>
</head>
body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
ul#tabs li { display: inline; }
ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
ul#tabs li a:hover { background-color: #f1f0ee; }
ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
div.tabContent.hide { display: none; }
</style>
</head>
"}
dat += {"[content]</body></html>"}
return dat
+7 -9
View File
@@ -57,19 +57,19 @@
if(!GLOB.wizardstart.len)
SSjob.SendToLateJoin(owner.current)
to_chat(owner, "HOT INSERTION, GO GO GO")
owner.current.forceMove(pick(GLOB.wizardstart))
else
owner.current.forceMove(pick(GLOB.wizardstart))
/datum/antagonist/wizard/proc/create_objectives()
var/datum/objective/new_objective = new("Cause as much creative mayhem as you can aboard the station! The more outlandish your methods of achieving this, the better! Make sure there's a decent amount of crew alive to tell of your tale.")
new_objective.completed = TRUE //So they can greentext without admin intervention.
new_objective.owner = owner
objectives += new_objective
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
objectives += escape_objective
for(var/datum/objective/O in objectives)
owner.objectives += O
if (!(locate(/datum/objective/escape) in objectives))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = owner
objectives += escape_objective
/datum/antagonist/wizard/on_removal()
unregister()
@@ -183,7 +183,6 @@
new_objective.owner = owner
new_objective.target = master
new_objective.explanation_text = "Protect [master.current.real_name], the wizard."
owner.objectives += new_objective
objectives += new_objective
//Random event wizard
@@ -251,7 +250,6 @@
/datum/antagonist/wizard/academy/create_objectives()
var/datum/objective/new_objective = new("Protect Wizard Academy from the intruders")
new_objective.owner = owner
owner.objectives += new_objective
objectives += new_objective
//Solo wizard report
+3 -1
View File
@@ -201,8 +201,10 @@
/obj/item/assembly/flash/cyborg
/obj/item/assembly/flash/cyborg/attack(mob/living/M, mob/user)
..()
. = ..()
new /obj/effect/temp_visual/borgflash(get_turf(src))
if(. && !CONFIG_GET(flag/disable_borg_flash_knockdown) && iscarbon(M) && !M.resting && !M.get_eye_protection())
M.Knockdown(80)
/obj/item/assembly/flash/cyborg/attack_self(mob/user)
..()
+9 -5
View File
@@ -10,7 +10,7 @@
var/maxlength = 8
var/list/obj/effect/beam/i_beam/beams
var/olddir = 0
var/datum/component/redirect/listener
var/turf/listeningTo
var/hearing_range = 3
/obj/item/assembly/infra/Initialize()
@@ -33,7 +33,7 @@
/obj/item/assembly/infra/Destroy()
STOP_PROCESSING(SSobj, src)
QDEL_NULL(listener)
listeningTo = null
QDEL_LIST(beams)
. = ..()
@@ -138,7 +138,7 @@
. = ..()
setDir(t)
/obj/item/assembly/infra/throw_at()
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
. = ..()
olddir = dir
@@ -163,8 +163,12 @@
next_activate = world.time + 30
/obj/item/assembly/infra/proc/switchListener(turf/newloc)
QDEL_NULL(listener)
listener = newloc.AddComponent(/datum/component/redirect, list(COMSIG_ATOM_EXITED = CALLBACK(src, .proc/check_exit)))
if(listeningTo == newloc)
return
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_ATOM_EXITED)
RegisterSignal(newloc, COMSIG_ATOM_EXITED, .proc/check_exit)
listeningTo = newloc
/obj/item/assembly/infra/proc/check_exit(datum/source, atom/movable/offender)
if(QDELETED(src))
@@ -199,7 +199,7 @@
var/radiated_temperature = location.air.temperature*FIRE_SPREAD_RADIOSITY_SCALE
for(var/t in location.atmos_adjacent_turfs)
var/turf/open/T = t
if(T.active_hotspot)
if(!T.active_hotspot)
T.hotspot_expose(radiated_temperature, CELL_VOLUME/4)
else
@@ -1,4 +1,6 @@
/atom/var/CanAtmosPass = ATMOS_PASS_YES
/atom/var/CanAtmosPassVertical = ATMOS_PASS_YES
/atom/proc/CanAtmosPass(turf/T)
switch (CanAtmosPass)
if (ATMOS_PASS_PROC)
@@ -8,42 +10,47 @@
else
return CanAtmosPass
/turf/closed/CanAtmosPass = ATMOS_PASS_NO
/turf/CanAtmosPass = ATMOS_PASS_NO
/turf/CanAtmosPassVertical = ATMOS_PASS_NO
/turf/open/CanAtmosPass = ATMOS_PASS_PROC
/turf/open/CanAtmosPass(turf/T)
var/R
if(blocks_air || T.blocks_air)
R = 1
/turf/open/CanAtmosPassVertical = ATMOS_PASS_PROC
/turf/open/CanAtmosPass(turf/T, vertical = FALSE)
var/dir = vertical? get_dir_multiz(src, T) : get_dir(src, T)
var/opp = dir_inverse_multiz(dir)
var/R = FALSE
if(vertical && !(zAirOut(dir, T) && T.zAirIn(dir, src)))
R = TRUE
if(blocks_air || T.blocks_air)
R = TRUE
if (T == src)
return !R
for(var/obj/O in contents+T.contents)
var/turf/other = (O.loc == src ? T : src)
if(!CANATMOSPASS(O, other))
R = 1
if(!(vertical? (CANVERTICALATMOSPASS(O, other)) : (CANATMOSPASS(O, other))))
R = TRUE
if(O.BlockSuperconductivity()) //the direction and open/closed are already checked on CanAtmosPass() so there are no arguments
var/D = get_dir(src, T)
atmos_supeconductivity |= D
D = get_dir(T, src)
T.atmos_supeconductivity |= D
return 0 //no need to keep going, we got all we asked
atmos_supeconductivity |= dir
T.atmos_supeconductivity |= opp
return FALSE //no need to keep going, we got all we asked
atmos_supeconductivity &= ~get_dir(src, T)
T.atmos_supeconductivity &= ~get_dir(T, src)
atmos_supeconductivity &= ~dir
T.atmos_supeconductivity &= ~opp
return !R
/atom/movable/proc/BlockSuperconductivity() // objects that block air and don't let superconductivity act. Only firelocks atm.
return 0
return FALSE
/turf/proc/CalculateAdjacentTurfs()
var/list/atmos_adjacent_turfs = src.atmos_adjacent_turfs
for(var/direction in GLOB.cardinals)
var/turf/T = get_step(src, direction)
if(!T)
/turf/proc/ImmediateCalculateAdjacentTurfs()
var/canpass = CANATMOSPASS(src, src)
var/canvpass = CANVERTICALATMOSPASS(src, src)
for(var/direction in GLOB.cardinals_multiz)
var/turf/T = get_step_multiz(src, direction)
if(!isopenturf(T))
continue
if( !(blocks_air || T.blocks_air) && CANATMOSPASS(T, src) )
if(!(blocks_air || T.blocks_air) && ((direction & (UP|DOWN))? (canvpass && CANVERTICALATMOSPASS(T, src)) : (canpass && CANATMOSPASS(T, src))) )
LAZYINITLIST(atmos_adjacent_turfs)
LAZYINITLIST(T.atmos_adjacent_turfs)
atmos_adjacent_turfs[T] = TRUE
@@ -72,11 +79,13 @@
var/turf/curloc = src
for (var/direction in GLOB.diagonals)
for (var/direction in GLOB.diagonals_multiz)
var/matchingDirections = 0
var/turf/S = get_step(curloc, direction)
var/turf/S = get_step_multiz(curloc, direction)
if(!S)
continue
for (var/checkDirection in GLOB.cardinals)
for (var/checkDirection in GLOB.cardinals_multiz)
var/turf/checkTurf = get_step(S, checkDirection)
if(!S.atmos_adjacent_turfs || !S.atmos_adjacent_turfs[checkTurf])
continue
@@ -98,13 +107,13 @@
/turf/air_update_turf(command = 0)
if(command)
CalculateAdjacentTurfs()
ImmediateCalculateAdjacentTurfs()
SSair.add_to_active(src,command)
/atom/movable/proc/move_update_air(turf/T)
if(isturf(T))
T.air_update_turf(1)
air_update_turf(1)
if(isturf(T))
T.air_update_turf(1)
air_update_turf(1)
/atom/proc/atmos_spawn_air(text) //because a lot of people loves to copy paste awful code lets just make an easy proc to spawn your plasma fires
var/turf/open/T = get_turf(src)
@@ -15,7 +15,7 @@
//used for mapping and for breathing while in walls (because that's a thing that needs to be accounted for...)
//string parsed by /datum/gas/proc/copy_from_turf
var/initial_gas_mix = "o2=22;n2=82;TEMP=293.15"
var/initial_gas_mix = OPENTURF_DEFAULT_ATMOS
//approximation of MOLES_O2STANDARD and MOLES_N2STANDARD pending byond allowing constant expressions to be embedded in constant strings
// If someone will place 0 of some gas there, SHIT WILL BREAK. Do not do that.
@@ -42,8 +42,7 @@
/turf/open/Destroy()
if(active_hotspot)
qdel(active_hotspot)
active_hotspot = null
QDEL_NULL(active_hotspot)
// Adds the adjacent turfs to the current atmos processing
for(var/T in atmos_adjacent_turfs)
SSair.add_to_active(T)
@@ -210,9 +210,9 @@
return cached_results["fire"] ? REACTING : NO_REACTION
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again)
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again (and again, and again). Again!
//Fusion Rework Counter: Please increment this if you make a major overhaul to this system again.
//5 reworks
//6 reworks
/datum/gas_reaction/fusion
exclude = FALSE
@@ -220,100 +220,79 @@
name = "Plasmic Fusion"
id = "fusion"
//Since fusion isn't really intended to happen in successive chains, the requirements are very high
/datum/gas_reaction/fusion/init_reqs()
min_requirements = list(
"TEMP" = FUSION_TEMPERATURE_THRESHOLD,
"ENER" = FUSION_ENERGY_THRESHOLD,
/datum/gas/tritium = FUSION_TRITIUM_MOLES_USED,
/datum/gas/plasma = FUSION_MOLE_THRESHOLD,
/datum/gas/tritium = FUSION_MOLE_THRESHOLD
)
/datum/gas/carbon_dioxide = FUSION_MOLE_THRESHOLD)
/datum/gas_reaction/fusion/react(datum/gas_mixture/air, datum/holder)
var/list/cached_gases = air.gases
var/temperature = air.temperature
if(!air.analyzer_results)
air.analyzer_results = new
var/list/cached_scan_results = air.analyzer_results
var/turf/open/location
if (istype(holder,/datum/pipeline)) //Find the tile the reaction is occuring on, or a random part of the network if it's a pipenet.
var/datum/pipeline/fusion_pipenet = holder
location = get_turf(pick(fusion_pipenet.members))
else
location = get_turf(holder)
if(!air.analyzer_results)
air.analyzer_results = new
var/list/cached_scan_results = air.analyzer_results
var/old_heat_capacity = air.heat_capacity()
var/reaction_energy = 0
var/mediation = FUSION_MEDIATION_FACTOR*(air.heat_capacity()-(cached_gases[/datum/gas/plasma]*GLOB.meta_gas_specific_heats[/datum/gas/plasma]))/(air.total_moles()-cached_gases[/datum/gas/plasma]) //This is the average specific heat of the mixture,not including plasma.
var/gases_fused = air.total_moles() - cached_gases[/datum/gas/plasma]
var/plasma_differential = (cached_gases[/datum/gas/plasma] - gases_fused) / air.total_moles()
var/reaction_efficiency = FUSION_EFFICIENCY_BASE ** -((plasma_differential ** 2) / FUSION_EFFICIENCY_DIVISOR) //https://www.desmos.com/calculator/6jjx3vdrvx
var/reaction_energy = 0 //Reaction energy can be negative or positive, for both exothermic and endothermic reactions.
var/initial_plasma = cached_gases[/datum/gas/plasma]
var/initial_carbon = cached_gases[/datum/gas/carbon_dioxide]
var/scale_factor = (air.volume)/(PI) //We scale it down by volume/Pi because for fusion conditions, moles roughly = 2*volume, but we want it to be based off something constant between reactions.
var/toroidal_size = (2*PI)+TORADIANS(arctan((air.volume-TOROID_VOLUME_BREAKEVEN)/TOROID_VOLUME_BREAKEVEN)) //The size of the phase space hypertorus
var/gas_power = 0
var/list/gas_fusion_powers = GLOB.meta_gas_fusions
for (var/gas_id in cached_gases)
gas_power += reaction_efficiency * (GLOB.meta_gas_fusions[gas_id]*cached_gases[gas_id])
gas_power += (gas_fusion_powers[gas_id]*cached_gases[gas_id])
var/instability = MODULUS((gas_power*INSTABILITY_GAS_POWER_FACTOR)**2,toroidal_size) //Instability effects how chaotic the behavior of the reaction is
cached_scan_results[id] = instability//used for analyzer feedback
var/power_ratio = gas_power/mediation
cached_scan_results[id] = power_ratio //used for analyzer feedback
var/plasma = (initial_plasma-FUSION_MOLE_THRESHOLD)/(scale_factor) //We have to scale the amounts of carbon and plasma down a significant amount in order to show the chaotic dynamics we want
var/carbon = (initial_carbon-FUSION_MOLE_THRESHOLD)/(scale_factor) //We also subtract out the threshold amount to make it harder for fusion to burn itself out.
for (var/gas_id in cached_gases) //and now we fuse
cached_gases[gas_id] = 0
//The reaction is a specific form of the Kicked Rotator system, which displays chaotic behavior and can be used to model particle interactions.
plasma = MODULUS(plasma - (instability*sin(TODEGREES(carbon))), toroidal_size)
carbon = MODULUS(carbon - plasma, toroidal_size)
var/radiation_power = (FUSION_RADIATION_FACTOR * power_ratio) / (power_ratio + FUSION_RADIATION_CONSTANT) //https://www.desmos.com/calculator/4i1f296phl
var/zap_power = ((FUSION_ZAP_POWER_ASYMPTOTE * power_ratio) / (power_ratio + FUSION_ZAP_POWER_CONSTANT)) + FUSION_ZAP_POWER_BASE //https://www.desmos.com/calculator/n0zkdpxnrr
var/do_explosion = FALSE
var/zap_range //these ones are set later
var/fusion_prepare_to_die_edition_rng
if (power_ratio > FUSION_SUPER_TIER_THRESHOLD) //power ratio 50+: SUPER TIER. The gases become so energized that they fuse into a ton of tritium, which is pretty nice! Until you consider the fact that everything just exploded, the canister is probably going to break and you're irradiated.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_SUPER * (power_ratio / FUSION_ENERGY_DIVISOR_SUPER)
cached_gases[/datum/gas/tritium] += gases_fused * FUSION_GAS_CREATION_FACTOR_TRITIUM //60% of the gas is converted to energy, 40% to trit
fusion_prepare_to_die_edition_rng = 100 //Wait a minute..
do_explosion = TRUE
zap_range = FUSION_ZAP_RANGE_SUPER
cached_gases[/datum/gas/plasma] = plasma*scale_factor + FUSION_MOLE_THRESHOLD //Scales the gases back up
cached_gases[/datum/gas/carbon_dioxide] = carbon*scale_factor + FUSION_MOLE_THRESHOLD
var/delta_plasma = initial_plasma - cached_gases[/datum/gas/plasma]
else if (power_ratio > FUSION_HIGH_TIER_THRESHOLD) //power ratio 20-50; High tier. The reaction is so energized that it fuses into a small amount of stimulum, and some pluoxium. Very dangerous, but super cool and super useful.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_HIGH * (power_ratio / FUSION_ENERGY_DIVISOR_HIGH)
cached_gases[/datum/gas/stimulum] += gases_fused * FUSION_GAS_CREATION_FACTOR_STIM //40% of the gas is converted to energy, 60% to stim and pluox
cached_gases[/datum/gas/pluoxium] += gases_fused * FUSION_GAS_CREATION_FACTOR_PLUOX
fusion_prepare_to_die_edition_rng = power_ratio //Now we're getting into dangerous territory
do_explosion = TRUE
zap_range = FUSION_ZAP_RANGE_HIGH
else if (power_ratio > FUSION_MID_TIER_THRESHOLD) //power_ratio 5 to 20; Mediation is overpowered, fusion reaction starts to break down.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_MID * (power_ratio / FUSION_ENERGY_DIVISOR_MID)
cached_gases[/datum/gas/nitryl] += gases_fused * FUSION_GAS_CREATION_FACTOR_NITRYL //20% of the gas is converted to energy, 80% to nitryl and N2O
cached_gases[/datum/gas/nitrous_oxide] += gases_fused * FUSION_GAS_CREATION_FACTOR_N2O
fusion_prepare_to_die_edition_rng = power_ratio * FUSION_MID_TIER_RAD_PROB_FACTOR //Still unlikely, but don't stand next to the reaction unprotected
zap_range = FUSION_ZAP_RANGE_MID
else //power ratio 0 to 5; Gas power is overpowered. Fusion isn't nearly as powerful.
reaction_energy += gases_fused * FUSION_RELEASE_ENERGY_LOW * (power_ratio / FUSION_ENERGY_DIVISOR_LOW)
cached_gases[/datum/gas/bz] += gases_fused * FUSION_GAS_CREATION_FACTOR_BZ //10% of the gas is converted to energy, 90% to BZ and CO2
cached_gases[/datum/gas/carbon_dioxide] += gases_fused * FUSION_GAS_CREATION_FACTOR_CO2
fusion_prepare_to_die_edition_rng = power_ratio * FUSION_LOW_TIER_RAD_PROB_FACTOR //Low, but still something to look out for
zap_range = FUSION_ZAP_RANGE_LOW
//All the deadly consequences of fusion, consolidated for your viewing pleasure
if (location)
if(prob(fusion_prepare_to_die_edition_rng)) //Some.. permanent effects
if(do_explosion)
explosion(location, 0, 0, 5, power_ratio, TRUE, TRUE) //large shockwave, the actual radius is quite small - people will recognize that you're doing fusion
radiation_pulse(location, radiation_power) //You mean causing a super-tier fusion reaction in the halls is a bad idea?
SSresearch.science_tech.add_point_type(TECHWEB_POINT_TYPE_DEFAULT, 30000)//The science is cool though.
playsound(location, 'sound/effects/supermatter.ogg', 100, 0)
else
playsound(location, 'sound/effects/phasein.ogg', 75, 0)
//These will always happen, so be prepared
tesla_zap(location, zap_range, zap_power, TESLA_FUSION_FLAGS) //larpers beware
location.fire_nuclear_particles(power_ratio) //see code/modules/projectile/energy/nuclear_particle.dm
reaction_energy += delta_plasma*PLASMA_BINDING_ENERGY //Energy is gained or lost corresponding to the creation or destruction of mass.
if(instability < FUSION_INSTABILITY_ENDOTHERMALITY)
reaction_energy = max(reaction_energy,0) //Stable reactions don't end up endothermic.
else if (reaction_energy < 0)
reaction_energy *= (instability-FUSION_INSTABILITY_ENDOTHERMALITY)**0.5
if(air.thermal_energy() + reaction_energy < 0) //No using energy that doesn't exist.
cached_gases[/datum/gas/plasma] = initial_plasma
cached_gases[/datum/gas/carbon_dioxide] = initial_carbon
return NO_REACTION
cached_gases[/datum/gas/tritium] -= FUSION_TRITIUM_MOLES_USED
//The decay of the tritium and the reaction's energy produces waste gases, different ones depending on whether the reaction is endo or exothermic
if(reaction_energy > 0)
cached_gases[/datum/gas/oxygen] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)
cached_gases[/datum/gas/nitrous_oxide] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*FUSION_TRITIUM_CONVERSION_COEFFICIENT)
else
cached_gases[/datum/gas/bz] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)
cached_gases[/datum/gas/nitryl] += FUSION_TRITIUM_MOLES_USED*(reaction_energy*-FUSION_TRITIUM_CONVERSION_COEFFICIENT)
if(reaction_energy)
if(location)
var/particle_chance = ((PARTICLE_CHANCE_CONSTANT)/(reaction_energy-PARTICLE_CHANCE_CONSTANT)) + 1//Asymptopically approaches 100% as the energy of the reaction goes up.
if(prob(PERCENT(particle_chance)))
location.fire_nuclear_particle()
var/rad_power = max((FUSION_RAD_COEFFICIENT/instability) + FUSION_RAD_MAX,0)
radiation_pulse(location,rad_power)
var/new_heat_capacity = air.heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
air.temperature = max(((temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB)
air.temperature = CLAMP(((air.temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB,INFINITY)
return REACTING
/datum/gas_reaction/nitrylformation //The formation of nitryl. Endothermic. Requires N2O as a catalyst.
@@ -28,8 +28,8 @@ Pipelines + Other Objects -> Pipe network
var/piping_layer = PIPING_LAYER_DEFAULT
var/pipe_flags = NONE
var/global/list/iconsetids = list()
var/global/list/pipeimages = list()
var/static/list/iconsetids = list()
var/static/list/pipeimages = list()
var/image/pipe_vision_img = null
@@ -1,5 +1,3 @@
#define CRYOMOBS 'icons/obj/cryo_mobs.dmi'
/obj/machinery/atmospherics/components/unary/cryo_cell
name = "cryo cell"
icon = 'icons/obj/cryogenics.dmi'
@@ -211,7 +209,7 @@
if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
cold_protection = H.get_cold_protection(air1.temperature)
cold_protection = H.get_thermal_protection(air1.temperature, TRUE)
if(abs(temperature_delta) > 1)
var/air_heat_capacity = air1.heat_capacity()
+29
View File
@@ -0,0 +1,29 @@
obj/machinery/atmospherics/pipe/simple/multiz ///This is an atmospherics pipe which can relay air up a deck (Z+1). It currently only supports being on pipe layer 1
name = "multi deck pipe adapter"
desc = "An adapter which allows pipes to connect to other pipenets on different decks."
icon_state = "multiz_pipe"
icon = 'icons/obj/atmos.dmi'
/obj/machinery/atmospherics/pipe/simple/multiz/update_icon()
. = ..()
cut_overlays() //This adds the overlay showing it's a multiz pipe. This should go above turfs and such
var/image/multiz_overlay_node = new(src) //If we have a firing state, light em up!
multiz_overlay_node.icon = 'icons/obj/atmos.dmi'
multiz_overlay_node.icon_state = "multiz_pipe"
multiz_overlay_node.layer = HIGH_OBJ_LAYER
add_overlay(multiz_overlay_node)
///Attempts to locate a multiz pipe that's above us, if it finds one it merges us into its pipenet
/obj/machinery/atmospherics/pipe/simple/multiz/pipeline_expansion()
icon = 'icons/obj/atmos.dmi' //Just to refresh.
var/turf/T = get_turf(src)
var/obj/machinery/atmospherics/pipe/simple/multiz/above = locate(/obj/machinery/atmospherics/pipe/simple/multiz) in(SSmapping.get_turf_above(T))
var/obj/machinery/atmospherics/pipe/simple/multiz/below = locate(/obj/machinery/atmospherics/pipe/simple/multiz) in(SSmapping.get_turf_below(T))
if(below)
below.pipeline_expansion() //If we've got one below us, force it to add us on facebook
if(above)
nodes += above
above.nodes += src //Two way travel :)
return ..()
else
return ..()
+67 -6
View File
@@ -17,6 +17,7 @@
var/faction = null
var/permanent = FALSE //If true, the spawner will not disappear upon running out of uses.
var/random = FALSE //Don't set a name or gender, just go random
var/antagonist_type
var/objectives = null
var/uses = 1 //how many times can we spawn from it. set to -1 for infinite.
var/brute_damage = 0
@@ -43,9 +44,8 @@
return
if(isobserver(user))
var/mob/dead/observer/O = user
if(!O.can_reenter_round)
to_chat(user, "<span class='warning'>You are unable to reenter the round.</span>")
return
if(!O.can_reenter_round())
return FALSE
var/ghost_role = alert(latejoinercalling ? "Latejoin as [mob_name]? (This is a ghost role, and as such, it's very likely to be off-station.)" : "Become [mob_name]? (Warning, You can no longer be cloned!)",,"Yes","No")
if(ghost_role == "No" || !loc)
return
@@ -111,9 +111,16 @@
if(show_flavour)
to_chat(M, "[flavour_text]")
var/datum/mind/MM = M.mind
var/datum/antagonist/A
if(antagonist_type)
A = MM.add_antag_datum(antagonist_type)
if(objectives)
if(!A)
A = MM.add_antag_datum(/datum/antagonist/custom)
for(var/objective in objectives)
MM.objectives += new/datum/objective(objective)
var/datum/objective/O = new/datum/objective(objective)
O.owner = MM
A.objectives += O
if(assignedrole)
M.mind.assigned_role = assignedrole
special(M, name)
@@ -249,7 +256,7 @@
//Non-human spawners
/obj/effect/mob_spawn/AICorpse/create() //Creates a corrupted AI
/obj/effect/mob_spawn/AICorpse/create(ckey, name) //Creates a corrupted AI
var/A = locate(/mob/living/silicon/ai) in loc
if(A)
return
@@ -269,7 +276,7 @@
/obj/effect/mob_spawn/slime/equip(mob/living/simple_animal/slime/S)
S.colour = mobcolour
/obj/effect/mob_spawn/human/facehugger/create() //Creates a squashed facehugger
/obj/effect/mob_spawn/human/facehugger/create(ckey, name) //Creates a squashed facehugger
var/obj/item/clothing/mask/facehugger/O = new(src.loc) //variable O is a new facehugger at the location of the landmark
O.name = src.name
O.Die() //call the facehugger's death proc
@@ -587,3 +594,57 @@
shoes = /obj/item/clothing/shoes/sneakers/black
suit = /obj/item/clothing/suit/armor/vest
glasses = /obj/item/clothing/glasses/sunglasses/reagent
/obj/effect/mob_spawn/human/lavaknight
name = "odd cryogenics pod"
desc = "A humming cryo pod. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant."
mob_name = "a displaced knight from another dimension"
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
roundstart = FALSE
id_job = "Knight"
job_description = "Cydonian Knight"
death = FALSE
random = TRUE
outfit = /datum/outfit/lavaknight
mob_species = /datum/species/human
flavour_text = "<font size=3><b>Y</b></font><b>ou are a knight who conveniently has some form of retrograde amnesia. \
You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \
Remember: hostile creatures and such are fair game for attacking, but <span class='danger'>under no circumstances are you to attack anything capable of thought and/or speech</span> unless it has made it its life's calling to chase you to the ends of the earth."
assignedrole = "Cydonian Knight"
/obj/effect/mob_spawn/human/lavaknight/special(mob/living/new_spawn)
if(ishuman(new_spawn))
var/mob/living/carbon/human/H = new_spawn
H.dna.features["mam_ears"] = "Cat, Big" //cat people
H.dna.features["mcolor"] = H.hair_color
H.update_body()
/obj/effect/mob_spawn/human/lavaknight/Destroy()
new/obj/structure/showcase/machinery/oldpod/used(drop_location())
return ..()
/datum/outfit/lavaknight
name = "Cydonian Knight"
uniform = /obj/item/clothing/under/assistantformal
mask = /obj/item/clothing/mask/breath
shoes = /obj/item/clothing/shoes/sneakers/black
r_pocket = /obj/item/melee/transforming/energy/sword/cx
suit = /obj/item/clothing/suit/space/hardsuit/lavaknight
suit_store = /obj/item/tank/internals/oxygen
id = /obj/item/card/id/knight/blue
/obj/effect/mob_spawn/human/lavaknight/captain
name = "odd gilded cryogenics pod"
desc = "A humming cryo pod that appears to be gilded. You can barely recognise a faint glow underneath the built up ice. The machine is attempting to wake up its occupant."
flavour_text = "<font size=3><b>Y</b></font><b>ou are a knight who conveniently has some form of retrograde amnesia. \
You cannot remember where you came from. However, a few things remain burnt into your mind, most prominently a vow to never harm another sapient being under any circumstances unless it is hellbent on ending your life. \
Remember: hostile creatures and such are fair game for attacking, but <span class='danger'>under no circumstances are you to attack anything capable of thought and/or speech</span> unless it has made it its life's calling to chase you to the ends of the earth. \
You feel a natural instict to lead, and as such, you should strive to lead your comrades to safety, and hopefully home. You also feel a burning determination to uphold your vow, as well as your fellow comrade's."
outfit = /datum/outfit/lavaknight/captain
id_job = "Knight Captain"
/datum/outfit/lavaknight/captain
name ="Cydonian Knight Captain"
l_pocket = /obj/item/twohanded/dualsaber/hypereutactic
id = /obj/item/card/id/knight/captain

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