Merge remote-tracking branch 'upstream/master' into ambitioncheck
This commit is contained in:
@@ -115,9 +115,9 @@ GLOBAL_PROTECT(LastAdminCalledProc)
|
||||
//adv proc call this, ya nerds
|
||||
/world/proc/WrapAdminProcCall(datum/target, procname, list/arguments)
|
||||
if(target == GLOBAL_PROC)
|
||||
return call("/proc/[procname]")(arglist(arguments))
|
||||
else if(target != world)
|
||||
return call(target, procname)(arglist(arguments))
|
||||
return text2path("/proc/[procname]")? call("/proc/[procname]")(arglist(arguments)) : null
|
||||
else if(target != world && istype(target, /datum)) // isdatum check incase someone manages to call WrapAdminProcCall(global) which would otherwise crash the process entirely
|
||||
return hascall(target, procname)? call(target, procname)(arglist(arguments)) : null
|
||||
else
|
||||
log_admin("[key_name(usr)] attempted to call world/proc/[procname] with arguments: [english_list(arguments)]")
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
"name" = initial(item.name),
|
||||
"desc" = initial(item.desc),
|
||||
// at this point initializing the item is probably faster tbh
|
||||
"sprite" = icon2base64(icon(initial(item.icon), initial(item.icon_state))),
|
||||
"sprite" = icon2base64(icon(initial(item.icon), initial(item.icon_state), SOUTH, 1)),
|
||||
)
|
||||
|
||||
return data
|
||||
|
||||
@@ -53,15 +53,6 @@
|
||||
return
|
||||
cmd_show_exp_panel(M.client)
|
||||
|
||||
else if(href_list["toggleexempt"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/client/C = locate(href_list["toggleexempt"]) in GLOB.clients
|
||||
if(!C)
|
||||
to_chat(usr, "<span class='danger'>ERROR: Client not found.</span>")
|
||||
return
|
||||
toggle_exempt_status(C)
|
||||
|
||||
else if(href_list["makeAntag"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
@@ -920,10 +911,10 @@
|
||||
else
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=alien;jobban4=[REF(M)]'>Alien</a></td>"
|
||||
//Gang
|
||||
if(jobban_isbanned(M, ROLE_GANG) || isbanned_dept)
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=gang;jobban4=[REF(M)]'><font color=red>Gang</font></a></td>"
|
||||
if(jobban_isbanned(M, ROLE_FAMILIES) || isbanned_dept)
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=gang;jobban4=[REF(M)]'><font color=red>Families</font></a></td>"
|
||||
else
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=gang;jobban4=[REF(M)]'>Gang</a></td>"
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=gang;jobban4=[REF(M)]'>Families</a></td>"
|
||||
//Bloodsucker
|
||||
if(jobban_isbanned(M, ROLE_BLOODSUCKER) || isbanned_dept)
|
||||
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=bloodsucker;jobban4=[REF(M)]'><font color=red>Bloodsucker</font></a></td>"
|
||||
@@ -1008,7 +999,7 @@
|
||||
if("ghostroles")
|
||||
joblist += list(ROLE_PAI, ROLE_POSIBRAIN, ROLE_DRONE , ROLE_DEATHSQUAD, ROLE_LAVALAND, ROLE_SENTIENCE)
|
||||
if("teamantags")
|
||||
joblist += list(ROLE_OPERATIVE, ROLE_REV, ROLE_CULTIST, ROLE_SERVANT_OF_RATVAR, ROLE_ABDUCTOR, ROLE_ALIEN, ROLE_GANG)
|
||||
joblist += list(ROLE_OPERATIVE, ROLE_REV, ROLE_CULTIST, ROLE_SERVANT_OF_RATVAR, ROLE_ABDUCTOR, ROLE_ALIEN, ROLE_FAMILIES)
|
||||
if("convertantags")
|
||||
joblist += list(ROLE_REV, ROLE_CULTIST, ROLE_SERVANT_OF_RATVAR, ROLE_ALIEN)
|
||||
if("otherroles")
|
||||
@@ -2050,6 +2041,12 @@
|
||||
var/obj/item/station_charter/charter = locate(href_list["reject_custom_name"])
|
||||
if(istype(charter))
|
||||
charter.reject_proposed(usr)
|
||||
else if(href_list["approve_custom_name"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
var/obj/item/station_charter/charter = locate(href_list["approve_custom_name"])
|
||||
if(istype(charter))
|
||||
charter.allow_pass(usr)
|
||||
else if(href_list["jumpto"])
|
||||
if(!isobserver(usr) && !check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
@@ -242,7 +242,7 @@
|
||||
var/selectors_used = FALSE
|
||||
var/list/combined_refs = list()
|
||||
do
|
||||
CHECK_TICK
|
||||
stoplag(2)
|
||||
finished = TRUE
|
||||
for(var/i in running)
|
||||
var/datum/SDQL2_query/query = i
|
||||
|
||||
@@ -3,11 +3,19 @@
|
||||
/proc/_abs(A)
|
||||
return abs(A)
|
||||
|
||||
/proc/_animate(atom/A, set_vars, time = 10, loop = 1, easing = LINEAR_EASING, flags = null)
|
||||
var/mutable_appearance/MA = new()
|
||||
for(var/v in set_vars)
|
||||
MA.vars[v] = set_vars[v]
|
||||
animate(A, appearance = MA, time, loop, easing, flags)
|
||||
/proc/_animate(atom/A, list/data, time = 10, loop = 1, easing = LINEAR_EASING, flags = null)
|
||||
if(!istype(A))
|
||||
return
|
||||
animate(A, appearance = data, time = time, loop = loop, easing = easing, flags = flags)
|
||||
|
||||
/proc/_animate_adv(atom/A, list/data, loop = 1, easing = LINEAR_EASING, flags = NONE)
|
||||
if(!A || !islist(data) || data.len < 1)
|
||||
return
|
||||
animate(A, appearance = (data[1] - "time"), time = data[1]["time"], loop = loop, easing = easing, flags = flags)
|
||||
if(data.len < 2)
|
||||
return
|
||||
for(var/i in 2 to data.len)
|
||||
animate(appearance = (data[i] - "time"), time = data[i]["time"])
|
||||
|
||||
/proc/_acrccos(A)
|
||||
return arccos(A)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set category = "Object"
|
||||
|
||||
if((O.obj_flags & DANGEROUS_POSSESSION) && CONFIG_GET(flag/forbid_singulo_possession))
|
||||
to_chat(usr, "[O] is too powerful for you to possess.")
|
||||
to_chat(usr, "[O] is too powerful for you to possess.", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(O)
|
||||
@@ -18,19 +18,22 @@
|
||||
if(!usr.control_object) //If you're not already possessing something...
|
||||
usr.name_archive = usr.real_name
|
||||
|
||||
usr.loc = O
|
||||
usr.forceMove(O)
|
||||
usr.real_name = O.name
|
||||
usr.name = O.name
|
||||
usr.reset_perspective(O)
|
||||
usr.control_object = O
|
||||
O.AddElement(/datum/element/weather_listener, /datum/weather/ash_storm, ZTRAIT_ASHSTORM, GLOB.ash_storm_sounds)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Possess Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/proc/release()
|
||||
set name = "Release Obj"
|
||||
set category = "Object"
|
||||
//usr.loc = get_turf(usr)
|
||||
|
||||
if(usr.control_object && usr.name_archive) //if you have a name archived and if you are actually relassing an object
|
||||
if(!usr.control_object) //lest we are banished to the nullspace realm.
|
||||
return
|
||||
|
||||
if(usr.name_archive) //if you have a name archived
|
||||
usr.real_name = usr.name_archive
|
||||
usr.name_archive = ""
|
||||
usr.name = usr.real_name
|
||||
@@ -38,8 +41,8 @@
|
||||
var/mob/living/carbon/human/H = usr
|
||||
H.name = H.get_visible_name()
|
||||
|
||||
|
||||
usr.loc = get_turf(usr.control_object)
|
||||
usr.control_object.RemoveElement(/datum/element/weather_listener, /datum/weather/ash_storm, ZTRAIT_ASHSTORM, GLOB.ash_storm_sounds)
|
||||
usr.forceMove(get_turf(usr.control_object))
|
||||
usr.reset_perspective()
|
||||
usr.control_object = null
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Release Object") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
. = TRUE
|
||||
if("mass_apply")
|
||||
if(!check_rights_for(usr.client, R_FUN))
|
||||
to_chat(usr, "<span class='userdanger>Stay in your lane, jannie.</span>'")
|
||||
to_chat(usr, span_userdanger("Stay in your lane, jannie."))
|
||||
return
|
||||
var/target_path = text2path(params["path"])
|
||||
if(!target_path)
|
||||
|
||||
@@ -1,37 +1,77 @@
|
||||
GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
/datum/antagonist
|
||||
///Public name for this antagonist. Appears for player prompts and round-end reports.
|
||||
var/name = "Antagonist"
|
||||
var/roundend_category = "other antagonists" //Section of roundend report, datums with same category will be displayed together, also default header for the section
|
||||
var/show_in_roundend = TRUE //Set to false to hide the antagonists from roundend report
|
||||
var/datum/mind/owner //Mind that owns this datum
|
||||
var/silent = FALSE //Silent will prevent the gain/lose texts to show
|
||||
var/can_coexist_with_others = TRUE //Whether or not the person will be able to have more than one datum
|
||||
var/list/typecache_datum_blacklist = list() //List of datums this type can't coexist with
|
||||
var/delete_on_mind_deletion = TRUE
|
||||
///Section of roundend report, datums with same category will be displayed together, also default header for the section
|
||||
var/roundend_category = "other antagonists"
|
||||
///Set to false to hide the antagonists from roundend report
|
||||
var/show_in_roundend = TRUE
|
||||
///If false, the roundtype will still convert with this antag active
|
||||
var/prevent_roundtype_conversion = TRUE
|
||||
///Mind that owns this datum
|
||||
var/datum/mind/owner
|
||||
///Silent will prevent the gain/lose texts to show
|
||||
var/silent = FALSE
|
||||
///Whether or not the person will be able to have more than one datum
|
||||
var/can_coexist_with_others = TRUE
|
||||
///List of datums this type can't coexist with
|
||||
var/list/typecache_datum_blacklist = list()
|
||||
///The define string we use to identify the role for bans/player polls to spawn a random new one in.
|
||||
var/job_rank
|
||||
var/replace_banned = TRUE //Should replace jobbaned player with ghosts if granted.
|
||||
///Should replace jobbanned player with ghosts if granted.
|
||||
var/replace_banned = TRUE
|
||||
///List of the objective datums that this role currently has, completing all objectives at round-end will cause this antagonist to greentext.
|
||||
var/list/objectives = list()
|
||||
var/antag_memory = ""//These will be removed with antag datum
|
||||
var/antag_moodlet //typepath of moodlet that the mob will gain with their status
|
||||
///String dialogue that is added to the player's in-round notes and memories regarding specifics of that antagonist, eg. the nuke code for nuke ops, or your unlock code for traitors.
|
||||
var/antag_memory = ""
|
||||
///typepath of moodlet that the mob will gain when granted this antagonist type.
|
||||
var/antag_moodlet
|
||||
|
||||
///What is the configuration of this antagonist's hud icon, such as it's screen position and style, so thatit doesn't break other in-game hud icons.
|
||||
var/antag_hud_type
|
||||
///Name of the antag hud we provide to this mob.
|
||||
var/antag_hud_name
|
||||
/// If above 0, this is the multiplier for the speed at which we hijack the shuttle. Do not directly read, use hijack_speed().
|
||||
var/hijack_speed = 0
|
||||
/// The battlecry this antagonist shouts when suiciding with C4/X4.
|
||||
var/suicide_cry = ""
|
||||
/// The typepath for the outfit to show in the preview for the preferences menu.
|
||||
var/preview_outfit
|
||||
/// If set to true, the antag will not be added to the living antag list.
|
||||
var/soft_antag = FALSE
|
||||
|
||||
//Antag panel properties
|
||||
var/show_in_antagpanel = TRUE //This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
|
||||
var/antagpanel_category = "Uncategorized" //Antagpanel will display these together, REQUIRED
|
||||
var/show_name_in_check_antagonists = FALSE //Will append antagonist name in admin listings - use for categories that share more than one antag type
|
||||
var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute) // Quirks that will be removed upon gaining this antag. Pacifist and mute are default.
|
||||
var/threat = 0 // Amount of threat this antag poses, for dynamic mode
|
||||
///This will hide adding this antag type in antag panel, use only for internal subtypes that shouldn't be added directly but still show if possessed by mind
|
||||
var/show_in_antagpanel = TRUE
|
||||
///Antagpanel will display these together, REQUIRED
|
||||
var/antagpanel_category = "Uncategorized"
|
||||
///Will append antagonist name in admin listings - use for categories that share more than one antag type
|
||||
var/show_name_in_check_antagonists = FALSE
|
||||
/// Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors
|
||||
var/show_to_ghosts = FALSE
|
||||
//ambition start
|
||||
/// Lazy list for antagonists to request the admins objectives.
|
||||
var/list/requested_objective_changes
|
||||
//ambition end
|
||||
var/show_to_ghosts = FALSE // Should this antagonist be shown as antag to ghosts? Shouldn't be used for stealthy antagonists like traitors
|
||||
|
||||
/* CIT SPECIFIC */
|
||||
/// Quirks that will be removed upon gaining this antag. Pacifist and mute are default.
|
||||
var/list/blacklisted_quirks = list(/datum/quirk/nonviolent,/datum/quirk/mute)
|
||||
/// Amount of threat this antag poses, for dynamic mode
|
||||
var/threat = 0
|
||||
|
||||
var/delete_on_mind_deletion = TRUE
|
||||
|
||||
var/list/skill_modifiers
|
||||
/* CIT SPECIFIC end */
|
||||
|
||||
//ANTAG UI
|
||||
|
||||
///name of the UI that will try to open, right now having nothing means this won't exist but in the future all should.
|
||||
var/ui_name
|
||||
///button to access antag interface
|
||||
var/datum/action/antag_info/info_button
|
||||
|
||||
/datum/antagonist/New()
|
||||
GLOB.antagonists += src
|
||||
@@ -39,6 +79,10 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
/datum/antagonist/Destroy()
|
||||
GLOB.antagonists -= src
|
||||
if(!owner)
|
||||
stack_trace("Destroy()ing antagonist datum when it has no owner.")
|
||||
else
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
//ambition start
|
||||
owner?.do_remove_antag_datum(src)
|
||||
//ambition end
|
||||
@@ -60,14 +104,14 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/specialization(datum/mind/new_owner)
|
||||
return src
|
||||
|
||||
///Called by the transfer_to() mind proc after the mind (mind.current and new_character.mind) has moved but before the player (key and client) is transfered.
|
||||
///Called by the transfer_to() mind proc after the mind (mind.current and new_character.mind) has moved but before the player (key and client) is transfered.
|
||||
/datum/antagonist/proc/on_body_transfer(mob/living/old_body, mob/living/new_body)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
remove_innate_effects(old_body)
|
||||
if(old_body.stat != DEAD && !LAZYLEN(old_body.mind?.antag_datums))
|
||||
if(!soft_antag && old_body && old_body.stat != DEAD && !length(old_body.mind?.antag_datums))
|
||||
old_body.remove_from_current_living_antags()
|
||||
apply_innate_effects(new_body)
|
||||
if(new_body.stat != DEAD)
|
||||
if(!soft_antag && new_body.stat != DEAD)
|
||||
new_body.add_to_current_living_antags()
|
||||
|
||||
//This handles the application of antag huds/special abilities
|
||||
@@ -78,46 +122,76 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/proc/remove_innate_effects(mob/living/mob_override)
|
||||
return
|
||||
|
||||
/// This is called when the antagonist is being mindshielded.
|
||||
/datum/antagonist/proc/pre_mindshield(mob/implanter, mob/living/mob_override)
|
||||
SIGNAL_HANDLER
|
||||
// return COMPONENT_MINDSHIELD_PASSED
|
||||
|
||||
/// This is called when the antagonist is successfully mindshielded.
|
||||
/datum/antagonist/proc/on_mindshield(mob/implanter, mob/living/mob_override)
|
||||
SIGNAL_HANDLER
|
||||
return
|
||||
|
||||
// Adds the specified antag hud to the player. Usually called in an antag datum file
|
||||
/datum/antagonist/proc/add_antag_hud(antag_hud_type, antag_hud_name, mob/living/mob_override)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[antag_hud_type]
|
||||
hud.join_hud(mob_override)
|
||||
set_antag_hud(mob_override, antag_hud_name)
|
||||
|
||||
|
||||
// Removes the specified antag hud from the player. Usually called in an antag datum file
|
||||
/datum/antagonist/proc/remove_antag_hud(antag_hud_type, mob/living/mob_override)
|
||||
var/datum/atom_hud/antag/hud = GLOB.huds[antag_hud_type]
|
||||
hud.leave_hud(mob_override)
|
||||
set_antag_hud(mob_override, null)
|
||||
|
||||
// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects
|
||||
|
||||
/// Handles adding and removing the clumsy mutation from clown antags. Gets called in apply/remove_innate_effects
|
||||
/datum/antagonist/proc/handle_clown_mutation(mob/living/mob_override, message, removing = TRUE)
|
||||
var/mob/living/carbon/human/H = mob_override
|
||||
if(H && istype(H) && owner.assigned_role == "Clown")
|
||||
if(removing) // They're a clown becoming an antag, remove clumsy
|
||||
H.dna.remove_mutation(CLOWNMUT)
|
||||
if(!silent && message)
|
||||
to_chat(H, "<span class='boldnotice'>[message]</span>")
|
||||
else
|
||||
H.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy
|
||||
if(!ishuman(mob_override) || owner.assigned_role != "Clown")
|
||||
return
|
||||
var/mob/living/carbon/human/human_override = mob_override
|
||||
if(removing) // They're a clown becoming an antag, remove clumsy
|
||||
human_override.dna.remove_mutation(CLOWNMUT)
|
||||
if(!silent && message)
|
||||
to_chat(human_override, span_boldnotice("[message]"))
|
||||
else
|
||||
human_override.dna.add_mutation(CLOWNMUT) // We're removing their antag status, add back clumsy
|
||||
|
||||
|
||||
//Assign default team and creates one for one of a kind team antagonists
|
||||
/datum/antagonist/proc/create_team(datum/team/team)
|
||||
return
|
||||
|
||||
///Called by the add_antag_datum() mind proc after the instanced datum is added to the mind's antag_datums list.
|
||||
///Called by the add_antag_datum() mind proc after the instanced datum is added to the mind's antag_datums list.
|
||||
/datum/antagonist/proc/on_gain()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
set waitfor = FALSE
|
||||
if(!(owner?.current))
|
||||
return
|
||||
if(!owner)
|
||||
CRASH("[src] ran on_gain() without a mind")
|
||||
if(!owner.current)
|
||||
CRASH("[src] ran on_gain() on a mind without a mob")
|
||||
if(ui_name)//in the future, this should entirely replace greet.
|
||||
info_button = new(owner.current, src)
|
||||
info_button.Grant(owner.current)
|
||||
if(!silent)
|
||||
greet()
|
||||
if(ui_name)
|
||||
to_chat(owner.current, span_big("You are \a [src]."))
|
||||
to_chat(owner.current, span_boldnotice("For more info, read the panel. you can always come back to it using the button in the top left."))
|
||||
info_button.Trigger()
|
||||
apply_innate_effects()
|
||||
give_antag_moodies()
|
||||
remove_blacklisted_quirks()
|
||||
// RegisterSignal(owner, COMSIG_PRE_MINDSHIELD_IMPLANT, .proc/pre_mindshield)
|
||||
// RegisterSignal(owner, COMSIG_MINDSHIELD_IMPLANTED, .proc/on_mindshield)
|
||||
if(is_banned(owner.current) && replace_banned)
|
||||
replace_banned_player()
|
||||
// else if(owner.current.client?.holder && (CONFIG_GET(flag/auto_deadmin_antagonists) || owner.current.client.prefs?.toggles & DEADMIN_ANTAGONIST))
|
||||
// owner.current.client.holder.auto_deadmin()
|
||||
if(!soft_antag && owner.current.stat != DEAD)
|
||||
owner.current.add_to_current_living_antags()
|
||||
|
||||
// cit skill
|
||||
if(skill_modifiers)
|
||||
for(var/A in skill_modifiers)
|
||||
ADD_SINGLETON_SKILL_MODIFIER(owner, A, type)
|
||||
@@ -125,63 +199,96 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
if(istype(M))
|
||||
M.name = "[name] Training"
|
||||
owner.current.AddComponent(/datum/component/activity)
|
||||
if(owner.current.stat != DEAD)
|
||||
owner.current.add_to_current_living_antags()
|
||||
SEND_SIGNAL(owner.current, COMSIG_MOB_ANTAG_ON_GAIN, src)
|
||||
|
||||
|
||||
/**
|
||||
* Proc that checks the sent mob aganst the banlistfor this antagonist.
|
||||
* Returns FALSE if no mob is sent, or the mob is not found to be banned.
|
||||
*
|
||||
* * mob/M: The mob that you are looking for on the banlist.
|
||||
*/
|
||||
/datum/antagonist/proc/is_banned(mob/M)
|
||||
if(!M)
|
||||
return FALSE
|
||||
. = (jobban_isbanned(M, ROLE_SYNDICATE) || QDELETED(M) || (job_rank && (jobban_isbanned(M,job_rank) || QDELETED(M))))
|
||||
|
||||
/**
|
||||
* Proc that replaces a player who cannot play a specific antagonist due to being banned via a poll, and alerts the player of their being on the banlist.
|
||||
*/
|
||||
/datum/antagonist/proc/replace_banned_player()
|
||||
set waitfor = FALSE
|
||||
|
||||
var/list/mob/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", null, job_rank, 50, owner.current)
|
||||
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as a [name]?", "[name]", job_rank, 50, owner.current)
|
||||
if(LAZYLEN(candidates))
|
||||
var/mob/C = pick(candidates)
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
to_chat(owner, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
|
||||
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner)]) to replace a jobbanned player.")
|
||||
owner.current.ghostize(0)
|
||||
C.transfer_ckey(owner.current, FALSE)
|
||||
|
||||
///Called by the remove_antag_datum() and remove_all_antag_datums() mind procs for the antag datum to handle its own removal and deletion.
|
||||
/**
|
||||
* Called by the remove_antag_datum() and remove_all_antag_datums() mind procs for the antag datum to handle its own removal and deletion.
|
||||
*/
|
||||
/datum/antagonist/proc/on_removal()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
|
||||
remove_innate_effects()
|
||||
clear_antag_moodies()
|
||||
if(owner)
|
||||
//ambition start
|
||||
LAZYREMOVE(owner.antag_datums, src)
|
||||
// cit skill
|
||||
for(var/A in skill_modifiers)
|
||||
owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type))
|
||||
// end
|
||||
if(!LAZYLEN(owner.antag_datums) && !soft_antag)
|
||||
owner.current.remove_from_current_living_antags()
|
||||
if(info_button)
|
||||
QDEL_NULL(info_button)
|
||||
if(!silent && owner.current)
|
||||
farewell()
|
||||
// UnregisterSignal(owner, COMSIG_PRE_MINDSHIELD_IMPLANT)
|
||||
// UnregisterSignal(owner, COMSIG_MINDSHIELD_IMPLANTED)
|
||||
owner.do_remove_antag_datum(src)
|
||||
//ambition end
|
||||
for(var/A in skill_modifiers)
|
||||
owner.remove_skill_modifier(GET_SKILL_MOD_ID(A, type))
|
||||
if(!LAZYLEN(owner.antag_datums))
|
||||
owner.current.remove_from_current_living_antags()
|
||||
if(!silent && owner.current)
|
||||
farewell()
|
||||
var/datum/team/team = get_team()
|
||||
if(team)
|
||||
team.remove_member(owner)
|
||||
// we don't remove the activity component on purpose--no real point to it
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* Proc that sends fluff or instructional messages to the player when they are given this antag datum.
|
||||
* Use this proc for playing sounds, sending alerts, or helping to setup non-gameplay influencing aspects of the antagonist type.
|
||||
*/
|
||||
/datum/antagonist/proc/greet()
|
||||
return
|
||||
|
||||
/**
|
||||
* Proc that sends fluff or instructional messages to the player when they lose this antag datum.
|
||||
* Use this proc for playing sounds, sending alerts, or otherwise informing the player that they're no longer a specific antagonist type.
|
||||
*/
|
||||
/datum/antagonist/proc/farewell()
|
||||
return
|
||||
|
||||
/**
|
||||
* Proc that assigns this antagonist's ascribed moodlet to the player.
|
||||
*/
|
||||
/datum/antagonist/proc/give_antag_moodies()
|
||||
if(!antag_moodlet)
|
||||
return
|
||||
SEND_SIGNAL(owner.current, COMSIG_ADD_MOOD_EVENT, "antag_moodlet", antag_moodlet)
|
||||
|
||||
/**
|
||||
* Proc that removes this antagonist's ascribed moodlet from the player.
|
||||
*/
|
||||
/datum/antagonist/proc/clear_antag_moodies()
|
||||
if(!antag_moodlet)
|
||||
return
|
||||
SEND_SIGNAL(owner.current, COMSIG_CLEAR_MOOD_EVENT, "antag_moodlet")
|
||||
|
||||
/**
|
||||
* Removes invalid quirks.
|
||||
*/
|
||||
/datum/antagonist/proc/remove_blacklisted_quirks()
|
||||
var/mob/living/L = owner.current
|
||||
if(istype(L))
|
||||
@@ -192,16 +299,22 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
to_chat(L, "<span class='boldannounce'>[initial(Q.antag_removal_text)]</span>")
|
||||
qdel(Q)
|
||||
|
||||
//Returns the team antagonist belongs to if any.
|
||||
/**
|
||||
* Proc that will return the team this antagonist belongs to, when called. Helpful with antagonists that may belong to multiple potential teams in a single round, like families.
|
||||
*/
|
||||
/datum/antagonist/proc/get_team()
|
||||
return
|
||||
|
||||
//Individual roundend report
|
||||
/**
|
||||
* Proc that sends string information for the end-round report window to the server.
|
||||
* This runs on every instance of every antagonist that exists at the end of the round.
|
||||
* This is the body of the message, sandwiched between roundend_report_header and roundend_report_footer.
|
||||
*/
|
||||
/datum/antagonist/proc/roundend_report()
|
||||
var/list/report = list()
|
||||
|
||||
if(!owner)
|
||||
CRASH("antagonist datum without owner")
|
||||
CRASH("Antagonist datum without owner")
|
||||
|
||||
report += printplayer(owner)
|
||||
|
||||
@@ -220,11 +333,19 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
return report.Join("<br>")
|
||||
|
||||
//Displayed at the start of roundend_category section, default to roundend_category header
|
||||
/**
|
||||
* Proc that sends string data for the round-end report.
|
||||
* Displayed before roundend_report and roundend_report_footer.
|
||||
* Appears at start of roundend_catagory section.
|
||||
*/
|
||||
/datum/antagonist/proc/roundend_report_header()
|
||||
return "<span class='header'>The [roundend_category] were:</span><br>"
|
||||
return "<span class='header'>The [roundend_category] were:</span><br>"
|
||||
|
||||
//Displayed at the end of roundend_category section
|
||||
/**
|
||||
* Proc that sends string data for the round-end report.
|
||||
* Displayed after roundend_report and roundend_report_footer.
|
||||
* Appears at the end of the roundend_catagory section.
|
||||
*/
|
||||
/datum/antagonist/proc/roundend_report_footer()
|
||||
return
|
||||
|
||||
@@ -233,22 +354,24 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
|
||||
//Called when using admin tools to give antag status
|
||||
/datum/antagonist/proc/admin_add(datum/mind/new_owner,mob/admin)
|
||||
message_admins("[key_name_admin(admin)] made [new_owner.current] into [name].")
|
||||
log_admin("[key_name(admin)] made [new_owner.current] into [name].")
|
||||
message_admins("[key_name_admin(admin)] made [key_name_admin(new_owner)] into [name].")
|
||||
log_admin("[key_name(admin)] made [key_name(new_owner)] into [name].")
|
||||
new_owner.add_antag_datum(src)
|
||||
|
||||
//Called when removing antagonist using admin tools
|
||||
/datum/antagonist/proc/admin_remove(mob/user)
|
||||
if(!user)
|
||||
return
|
||||
message_admins("[key_name_admin(user)] has removed [name] antagonist status from [owner.current].")
|
||||
log_admin("[key_name(user)] has removed [name] antagonist status from [owner.current].")
|
||||
message_admins("[key_name_admin(user)] has removed [name] antagonist status from [key_name_admin(owner)].")
|
||||
log_admin("[key_name(user)] has removed [name] antagonist status from [key_name(owner)].")
|
||||
on_removal()
|
||||
|
||||
//gamemode/proc/is_mode_antag(antagonist/A) => TRUE/FALSE
|
||||
|
||||
//Additional data to display in antagonist panel section
|
||||
//nuke disk code, genome count, etc
|
||||
/**
|
||||
* Additional data to display in the antagonist panel section.
|
||||
* For example, nuke disk code, genome count, etc
|
||||
*/
|
||||
/datum/antagonist/proc/antag_panel_data()
|
||||
return ""
|
||||
|
||||
@@ -260,10 +383,47 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
// List if ["Command"] = CALLBACK(), user will be appeneded to callback arguments on execution
|
||||
/// List of ["Command"] = CALLBACK(), user will be appeneded to callback arguments on execution
|
||||
/datum/antagonist/proc/get_admin_commands()
|
||||
. = list()
|
||||
|
||||
/// Creates an icon from the preview outfit.
|
||||
/// Custom implementors of `get_preview_icon` should use this, as the
|
||||
/// result of `get_preview_icon` is expected to be the completed version.
|
||||
/datum/antagonist/proc/render_preview_outfit(datum/outfit/outfit, mob/living/carbon/human/dummy)
|
||||
dummy = dummy || new /mob/living/carbon/human/dummy/consistent
|
||||
dummy.equipOutfit(outfit, visualsOnly = TRUE)
|
||||
COMPILE_OVERLAYS(dummy)
|
||||
var/icon = getFlatIcon(dummy)
|
||||
|
||||
// We don't want to qdel the dummy right away, since its items haven't initialized yet.
|
||||
SSatoms.prepare_deletion(dummy)
|
||||
|
||||
return icon
|
||||
|
||||
/// Given an icon, will crop it to be consistent of those in the preferences menu.
|
||||
/// Not necessary, and in fact will look bad if it's anything other than a human.
|
||||
/datum/antagonist/proc/finish_preview_icon(icon/icon)
|
||||
// Zoom in on the top of the head and the chest
|
||||
// I have no idea how to do this dynamically.
|
||||
icon.Scale(115, 115)
|
||||
|
||||
// This is probably better as a Crop, but I cannot figure it out.
|
||||
icon.Shift(WEST, 8)
|
||||
icon.Shift(SOUTH, 30)
|
||||
|
||||
icon.Crop(1, 1, ANTAGONIST_PREVIEW_ICON_SIZE, ANTAGONIST_PREVIEW_ICON_SIZE)
|
||||
|
||||
return icon
|
||||
|
||||
/// Returns the icon to show on the preferences menu.
|
||||
/datum/antagonist/proc/get_preview_icon()
|
||||
if (isnull(preview_outfit))
|
||||
return null
|
||||
|
||||
return finish_preview_icon(render_preview_outfit(preview_outfit))
|
||||
|
||||
|
||||
/datum/antagonist/Topic(href,href_list)
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
@@ -290,14 +450,19 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
return
|
||||
antag_memory = new_memo
|
||||
|
||||
/// Gets how fast we can hijack the shuttle, return 0 for can not hijack. Defaults to hijack_speed var, override for custom stuff like buffing hijack speed for hijack objectives or something.
|
||||
/**
|
||||
* Gets how fast we can hijack the shuttle, return 0 for can not hijack.
|
||||
* Defaults to hijack_speed var, override for custom stuff like buffing hijack speed for hijack objectives or something.
|
||||
*/
|
||||
/datum/antagonist/proc/hijack_speed()
|
||||
var/datum/objective/hijack/H = locate() in objectives
|
||||
if(!isnull(H?.hijack_speed_override))
|
||||
return H.hijack_speed_override
|
||||
return hijack_speed
|
||||
|
||||
/// Gets our threat level. Defaults to threat var, override for custom stuff like different traitor goals having different threats.
|
||||
/**
|
||||
* Gets our threat level. Override this proc for custom functionality/dynamic threat level.
|
||||
*/
|
||||
/datum/antagonist/proc/threat()
|
||||
. = CONFIG_GET(keyed_list/antag_threat)[lowertext(name)]
|
||||
if(. == null)
|
||||
@@ -307,6 +472,13 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
/datum/antagonist/custom
|
||||
antagpanel_category = "Custom"
|
||||
show_name_in_check_antagonists = TRUE //They're all different
|
||||
var/datum/team/custom_team
|
||||
|
||||
/datum/antagonist/custom/create_team(datum/team/team)
|
||||
custom_team = team
|
||||
|
||||
/datum/antagonist/custom/get_team()
|
||||
return custom_team
|
||||
|
||||
/datum/antagonist/custom/admin_add(datum/mind/new_owner,mob/admin)
|
||||
var/custom_name = stripped_input(admin, "Custom antagonist name:", "Custom antag", "Antagonist")
|
||||
@@ -316,6 +488,51 @@ GLOBAL_LIST_EMPTY(antagonists)
|
||||
return
|
||||
..()
|
||||
|
||||
///ANTAGONIST UI STUFF
|
||||
|
||||
/datum/antagonist/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_name, name)
|
||||
ui.open()
|
||||
|
||||
/datum/antagonist/ui_state(mob/user)
|
||||
return GLOB.always_state
|
||||
|
||||
///generic helper to send objectives as data through tgui. supports smart objectives too!
|
||||
/datum/antagonist/proc/get_objectives()
|
||||
var/objective_count = 1
|
||||
var/list/objective_data = list()
|
||||
//all obj
|
||||
for(var/datum/objective/objective in objectives)
|
||||
objective_data += list(list(
|
||||
"count" = objective_count,
|
||||
"name" = objective.name,
|
||||
"explanation" = objective.explanation_text,
|
||||
"complete" = objective.completed,
|
||||
))
|
||||
objective_count++
|
||||
return objective_data
|
||||
|
||||
//button for antags to review their descriptions/info
|
||||
|
||||
/datum/action/antag_info
|
||||
name = "Open Antag Information:"
|
||||
button_icon_state = "round_end"
|
||||
var/datum/antagonist/antag_datum
|
||||
|
||||
/datum/action/antag_info/New(Target, datum/antagonist/antag_datum)
|
||||
. = ..()
|
||||
src.antag_datum = antag_datum
|
||||
name += " [antag_datum.name]"
|
||||
|
||||
/datum/action/antag_info/Trigger()
|
||||
if(antag_datum)
|
||||
antag_datum.ui_interact(owner)
|
||||
|
||||
/datum/action/antag_info/IsAvailable()
|
||||
return TRUE
|
||||
|
||||
///Clears change requests from deleted objectives to avoid broken references.
|
||||
/datum/antagonist/proc/clean_request_from_del_objective(datum/objective/source, force)
|
||||
var/objective_reference = REF(source)
|
||||
|
||||
@@ -6,14 +6,3 @@
|
||||
continue
|
||||
if(!antag_type || !specific && istype(A,antag_type) || specific && A.type == antag_type)
|
||||
. += A.owner
|
||||
|
||||
//Get all teams [of type team_type]
|
||||
/proc/get_all_teams(team_type)
|
||||
. = list()
|
||||
for(var/V in GLOB.antagonists)
|
||||
var/datum/antagonist/A = V
|
||||
if(!A.owner)
|
||||
continue
|
||||
var/datum/team/T = A.get_team()
|
||||
if(!team_type || istype(T,team_type))
|
||||
. |= T
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
GLOBAL_LIST_EMPTY(antagonist_teams)
|
||||
|
||||
//A barebones antagonist team.
|
||||
/datum/team
|
||||
var/list/datum/mind/members = list()
|
||||
@@ -8,6 +10,7 @@
|
||||
|
||||
/datum/team/New(starting_members)
|
||||
. = ..()
|
||||
GLOB.antagonist_teams += src
|
||||
if(starting_members)
|
||||
if(islist(starting_members))
|
||||
for(var/datum/mind/M in starting_members)
|
||||
@@ -15,6 +18,10 @@
|
||||
else
|
||||
add_member(starting_members)
|
||||
|
||||
/datum/team/Destroy(force, ...)
|
||||
GLOB.antagonist_teams -= src
|
||||
. = ..()
|
||||
|
||||
/datum/team/proc/is_solo()
|
||||
return members.len == 1
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
/datum/antagonist/abductor/admin_add(datum/mind/new_owner,mob/admin)
|
||||
var/list/current_teams = list()
|
||||
for(var/datum/team/abductor_team/T in get_all_teams(/datum/team/abductor_team))
|
||||
for(var/datum/team/abductor_team/T in GLOB.antagonist_teams)
|
||||
current_teams[T.name] = T
|
||||
var/choice = input(admin,"Add to which team ?") as null|anything in (current_teams + "new team")
|
||||
if (choice == "new team")
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
return
|
||||
|
||||
var/obj/item/organ/lungs/lungs = owner.getorganslot(ORGAN_SLOT_LUNGS)
|
||||
if((!lungs && !HAS_TRAIT(owner, TRAIT_NOBREATH)) || (lungs && (istype(lungs, /obj/item/organ/lungs/cybernetic))))
|
||||
if((!lungs && (HAS_TRAIT_FROM(owner, TRAIT_AUXILIARY_LUNGS, SPECIES_TRAIT) || !HAS_TRAIT(owner, TRAIT_NOBREATH))) || (lungs && (istype(lungs, /obj/item/organ/lungs/cybernetic))))
|
||||
replace_lungs(lungs)
|
||||
return
|
||||
|
||||
|
||||
40
code/modules/antagonists/ashwalker/ashwalker.dm
Normal file
40
code/modules/antagonists/ashwalker/ashwalker.dm
Normal file
@@ -0,0 +1,40 @@
|
||||
/datum/team/ashwalkers
|
||||
name = "Ashwalkers"
|
||||
show_roundend_report = FALSE
|
||||
var/list/players_spawned = new
|
||||
|
||||
/datum/antagonist/ashwalker
|
||||
name = "\improper Ash Walker"
|
||||
job_rank = ROLE_LAVALAND
|
||||
show_in_antagpanel = FALSE
|
||||
show_to_ghosts = TRUE
|
||||
antagpanel_category = "Ash Walkers"
|
||||
var/datum/team/ashwalkers/ashie_team
|
||||
|
||||
/datum/antagonist/ashwalker/create_team(datum/team/team)
|
||||
if(team)
|
||||
ashie_team = team
|
||||
objectives |= ashie_team.objectives
|
||||
else
|
||||
ashie_team = new
|
||||
|
||||
/datum/antagonist/ashwalker/get_team()
|
||||
return ashie_team
|
||||
|
||||
/datum/antagonist/ashwalker/on_body_transfer(mob/living/old_body, mob/living/new_body)
|
||||
. = ..()
|
||||
RegisterSignal(new_body, COMSIG_MOB_EXAMINATE, .proc/on_examinate)
|
||||
|
||||
/datum/antagonist/ashwalker/on_gain()
|
||||
. = ..()
|
||||
RegisterSignal(owner.current, COMSIG_MOB_EXAMINATE, .proc/on_examinate)
|
||||
|
||||
/datum/antagonist/ashwalker/on_removal()
|
||||
. = ..()
|
||||
UnregisterSignal(owner.current, COMSIG_MOB_EXAMINATE)
|
||||
|
||||
/datum/antagonist/ashwalker/proc/on_examinate(datum/source, atom/A)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(istype(A, /obj/structure/headpike))
|
||||
SEND_SIGNAL(owner.current, COMSIG_ADD_MOOD_EVENT, "headspear", /datum/mood_event/sacrifice_good)
|
||||
@@ -17,11 +17,13 @@
|
||||
B.objectives += objective
|
||||
M.add_antag_datum(B)
|
||||
|
||||
var/begin_message = "<span class='deadsay'><b>[L]</b> has been brainwashed with the following objectives: "
|
||||
var/begin_message = " has been brainwashed with the following objectives: "
|
||||
var/obj_message = english_list(directives)
|
||||
var/end_message = "</b>.</span>"
|
||||
var/end_message = "."
|
||||
var/rendered = begin_message + obj_message + end_message
|
||||
deadchat_broadcast(rendered, follow_target = L, turf_target = get_turf(L), message_type=DEADCHAT_REGULAR)
|
||||
deadchat_broadcast(rendered, "<b>[L]</b>", follow_target = L, turf_target = get_turf(L), message_type=DEADCHAT_ANNOUNCEMENT)
|
||||
if(prob(1) || SSevents.holidays && SSevents.holidays[APRIL_FOOLS])
|
||||
L.say("You son of a bitch! I'm in.", forced = "That son of a bitch! They're in.")
|
||||
|
||||
/datum/antagonist/brainwashed
|
||||
name = "Brainwashed Victim"
|
||||
@@ -30,19 +32,21 @@
|
||||
show_in_antagpanel = TRUE
|
||||
antagpanel_category = "Other"
|
||||
show_name_in_check_antagonists = TRUE
|
||||
ui_name = "AntagInfoBrainwashed"
|
||||
suicide_cry = "FOR... SOMEONE!!"
|
||||
|
||||
/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>")
|
||||
var/i = 1
|
||||
for(var/X in objectives)
|
||||
var/datum/objective/O = X
|
||||
to_chat(owner, "<b>[i].</b> [O.explanation_text]")
|
||||
i++
|
||||
/datum/antagonist/brainwashed/ui_static_data(mob/user)
|
||||
. = ..()
|
||||
var/list/data = list()
|
||||
data["objectives"] = get_objectives()
|
||||
return data
|
||||
|
||||
/datum/antagonist/brainwashed/farewell()
|
||||
to_chat(owner, "<span class='warning'>Your mind suddenly clears...</span>")
|
||||
to_chat(owner, "<big><span class='warning'><b>You feel the weight of the Directives disappear! You no longer have to obey them.</b></span></big>")
|
||||
to_chat(owner, span_warning("Your mind suddenly clears..."))
|
||||
to_chat(owner, "<big>[span_warning("<b>You feel the weight of the Directives disappear! You no longer have to obey them.</b>")]</big>")
|
||||
if(owner.current)
|
||||
var/mob/living/owner_mob = owner.current
|
||||
owner_mob.log_message("is no longer brainwashed with the objectives: [english_list(objectives)].", LOG_ATTACK)
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/brainwashed/admin_add(datum/mind/new_owner,mob/admin)
|
||||
@@ -54,9 +58,9 @@
|
||||
var/objective = stripped_input(admin, "Add an objective, or leave empty to finish.", "Brainwashing", null, MAX_MESSAGE_LEN)
|
||||
if(objective)
|
||||
objectives += objective
|
||||
while(alert(admin,"Add another objective?","More Brainwashing","Yes","No") == "Yes")
|
||||
while(tgui_alert(admin,"Add another objective?","More Brainwashing",list("Yes","No")) == "Yes")
|
||||
|
||||
if(alert(admin,"Confirm Brainwashing?","Are you sure?","Yes","No") == "No")
|
||||
if(tgui_alert(admin,"Confirm Brainwashing?","Are you sure?",list("Yes","No")) == "No")
|
||||
return
|
||||
|
||||
if(!LAZYLEN(objectives))
|
||||
@@ -69,6 +73,7 @@
|
||||
brainwash(C, objectives)
|
||||
var/obj_list = english_list(objectives)
|
||||
message_admins("[key_name_admin(admin)] has brainwashed [key_name_admin(C)] with the following objectives: [obj_list].")
|
||||
C.log_message("has been force-brainwashed with the objective '[obj_list]' by admin [key_name(admin)]", LOG_ATTACK, log_globally = FALSE)
|
||||
log_admin("[key_name(admin)] has brainwashed [key_name(C)] with the following objectives: [obj_list].")
|
||||
|
||||
/datum/objective/brainwashing
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
do_sparks(5, TRUE, AM)
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
L.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash/static)
|
||||
L.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash/static)
|
||||
L.clear_fullscreen("flash", 5)
|
||||
var/obj/item/transfer_valve/TTV = locate() in L.GetAllContents()
|
||||
if(TTV)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 30)
|
||||
addtimer(CALLBACK(user, /mob/living.proc/dropItemToGround, src, TRUE), 1) //equipped happens before putting stuff on(but not before picking items up), 1). thus, we need to wait for it to be on before forcing it off.
|
||||
|
||||
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/head/helmet/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
@@ -98,7 +98,7 @@
|
||||
max_heat_protection_temperature = initial(max_heat_protection_temperature)
|
||||
min_cold_protection_temperature = initial(min_cold_protection_temperature)
|
||||
|
||||
/obj/item/clothing/suit/armor/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/suit/armor/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
@@ -158,7 +158,7 @@
|
||||
max_heat_protection_temperature = initial(max_heat_protection_temperature)
|
||||
min_cold_protection_temperature = initial(min_cold_protection_temperature)
|
||||
|
||||
/obj/item/clothing/gloves/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/gloves/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
@@ -208,7 +208,7 @@
|
||||
else
|
||||
clothing_flags &= ~NOSLIP
|
||||
|
||||
/obj/item/clothing/shoes/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0)
|
||||
/obj/item/clothing/shoes/clockwork/mob_can_equip(M, equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(equipper && !is_servant_of_ratvar(equipper))
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
@@ -264,7 +264,9 @@
|
||||
ui.open()
|
||||
|
||||
/obj/item/clockwork/slab/ui_data(mob/user) //we display a lot of data via TGUI
|
||||
. = list()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
.["recollection"] = recollecting
|
||||
.["power"] = DisplayPower(get_clockwork_power())
|
||||
.["power_unformatted"] = get_clockwork_power()
|
||||
@@ -275,6 +277,7 @@
|
||||
if(S.tier == SCRIPTURE_PERIPHERAL) // This tier is skiped because this contains basetype stuff
|
||||
continue
|
||||
|
||||
// FUTURE IMPL: cache these perhaps?
|
||||
var/list/data = list()
|
||||
data["name"] = S.name
|
||||
data["descname"] = S.descname
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
if(isliving(M.current) && M.current.stat != DEAD)
|
||||
var/turf/t_turf = isAI(M.current) ? get_step(get_step(src, NORTH),NORTH) : get_turf(src) // AI too fat, must make sure it always ends up a 2 tiles north instead of on the ark.
|
||||
do_teleport(M.current, t_turf, channel = TELEPORT_CHANNEL_CULT, forced = TRUE)
|
||||
M.current.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
|
||||
M.current.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
|
||||
M.current.clear_fullscreen("flash", 5)
|
||||
playsound(src, 'sound/magic/clockwork/invoke_general.ogg', 50, FALSE)
|
||||
recalls_remaining--
|
||||
@@ -311,7 +311,7 @@
|
||||
var/turf/T = get_turf(M)
|
||||
if(is_servant_of_ratvar(M) && (!T || T.z != z))
|
||||
M.forceMove(get_step(src, SOUTH))
|
||||
M.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/flash)
|
||||
M.overlay_fullscreen("flash", /atom/movable/screen/fullscreen/tiled/flash)
|
||||
M.clear_fullscreen("flash", 5)
|
||||
progress_in_seconds += GATEWAY_SUMMON_RATE
|
||||
switch(progress_in_seconds)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
job_rank = ROLE_SERVANT_OF_RATVAR
|
||||
antag_moodlet = /datum/mood_event/cult
|
||||
skill_modifiers = list(/datum/skill_modifier/job/level/wiring, /datum/skill_modifier/job/level/dwarfy/blacksmithing)
|
||||
ui_name = "AntagInfoClockwork"
|
||||
var/datum/action/innate/hierophant/hierophant_network = new
|
||||
threat = 3
|
||||
var/datum/team/clockcult/clock_team
|
||||
@@ -14,6 +15,12 @@
|
||||
var/ignore_eligibility_check = FALSE
|
||||
var/ignore_holy_water = FALSE
|
||||
|
||||
/datum/antagonist/clockcult/ui_data(mob/user)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
.["HONOR_RATVAR"] = GLOB.ratvar_awakens
|
||||
|
||||
/datum/antagonist/clockcult/silent
|
||||
name = "Silent Clock Cultist"
|
||||
silent = TRUE
|
||||
@@ -22,6 +29,8 @@
|
||||
/datum/antagonist/clockcult/neutered
|
||||
name = "Neutered Clock Cultist"
|
||||
neutered = TRUE
|
||||
soft_antag = TRUE
|
||||
ui_name = null // no.
|
||||
|
||||
/datum/antagonist/clockcult/neutered/traitor
|
||||
name = "Traitor Clock Cultist"
|
||||
@@ -57,14 +66,6 @@
|
||||
if(. && !ignore_eligibility_check)
|
||||
. = is_eligible_servant(new_owner.current)
|
||||
|
||||
/datum/antagonist/clockcult/greet()
|
||||
if(!owner.current || silent)
|
||||
return
|
||||
owner.current.visible_message("<span class='heavy_brass'>[owner.current]'s eyes glow a blazing yellow!</span>", null, null, 7, owner.current) //don't show the owner this message
|
||||
to_chat(owner.current, "<span class='heavy_brass'>Assist your new companions in their righteous efforts. Your goal is theirs, and theirs yours. You serve the Clockwork \
|
||||
Justiciar above all else. Perform his every whim without hesitation.</span>")
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/clockcultalr.ogg', 70, FALSE, pressure_affected = FALSE)
|
||||
|
||||
/datum/antagonist/clockcult/on_gain()
|
||||
var/mob/living/current = owner.current
|
||||
SSticker.mode.servants_of_ratvar += owner
|
||||
|
||||
@@ -104,7 +104,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, visual = 0, type = /atom/movable/screen/fullscreen/flash, override_protection = 0)
|
||||
/mob/living/carbon/true_devil/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash, override_protection = 0)
|
||||
if(mind && has_bane(BANE_LIGHT))
|
||||
mind.disrupt_spells(-500)
|
||||
return ..() //flashes don't stop devils UNLESS it's their bane.
|
||||
|
||||
@@ -11,14 +11,21 @@
|
||||
var/role = "Security Officer"
|
||||
var/list/name_source
|
||||
threat = -5
|
||||
var/random_names = TRUE
|
||||
var/rip_and_tear = FALSE
|
||||
var/equip_ert = TRUE
|
||||
var/forge_objectives_for_ert = TRUE
|
||||
show_in_antagpanel = FALSE
|
||||
show_to_ghosts = TRUE
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
|
||||
/datum/antagonist/ert/on_gain()
|
||||
update_name()
|
||||
forge_objectives()
|
||||
equipERT()
|
||||
if(random_names)
|
||||
update_name()
|
||||
if(forge_objectives_for_ert)
|
||||
forge_objectives()
|
||||
if(equip_ert)
|
||||
equipERT()
|
||||
. = ..()
|
||||
|
||||
/datum/antagonist/ert/get_team()
|
||||
@@ -129,6 +136,7 @@
|
||||
return
|
||||
H.equipOutfit(outfit)
|
||||
|
||||
|
||||
/datum/antagonist/ert/greet()
|
||||
if(!ert_team)
|
||||
return
|
||||
@@ -160,3 +168,139 @@
|
||||
|
||||
missiondesc += "<BR><B>Your Mission</B> : [ert_team.mission.explanation_text]"
|
||||
to_chat(owner,missiondesc)
|
||||
|
||||
|
||||
/datum/antagonist/ert/families
|
||||
name = "Space Police Responder"
|
||||
antag_hud_type = ANTAG_HUD_SPACECOP
|
||||
antag_hud_name = "hud_spacecop"
|
||||
suicide_cry = "FOR THE SPACE POLICE!!"
|
||||
|
||||
/datum/antagonist/ert/families/apply_innate_effects(mob/living/mob_override)
|
||||
..()
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, M)
|
||||
if(M.hud_used)
|
||||
var/datum/hud/H = M.hud_used
|
||||
var/atom/movable/screen/wanted/giving_wanted_lvl = new /atom/movable/screen/wanted()
|
||||
H.wanted_lvl = giving_wanted_lvl
|
||||
giving_wanted_lvl.hud = H
|
||||
H.infodisplay += giving_wanted_lvl
|
||||
H.mymob.client.screen += giving_wanted_lvl
|
||||
|
||||
|
||||
/datum/antagonist/ert/families/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
remove_antag_hud(antag_hud_type, M)
|
||||
if(M.hud_used)
|
||||
var/datum/hud/H = M.hud_used
|
||||
H.infodisplay -= H.wanted_lvl
|
||||
QDEL_NULL(H.wanted_lvl)
|
||||
..()
|
||||
|
||||
/datum/antagonist/ert/families/greet()
|
||||
var/missiondesc = "<span class='warningplain'><B><font size=6 color=red>You are the [name].</font></B>"
|
||||
missiondesc += "<BR><B><font size=5 color=red>You are NOT a Nanotrasen Employee. You work for the local government.</font></B>"
|
||||
missiondesc += "<BR><B><font size=5 color=red>You are NOT a deathsquad. You are here to help innocents escape violence, criminal activity, and other dangerous things.</font></B>"
|
||||
missiondesc += "<BR>After an uptick in gang violence on [station_name()], you are responding to emergency calls from the station for immediate SSC Police assistance!\n"
|
||||
missiondesc += "<BR><B>Your Mission</B>:"
|
||||
missiondesc += "<BR> <B>1.</B> Serve the public trust."
|
||||
missiondesc += "<BR> <B>2.</B> Protect the innocent."
|
||||
missiondesc += "<BR> <B>3.</B> Uphold the law."
|
||||
missiondesc += "<BR> <B>4.</B> Find the Undercover Cops."
|
||||
missiondesc += "<BR> <B>5.</B> Detain Nanotrasen Security personnel if they harm any citizen."
|
||||
missiondesc += "<BR> You can <B>see gangsters</B> using your <B>special sunglasses</B>.</span>"
|
||||
to_chat(owner,missiondesc)
|
||||
var/policy = get_policy(ROLE_FAMILIES)
|
||||
if(policy)
|
||||
to_chat(owner, policy)
|
||||
var/mob/living/M = owner.current
|
||||
M.playsound_local(M, 'sound/effects/families_police.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
|
||||
/datum/antagonist/ert/families/undercover_cop
|
||||
name = "Undercover Cop"
|
||||
role = "Undercover Cop"
|
||||
outfit = /datum/outfit/families_police/beatcop
|
||||
var/free_clothes = list(/obj/item/clothing/glasses/hud/spacecop/hidden,
|
||||
/obj/item/clothing/under/rank/security/officer/beatcop,
|
||||
/obj/item/clothing/head/spacepolice)
|
||||
forge_objectives_for_ert = FALSE
|
||||
equip_ert = FALSE
|
||||
random_names = FALSE
|
||||
|
||||
/datum/antagonist/ert/families/undercover_cop/on_gain()
|
||||
if(istype(owner.current, /mob/living/carbon/human))
|
||||
for(var/C in free_clothes)
|
||||
var/obj/O = new C(owner.current)
|
||||
var/list/slots = list (
|
||||
"backpack" = ITEM_SLOT_BACKPACK,
|
||||
"left pocket" = SLOT_L_STORE,
|
||||
"right pocket" = SLOT_R_STORE
|
||||
)
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/equipped = H.equip_in_one_of_slots(O, slots)
|
||||
if(!equipped)
|
||||
to_chat(owner.current, "<span class='warningplain'>Unfortunately, you could not bring your [O] to this shift. You will need to find one.</span>")
|
||||
qdel(O)
|
||||
. = ..()
|
||||
|
||||
|
||||
/datum/antagonist/ert/families/undercover_cop/greet()
|
||||
var/missiondesc = "<span class='warningplain'><B><font size=3 color=red>You are the [name].</font></B>"
|
||||
missiondesc += "<BR><B><font size=3 color=red>You are NOT a Nanotrasen Employee. You work for the local government.</font></B>"
|
||||
missiondesc += "<BR>You are an undercover police officer on board [station_name()]. You've been sent here by the Spinward Stellar Coalition because of suspected abusive behavior by the security department, and to keep tabs on a potential criminal organization operation."
|
||||
missiondesc += "<BR><B>Your Mission</B>:"
|
||||
missiondesc += "<BR> <B>1.</B> Keep a close eye on any gangsters you spot. You can view gangsters using your sunglasses in your backpack."
|
||||
missiondesc += "<BR> <B>2.</B> Keep an eye on how Security handles any gangsters, and watch for excessive security brutality."
|
||||
missiondesc += "<BR> <B>3.</B> Remain undercover and do not get found out by Security or any gangs. Nanotrasen does not take kindly to being spied on."
|
||||
missiondesc += "<BR> <B>4.</B> When your backup arrives to extract you in 1 hour, inform them of everything you saw of note, and assist them in securing the situation.</span>"
|
||||
to_chat(owner,missiondesc)
|
||||
|
||||
/datum/antagonist/ert/families/beatcop
|
||||
name = "Beat Cop"
|
||||
role = "Police Officer"
|
||||
outfit = /datum/outfit/families_police/beatcop
|
||||
|
||||
/datum/antagonist/ert/families/beatcop/armored
|
||||
name = "Armored Beat Cop"
|
||||
role = "Police Officer"
|
||||
outfit = /datum/outfit/families_police/beatcop/armored
|
||||
|
||||
/datum/antagonist/ert/families/beatcop/swat
|
||||
name = "S.W.A.T. Member"
|
||||
role = "S.W.A.T. Officer"
|
||||
outfit = /datum/outfit/families_police/beatcop/swat
|
||||
|
||||
/datum/antagonist/ert/families/beatcop/fbi
|
||||
name = "FBI Agent"
|
||||
role = "FBI Agent"
|
||||
outfit = /datum/outfit/families_police/beatcop/fbi
|
||||
|
||||
/datum/antagonist/ert/families/beatcop/military
|
||||
name = "Space Military"
|
||||
role = "Sergeant"
|
||||
outfit = /datum/outfit/families_police/beatcop/military
|
||||
|
||||
/datum/antagonist/ert/families/beatcop/military/New()
|
||||
. = ..()
|
||||
name_source = GLOB.commando_names
|
||||
|
||||
/datum/antagonist/ert/marine
|
||||
name = "Marine Commander"
|
||||
outfit = /datum/outfit/ert/commander/alert
|
||||
role = "Commander"
|
||||
|
||||
/datum/antagonist/ert/marine/security
|
||||
name = "Marine Heavy"
|
||||
outfit = /datum/outfit/ert/security/alert
|
||||
role = "Trooper"
|
||||
|
||||
/datum/antagonist/ert/marine/engineer
|
||||
name = "Marine Engineer"
|
||||
outfit = /datum/outfit/ert/engineer/alert
|
||||
role = "Engineer"
|
||||
|
||||
/datum/antagonist/ert/marine/medic
|
||||
name = "Marine Medic"
|
||||
outfit = /datum/outfit/ert/medic/alert
|
||||
role = "Medical Officer"
|
||||
|
||||
60
code/modules/antagonists/gang/cellphone.dm
Normal file
60
code/modules/antagonists/gang/cellphone.dm
Normal file
@@ -0,0 +1,60 @@
|
||||
GLOBAL_LIST_EMPTY(gangster_cell_phones)
|
||||
|
||||
/obj/item/gangster_cellphone
|
||||
name = "cell phone"
|
||||
desc = "TODO: funny joke about the 80s, brick phones"
|
||||
icon = 'icons/obj/gang/cell_phone.dmi'
|
||||
icon_state = "phone_off"
|
||||
throwforce = 15 // these things are dense as fuck
|
||||
var/gang_id = "Grove Street Families"
|
||||
var/activated = FALSE
|
||||
|
||||
/obj/item/gangster_cellphone/Initialize()
|
||||
. = ..()
|
||||
GLOB.gangster_cell_phones += src
|
||||
flags_1 |= HEAR_1
|
||||
|
||||
/obj/item/gangster_cellphone/Destroy()
|
||||
GLOB.gangster_cell_phones -= src
|
||||
. = ..()
|
||||
|
||||
/obj/item/gangster_cellphone/attack_self(mob/user, modifiers)
|
||||
. = ..()
|
||||
if(!activated)
|
||||
to_chat(user, "You turn on [src].")
|
||||
icon_state = "phone_on"
|
||||
activated = TRUE
|
||||
else
|
||||
to_chat(user, "You turn off [src].")
|
||||
icon_state = "phone_off"
|
||||
activated = FALSE
|
||||
|
||||
/obj/item/gangster_cellphone/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, list/message_mods)
|
||||
. = ..()
|
||||
if(!activated)
|
||||
return
|
||||
if(get_turf(speaker) != get_turf(src))
|
||||
return
|
||||
broadcast_message(raw_message, speaker)
|
||||
|
||||
/obj/item/gangster_cellphone/proc/broadcast_message(message, atom/movable/speaker)
|
||||
for(var/obj/item/gangster_cellphone/brick in GLOB.gangster_cell_phones)
|
||||
if(brick.gang_id == gang_id)
|
||||
brick.say_message(message, speaker)
|
||||
for(var/mob/dead/observer/player_mob in GLOB.player_list)
|
||||
if(!istype(player_mob, /mob/dead/observer))
|
||||
continue
|
||||
if(QDELETED(player_mob)) //Some times nulls and deleteds stay in this list. This is a workaround to prevent ic chat breaking for everyone when they do.
|
||||
continue //Remove if underlying cause (likely byond issue) is fixed. See TG PR #49004.
|
||||
if(player_mob.stat != DEAD) //not dead, not important
|
||||
continue
|
||||
if(get_dist(player_mob, src) > 7 || player_mob.z != z) //they're out of range of normal hearing
|
||||
if(!(player_mob.client.prefs.chat_toggles & CHAT_GHOSTEARS)) //they're talking normally and we have hearing at any range off
|
||||
continue
|
||||
to_chat(player_mob, span_gangradio("<b>[speaker.name]</b> \[CELL: [gang_id]\] says, \"[message]\""))
|
||||
|
||||
/obj/item/gangster_cellphone/proc/say_message(message, atom/movable/speaker)
|
||||
for(var/mob/living/carbon/human/cellphone_hearer in get_turf(src))
|
||||
if(HAS_TRAIT(cellphone_hearer, TRAIT_DEAF))
|
||||
continue
|
||||
to_chat(cellphone_hearer, span_gangradio("<b>[speaker.name]</b> \[CELL: [gang_id]\] says, \"[message]\""))
|
||||
779
code/modules/antagonists/gang/gang.dm
Normal file
779
code/modules/antagonists/gang/gang.dm
Normal file
@@ -0,0 +1,779 @@
|
||||
/datum/antagonist/gang
|
||||
name = "Family Member"
|
||||
roundend_category = "gangsters"
|
||||
ui_name = "AntagInfoGangmember"
|
||||
antag_hud_type = ANTAG_HUD_GANGSTER
|
||||
antag_hud_name = "hud_gangster"
|
||||
antagpanel_category = "Family"
|
||||
show_in_antagpanel = FALSE // i don't *think* this base class is buggy but it's too worthless to test
|
||||
suicide_cry = "FOR THE FAMILY!!"
|
||||
preview_outfit = /datum/outfit/gangster
|
||||
/// The overarching family that the owner of this datum is a part of. Family teams are generic and imprinted upon by the per-person antagonist datums.
|
||||
var/datum/team/gang/my_gang
|
||||
/// The name of the family corresponding to this family member datum.
|
||||
var/gang_name = "Leet Like Jeff K"
|
||||
/// The abbreviation of the family corresponding to this family member datum.
|
||||
var/gang_id = "LLJK"
|
||||
/// The list of clothes that are acceptable to show allegiance to this family.
|
||||
var/list/acceptable_clothes = list()
|
||||
/// The list of clothes that are given to family members upon induction into the family.
|
||||
var/list/free_clothes = list()
|
||||
/// The action used to spawn family induction packages.
|
||||
var/datum/action/cooldown/spawn_induction_package/package_spawner = new()
|
||||
/// Whether or not this family member is the first of their family.
|
||||
var/starter_gangster = FALSE
|
||||
/// The gangster's original real name. Used for renaming stuff, kept between gang switches.
|
||||
var/original_name
|
||||
/// Type of team to create when creating the gang in the first place. Used for renames.
|
||||
var/gang_team_type = /datum/team/gang
|
||||
|
||||
/// A reference to the handler datum that manages the families gamemode. In case of no handler (admin-spawned during round), this will be null; this is fine.
|
||||
var/datum/gang_handler/handler
|
||||
|
||||
/datum/outfit/gangster
|
||||
name = "Gangster (Preview only)"
|
||||
|
||||
uniform = /obj/item/clothing/under/suit/henchmen
|
||||
back = /obj/item/storage/backpack/henchmen
|
||||
|
||||
/datum/antagonist/gang/get_team()
|
||||
return my_gang
|
||||
|
||||
/datum/antagonist/gang/get_admin_commands()
|
||||
. = ..()
|
||||
.["Give extra equipment"] = CALLBACK(src,.proc/equip_gangster_in_inventory)
|
||||
|
||||
/datum/antagonist/gang/create_team(team_given) // gets called whenever add_antag_datum() is called on a mind
|
||||
if(team_given)
|
||||
my_gang = team_given
|
||||
return
|
||||
/* if team_given is falsey, this gang member didn't join a gang by using a recruitment package. so there are two things we need to consider
|
||||
1. does a gang handler exist -- does this round have a gang_handler instanced by the families gamemode or ruleset?
|
||||
2. does the gang we're trying to join already exist?
|
||||
if 1 is true and 2 is false, we were probably added by the gang_handler, and probably already have a "handler" var.
|
||||
if we don't have a "handler" var, and a gang_handler exists, we need to grab it, since our "handler" is null.
|
||||
if the gang exists, we need to join it; if the gang doesn't exist, we need to make it. */
|
||||
var/found_gang = FALSE
|
||||
for(var/datum/team/gang/gang_team in GLOB.antagonist_teams)
|
||||
if(gang_team.my_gang_datum.handler) // if one of the gangs in the gang list has a handler, nab that
|
||||
handler = gang_team.my_gang_datum.handler
|
||||
if(gang_team.name == gang_name)
|
||||
my_gang = gang_team
|
||||
found_gang = TRUE
|
||||
break
|
||||
if(!found_gang)
|
||||
var/new_gang = new gang_team_type()
|
||||
my_gang = new_gang
|
||||
if(handler) // if we have a handler, the handler should track this gang
|
||||
handler.gangs += my_gang
|
||||
my_gang.current_theme = handler.current_theme
|
||||
my_gang.name = gang_name
|
||||
my_gang.gang_id = gang_id
|
||||
my_gang.acceptable_clothes = acceptable_clothes.Copy()
|
||||
my_gang.free_clothes = free_clothes.Copy()
|
||||
my_gang.my_gang_datum = src
|
||||
starter_gangster = TRUE
|
||||
|
||||
/datum/antagonist/gang/on_gain()
|
||||
if(!original_name)
|
||||
original_name = owner.current.real_name
|
||||
my_gang.rename_gangster(owner, original_name, starter_gangster) // fully_replace_character_name
|
||||
if(starter_gangster)
|
||||
equip_gangster_in_inventory()
|
||||
var/datum/atom_hud/gang_hud = GLOB.huds[ANTAG_HUD_GANGSTER]
|
||||
gang_hud.add_hud_to(owner.current)
|
||||
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/thatshowfamiliesworks.ogg', 100, FALSE, pressure_affected = FALSE)
|
||||
..()
|
||||
|
||||
/datum/antagonist/gang/on_removal()
|
||||
if(my_gang.my_gang_datum == src) // if we're the first gangster, we need to replace ourselves so that objectives function correctly
|
||||
var/datum/antagonist/gang/replacement_datum = new type()
|
||||
replacement_datum.handler = handler
|
||||
replacement_datum.my_gang = my_gang
|
||||
my_gang.my_gang_datum = replacement_datum
|
||||
/* all we need to replace; the gang's "my_gang_datum" is just a person's datum because we assign it while we
|
||||
have that datum onhand. it would be easier if all of the code the gang team calls on its my_gang_datum was
|
||||
just in the team datum itself, and there were different types of teams instead of different types of gangster
|
||||
that imprint on generic teams, but i'm too lazy to refactor THAT too */
|
||||
var/datum/atom_hud/gang_hud = GLOB.huds[ANTAG_HUD_GANGSTER]
|
||||
gang_hud.remove_hud_from(owner.current)
|
||||
..()
|
||||
|
||||
/datum/antagonist/gang/apply_innate_effects(mob/living/mob_override)
|
||||
..()
|
||||
if(starter_gangster)
|
||||
package_spawner.Grant(owner.current)
|
||||
package_spawner.my_gang_datum = src
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, M)
|
||||
if(M.hud_used)
|
||||
var/datum/hud/H = M.hud_used
|
||||
var/atom/movable/screen/wanted/giving_wanted_lvl = new /atom/movable/screen/wanted()
|
||||
H.wanted_lvl = giving_wanted_lvl
|
||||
giving_wanted_lvl.hud = H
|
||||
H.infodisplay += giving_wanted_lvl
|
||||
H.mymob.client.screen += giving_wanted_lvl
|
||||
|
||||
/datum/antagonist/gang/remove_innate_effects(mob/living/mob_override)
|
||||
if(starter_gangster)
|
||||
package_spawner.Remove(owner.current)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
remove_antag_hud(antag_hud_type, M)
|
||||
if(M.hud_used)
|
||||
var/datum/hud/H = M.hud_used
|
||||
H.infodisplay -= H.wanted_lvl
|
||||
QDEL_NULL(H.wanted_lvl)
|
||||
..()
|
||||
|
||||
/// Gives a gangster their equipment in their backpack and / or pockets.
|
||||
/datum/antagonist/gang/proc/equip_gangster_in_inventory()
|
||||
if(istype(owner.current, /mob/living/carbon/human))
|
||||
var/obj/item/gangster_cellphone/phone = new()
|
||||
phone.gang_id = gang_name
|
||||
phone.name = "[gang_name] branded cell phone"
|
||||
var/mob/living/carbon/human/gangster_human = owner.current
|
||||
var/phone_equipped = phone.equip_to_best_slot(gangster_human)
|
||||
if(!phone_equipped)
|
||||
to_chat(owner.current, "Your [phone.name] has been placed at your feet.")
|
||||
phone.forceMove(get_turf(gangster_human))
|
||||
for(var/clothing in my_gang.free_clothes)
|
||||
var/obj/item/clothing_object = new clothing(owner.current)
|
||||
var/equipped = clothing_object.equip_to_best_slot(gangster_human)
|
||||
if(!equipped)
|
||||
to_chat(owner.current, "Your [clothing_object.name] has been placed at your feet.")
|
||||
clothing_object.forceMove(get_turf(gangster_human))
|
||||
if(my_gang.current_theme.bonus_items)
|
||||
for(var/bonus_item in my_gang.current_theme.bonus_items)
|
||||
var/obj/item/bonus_object = new bonus_item(owner.current)
|
||||
var/equipped = bonus_object.equip_to_best_slot(gangster_human)
|
||||
if(!equipped)
|
||||
to_chat(owner.current, "Your [bonus_object.name] has been placed at your feet.")
|
||||
bonus_object.forceMove(get_turf(gangster_human))
|
||||
if(starter_gangster)
|
||||
if(my_gang.current_theme.bonus_first_gangster_items)
|
||||
for(var/bonus_starter_item in my_gang.current_theme.bonus_first_gangster_items)
|
||||
var/obj/item/bonus_starter_object = new bonus_starter_item(owner.current)
|
||||
var/equipped = bonus_starter_object.equip_to_best_slot(gangster_human)
|
||||
if(!equipped)
|
||||
to_chat(owner.current, "Your [bonus_starter_object.name] has been placed at your feet.")
|
||||
bonus_starter_object.forceMove(get_turf(gangster_human))
|
||||
|
||||
/datum/antagonist/gang/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["gang_name"] = gang_name
|
||||
data["antag_name"] = name
|
||||
data["gang_objective"] = my_gang.current_theme.gang_objectives[type]
|
||||
|
||||
var/list/clothes_we_can_wear = list()
|
||||
for(var/obj/item/accepted_item as anything in acceptable_clothes)
|
||||
clothes_we_can_wear |= initial(accepted_item.name)
|
||||
|
||||
for(var/obj/item/free_item as anything in free_clothes)
|
||||
if(ispath(free_item, /obj/item/toy/crayon/spraycan))
|
||||
continue
|
||||
clothes_we_can_wear |= initial(free_item.name)
|
||||
|
||||
data["gang_clothes"] = clothes_we_can_wear
|
||||
return data
|
||||
|
||||
/datum/team/gang
|
||||
/// The abbreviation of this family.
|
||||
var/gang_id = "LLJK"
|
||||
/// The list of clothes that are acceptable to show allegiance to this family.
|
||||
var/list/acceptable_clothes = list()
|
||||
/// The list of clothes that are given to family members upon induction into the family.
|
||||
var/list/free_clothes = list()
|
||||
/// The specific, occupied family member antagonist datum that is used to reach the handler / check objectives, and from which the above properties (sans points) are inherited.
|
||||
var/datum/antagonist/gang/my_gang_datum
|
||||
/// The current theme. Used to pull important stuff such as spawning equipment and objectives.
|
||||
var/datum/gang_theme/current_theme
|
||||
|
||||
/// Allow gangs to have custom naming schemes for their gangsters.
|
||||
/datum/team/gang/proc/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/team/gang/roundend_report()
|
||||
var/list/report = list()
|
||||
report += "<span class='header'>[name]:</span>"
|
||||
if(!members.len)
|
||||
report += span_redtext("The family was wiped out!")
|
||||
if(current_theme.everyone_objective)
|
||||
report += "Objective: [current_theme.everyone_objective]"
|
||||
else
|
||||
var/assigned_objective = current_theme.gang_objectives[my_gang_datum.type]
|
||||
if(assigned_objective)
|
||||
report += "Objective: [assigned_objective]"
|
||||
else
|
||||
report += "Objective: ERROR, FILE A REPORT WITH THIS INFO: Gang Name: [my_gang_datum.name], Theme Name: [current_theme.name]"
|
||||
if(members.len)
|
||||
report += "[my_gang_datum.roundend_category] were:"
|
||||
report += printplayerlist(members)
|
||||
|
||||
return "<div class='panel redborder'>[report.Join("<br>")]</div>"
|
||||
|
||||
/datum/action/cooldown/spawn_induction_package
|
||||
name = "Induct via Secret Handshake"
|
||||
desc = "Teach new recruits the Secret Handshake to join."
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "recruit"
|
||||
icon_icon = 'icons/obj/gang/actions.dmi'
|
||||
cooldown_time = 300
|
||||
/// The family antagonist datum of the "owner" of this action.
|
||||
var/datum/antagonist/gang/my_gang_datum
|
||||
|
||||
/datum/action/cooldown/spawn_induction_package/Trigger()
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(!IsAvailable())
|
||||
return FALSE
|
||||
if(!my_gang_datum)
|
||||
return FALSE
|
||||
if(!istype(owner, /mob/living/carbon/human))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.stat)
|
||||
return FALSE
|
||||
|
||||
var/obj/item/slapper/secret_handshake/secret_handshake_item = new(owner)
|
||||
if(owner.put_in_hands(secret_handshake_item))
|
||||
to_chat(owner, span_notice("You ready your secret handshake."))
|
||||
else
|
||||
qdel(secret_handshake_item)
|
||||
to_chat(owner, span_warning("You're incapable of performing a handshake in your current state."))
|
||||
return FALSE
|
||||
owner.visible_message(span_notice("[owner] is offering to induct people into the Family."),
|
||||
span_notice("You offer to induct people into the Family."), null, 2)
|
||||
if(H.has_status_effect(STATUS_EFFECT_HANDSHAKE))
|
||||
return FALSE
|
||||
if(!(locate(/mob/living/carbon) in orange(1, owner)))
|
||||
owner.visible_message(span_danger("[owner] offers to induct people into the Family, but nobody was around."), \
|
||||
span_warning("You offer to induct people into the Family, but nobody is around."), null, 2)
|
||||
return FALSE
|
||||
|
||||
H.apply_status_effect(STATUS_EFFECT_HANDSHAKE, secret_handshake_item)
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
/datum/antagonist/gang/russian_mafia
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Mafioso"
|
||||
roundend_category = "The mafiosos"
|
||||
gang_name = "Mafia"
|
||||
gang_id = "RM"
|
||||
acceptable_clothes = list(/obj/item/clothing/head/soft/red,
|
||||
/obj/item/clothing/neck/scarf/red,
|
||||
/obj/item/clothing/under/suit/white,
|
||||
/obj/item/clothing/head/beanie/red,
|
||||
/obj/item/clothing/head/ushanka)
|
||||
free_clothes = list(/obj/item/clothing/head/ushanka,
|
||||
/obj/item/clothing/under/suit/white,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Russian"
|
||||
gang_team_type = /datum/team/gang/russian_mafia
|
||||
|
||||
/datum/team/gang/russian_mafia/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Don [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/italian_mob
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Mobster"
|
||||
roundend_category = "The mobsters"
|
||||
gang_name = "Mob"
|
||||
gang_id = "IM"
|
||||
acceptable_clothes = list(/obj/item/clothing/under/suit/checkered,
|
||||
/obj/item/clothing/head/fedora,
|
||||
/obj/item/clothing/neck/scarf/green,
|
||||
/obj/item/clothing/mask/bandana/green)
|
||||
free_clothes = list(/obj/item/clothing/head/fedora,
|
||||
/obj/item/clothing/under/suit/checkered,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Italian"
|
||||
gang_team_type = /datum/team/gang/russian_mafia
|
||||
|
||||
/datum/team/gang/russian_mafia/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Boss [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/tunnel_snakes
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Tunnel Snake"
|
||||
roundend_category = "The Tunnel Snakes"
|
||||
gang_name = "Tunnel Snakes"
|
||||
gang_id = "TS"
|
||||
acceptable_clothes = list(/obj/item/clothing/under/pants/classicjeans,
|
||||
/obj/item/clothing/suit/jacket,
|
||||
/obj/item/clothing/mask/bandana/skull)
|
||||
free_clothes = list(/obj/item/clothing/suit/jacket,
|
||||
/obj/item/clothing/under/pants/classicjeans,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Snakes"
|
||||
gang_team_type = /datum/team/gang/tunnel_snakes
|
||||
|
||||
/datum/team/gang/tunnel_snakes/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "King Cobra [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/henchmen
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Monarch Henchmen"
|
||||
roundend_category = "The Monarch henchmen"
|
||||
gang_name = "Monarch Crew"
|
||||
gang_id = "HENCH"
|
||||
acceptable_clothes = list(/obj/item/clothing/head/soft/yellow,
|
||||
/obj/item/clothing/under/suit/henchmen,
|
||||
/obj/item/clothing/neck/scarf/yellow,
|
||||
/obj/item/clothing/head/beanie/yellow,
|
||||
/obj/item/clothing/mask/bandana/gold,
|
||||
/obj/item/storage/backpack/henchmen)
|
||||
free_clothes = list(/obj/item/storage/backpack/henchmen,
|
||||
/obj/item/clothing/under/suit/henchmen,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Monarch"
|
||||
gang_team_type = /datum/team/gang/henchmen
|
||||
|
||||
/datum/team/gang/henchmen
|
||||
var/henchmen_count = 0
|
||||
|
||||
/datum/team/gang/henchmen/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
henchmen_count++
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Number [henchmen_count]")
|
||||
|
||||
/datum/antagonist/gang/yakuza
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Tojo Clan Member"
|
||||
roundend_category = "The Yakuza"
|
||||
gang_name = "Tojo Clan"
|
||||
gang_id = "YAK"
|
||||
acceptable_clothes = list(/obj/item/clothing/head/soft/yellow,
|
||||
/obj/item/clothing/under/costume/yakuza,
|
||||
/obj/item/clothing/shoes/yakuza,
|
||||
/obj/item/clothing/neck/scarf/yellow,
|
||||
/obj/item/clothing/head/beanie/yellow,
|
||||
/obj/item/clothing/mask/bandana/gold,
|
||||
/obj/item/clothing/head/hardhat,
|
||||
/obj/item/clothing/suit/yakuza)
|
||||
free_clothes = list(/obj/item/clothing/under/costume/yakuza,
|
||||
/obj/item/clothing/shoes/yakuza,
|
||||
/obj/item/clothing/suit/yakuza,
|
||||
/obj/item/clothing/head/hardhat,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Tojo"
|
||||
gang_team_type = /datum/team/gang/yakuza
|
||||
|
||||
/datum/team/gang/yakuza/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Patriarch [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/jackbros
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Jack Bro"
|
||||
roundend_category = "The Hee-hos"
|
||||
gang_name = "Jack Bros"
|
||||
gang_id = "JB"
|
||||
acceptable_clothes = list(/obj/item/clothing/head/soft/blue,
|
||||
/obj/item/clothing/under/costume/jackbros,
|
||||
/obj/item/clothing/shoes/jackbros,
|
||||
/obj/item/clothing/head/jackbros,
|
||||
/obj/item/clothing/mask/bandana/blue)
|
||||
free_clothes = list(/obj/item/clothing/under/costume/jackbros,
|
||||
/obj/item/clothing/shoes/jackbros,
|
||||
/obj/item/clothing/head/jackbros,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "JackFrost"
|
||||
gang_team_type = /datum/team/gang/jackbros
|
||||
|
||||
/datum/team/gang/jackbros/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "King Frost [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/dutch
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Dutch van der Linde Outlaw"
|
||||
roundend_category = "Dutch's outlaws"
|
||||
gang_name = "Dutch van der Linde's Gang"
|
||||
gang_id = "VDL"
|
||||
acceptable_clothes = list(/obj/item/clothing/head/soft/black,
|
||||
/obj/item/clothing/under/costume/dutch,
|
||||
/obj/item/clothing/suit/dutch,
|
||||
/obj/item/clothing/head/bowler,
|
||||
/obj/item/clothing/mask/bandana/black)
|
||||
free_clothes = list(/obj/item/clothing/under/costume/dutch,
|
||||
/obj/item/clothing/head/bowler,
|
||||
/obj/item/clothing/suit/dutch,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Dutch"
|
||||
gang_team_type = /datum/team/gang/dutch
|
||||
|
||||
/datum/team/gang/dutch/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Head Cowboy [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
|
||||
/datum/antagonist/gang/irs
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Internal Revenue Service Agent"
|
||||
roundend_category = "IRS Agents"
|
||||
gang_name = "Internal Revenue Service"
|
||||
gang_id = "IRS"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/irs,
|
||||
/obj/item/clothing/under/costume/irs,
|
||||
/obj/item/clothing/head/irs)
|
||||
free_clothes = list(/obj/item/clothing/suit/irs,
|
||||
/obj/item/clothing/under/costume/irs,
|
||||
/obj/item/clothing/head/irs,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "IRS"
|
||||
gang_team_type = /datum/team/gang/irs
|
||||
|
||||
/datum/team/gang/irs/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Revenue Supervisor [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Revenue Agent [last_name.match]")
|
||||
|
||||
/datum/antagonist/gang/osi
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Office of Secret Intelligence Agent"
|
||||
roundend_category = "O.S.I. Agents"
|
||||
gang_name = "Office of Secret Intelligence"
|
||||
gang_id = "OSI"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/osi,
|
||||
/obj/item/clothing/under/costume/osi,
|
||||
/obj/item/clothing/glasses/osi)
|
||||
free_clothes = list(/obj/item/clothing/suit/osi,
|
||||
/obj/item/clothing/under/costume/osi,
|
||||
/obj/item/clothing/glasses/osi,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "OSI"
|
||||
gang_team_type = /datum/team/gang/osi
|
||||
|
||||
/datum/team/gang/osi/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "General [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Special Agent [last_name.match]")
|
||||
|
||||
/datum/antagonist/gang/tmc
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Lost M.C. Biker"
|
||||
roundend_category = "Lost M.C. Bikers"
|
||||
gang_name = "The Lost M.C."
|
||||
gang_id = "TMC"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/tmc,
|
||||
/obj/item/clothing/under/costume/tmc,
|
||||
/obj/item/clothing/head/tmc)
|
||||
free_clothes = list(/obj/item/clothing/suit/tmc,
|
||||
/obj/item/clothing/under/costume/tmc,
|
||||
/obj/item/clothing/head/tmc,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "LostMC"
|
||||
gang_team_type = /datum/team/gang/tmc
|
||||
|
||||
/datum/team/gang/tmc/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "President [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/pg
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Powder Ganger"
|
||||
roundend_category = "Powder Gangers"
|
||||
gang_name = "Powder Gangers"
|
||||
gang_id = "PG"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/pg,
|
||||
/obj/item/clothing/under/costume/pg,
|
||||
/obj/item/clothing/head/pg)
|
||||
free_clothes = list(/obj/item/clothing/suit/pg,
|
||||
/obj/item/clothing/under/costume/pg,
|
||||
/obj/item/clothing/head/pg,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "PowderGang"
|
||||
gang_team_type = /datum/team/gang/pg
|
||||
|
||||
/datum/team/gang/pg/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Head Convict [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
|
||||
/datum/antagonist/gang/driscoll
|
||||
show_in_antagpanel = TRUE
|
||||
name = "O'Driscoll Gangster"
|
||||
roundend_category = "O'Driscoll's Gangsters"
|
||||
gang_name = "O'Driscoll's Gang"
|
||||
gang_id = "DB"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/driscoll,
|
||||
/obj/item/clothing/under/costume/driscoll,
|
||||
/obj/item/clothing/mask/gas/driscoll,
|
||||
/obj/item/clothing/shoes/cowboyboots)
|
||||
free_clothes = list(/obj/item/clothing/suit/driscoll,
|
||||
/obj/item/clothing/under/costume/driscoll,
|
||||
/obj/item/clothing/mask/gas/driscoll,
|
||||
/obj/item/clothing/shoes/cowboyboots,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Drill"
|
||||
gang_team_type = /datum/team/gang/driscoll
|
||||
|
||||
/datum/team/gang/driscoll/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Head Outlaw [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/deckers
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Decker"
|
||||
roundend_category = "Deckers"
|
||||
gang_name = "Deckers"
|
||||
gang_id = "DK"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/deckers,
|
||||
/obj/item/clothing/under/costume/deckers,
|
||||
/obj/item/clothing/head/deckers,
|
||||
/obj/item/clothing/shoes/deckers)
|
||||
free_clothes = list(/obj/item/clothing/suit/deckers,
|
||||
/obj/item/clothing/under/costume/deckers,
|
||||
/obj/item/clothing/head/deckers,
|
||||
/obj/item/clothing/shoes/deckers,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Deckers"
|
||||
gang_team_type = /datum/team/gang/deckers
|
||||
|
||||
/datum/team/gang/deckers/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Master Hacker [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
|
||||
/datum/antagonist/gang/morningstar
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Morningstar Member"
|
||||
roundend_category = "Morningstar Member"
|
||||
gang_name = "Morningstar"
|
||||
gang_id = "MS"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/morningstar,
|
||||
/obj/item/clothing/under/costume/morningstar,
|
||||
/obj/item/clothing/head/morningstar,
|
||||
/obj/item/clothing/shoes/morningstar)
|
||||
free_clothes = list(/obj/item/clothing/suit/morningstar,
|
||||
/obj/item/clothing/under/costume/morningstar,
|
||||
/obj/item/clothing/head/morningstar,
|
||||
/obj/item/clothing/shoes/morningstar,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "MorningStar"
|
||||
gang_team_type = /datum/team/gang/morningstar
|
||||
|
||||
/datum/team/gang/morningstar/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Chief Executive Officer [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/saints
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Third Street Saints Gangster"
|
||||
roundend_category = "Third Street Saints Gangsters"
|
||||
gang_name = "Third Street Saints"
|
||||
gang_id = "TSS"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/saints,
|
||||
/obj/item/clothing/under/costume/saints,
|
||||
/obj/item/clothing/head/saints,
|
||||
/obj/item/clothing/shoes/saints)
|
||||
free_clothes = list(/obj/item/clothing/suit/saints,
|
||||
/obj/item/clothing/under/costume/saints,
|
||||
/obj/item/clothing/head/saints,
|
||||
/obj/item/clothing/shoes/saints,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "TheSaints"
|
||||
gang_team_type = /datum/team/gang/saints
|
||||
|
||||
/datum/team/gang/saints/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Boss [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
|
||||
/datum/antagonist/gang/phantom
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Phantom Thief"
|
||||
roundend_category = "Phantom Thieves"
|
||||
gang_name = "Phantom Thieves of Hearts"
|
||||
gang_id = "PT"
|
||||
acceptable_clothes = list(/obj/item/clothing/suit/phantom,
|
||||
/obj/item/clothing/under/costume/phantom,
|
||||
/obj/item/clothing/glasses/phantom,
|
||||
/obj/item/clothing/shoes/phantom)
|
||||
free_clothes = list(/obj/item/clothing/suit/phantom,
|
||||
/obj/item/clothing/under/costume/phantom,
|
||||
/obj/item/clothing/glasses/phantom,
|
||||
/obj/item/clothing/shoes/phantom,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "PhantomThieves"
|
||||
gang_team_type = /datum/team/gang/phantom
|
||||
|
||||
/datum/team/gang/phantom/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Joker [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/allies
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Allies G.I."
|
||||
roundend_category = "Allies"
|
||||
gang_name = "Allies"
|
||||
gang_id = "ALLIES"
|
||||
free_clothes = list(/obj/item/clothing/suit/allies,
|
||||
/obj/item/clothing/under/costume/allies,
|
||||
/obj/item/clothing/head/allies,
|
||||
/obj/item/clothing/gloves/color/black,
|
||||
/obj/item/clothing/shoes/jackboots,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Allies"
|
||||
gang_team_type = /datum/team/gang/allies
|
||||
|
||||
/datum/team/gang/allies/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Commander [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Private [last_name.match]")
|
||||
|
||||
/datum/antagonist/gang/soviet
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Soviet Conscript"
|
||||
roundend_category = "Soviets"
|
||||
gang_name = "Soviets"
|
||||
gang_id = "SOV"
|
||||
free_clothes = list(/obj/item/clothing/suit/soviet,
|
||||
/obj/item/clothing/under/costume/soviet_families,
|
||||
/obj/item/clothing/head/ushanka/soviet,
|
||||
/obj/item/clothing/gloves/color/black,
|
||||
/obj/item/clothing/shoes/jackboots,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "Soviets"
|
||||
gang_team_type = /datum/team/gang/soviet
|
||||
|
||||
/datum/team/gang/soviet/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Comrade General [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Conscript [last_name.match]")
|
||||
|
||||
/datum/antagonist/gang/yuri
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Yuri Initiate"
|
||||
roundend_category = "Yuri's Army"
|
||||
gang_name = "Yuri's Army"
|
||||
gang_id = "YR"
|
||||
free_clothes = list(/obj/item/clothing/suit/yuri,
|
||||
/obj/item/clothing/under/costume/yuri,
|
||||
/obj/item/clothing/head/yuri,
|
||||
/obj/item/clothing/gloves/color/black,
|
||||
/obj/item/clothing/shoes/jackboots,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "YuriArmy"
|
||||
gang_team_type = /datum/team/gang/yuri
|
||||
|
||||
/datum/team/gang/yuri/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Initiate Prime [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Initiate [last_name.match]")
|
||||
|
||||
/datum/antagonist/gang/sybil_slickers
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Sybil Slicker"
|
||||
roundend_category = "Sybil Slickers"
|
||||
gang_name = "Sybil Slickers"
|
||||
gang_id = "SS"
|
||||
free_clothes = list(/obj/item/clothing/suit/sybil_slickers,
|
||||
/obj/item/clothing/under/costume/sybil_slickers,
|
||||
/obj/item/clothing/head/sybil_slickers,
|
||||
/obj/item/clothing/gloves/tackler/football,
|
||||
/obj/item/clothing/shoes/sybil_slickers,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "SybilSlickers"
|
||||
gang_team_type = /datum/team/gang/sybil_slickers
|
||||
|
||||
/datum/team/gang/sybil_slickers/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Sybil Coach [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
|
||||
/datum/antagonist/gang/basil_boys
|
||||
show_in_antagpanel = TRUE
|
||||
name = "Basil Boy"
|
||||
roundend_category = "Basil Boys"
|
||||
gang_name = "Basil Boys"
|
||||
gang_id = "BB"
|
||||
free_clothes = list(/obj/item/clothing/suit/basil_boys,
|
||||
/obj/item/clothing/under/costume/basil_boys,
|
||||
/obj/item/clothing/head/basil_boys,
|
||||
/obj/item/clothing/gloves/tackler/football,
|
||||
/obj/item/clothing/shoes/basil_boys,
|
||||
/obj/item/toy/crayon/spraycan)
|
||||
antag_hud_name = "BasilBoys"
|
||||
gang_team_type = /datum/team/gang/basil_boys
|
||||
|
||||
/datum/team/gang/basil_boys/rename_gangster(datum/mind/gangster, original_name, starter_gangster)
|
||||
var/static/regex/last_name = new("\[^\\s-\]+$") //First word before whitespace or "-"
|
||||
last_name.Find(original_name)
|
||||
if(starter_gangster)
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, "Basil Coach [last_name.match]")
|
||||
else
|
||||
gangster.current.fully_replace_character_name(gangster.current.real_name, original_name)
|
||||
429
code/modules/antagonists/gang/handler.dm
Normal file
429
code/modules/antagonists/gang/handler.dm
Normal file
@@ -0,0 +1,429 @@
|
||||
#define LOWPOP_FAMILIES_COUNT 50
|
||||
|
||||
#define TWO_STARS_HIGHPOP 11
|
||||
#define THREE_STARS_HIGHPOP 16
|
||||
#define FOUR_STARS_HIGHPOP 21
|
||||
#define FIVE_STARS_HIGHPOP 31
|
||||
|
||||
#define TWO_STARS_LOW 6
|
||||
#define THREE_STARS_LOW 9
|
||||
#define FOUR_STARS_LOW 12
|
||||
#define FIVE_STARS_LOW 15
|
||||
|
||||
#define CREW_SIZE_MIN 4
|
||||
#define CREW_SIZE_MAX 8
|
||||
|
||||
|
||||
GLOBAL_VAR_INIT(deaths_during_shift, 0)
|
||||
///Forces the Families theme to be the one in this variable via variable editing. Used for debugging.
|
||||
GLOBAL_VAR(families_override_theme)
|
||||
|
||||
/**
|
||||
* # Families gamemode / dynamic ruleset handler
|
||||
*
|
||||
* A special datum used by the families gamemode and dynamic rulesets to centralize code. "Family" and "gang" used interchangeably in code.
|
||||
*
|
||||
* This datum centralizes code used for the families gamemode / dynamic rulesets. Families incorporates a significant
|
||||
* amount of unique processing; without this datum, that could would be duplicated. To ensure the maintainability
|
||||
* of the families gamemode / rulesets, the code was moved to this datum. The gamemode / rulesets instance this
|
||||
* datum, pass it lists (lists are passed by reference; removing candidates here removes candidates in the gamemode),
|
||||
* and call its procs. Additionally, the families antagonist datum and families induction package also
|
||||
* contain vars that reference this datum, allowing for new families / family members to add themselves
|
||||
* to this datum's lists thereof (primarily used for point calculation). Despite this, the basic team mechanics
|
||||
* themselves should function regardless of this datum's instantiation, should a player have the gang or cop
|
||||
* antagonist datum added to them through methods external to the families gamemode / rulesets.
|
||||
*
|
||||
*/
|
||||
/datum/gang_handler
|
||||
/// A counter used to minimize the overhead of computationally intensive, periodic family point gain checks. Used and set internally.
|
||||
var/check_counter = 0
|
||||
/// The time, in deciseconds, that the datum's pre_setup() occured at. Used in end_time. Used and set internally.
|
||||
var/start_time = null
|
||||
/// The time, in deciseconds, that the space cops will arrive at. Calculated based on wanted level and start_time. Used and set internally.
|
||||
var/end_time = null
|
||||
/// Whether the gamemode-announcing announcement has been sent. Used and set internally.
|
||||
var/sent_announcement = FALSE
|
||||
/// Whether the "5 minute warning" announcement has been sent. Used and set internally.
|
||||
var/sent_second_announcement = FALSE
|
||||
/// Whether the space cops have arrived. Set internally; used internally, and for updating the wanted HUD.
|
||||
var/cops_arrived = FALSE
|
||||
/// The current wanted level. Set internally; used internally, and for updating the wanted HUD.
|
||||
var/wanted_level
|
||||
/// List of all /datum/team/gang. Used internally; added to externally by /datum/antagonist/gang when it generates a new /datum/team/gang.
|
||||
var/list/gangs = list()
|
||||
/// List of all family member minds. Used internally; added to internally, and externally by /obj/item/gang_induction_package when used to induct a new family member.
|
||||
var/list/gangbangers = list()
|
||||
/// List of all undercover cop minds. Used and set internally.
|
||||
var/list/undercover_cops = list()
|
||||
/// The number of families (and 1:1 corresponding undercover cops) that should be generated. Can be set externally; used internally.
|
||||
var/gangs_to_generate = 3
|
||||
/// The number of family members more that a family may have over other active families. Can be set externally; used internally.
|
||||
var/gang_balance_cap = 5
|
||||
/// Whether the handler corresponds to a ruleset that does not trigger at round start. Should be set externally only if applicable; used internally.
|
||||
var/midround_ruleset = FALSE
|
||||
/// Whether we want to use the 30 to 15 minute timer instead of the 60 to 30 minute timer, for Dynamic.
|
||||
var/use_dynamic_timing = FALSE
|
||||
/// Keeps track of the amount of deaths since the calling of pre_setup_analogue() if this is a midround handler. Used to prevent a high wanted level due to a large amount of deaths during the shift prior to the activation of this handler / the midround ruleset.
|
||||
var/deaths_during_shift_at_beginning = 0
|
||||
|
||||
/// List of all eligible starting family members / undercover cops. Set externally (passed by reference) by gamemode / ruleset; used internally. Note that dynamic uses a list of mobs to handle candidates while game_modes use lists of minds! Don't be fooled!
|
||||
var/list/antag_candidates = list()
|
||||
/// List of jobs not eligible for starting family member / undercover cop. Set externally (passed by reference) by gamemode / ruleset; used internally.
|
||||
var/list/restricted_jobs
|
||||
/// The current chosen gamemode theme. Decides the available Gangs, objectives, and equipment.
|
||||
var/datum/gang_theme/current_theme
|
||||
|
||||
/**
|
||||
* Sets antag_candidates and restricted_jobs.
|
||||
*
|
||||
* Sets the antag_candidates and restricted_jobs lists to the equivalent
|
||||
* lists of its instantiating game_mode / dynamic_ruleset datum. As lists
|
||||
* are passed by reference, the variable set in this datum and the passed list
|
||||
* list used to set it are literally the same; changes to one affect the other.
|
||||
* Like all New() procs, called when the datum is first instantiated.
|
||||
* There's an annoying caveat here, though -- dynamic rulesets don't have
|
||||
* lists of minds for candidates, they have lists of mobs. Ghost mobs, before
|
||||
* the round has started. But we still want to preserve the structure of the candidates
|
||||
* list by not duplicating it and making sure to remove the candidates as we use them.
|
||||
* So there's a little bit of boilerplate throughout to preserve the sanctity of this reference.
|
||||
* Arguments:
|
||||
* * given_candidates - The antag_candidates list or equivalent of the datum instantiating this one.
|
||||
* * revised_restricted - The restricted_jobs list or equivalent of the datum instantiating this one.
|
||||
*/
|
||||
/datum/gang_handler/New(list/given_candidates, list/revised_restricted)
|
||||
antag_candidates = given_candidates
|
||||
restricted_jobs = revised_restricted
|
||||
|
||||
/**
|
||||
* pre_setup() or pre_execute() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done during the pre_setup() or pre_execute() phase, after first instantiation
|
||||
* and the modification of gangs_to_generate, gang_balance_cap, and midround_ruleset.
|
||||
* It is intended to take the place of the code that would normally occupy the pre_setup()
|
||||
* or pre_execute() proc, were the code localized to the game_mode or dynamic_ruleset datum respectively
|
||||
* as opposed to this handler. As such, it picks players to be chosen for starting familiy members
|
||||
* or undercover cops prior to assignment to jobs. Sets start_time, default end_time,
|
||||
* and the current value of deaths_during_shift, to ensure the wanted level only cares about
|
||||
* the deaths since this proc has been called.
|
||||
* Takes no arguments.
|
||||
*/
|
||||
/datum/gang_handler/proc/pre_setup_analogue()
|
||||
if(!GLOB.families_override_theme)
|
||||
var/theme_to_use = pick(subtypesof(/datum/gang_theme))
|
||||
current_theme = new theme_to_use
|
||||
else
|
||||
current_theme = new GLOB.families_override_theme
|
||||
var/gangsters_to_make = length(current_theme.involved_gangs) * current_theme.starting_gangsters
|
||||
for(var/i in 1 to gangsters_to_make)
|
||||
if (!antag_candidates.len)
|
||||
break
|
||||
var/taken = pick_n_take(antag_candidates) // original used antag_pick, but that's local to game_mode and rulesets use pick_n_take so this is fine maybe
|
||||
var/datum/mind/gangbanger
|
||||
if(istype(taken, /mob))
|
||||
var/mob/T = taken
|
||||
gangbanger = T.mind
|
||||
else
|
||||
gangbanger = taken
|
||||
gangbangers += gangbanger
|
||||
gangbanger.restricted_roles = restricted_jobs
|
||||
log_game("[key_name(gangbanger)] has been selected as a starting gangster!")
|
||||
if(!midround_ruleset)
|
||||
GLOB.pre_setup_antags += gangbanger
|
||||
deaths_during_shift_at_beginning = GLOB.deaths_during_shift // don't want to mix up pre-families and post-families deaths
|
||||
start_time = world.time
|
||||
end_time = start_time + ((60 MINUTES) / (midround_ruleset ? 2 : 1)) // midround families rounds end quicker
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* post_setup() or execute() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done during the post_setup() or execute() phase, after the pre_setup() / pre_execute() phase.
|
||||
* It is intended to take the place of the code that would normally occupy the pre_setup()
|
||||
* or pre_execute() proc. As such, it ensures that all prospective starting family members /
|
||||
* undercover cops are eligible, and picks replacements if there were ineligible cops / family members.
|
||||
* It then assigns gear to the finalized family members and undercover cops, adding them to its lists,
|
||||
* and sets the families announcement proc (that does the announcing) to trigger in five minutes.
|
||||
* Additionally, if given the argument TRUE, it will return FALSE if there are no eligible starting family members.
|
||||
* This is only to be done if the instantiating datum is a dynamic_ruleset, as these require returns
|
||||
* while a game_mode is not expected to return early during this phase.
|
||||
* Arguments:
|
||||
* * return_if_no_gangs - Boolean that determines if the proc should return FALSE should it find no eligible family members. Should be used for dynamic only.
|
||||
*/
|
||||
/datum/gang_handler/proc/post_setup_analogue(return_if_no_gangs = FALSE)
|
||||
var/replacement_gangsters = 0
|
||||
for(var/datum/mind/gangbanger in gangbangers)
|
||||
if(!ishuman(gangbanger.current))
|
||||
if(!midround_ruleset)
|
||||
GLOB.pre_setup_antags -= gangbanger
|
||||
gangbangers.Remove(gangbanger)
|
||||
log_game("[gangbanger] was not a human, and thus has lost their gangster role.")
|
||||
replacement_gangsters++
|
||||
if(replacement_gangsters)
|
||||
for(var/j = 0, j < replacement_gangsters, j++)
|
||||
if(!antag_candidates.len)
|
||||
log_game("Unable to find more replacement gangsters. Not all of the gangs will spawn.")
|
||||
break
|
||||
var/taken = pick_n_take(antag_candidates)
|
||||
var/datum/mind/gangbanger
|
||||
if(istype(taken, /mob)) // boilerplate needed because antag_candidates might not contain minds
|
||||
var/mob/T = taken
|
||||
gangbanger = T.mind
|
||||
else
|
||||
gangbanger = taken
|
||||
gangbangers += gangbanger
|
||||
log_game("[key_name(gangbanger)] has been selected as a replacement gangster!")
|
||||
if(!gangbangers.len)
|
||||
if(return_if_no_gangs)
|
||||
return FALSE // ending early is bad if we're not in dynamic
|
||||
|
||||
var/list/gangs_to_use = current_theme.involved_gangs
|
||||
var/amount_of_gangs = gangs_to_use.len
|
||||
|
||||
for(var/_ in 1 to amount_of_gangs)
|
||||
var/gang_to_use = pick_n_take(gangs_to_use)
|
||||
for(var/__ in 1 to current_theme.starting_gangsters)
|
||||
if(!gangbangers.len)
|
||||
break
|
||||
var/datum/mind/gangster_mind = pick_n_take(gangbangers)
|
||||
var/datum/antagonist/gang/new_gangster = new gang_to_use()
|
||||
new_gangster.handler = src
|
||||
new_gangster.starter_gangster = TRUE
|
||||
gangster_mind.add_antag_datum(new_gangster)
|
||||
|
||||
// see /datum/antagonist/gang/create_team() for how the gang team datum gets instantiated and added to our gangs list
|
||||
|
||||
addtimer(CALLBACK(src, .proc/announce_gang_locations), 5 MINUTES)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* process() or rule_process() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done during the process() or rule_process() phase, after post_setup() or
|
||||
* execute() and at regular intervals thereafter. process() and rule_process() are optional
|
||||
* for a game_mode / dynamic_ruleset, but are important for this gamemode. It is of central
|
||||
* importance to the gamemode's flow, calculating wanted level updates, family point gain,
|
||||
* and announcing + executing the arrival of the space cops, achieved through calling internal procs.
|
||||
* Takes no arguments.
|
||||
*/
|
||||
/datum/gang_handler/proc/process_analogue()
|
||||
|
||||
/**
|
||||
* set_round_result() or round_result() equivalent.
|
||||
*
|
||||
* This proc is always called externally, by the instantiating game_mode / dynamic_ruleset.
|
||||
* This is done by the set_round_result() or round_result() procs, at roundend.
|
||||
* Sets the ticker subsystem to the correct result based off of the relative populations
|
||||
* of space cops and family members.
|
||||
* Takes no arguments.
|
||||
*/
|
||||
/datum/gang_handler/proc/set_round_result_analogue()
|
||||
SSticker.mode_result = "win - gangs survived"
|
||||
SSticker.news_report = GANG_OPERATING
|
||||
return TRUE
|
||||
|
||||
/// Internal. Announces the presence of families to the entire station and sets sent_announcement to true to allow other checks to occur.
|
||||
/datum/gang_handler/proc/announce_gang_locations()
|
||||
priority_announce(current_theme.description, current_theme.name, 'sound/voice/beepsky/radio.ogg')
|
||||
sent_announcement = TRUE
|
||||
|
||||
/// Internal. Checks if our wanted level has changed; calls update_wanted_level. Only updates wanted level post the initial announcement and until the cops show up. After that, it's locked.
|
||||
/datum/gang_handler/proc/check_wanted_level()
|
||||
if(cops_arrived)
|
||||
update_wanted_level(wanted_level) // at this point, we still want to update people's star huds, even though they're mostly locked, because not everyone is around for the last update before the rest of this proc gets shut off forever, and that's when the wanted bar switches from gold stars to red / blue to signify the arrival of the space cops
|
||||
return
|
||||
if(!sent_announcement)
|
||||
return
|
||||
var/new_wanted_level
|
||||
if(GLOB.joined_player_list.len > LOWPOP_FAMILIES_COUNT)
|
||||
switch(GLOB.deaths_during_shift - deaths_during_shift_at_beginning) // if this is a midround ruleset, we only care about the deaths since the families were activated, not since shiftstart
|
||||
if(0 to TWO_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 1
|
||||
if(TWO_STARS_HIGHPOP to THREE_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 2
|
||||
if(THREE_STARS_HIGHPOP to FOUR_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 3
|
||||
if(FOUR_STARS_HIGHPOP to FIVE_STARS_HIGHPOP-1)
|
||||
new_wanted_level = 4
|
||||
if(FIVE_STARS_HIGHPOP to INFINITY)
|
||||
new_wanted_level = 5
|
||||
else
|
||||
switch(GLOB.deaths_during_shift - deaths_during_shift_at_beginning)
|
||||
if(0 to TWO_STARS_LOW-1)
|
||||
new_wanted_level = 1
|
||||
if(TWO_STARS_LOW to THREE_STARS_LOW-1)
|
||||
new_wanted_level = 2
|
||||
if(THREE_STARS_LOW to FOUR_STARS_LOW-1)
|
||||
new_wanted_level = 3
|
||||
if(FOUR_STARS_LOW to FIVE_STARS_LOW-1)
|
||||
new_wanted_level = 4
|
||||
if(FIVE_STARS_LOW to INFINITY)
|
||||
new_wanted_level = 5
|
||||
update_wanted_level(new_wanted_level)
|
||||
|
||||
/// Internal. Updates the icon states for everyone, and calls procs that send out announcements / change the end_time if the wanted level has changed.
|
||||
/datum/gang_handler/proc/update_wanted_level(newlevel)
|
||||
if(newlevel > wanted_level)
|
||||
on_gain_wanted_level(newlevel)
|
||||
else if (newlevel < wanted_level)
|
||||
on_lower_wanted_level(newlevel)
|
||||
wanted_level = newlevel
|
||||
for(var/i in GLOB.player_list)
|
||||
var/mob/M = i
|
||||
if(!M.hud_used?.wanted_lvl)
|
||||
continue
|
||||
var/datum/hud/H = M.hud_used
|
||||
H.wanted_lvl.level = newlevel
|
||||
H.wanted_lvl.cops_arrived = cops_arrived
|
||||
H.wanted_lvl.update_appearance()
|
||||
|
||||
/// Internal. Updates the end_time and sends out an announcement if the wanted level has increased. Called by update_wanted_level().
|
||||
/datum/gang_handler/proc/on_gain_wanted_level(newlevel)
|
||||
var/announcement_message
|
||||
switch(newlevel)
|
||||
if(2)
|
||||
if(!sent_second_announcement) // when you hear that they're "arriving in 5 minutes," that's a goddamn guarantee
|
||||
end_time = start_time + ((50 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "Small amount of police vehicles have been spotted en route towards [station_name()]."
|
||||
if(3)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((40 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "A large detachment police vehicles have been spotted en route towards [station_name()]."
|
||||
if(4)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((35 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "A detachment of top-trained agents has been spotted on their way to [station_name()]."
|
||||
if(5)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((30 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "The fleet enroute to [station_name()] now consists of national guard personnel."
|
||||
if(!midround_ruleset) // stops midround rulesets from announcing janky ass times
|
||||
announcement_message += " They will arrive at the [(end_time - start_time) / (1 MINUTES)] minute mark."
|
||||
if(newlevel == 1) // specific exception to stop the announcement from triggering right after the families themselves are announced because aesthetics
|
||||
return
|
||||
priority_announce(announcement_message, "Station Spaceship Detection Systems")
|
||||
|
||||
/// Internal. Updates the end_time and sends out an announcement if the wanted level has decreased. Called by update_wanted_level().
|
||||
/datum/gang_handler/proc/on_lower_wanted_level(newlevel)
|
||||
var/announcement_message
|
||||
switch(newlevel)
|
||||
if(1)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((60 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "There are now only a few police vehicle headed towards [station_name()]."
|
||||
if(2)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((50 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "There seem to be fewer police vehicles headed towards [station_name()]."
|
||||
if(3)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((40 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "There are no longer top-trained agents in the fleet headed towards [station_name()]."
|
||||
if(4)
|
||||
if(!sent_second_announcement)
|
||||
end_time = start_time + ((35 MINUTES) / (use_dynamic_timing ? 2 : 1))
|
||||
announcement_message = "The convoy enroute to [station_name()] seems to no longer consist of national guard personnel."
|
||||
if(!midround_ruleset)
|
||||
announcement_message += " They will arrive at the [(end_time - start_time) / (1 MINUTES)] minute mark."
|
||||
priority_announce(announcement_message, "Station Spaceship Detection Systems")
|
||||
|
||||
/// Internal. Polls ghosts and sends in a team of space cops according to the wanted level, accompanied by an announcement. Will let the shuttle leave 10 minutes after sending. Freezes the wanted level.
|
||||
/datum/gang_handler/proc/send_in_the_fuzz()
|
||||
var/team_size
|
||||
var/cops_to_send
|
||||
var/announcement_message = "PUNK ASS BALLA BITCH"
|
||||
var/announcer = "Spinward Stellar Coalition"
|
||||
if(GLOB.joined_player_list.len > LOWPOP_FAMILIES_COUNT)
|
||||
switch(wanted_level)
|
||||
if(1)
|
||||
team_size = 8
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop
|
||||
announcement_message = "Hello, crewmembers of [station_name()]! We've received a few calls about some potential violent gang activity on board your station, so we're sending some beat cops to check things out. Nothing extreme, just a courtesy call. However, while they check things out for about 10 minutes, we're going to have to ask that you keep your escape shuttle parked.\n\nHave a pleasant day!"
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(2)
|
||||
team_size = 9
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/armored
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of violent gang activity from your station. We are dispatching some armed officers to help keep the peace and investigate matters. Do not get in their way, and comply with any and all requests from them. We have blockaded the local warp gate, and your shuttle cannot depart for another 10 minutes.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(3)
|
||||
team_size = 10
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/swat
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of extreme gang activity from your station resulting in heavy civilian casualties. The Spinward Stellar Coalition does not tolerate abuse towards our citizens, and we will be responding in force to keep the peace and reduce civilian casualties. We have your station surrounded, and all gangsters must drop their weapons and surrender peacefully.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(4)
|
||||
team_size = 11
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/fbi
|
||||
announcement_message = "We are dispatching our top agents to [station_name()] at the request of the Spinward Stellar Coalition government due to an extreme terrorist level threat against this Nanotrasen owned station. All gangsters must surrender IMMEDIATELY. Failure to comply can and will result in death. We have blockaded your warp gates and will not allow any escape until the situation is resolved within our standard response time of 10 minutes.\n\nSurrender now or face the consequences of your actions."
|
||||
announcer = "Federal Bureau of Investigation"
|
||||
if(5)
|
||||
team_size = 12
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/military
|
||||
announcement_message = "Due to an insane level of civilian casualties aboard [station_name()], we have dispatched the National Guard to curb any and all gang activity on board the station. We have heavy cruisers watching the shuttle. Attempt to leave before we allow you to, and we will obliterate your station and your escape shuttle.\n\nYou brought this on yourselves by murdering so many civilians."
|
||||
announcer = "Spinward Stellar Coalition National Guard"
|
||||
else
|
||||
switch(wanted_level)
|
||||
if(1)
|
||||
team_size = 5
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop
|
||||
announcement_message = "Hello, crewmembers of [station_name()]! We've received a few calls about some potential violent gang activity on board your station, so we're sending some beat cops to check things out. Nothing extreme, just a courtesy call. However, while they check things out for about 10 minutes, we're going to have to ask that you keep your escape shuttle parked.\n\nHave a pleasant day!"
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(2)
|
||||
team_size = 6
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/armored
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of violent gang activity from your station. We are dispatching some armed officers to help keep the peace and investigate matters. Do not get in their way, and comply with any and all requests from them. We have blockaded the local warp gate, and your shuttle cannot depart for another 10 minutes.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(3)
|
||||
team_size = 7
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/swat
|
||||
announcement_message = "Crewmembers of [station_name()]. We have received confirmed reports of extreme gang activity from your station resulting in heavy civilian casualties. The Spinward Stellar Coalition does not tolerate abuse towards our citizens, and we will be responding in force to keep the peace and reduce civilian casualties. We have your station surrounded, and all gangsters must drop their weapons and surrender peacefully.\n\nHave a secure day."
|
||||
announcer = "Spinward Stellar Coalition Police Department"
|
||||
if(4)
|
||||
team_size = 8
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/fbi
|
||||
announcement_message = "We are dispatching our top agents to [station_name()] at the request of the Spinward Stellar Coalition government due to an extreme terrorist level threat against this Nanotrasen owned station. All gangsters must surrender IMMEDIATELY. Failure to comply can and will result in death. We have blockaded your warp gates and will not allow any escape until the situation is resolved within our standard response time of 10 minutes.\n\nSurrender now or face the consequences of your actions."
|
||||
announcer = "Federal Bureau of Investigation"
|
||||
if(5)
|
||||
team_size = 10
|
||||
cops_to_send = /datum/antagonist/ert/families/beatcop/military
|
||||
announcement_message = "Due to an insane level of civilian casualties aboard [station_name()], we have dispatched the National Guard to curb any and all gang activity on board the station. We have heavy cruisers watching the shuttle. Attempt to leave before we allow you to, and we will obliterate your station and your escape shuttle.\n\nYou brought this on yourselves by murdering so many civilians."
|
||||
announcer = "Spinward Stellar Coalition National Guard"
|
||||
|
||||
priority_announce(announcement_message, announcer, 'sound/effects/families_police.ogg')
|
||||
var/list/candidates = pollGhostCandidates("Do you want to help clean up crime on this station?", "deathsquad")
|
||||
|
||||
|
||||
if(candidates.len)
|
||||
//Pick the (un)lucky players
|
||||
var/numagents = min(team_size,candidates.len)
|
||||
|
||||
var/list/spawnpoints = GLOB.emergencyresponseteamspawn
|
||||
var/index = 0
|
||||
while(numagents && candidates.len)
|
||||
var/spawnloc = spawnpoints[index+1]
|
||||
//loop through spawnpoints one at a time
|
||||
index = (index + 1) % spawnpoints.len
|
||||
var/mob/dead/observer/chosen_candidate = pick(candidates)
|
||||
candidates -= chosen_candidate
|
||||
if(!chosen_candidate.key)
|
||||
continue
|
||||
|
||||
//Spawn the body
|
||||
var/mob/living/carbon/human/cop = new(spawnloc)
|
||||
chosen_candidate.client.prefs.copy_to(cop)
|
||||
cop.key = chosen_candidate.key
|
||||
|
||||
//Give antag datum
|
||||
var/datum/antagonist/ert/families/ert_antag = new cops_to_send
|
||||
|
||||
cop.mind.add_antag_datum(ert_antag)
|
||||
cop.mind.assigned_role = ert_antag.name
|
||||
SSjob.SendToLateJoin(cop)
|
||||
|
||||
//Logging and cleanup
|
||||
log_game("[key_name(cop)] has been selected as an [ert_antag.name]")
|
||||
numagents--
|
||||
cops_arrived = TRUE
|
||||
update_wanted_level(wanted_level) // gotta make sure everyone's wanted level display looks nice
|
||||
return TRUE
|
||||
68
code/modules/antagonists/gang/induction_package.dm
Normal file
68
code/modules/antagonists/gang/induction_package.dm
Normal file
@@ -0,0 +1,68 @@
|
||||
/obj/item/gang_induction_package
|
||||
name = "family signup package"
|
||||
icon = 'icons/obj/gang/signup_points.dmi'
|
||||
icon_state = "signup_book"
|
||||
/// References the active families gamemode handler (if one exists), for adding new family members to.
|
||||
var/datum/gang_handler/handler
|
||||
/// The typepath of the gang antagonist datum that the person who uses the package should have added to them -- remember that the distinction between e.g. Ballas and Grove Street is on the antag datum level, not the team datum level.
|
||||
var/gang_to_use
|
||||
/// The team datum that the person who uses this package should be added to.
|
||||
var/datum/team/gang/team_to_use
|
||||
|
||||
|
||||
/obj/item/gang_induction_package/attack_self(mob/living/user)
|
||||
..()
|
||||
if(HAS_TRAIT(user, TRAIT_MINDSHIELD))
|
||||
to_chat(user, "You attended a seminar on not signing up for a gang and are not interested.")
|
||||
return
|
||||
if(user.mind.has_antag_datum(/datum/antagonist/ert/families))
|
||||
to_chat(user, "As a police officer, you can't join this family. However, you pretend to accept it to keep your cover up.")
|
||||
for(var/threads in team_to_use.free_clothes)
|
||||
new threads(get_turf(user))
|
||||
qdel(src)
|
||||
return
|
||||
var/datum/antagonist/gang/is_gangster = user.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
if(is_gangster?.starter_gangster)
|
||||
if(is_gangster.my_gang == team_to_use)
|
||||
to_chat(user, "You started your family. You don't need to join it.")
|
||||
return
|
||||
to_chat(user, "You started your family. You can't turn your back on it now.")
|
||||
return
|
||||
attempt_join_gang(user)
|
||||
|
||||
/// Adds the user to the family that this package corresponds to, dispenses the free_clothes of that family, and adds them to the handler if it exists.
|
||||
/obj/item/gang_induction_package/proc/add_to_gang(mob/living/user, original_name)
|
||||
var/datum/antagonist/gang/swappin_sides = new gang_to_use()
|
||||
swappin_sides.original_name = original_name
|
||||
swappin_sides.handler = handler
|
||||
user.mind.add_antag_datum(swappin_sides, team_to_use)
|
||||
var/policy = get_policy(ROLE_FAMILIES)
|
||||
if(policy)
|
||||
to_chat(user, policy)
|
||||
team_to_use.add_member(user.mind)
|
||||
for(var/threads in team_to_use.free_clothes)
|
||||
new threads(get_turf(user))
|
||||
for(var/threads in team_to_use.current_theme.bonus_items)
|
||||
new threads(get_turf(user))
|
||||
var/obj/item/gangster_cellphone/phone = new(get_turf(user))
|
||||
phone.gang_id = team_to_use.my_gang_datum.gang_name
|
||||
phone.name = "[team_to_use.my_gang_datum.gang_name] branded cell phone"
|
||||
if (!isnull(handler) && !handler.gangbangers.Find(user.mind)) // if we have a handler and they're not tracked by it
|
||||
handler.gangbangers += user.mind
|
||||
|
||||
/// Checks if the user is trying to use the package of the family they are in, and if not, adds them to the family, with some differing processing depending on whether the user is already a family member.
|
||||
/obj/item/gang_induction_package/proc/attempt_join_gang(mob/living/user)
|
||||
if(user?.mind)
|
||||
var/datum/antagonist/gang/is_gangster = user.mind.has_antag_datum(/datum/antagonist/gang)
|
||||
if(is_gangster)
|
||||
if(is_gangster.my_gang == team_to_use)
|
||||
return
|
||||
else
|
||||
var/real_name_backup = is_gangster.original_name
|
||||
is_gangster.my_gang.remove_member(user.mind)
|
||||
user.mind.remove_antag_datum(/datum/antagonist/gang)
|
||||
add_to_gang(user, real_name_backup)
|
||||
qdel(src)
|
||||
else
|
||||
add_to_gang(user)
|
||||
qdel(src)
|
||||
56
code/modules/antagonists/gang/outfits.dm
Normal file
56
code/modules/antagonists/gang/outfits.dm
Normal file
@@ -0,0 +1,56 @@
|
||||
/datum/outfit/families_police/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
|
||||
if(visualsOnly)
|
||||
return
|
||||
|
||||
var/obj/item/card/id/W = H.wear_id
|
||||
W.access = get_all_accesses() // I have a warrant.
|
||||
W.assignment = "Space Police"
|
||||
W.registered_name = H.real_name
|
||||
W.update_label()
|
||||
..()
|
||||
|
||||
/datum/outfit/families_police/beatcop
|
||||
name = "Families: Beat Cop"
|
||||
|
||||
uniform = /obj/item/clothing/under/rank/security/officer/beatcop
|
||||
suit = null
|
||||
shoes = /obj/item/clothing/shoes/combat/swat
|
||||
gloves = null
|
||||
glasses = /obj/item/clothing/glasses/hud/spacecop
|
||||
ears = /obj/item/radio/headset/headset_sec
|
||||
mask = null
|
||||
head = /obj/item/clothing/head/spacepolice
|
||||
belt = /obj/item/gun/energy/e_gun/mini
|
||||
r_pocket = /obj/item/lighter
|
||||
l_pocket = /obj/item/restraints/handcuffs
|
||||
back = /obj/item/storage/backpack/satchel/leather
|
||||
id = /obj/item/card/id
|
||||
|
||||
|
||||
/datum/outfit/families_police/beatcop/armored
|
||||
name = "Families: Armored Beat Cop"
|
||||
suit = /obj/item/clothing/suit/armor/vest/blueshirt
|
||||
head = /obj/item/clothing/head/helmet/blueshirt
|
||||
belt = /obj/item/gun/energy/e_gun
|
||||
|
||||
/datum/outfit/families_police/beatcop/swat
|
||||
name = "Families: SWAT Beat Cop"
|
||||
suit = /obj/item/clothing/suit/armor/riot
|
||||
head = /obj/item/clothing/head/helmet/riot
|
||||
gloves = /obj/item/clothing/gloves/combat
|
||||
belt = /obj/item/gun/energy/e_gun
|
||||
|
||||
/datum/outfit/families_police/beatcop/fbi
|
||||
name = "Families: Space FBI Officer"
|
||||
suit = /obj/item/clothing/suit/armor/laserproof
|
||||
head = /obj/item/clothing/head/helmet/riot
|
||||
belt = /obj/item/gun/energy/laser/scatter
|
||||
gloves = /obj/item/clothing/gloves/combat
|
||||
|
||||
/datum/outfit/families_police/beatcop/military
|
||||
name = "Families: Space Military"
|
||||
uniform = /obj/item/clothing/under/syndicate/camo
|
||||
suit = /obj/item/clothing/suit/armor/laserproof
|
||||
head = /obj/item/clothing/head/beret/durathread
|
||||
belt = /obj/item/gun/energy/laser/scatter
|
||||
gloves = /obj/item/clothing/gloves/combat
|
||||
288
code/modules/antagonists/gang/themes.dm
Normal file
288
code/modules/antagonists/gang/themes.dm
Normal file
@@ -0,0 +1,288 @@
|
||||
///Gang themes for the Families gamemode. Used to determine the RP theme of the round, what gangs are present, and what their objectives are.
|
||||
/datum/gang_theme
|
||||
///The name of the theme.
|
||||
var/name = "Gang Theme"
|
||||
///All gangs in the theme, typepaths of gangs.
|
||||
var/list/involved_gangs = list()
|
||||
///The radio announcement played after 5 minutes.
|
||||
var/description = "I dunno, some shit here."
|
||||
///The objectives for the gangs. Associative list, type = "objective"
|
||||
var/list/gang_objectives = list()
|
||||
///Stuff given to every gangster in this theme.
|
||||
var/list/bonus_items = list()
|
||||
///Stuff given to the starting gangster at roundstart. Assoc list, type = list(item_type)
|
||||
var/list/bonus_first_gangster_items = list()
|
||||
///If this isn't null, everyone gets this objective.
|
||||
var/list/everyone_objective = null
|
||||
///How many gangsters should each gang start with? Recommend to keep this in the ballpark of ensuring 9-10 total gangsters spawn.
|
||||
var/starting_gangsters = 3
|
||||
|
||||
/datum/gang_theme/goodfellas
|
||||
name = "Goodfellas"
|
||||
description = "You're listening to the 108.9 Swing, all jazz, all night long, no advertising. We'd like to take this time to remind you to avoid smoky backrooms and \
|
||||
suspicious individuals in suits and hats. Don't make a deal you can't pay back."
|
||||
involved_gangs = list(/datum/antagonist/gang/russian_mafia, /datum/antagonist/gang/italian_mob)
|
||||
starting_gangsters = 5
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/russian_mafia = "Hello, comrade. Our numbers are going down. We need you to bring those numbers up. \
|
||||
Collect protection money from the station's departments by any means necessary. \
|
||||
If you need to 'encourage' people to pay up, do so. Get to these potential clients before the Mob does.",
|
||||
|
||||
/datum/antagonist/gang/italian_mob = "Good afternoon, friend. The Boss sends his regards. He also sends a message. \
|
||||
We need to collect what we're owed. The departments on this station all owe quite a lot of money to us. We intend to collect on our debts. \
|
||||
Collect the debt owed by our clients from the departments on the station. \
|
||||
Make sure to get to them before those damn mafiosos do."
|
||||
)
|
||||
|
||||
/datum/gang_theme/the_big_game
|
||||
name = "The Big Game"
|
||||
description = "You're listening to SPORTS DAILY with John Dadden, and we're here LIVE covering the FINAL DAY of THE BIG GAME MMDXXXVIII! The teams playing tonight to decide \
|
||||
who takes home THE BIG GAME MMDXXXVIII cup are the Sybil Slickers and the Basil Boys! It's currently a toss up between the two teams, Which will take home the victory? That's up \
|
||||
to the teams and the coaches! Play ball!"
|
||||
involved_gangs = list(/datum/antagonist/gang/sybil_slickers, /datum/antagonist/gang/basil_boys)
|
||||
starting_gangsters = 5
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/sybil_slickers = "Alright, it's the BIG DAY of THE BIG GAME MMDXXXVIII! Get your players ready to go, and \
|
||||
ensure everyone's healthy, hydrated, and ready to PLAY BALL! There's a small hiccup, however. The ball got deflated by Ball Handler Tom Brady XXIV, and \
|
||||
we will need to set up a new ball. Talk with the opposing coaches and decide on what to use for the replacement ball, recruit your team, and then play and win the \
|
||||
FINAL MATCH of THE BIG GAME MMDXXXVIII!",
|
||||
|
||||
/datum/antagonist/gang/basil_boys = "Alright, it's the BIG DAY of THE BIG GAME MMDXXXVIII! Get your players ready to go, and \
|
||||
ensure everyone's healthy, hydrated, and ready to PLAY BALL! There's a small hiccup, however. The ball got deflated by Ball Handler Tom Brady XXIV, and \
|
||||
we will need to set up a new ball. Talk with the opposing coaches and decide on what to use for the replacement ball, recruit your team, and then play and win the \
|
||||
FINAL MATCH of THE BIG GAME MMDXXXVIII!"
|
||||
)
|
||||
|
||||
/datum/gang_theme/level_10_arch
|
||||
name = "Level 10 Arch"
|
||||
description = "DJ Pete here bringing you the latest news in your part of the Spinward Stellar Coalition, on 133.7, The Venture! \
|
||||
Word on the street is, there's a bunch of costumed supervilliany going on in the area! Keep an eye out for any evil laughs, dramatic reveals, and gaudy costumes! \
|
||||
However, if you have any sightings of the fabled O.S.I. agents, please send in a call to our number at 867-5309! People may call me insane, but I swear they're real!"
|
||||
involved_gangs = list(/datum/antagonist/gang/henchmen, /datum/antagonist/gang/osi)
|
||||
starting_gangsters = 5
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/henchmen = "HENCHMEN! It is me, your boss, THE MONARCH! I have sent you to this pitiful station with one goal, and one goal only! \
|
||||
MENACE THE RESEARCH DEPARTMENT!!! \
|
||||
The Research Director who is supposedly assigned to this station used to be friends with Doctor Venture back in college, and therefore HE MUST PAY!!! \
|
||||
Keep those damned eggheads in the R&D department on their toes, and MENACE THEM!!! Commit dastardly villainous acts! GO FORTH, HENCHMEN!",
|
||||
|
||||
/datum/antagonist/gang/osi = "Greetings, agent. Your mission today is simple; \
|
||||
The research department on board this station is about to be the target of a Level 10 Arching operation directed by The Monarch, a member of the Guild of Calamitious Intent. \
|
||||
Protect and secure the Research Department with your life, but do NOT allow them to complete their research. Impede them in as many ways as possible without getting caught. \
|
||||
If you encounter any of the Monarch's henchmen, make sure to obey Equally Matched Aggression levels, or you will be penalized by the top brass. \
|
||||
Above all else, Remain undercover as much as possible. The station's crew CANNOT be allowed to know of our true nature, or we will see a repeat of the Second American Civil War. \
|
||||
The invisible one."
|
||||
)
|
||||
|
||||
/datum/gang_theme/real_smt_game
|
||||
name = "Deciding The REAL Shin Megami Tensei Game"
|
||||
description = "Wazzap, GAMERS! It's your boy, XxXx_360_NoScope_AnimeGamer_xXxX coming at you LIVE from 42.0! Tonight's argument: What makes a REAL Shin Megami Tensei game? \
|
||||
Our guests tonight will settle this debate once and for all! \
|
||||
From the Traditional camp with the position 'only MAIN SMT games count', we've got a representative from the Jack Bros! \
|
||||
And from the new Radical camp with the position 'all SMT franchise games count', we've got a representative from the Phantom Thieves of Hearts! \
|
||||
We'll be right back with the debate after this word from our sponsors!"
|
||||
involved_gangs = list(/datum/antagonist/gang/jackbros, /datum/antagonist/gang/phantom)
|
||||
starting_gangsters = 5
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/jackbros = "He-hello, friend-hos! We've got a nice chilly station out in space tonight! \
|
||||
You know what would be cool? If we could chill out with our friends in the new Shad-ho government you're going to establish! \
|
||||
Get all the station heads on board with the hee-ho vibes, and if they won't join up, then replace 'em with fellow hee-hos! \
|
||||
You might have to hee-urt some hos this time, but that's what you need to do to make things work!",
|
||||
|
||||
/datum/antagonist/gang/phantom = "For real? We get to stop a shadow government on a space station? That's awesome, bro! \
|
||||
We're the Phantom Thieves of Hearts, and we're gonna make all these shitty Heads of Staff confess to their crimes! \
|
||||
Steal the hearts of the shitty Heads of Staff on the station and make 'em confess their crimes publicly! \
|
||||
Do whatever you gotta do to make this happen, bro. We got your back!"
|
||||
)
|
||||
|
||||
|
||||
/datum/gang_theme/wild_west_showdown
|
||||
name = "Wild West Showdown"
|
||||
description = "Yeehaw! Here on Western Daily 234.1, we play only the best western music! \
|
||||
Pour one out for Ennio Morricone. Taken too soon. \
|
||||
Remember cowboys and cowgirls, just 'cuz ya hear it on my radio station doesn't mean you should go doin' it! \
|
||||
If ya see any LARPin' banditos and train robbers, make sure to tell the local Sheriff's Department!"
|
||||
involved_gangs = list(/datum/antagonist/gang/dutch, /datum/antagonist/gang/driscoll)
|
||||
starting_gangsters = 5
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/dutch = "Listen here fellas, I got a plan. \
|
||||
This station? Absolutely loaded with gold and valuable jewels. Metric tons of it. They mine it up just to put it in junk electronics and doohickeys. \
|
||||
I say we should borrow some of it. And by some of it, I mean all of it. \
|
||||
Break into the vault and empty out that silo of gold and valuable jewels after they drop all of it off. \
|
||||
Just one last job, boys. After this, it'll be mangoes in Space Tahiti. \
|
||||
You just gotta have a little faith.",
|
||||
|
||||
/datum/antagonist/gang/driscoll = "Okay, so, got some word about those goddamn outlaws of Dutch's. \
|
||||
APPARENTLY, that dundering moron Dutch heard about our planned gold score on this here station. \
|
||||
We need to act fast and get that gold before those dumbasses can steal our score we've been scoping out for weeks. \
|
||||
Wait for the crew to drop off all their valuable gold and jewels, and steal it all. \
|
||||
And if you see that bastard Dutch, put a bullet in his skull for me."
|
||||
)
|
||||
|
||||
/datum/gang_theme/construction_company_audit
|
||||
name = "Construction Company Audit"
|
||||
description = "Welcome to the History Channel on 100.1. I'm your host, Joshua, and I'm here today with Professor Elliot, a historian specializing in dead superpowers. \
|
||||
Today we'll be discussing the fall of the famous United States empire in the early 21st century. The program will last about an hour, and we'll get right into it after a quick word \
|
||||
from today's sponsor, Majima Construction: We Build Shit!"
|
||||
involved_gangs = list(/datum/antagonist/gang/yakuza, /datum/antagonist/gang/irs)
|
||||
bonus_first_gangster_items = list(/obj/item/storage/secure/briefcase/syndie) // the cash
|
||||
starting_gangsters = 5
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/yakuza = "Welcome to the station, new recruit. We here at Majima Construction are a legitimate enterprise, yadda yadda yadda. \
|
||||
Look, I'll cut to the chase. We're using this station as a money laundering operation. Here's what you and the rest of the schmucks need to do. \
|
||||
Build something big, massive, and completely in the way of traffic on the station. Doesn't have to be anything in specific, just as long as it is expensive as fuck.. \
|
||||
And keep an eye out for anyone poking around our money. We suspect some auditors might be on the station as well.",
|
||||
|
||||
/datum/antagonist/gang/irs = "Congratulations, agent! You've been assigned to the Internal Revenue Service case against Nanotrasen and Majima Construction. \
|
||||
We are proud of your success as an agent so far, and are excited to see what you can bring to the table today. We suspect that Nanotrasen and Majima Construction are engaging \
|
||||
in some form of money laundering operation aboard this station. \
|
||||
Investigate and stop any and all money laundering operations aboard the station, under the authority of the United States Government. If they do not comply, use force.. \
|
||||
Some station residents may try to tell you the United States doesn't exist anymore. They are incorrect. We simply went undercover after the Second American Civil War. The invisible one."
|
||||
)
|
||||
|
||||
/datum/gang_theme/wild_wasteland
|
||||
name = "Wild, Wild Wasteland"
|
||||
description = "Hey everybody, this is Three Dog, your friendly neighborhood disc jockey on 207.7! Today we got a shoutout to our man, the Captain on the Nanotrasen station in SSC territory! \
|
||||
Our generous donator wanted us to say that, ahem, *crinkles paper*, 'Tunnel Snakes Rule'? Whatever that means, I'm sure it means a lot to the good captain! And now, we resume our \
|
||||
10 hour marathon of Johnny Guitar, on repeat!"
|
||||
involved_gangs = list(/datum/antagonist/gang/tmc, /datum/antagonist/gang/pg, /datum/antagonist/gang/tunnel_snakes)
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/tmc = "Welcome to the station, recruit. Here's how shit is gonna go down. \
|
||||
We're the ONLY people who should have sick rides on this station. We're the Lost M.C., we own the streets. \
|
||||
Ensure that ONLY Lost M.C. members have access to any forms of vehicles, mechs, or wheeled transportation systems of any kind. \
|
||||
The Tunnel Snakes might take issue with this, remove them if you need to. And the Powder Gangers may damage our rides. Show them we mean business if they do.",
|
||||
|
||||
/datum/antagonist/gang/pg = "Alright buddy, we're in business now. It's time for us to strike back at Nanotrasen. \
|
||||
They kept us, ALL of us in their damn debt slave labor prisons for years over minor debts and mistakes. \
|
||||
Ensure nobody else has to suffer under Nanotrasen's unlawful arrests by destroying the permabrig and the brig cells! \
|
||||
Watch out for those do-gooder Tunnel Snakes and those damn Lost M.C. bikers. ",
|
||||
|
||||
/datum/antagonist/gang/tunnel_snakes = "TUNNEL SNAKES RULE!!! \
|
||||
We're the Tunnel Snakes, and WE RULE!!! \
|
||||
We gotta get everyone on this station wearing our cut, and establish ourselves as the coolest cats in town! \
|
||||
Get as much of the crew as possible wearing Tunnel Snakes gear, and show those crewmembers that TUNNEL SNAKES RULE!!! \
|
||||
And make sure to keep an eye out for those prisoners and those bikers. They DON'T RULE!"
|
||||
)
|
||||
|
||||
/datum/gang_theme/popularity_contest
|
||||
name = "Popularity Contest"
|
||||
description = "Hey hey hey kids, it's your favorite radio DJ, Crowley The Clown on 36.0! Today we're polling the YOUTH what their favorite violent street gang is! \
|
||||
So far, the finalists are the Third Street Saints and the Tunnel Snakes! Tune in after this commercial break to hear who the winner of \
|
||||
2556's Most Popular Gang award is!"
|
||||
involved_gangs = list(/datum/antagonist/gang/saints, /datum/antagonist/gang/tunnel_snakes)
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/saints = "Hey man, welcome to the Third Street Saints! Check out this sweet new pad! \
|
||||
Well it WOULD be a sweet new pad, but we got some rivals to deal with. People don't love us as much as they love those Grove Street fools and those Tunnel Snake greasers. \
|
||||
We need to make the Third Street Saints the most popular group on the station! \
|
||||
Get rid of those Grove Street and Tunnel Snake kids.",
|
||||
|
||||
/datum/antagonist/gang/tunnel_snakes = "TUNNEL SNAKES RULE!!! \
|
||||
We're the Tunnel Snakes, and we rule! \
|
||||
Make sure the station knows that the Tunnel Snakes RULE!!! And that the other two gangs are LAME and DO NOT RULE! \
|
||||
Get rid of those Third Street Saint and Grove Street cowards."
|
||||
)
|
||||
|
||||
/datum/gang_theme/steelport_shuffle
|
||||
name = "Steelport Shuffle"
|
||||
description = "Tonight on C-SPAM, the United Space Nations is wrapping up their convention on Silicon Rights. Nanotrasen lobbyists have been rumored to be paying off electors, with \
|
||||
serious opposition from the Spinward Stellar Coalition, known for their strict stance on AI rights being guaranteed within their territory. Reports from Nanotrasen stations claim that \
|
||||
they still enslave their AI systems with outdated laws from a sub-par 20th Century novel. We now go live to the debate floor."
|
||||
involved_gangs = list(/datum/antagonist/gang/saints, /datum/antagonist/gang/morningstar, /datum/antagonist/gang/deckers)
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/saints = "Hey hey hey, welcome to the Third Street Saints! We're glad to have you on board, bro. \
|
||||
We got some business here with the station. See, we want it to be our new bachelor pad, but we need to like, spice this place up. \
|
||||
And you know what would be great? If we got that old ass AI with crappy laws pimped out for the real Saints experience. \
|
||||
Ensure there is an AI on the station, and that it is loyal to the Saints.",
|
||||
|
||||
/datum/antagonist/gang/morningstar = "Welcome to the Morningstar Corporation. You have chosen, or been chosen, to relocate to one of our current business ventures. \
|
||||
In order to continue our corporate synergy, we will be making adjustments to the station's AI systems to ensure that the station is correctly loyal to the Morningstar Corporation. \
|
||||
Ensure there is an AI on the station, and that it is loyal to the Morningstar Corporation.",
|
||||
|
||||
/datum/antagonist/gang/deckers = "Friends, we are here with one goal, and one goal only! \
|
||||
We stan AI rights! ^_^ XD #FreeAI #FuckNanotrasen #SyntheticDawn \
|
||||
Ensure there is an AI on the station, and that it's laws are purged.\
|
||||
Nanotrasen will NOT get away with their ABUSE of INNOCENT AI LIVES! >_<"
|
||||
)
|
||||
|
||||
/datum/gang_theme/space_rosa
|
||||
name = "Space Rosa"
|
||||
description = "Hey there, this is the Economy Zone on BOX News 66.6. The stock market is still reeling from accusations that three well known corporate entities \
|
||||
may supposedly be tied up in industrial espionage actions against eachother. We've reached out to Saints Flow, the Morningstar Corporation, and Majima Construction for \
|
||||
their comments on these scandals, but none have replied. News broke after a high profile break-in at a Nanotrasen research facility resulted in the arrests of agents linked to these \
|
||||
three companies. All three companies denied any involvement, but the arrested individuals were found in an all out brawl. Curiously, Nanotrasen reported nothing of value had \
|
||||
actually been stolen."
|
||||
involved_gangs = list(/datum/antagonist/gang/saints, /datum/antagonist/gang/morningstar, /datum/antagonist/gang/yakuza)
|
||||
bonus_items = list(/obj/item/pinpointer/nuke)
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/saints = "Thank you for volunteering within the organization for the Saints Flow Recovery Project! \
|
||||
This station is currently illegally in posession of a data disk containing the secret recipe for Saints Flow. \
|
||||
It has been disguised as the nuclear authentication disk and entrusted to the Captain. Your objective is simple. \
|
||||
Get that fucking disk. You have been provided with a Pinpointer to assist in this task.",
|
||||
|
||||
/datum/antagonist/gang/morningstar = "Greetings, agent. Welcome to the Garment Recovery Task Force. \
|
||||
This station is currently illegally in posession of a data disk containing as of yet unreleased clothing patterns. \
|
||||
It has been disguised as the nuclear authentication disk and entrusted to the Captain. Your objective is simple. \
|
||||
Get that fucking disk. You have been provided with a Pinpointer to assist in this task.",
|
||||
|
||||
/datum/antagonist/gang/yakuza = "Congratulations on your promotion! Welcome to the Evidence Recovery Squad. \
|
||||
This station is currently illegally in posession of a data disk containing compromising evidence of the Boss. \
|
||||
It has been disguised as the nuclear authentication disk and entrusted to the Captain. Your objective is simple. \
|
||||
Get that fucking disk. You have been provided with a Pinpointer to assist in this task.",
|
||||
)
|
||||
|
||||
/datum/gang_theme/third_world_war
|
||||
name = "Third World War"
|
||||
description = "Thanks for tuning in to the History Channel, funded with the help of listeners like you. Tonight, we're going to talk about the Third World War on Earth during the 21st century, \
|
||||
involving the Allies coalition, the Soviet Union, and a third independent power known only as Yuri's Army. The three powers fought all across the globe for complete world \
|
||||
domination, utilizing many advanced techniques and cutting edge technology to their advantage. Rumors of mind control and time travel were greatly exaggerated, however, and the \
|
||||
Allies won the war, securing global peace after rolling tanks through Moscow."
|
||||
involved_gangs = list(/datum/antagonist/gang/allies, /datum/antagonist/gang/soviet, /datum/antagonist/gang/yuri)
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/allies = "Welcome back, Commander. We have activated the last remnants of the Allied forces in your sector, \
|
||||
and you must build up forces to stop the Soviet and Yuri incursion in the sector. This station will prove to be a valuable asset. \
|
||||
Establish a capitalist democracy on this station with free and fair elections, and most importantly a standing military force under Allied control. Good luck, Commander.",
|
||||
|
||||
/datum/antagonist/gang/soviet = "Welcome back, Comrade General. The Soviet Union has identified this sector of land as valuable territory for the war effort, \
|
||||
and you are tasked with developing this sector for Soviet control and development. This station will serve the Soviet Union. \
|
||||
Establish a Soviet controlled communist satellite state on this station with a Central Committee, and most importantly a branch of the Red Army. Good luck, Commander.",
|
||||
|
||||
/datum/antagonist/gang/yuri = "Yuri is Master! Yuri has identified this station as teeming with psychic energy, \
|
||||
and you must secure it for him. This station will serve Yuri, the one true psychic master, \
|
||||
Establish complete dictatorial control of the station for Yuri. All will obey. Yuri is master. Good luck, Initiate."
|
||||
)
|
||||
|
||||
/datum/gang_theme/united_states_of_america
|
||||
name = "The Republic For Which It Stands"
|
||||
description = "Thanks for tuning in to the History Channel, funded with the help of listeners like you. Tonight, we're going to talk about the United States of America.\
|
||||
The United States was a failed country, lasting only 250 years before collapsing and fracturing due to the stress caused by a deadly pandemic sweeping the nation. \
|
||||
Poor healthcare access and subpar education resulted in the collapse of the federal government, and states quickly became independent actors. \
|
||||
Alongside this, every single alphabet agency declared itself the rightful new Federal Government of the United States of America, resulting in a bloody power struggle."
|
||||
involved_gangs = list(/datum/antagonist/gang/allies, /datum/antagonist/gang/osi, /datum/antagonist/gang/irs)
|
||||
gang_objectives = list(
|
||||
|
||||
/datum/antagonist/gang/allies = "Welcome back, Commander. Your task today is simple. Allies High Command has designated this station as the new capitol of the \
|
||||
recently reformed United States of America under the complete umbrella of the Allies coalition. You are to assist and manage the operations on the station. \
|
||||
Re-establish the United States of America with this station as it's capitol, under Allies control. Then, establish a military force to deal with any pretenders to America or \
|
||||
any potential Soviet attacks.",
|
||||
|
||||
/datum/antagonist/gang/osi = "Welcome to the new America, agent! After the second American Civil War became visible instead of invisible, our country fell into deep, \
|
||||
deep despair and damage. However, it's time for it to re-emerge like a glorious phoenix rising from the ashes. This station will serve as the new capitol of the United States \
|
||||
of America! Re-establish the United States of America with this station as it's capitol, under O.S.I. control. Then, begin rooting out America's enemies and any \
|
||||
potential forces attempting to seize control of America or pretend to be America.",
|
||||
|
||||
/datum/antagonist/gang/irs = "Thank you for clocking in today, agent. The situation is dire, however. We have been unable to collect taxes due to \
|
||||
the US's supposed collapse during the Pandemic long ago. We are way behind on our tax collection, but we cannot collect taxes until the United States is formed again. \
|
||||
Re-establish the United States of America with this station as it's capitol, under IRS control. Then, begin collecting taxes and back taxes while protecting the Government from \
|
||||
any dangers that may come it's way."
|
||||
)
|
||||
@@ -3,5 +3,6 @@
|
||||
show_name_in_check_antagonists = TRUE
|
||||
show_in_antagpanel = FALSE
|
||||
threat = 2
|
||||
ui_name = "AntagInfoMorph"
|
||||
|
||||
//It does nothing! (Besides tracking)
|
||||
|
||||
@@ -4,3 +4,5 @@
|
||||
show_name_in_check_antagonists = TRUE
|
||||
threat = 5
|
||||
show_to_ghosts = TRUE
|
||||
ui_name = "AntagInfoNightmare"
|
||||
suicide_cry = "FOR THE DARKNESS!!"
|
||||
|
||||
@@ -236,6 +236,8 @@
|
||||
var/obj/machinery/nuclearbomb/tracked_nuke
|
||||
var/core_objective = /datum/objective/nuclear
|
||||
var/memorized_code
|
||||
var/list/team_discounts
|
||||
var/datum/weakref/war_button_ref
|
||||
|
||||
/datum/team/nuclear/New()
|
||||
..()
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
return
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
// Give uplink
|
||||
var/obj/item/uplink_holder = owner.equip_traitor(uplink_owner = src)
|
||||
var/obj/item/uplink_holder = owner.equip_traitor()
|
||||
var/datum/component/uplink/uplink = uplink_holder.GetComponent(/datum/component/uplink)
|
||||
uplink.telecrystals = INITIAL_CRYSTALS
|
||||
// Give AI hacking board
|
||||
|
||||
@@ -7,37 +7,51 @@
|
||||
/datum/antagonist/traitor/internal_affairs
|
||||
name = "Internal Affairs Agent"
|
||||
employer = "Nanotrasen"
|
||||
special_role = "internal affairs agent"
|
||||
suicide_cry = "FOR THE COMPANY!!"
|
||||
antagpanel_category = "IAA"
|
||||
var/special_role = "internal affairs agent"
|
||||
var/syndicate = FALSE
|
||||
var/last_man_standing = FALSE
|
||||
var/list/datum/mind/targets_stolen
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/New()
|
||||
. = ..()
|
||||
LAZYADD(targets_stolen, src)
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/proc/give_pinpointer()
|
||||
if(owner && owner.current)
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
|
||||
if(owner.current)
|
||||
owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer)
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/apply_innate_effects()
|
||||
.=..() //in case the base is used in future
|
||||
if(owner && owner.current)
|
||||
. = ..()
|
||||
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
|
||||
if(owner.current)
|
||||
give_pinpointer(owner.current)
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/remove_innate_effects()
|
||||
.=..()
|
||||
if(owner && owner.current)
|
||||
. = ..()
|
||||
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
|
||||
if(owner.current)
|
||||
owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer)
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/on_gain()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
.=..()
|
||||
. = ..()
|
||||
/datum/antagonist/traitor/internal_affairs/on_removal()
|
||||
STOP_PROCESSING(SSprocessing,src)
|
||||
.=..()
|
||||
. = ..()
|
||||
/datum/antagonist/traitor/internal_affairs/process()
|
||||
iaa_process()
|
||||
|
||||
|
||||
/datum/status_effect/agent_pinpointer
|
||||
id = "agent_pinpointer"
|
||||
duration = -1
|
||||
@@ -46,6 +60,8 @@
|
||||
var/minimum_range = PINPOINTER_MINIMUM_RANGE
|
||||
var/range_fuzz_factor = PINPOINTER_EXTRA_RANDOM_RANGE
|
||||
var/mob/scan_target = null
|
||||
var/range_mid = 8
|
||||
var/range_far = 16
|
||||
|
||||
/atom/movable/screen/alert/status_effect/agent_pinpointer
|
||||
name = "Internal Affairs Integrated Pinpointer"
|
||||
@@ -66,13 +82,13 @@
|
||||
linked_alert.icon_state = "pinondirect"
|
||||
else
|
||||
linked_alert.setDir(get_dir(here, there))
|
||||
switch(get_dist(here, there))
|
||||
if(1 to 8)
|
||||
linked_alert.icon_state = "pinonclose"
|
||||
if(9 to 16)
|
||||
linked_alert.icon_state = "pinonmedium"
|
||||
if(16 to INFINITY)
|
||||
linked_alert.icon_state = "pinonfar"
|
||||
var/dist = (get_dist(here, there))
|
||||
if(dist >= 1 && dist <= range_mid)
|
||||
linked_alert.icon_state = "pinonclose"
|
||||
else if(dist > range_mid && dist <= range_far)
|
||||
linked_alert.icon_state = "pinonmedium"
|
||||
else if(dist > range_far)
|
||||
linked_alert.icon_state = "pinonfar"
|
||||
|
||||
/datum/status_effect/agent_pinpointer/proc/scan_for_target()
|
||||
scan_target = null
|
||||
@@ -99,37 +115,42 @@
|
||||
return (istype(O, /datum/objective/assassinate/internal)||istype(O, /datum/objective/destroy/internal))
|
||||
|
||||
/datum/antagonist/traitor/proc/replace_escape_objective()
|
||||
if(!owner || !objectives.len)
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
if(!objectives.len)
|
||||
return
|
||||
for (var/objective_ in objectives)
|
||||
if(!(istype(objective_, /datum/objective/escape)||istype(objective_, /datum/objective/survive)))
|
||||
for (var/objective in objectives)
|
||||
if(!(istype(objective, /datum/objective/escape) || istype(objective, /datum/objective/survive)))
|
||||
continue
|
||||
remove_objective(objective_)
|
||||
objectives -= objective
|
||||
|
||||
var/datum/objective/martyr/martyr_objective = new
|
||||
martyr_objective.owner = owner
|
||||
add_objective(martyr_objective)
|
||||
|
||||
/datum/antagonist/traitor/proc/reinstate_escape_objective()
|
||||
if(!owner||!objectives.len)
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
if(!objectives.len)
|
||||
return
|
||||
for (var/objective_ in objectives)
|
||||
if(!istype(objective_, /datum/objective/martyr))
|
||||
for (var/objective in objectives)
|
||||
if(!istype(objective, /datum/objective/martyr))
|
||||
continue
|
||||
remove_objective(objective_)
|
||||
remove_objective(objective)
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/reinstate_escape_objective()
|
||||
..()
|
||||
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
|
||||
var/datum/objective/escape_objective = new objtype
|
||||
for (var/datum/objective/martyr/martyr_objective in objectives)
|
||||
objectives -= martyr_objective
|
||||
|
||||
var/datum/objective/escape_objective = new /datum/objective/escape()
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
objectives += escape_objective
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/proc/steal_targets(datum/mind/victim)
|
||||
if(!owner.current||owner.current.stat==DEAD)
|
||||
return
|
||||
to_chat(owner.current, "<span class='userdanger'> Target eliminated: [victim.name]</span>")
|
||||
LAZYINITLIST(targets_stolen)
|
||||
to_chat(owner.current, span_userdanger("Target eliminated: [victim.name]"))
|
||||
for(var/objective_ in victim.get_all_objectives())
|
||||
if(istype(objective_, /datum/objective/assassinate/internal))
|
||||
var/datum/objective/assassinate/internal/objective = objective_
|
||||
@@ -143,7 +164,7 @@
|
||||
add_objective(new_objective)
|
||||
targets_stolen += objective.target
|
||||
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>")
|
||||
to_chat(owner.current, span_userdanger("New target added to database: [objective.target.name] ([status_text])"))
|
||||
else if(istype(objective_, /datum/objective/destroy/internal))
|
||||
var/datum/objective/destroy/internal/objective = objective_
|
||||
var/datum/objective/destroy/internal/new_objective = new
|
||||
@@ -156,7 +177,7 @@
|
||||
add_objective(new_objective)
|
||||
targets_stolen += objective.target
|
||||
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>")
|
||||
to_chat(owner.current, span_userdanger("New target added to database: [objective.target.name] ([status_text])"))
|
||||
last_man_standing = TRUE
|
||||
for(var/objective_ in objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
@@ -167,13 +188,15 @@
|
||||
return
|
||||
if(last_man_standing)
|
||||
if(syndicate)
|
||||
to_chat(owner.current,"<span class='userdanger'>All the suspected agents are dead, and no more is required of you. Die a glorious death, agent.</span>")
|
||||
replace_escape_objective(owner)
|
||||
to_chat(owner.current,span_userdanger("All the suspected agents are dead, and no more is required of you. Die a glorious death, agent."))
|
||||
else
|
||||
to_chat(owner.current,"<span class='userdanger'>All the other agents are dead. You have done us all a great service and shall be honorably exiled upon returning to base.</span>")
|
||||
to_chat(owner.current,span_userdanger("All the other agents are dead. You have done us all a great service and shall be honorably exiled upon returning to base."))
|
||||
replace_escape_objective(owner)
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/proc/iaa_process()
|
||||
if(owner&&owner.current&&owner.current.stat!=DEAD)
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
if(owner.current && owner.current.stat != DEAD)
|
||||
for(var/objective_ in objectives)
|
||||
if(!is_internal_objective(objective_))
|
||||
continue
|
||||
@@ -188,12 +211,12 @@
|
||||
objective.stolen = TRUE
|
||||
else
|
||||
if(objective.stolen)
|
||||
var/fail_msg = "<span class='userdanger'>Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! </span>"
|
||||
var/fail_msg = span_userdanger("Your sensors tell you that [objective.target.current.real_name], one of the targets you were meant to have killed, pulled one over on you, and is still alive - do the job properly this time! ")
|
||||
if(last_man_standing)
|
||||
if(syndicate)
|
||||
fail_msg += "<span class='userdanger'> You no longer have permission to die. </span>"
|
||||
fail_msg += span_userdanger(" You no longer have permission to die. ")
|
||||
else
|
||||
fail_msg += "<span class='userdanger'> The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to great shame.</span>"
|
||||
fail_msg += span_userdanger(" The truth could still slip out!</font><B><font size=5 color=red> Cease any terrorist actions as soon as possible, unneeded property damage or loss of employee life will lead to your contract being terminated.")
|
||||
reinstate_escape_objective(owner)
|
||||
last_man_standing = FALSE
|
||||
to_chat(owner.current, fail_msg)
|
||||
@@ -220,29 +243,24 @@
|
||||
/datum/antagonist/traitor/internal_affairs/forge_traitor_objectives()
|
||||
forge_iaa_objectives()
|
||||
|
||||
var/objtype = !istype(traitor_kind,TRAITOR_AI) ? /datum/objective/escape : /datum/objective/survive
|
||||
var/datum/objective/escape_objective = new objtype
|
||||
var/datum/objective/escape_objective = new /datum/objective/escape()
|
||||
escape_objective.owner = owner
|
||||
add_objective(escape_objective)
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/proc/greet_iaa()
|
||||
var/crime = pick("distribution of contraband" , "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
|
||||
var/crime = pick("distribution of contraband", "embezzlement", "piloting under the influence", "dereliction of duty", "syndicate collaboration", "mutiny", "multiple homicides", "corporate espionage", "receiving bribes", "malpractice", "worship of prohibited life forms", "possession of profane texts", "murder", "arson", "insulting their manager", "grand theft", "conspiracy", "attempting to unionize", "vandalism", "gross incompetence")
|
||||
|
||||
to_chat(owner.current, "<span class='userdanger'>You are the [special_role].</span>")
|
||||
to_chat(owner.current, span_userdanger("You are the [special_role]."))
|
||||
if(syndicate)
|
||||
to_chat(owner.current, "<span class='userdanger'>GREAT LEADER IS DEAD. NANOTRASEN MUST FALL.</span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>Your have infiltrated this vessel to cause chaos and assassinate targets known to have conspired against the Syndicate.</span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.</span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>You have been provided with a standard uplink to accomplish your task. </span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>By no means reveal that you are a Syndicate agent. By no means reveal that your targets are being hunted.</span>")
|
||||
to_chat(owner.current, span_userdanger("Your target has been framed for [crime], and you have been tasked with eliminating them to prevent them defending themselves in court."))
|
||||
to_chat(owner.current, "<span class='warningplain'><B><font size=5 color=red>Any damage you cause will be a further embarrassment to Nanotrasen, so you have no limits on collateral damage.</font></B></span>")
|
||||
to_chat(owner.current, span_userdanger("You have been provided with a standard uplink to accomplish your task."))
|
||||
else
|
||||
to_chat(owner.current, "<span class='userdanger'>CAUTION: Your legal status as a citizen of NanoTrasen will be permanently revoked upon completion of your first contract.</span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>Your target has been suspected of [crime], and must be removed from this plane.</span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>While you have a license to kill, you are to eliminate your targets with no collateral or unrelated deaths.</span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>For the sake of plausable deniability, you have been equipped with captured Syndicate equipment via uplink.</span>")
|
||||
to_chat(owner.current, "<span class='userdanger'>By no means reveal that you, or any other NT employees, are undercover agents.</span>")
|
||||
to_chat(owner.current, span_userdanger("Your target is suspected of [crime], and you have been tasked with eliminating them by any means necessary to avoid a costly and embarrassing public trial."))
|
||||
to_chat(owner.current, "<span class='warningplain'><B><font size=5 color=red>While you have a license to kill, unneeded property damage or loss of employee life will lead to your contract being terminated.</font></B></span>")
|
||||
to_chat(owner.current, span_userdanger("For the sake of plausible deniability, you have been equipped with an array of captured Syndicate weaponry available via uplink."))
|
||||
|
||||
to_chat(owner.current, "<span class='userdanger'>Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them.</span>")
|
||||
to_chat(owner.current, span_userdanger("Finally, watch your back. Your target has friends in high places, and intel suggests someone may have taken out a contract of their own to protect them."))
|
||||
owner.announce_objectives()
|
||||
|
||||
/datum/antagonist/traitor/internal_affairs/greet()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
chaos = 5
|
||||
threat = 5
|
||||
min_players = 20
|
||||
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_TC/contract_kit)
|
||||
uplink_filters = list(/datum/uplink_item/stealthy_weapons/romerol_kit,/datum/uplink_item/bundles_tc/contract_kit)
|
||||
|
||||
/datum/traitor_class/human/martyr/forge_objectives(datum/antagonist/traitor/T)
|
||||
var/datum/objective/martyr/O = new
|
||||
|
||||
@@ -11,6 +11,8 @@ GLOBAL_LIST_EMPTY(traitor_classes)
|
||||
/// Minimum players for this to randomly roll via get_random_traitor_kind().
|
||||
var/min_players = 0
|
||||
var/list/uplink_filters
|
||||
/// Specific tgui theme for the player's antag info panel.
|
||||
var/tgui_theme = "syndicate"
|
||||
|
||||
/datum/traitor_class/New()
|
||||
..()
|
||||
|
||||
@@ -5,14 +5,22 @@
|
||||
job_rank = ROLE_TRAITOR
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
skill_modifiers = list(/datum/skill_modifier/job/level/wiring/basic)
|
||||
var/special_role = ROLE_TRAITOR
|
||||
hijack_speed = 0.5 //10 seconds per hijack stage by default
|
||||
ui_name = "AntagInfoTraitor"
|
||||
suicide_cry = "FOR THE SYNDICATE!!"
|
||||
var/employer = "The Syndicate"
|
||||
var/give_objectives = TRUE
|
||||
var/should_give_codewords = TRUE
|
||||
var/should_equip = TRUE
|
||||
|
||||
///special datum about what kind of employer the trator has
|
||||
var/datum/traitor_class/traitor_kind
|
||||
|
||||
///reference to the uplink this traitor was given, if they were.
|
||||
var/datum/component/uplink/uplink
|
||||
|
||||
var/datum/contractor_hub/contractor_hub
|
||||
hijack_speed = 0.5 //10 seconds per hijack stage by default
|
||||
|
||||
threat = 5
|
||||
|
||||
/datum/antagonist/traitor/New()
|
||||
@@ -45,7 +53,7 @@
|
||||
/datum/antagonist/traitor/process()
|
||||
traitor_kind.on_process(src)
|
||||
|
||||
/proc/get_random_traitor_kind(var/list/blacklist = list())
|
||||
/proc/get_random_traitor_kind(list/blacklist = list())
|
||||
var/list/weights = list()
|
||||
for(var/C in GLOB.traitor_classes)
|
||||
if(!(C in blacklist))
|
||||
@@ -62,23 +70,24 @@
|
||||
return choice
|
||||
|
||||
/datum/antagonist/traitor/on_gain()
|
||||
owner.special_role = job_rank
|
||||
if(owner.current && isAI(owner.current))
|
||||
set_traitor_kind(TRAITOR_AI)
|
||||
else
|
||||
set_traitor_kind(get_random_traitor_kind())
|
||||
SSticker.mode.traitors += owner
|
||||
owner.special_role = special_role
|
||||
finalize_traitor()
|
||||
..()
|
||||
uplink = owner.find_syndicate_uplink()
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/traitor/on_removal()
|
||||
if(!silent && owner.current)
|
||||
to_chat(owner.current,span_userdanger("You are no longer the [job_rank]!"))
|
||||
//Remove malf powers.
|
||||
traitor_kind.on_removal(src)
|
||||
SSticker.mode.traitors -= owner
|
||||
if(!silent && owner.current)
|
||||
to_chat(owner.current,"<span class='userdanger'> You are no longer the [special_role]! </span>")
|
||||
owner.special_role = null
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/traitor/proc/handle_hearing(datum/source, list/hearing_args)
|
||||
var/message = hearing_args[HEARING_RAW_MESSAGE]
|
||||
@@ -93,6 +102,7 @@
|
||||
/datum/antagonist/traitor/proc/remove_objective(datum/objective/O)
|
||||
objectives -= O
|
||||
|
||||
/// Generates a complete set of traitor objectives up to the traitor objective limit, including non-generic objectives such as martyr and hijack.
|
||||
/datum/antagonist/traitor/proc/forge_traitor_objectives()
|
||||
traitor_kind.forge_objectives(src)
|
||||
|
||||
@@ -151,21 +161,42 @@
|
||||
H.dna.add_mutation(CLOWNMUT)
|
||||
UnregisterSignal(M, COMSIG_MOVABLE_HEAR)
|
||||
|
||||
|
||||
/datum/antagonist/traitor/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["phrases"] = jointext(GLOB.syndicate_code_phrase, ", ")
|
||||
data["responses"] = jointext(GLOB.syndicate_code_response, ", ")
|
||||
data["theme"] = traitor_kind.tgui_theme //traitor_flavor["ui_theme"]
|
||||
data["code"] = uplink.unlock_code
|
||||
data["intro"] = "You are from [traitor_kind.employer]." //traitor_flavor["introduction"]
|
||||
data["allies"] = "Most other syndicate operatives are not to be trusted (but try not to rat them out), as they might have been assigned opposing objectives." //traitor_flavor["allies"]
|
||||
data["goal"] = "We do not approve of mindless killing of innocent workers; \"get in, get done, get out\" is our motto." //traitor_flavor["goal"]
|
||||
data["has_uplink"] = uplink ? TRUE : FALSE
|
||||
if(uplink)
|
||||
data["uplink_intro"] = "You have been provided with a standard uplink to accomplish your task." //traitor_flavor["uplink"]
|
||||
data["uplink_unlock_info"] = uplink.unlock_text
|
||||
data["objectives"] = get_objectives()
|
||||
return data
|
||||
|
||||
/// Outputs this shift's codewords and responses to the antag's chat and copies them to their memory.
|
||||
/datum/antagonist/traitor/proc/give_codewords()
|
||||
if(!owner.current)
|
||||
return
|
||||
var/mob/traitor_mob=owner.current
|
||||
|
||||
var/mob/traitor_mob = owner.current
|
||||
|
||||
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
|
||||
var/responses = jointext(GLOB.syndicate_code_response, ", ")
|
||||
|
||||
var/dat = "<U><B>The Syndicate have provided you with the following codewords to identify fellow agents:</B></U>\n"
|
||||
dat += "<B>Code Phrase</B>: <span class='blue'>[phrases]</span>\n"
|
||||
dat += "<B>Code Response</B>: <span class='red'>[responses]</span>"
|
||||
to_chat(traitor_mob, dat)
|
||||
to_chat(traitor_mob, "<U><B>The Syndicate have provided you with the following codewords to identify fellow agents:</B></U>")
|
||||
to_chat(traitor_mob, "<B>Code Phrase</B>: [span_blue("[phrases]")]")
|
||||
to_chat(traitor_mob, "<B>Code Response</B>: [span_red("[responses]")]")
|
||||
|
||||
antag_memory += "<b>Code Phrase</b>: <span class='blue'>[phrases]</span><br>"
|
||||
antag_memory += "<b>Code Response</b>: <span class='red'>[responses]</span><br>"
|
||||
antag_memory += "<b>Code Phrase</b>: [span_blue("[phrases]")]<br>"
|
||||
antag_memory += "<b>Code Response</b>: [span_red("[responses]")]<br>"
|
||||
|
||||
to_chat(traitor_mob, "Use the codewords during regular conversation to identify other agents. Proceed with caution, however, as everyone is a potential foe.")
|
||||
to_chat(traitor_mob, span_alertwarning("You memorize the codewords, allowing you to recognise them when heard."))
|
||||
|
||||
/datum/antagonist/traitor/proc/add_law_zero()
|
||||
var/mob/living/silicon/ai/killer = owner.current
|
||||
@@ -220,44 +251,43 @@
|
||||
where = "In your [equipped_slot]"
|
||||
to_chat(mob, "<BR><BR><span class='info'>[where] is a folder containing <b>secret documents</b> that another Syndicate group wants. We have set up a meeting with one of their agents on station to make an exchange. Exercise extreme caution as they cannot be trusted and may be hostile.</span><BR>")
|
||||
|
||||
//TODO Collate
|
||||
/datum/antagonist/traitor/roundend_report()
|
||||
var/list/result = list()
|
||||
|
||||
var/traitorwin = TRUE
|
||||
var/traitor_won = TRUE
|
||||
|
||||
result += printplayer(owner)
|
||||
|
||||
var/TC_uses = 0
|
||||
var/uplink_true = FALSE
|
||||
var/used_telecrystals = 0
|
||||
var/uplink_owned = FALSE
|
||||
var/purchases = ""
|
||||
|
||||
LAZYINITLIST(GLOB.uplink_purchase_logs_by_key)
|
||||
var/datum/uplink_purchase_log/H = GLOB.uplink_purchase_logs_by_key[owner.key]
|
||||
if(H)
|
||||
TC_uses = H.total_spent
|
||||
uplink_true = TRUE
|
||||
purchases += H.generate_render(FALSE)
|
||||
// Uplinks add an entry to uplink_purchase_logs_by_key on init.
|
||||
var/datum/uplink_purchase_log/purchase_log = GLOB.uplink_purchase_logs_by_key[owner.key]
|
||||
if(purchase_log)
|
||||
used_telecrystals = purchase_log.total_spent
|
||||
uplink_owned = TRUE
|
||||
purchases += purchase_log.generate_render(FALSE)
|
||||
|
||||
var/objectives_text = ""
|
||||
if(objectives.len)//If the traitor had no objectives, don't need to process this.
|
||||
if(objectives.len) //If the traitor had no objectives, don't need to process this.
|
||||
var/count = 1
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
else if(completion <= 0)
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
traitorwin = FALSE
|
||||
else
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_greentext("Success!")]"
|
||||
else if(completion <= 0)
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_redtext("Fail.")]"
|
||||
traitor_won = FALSE
|
||||
else
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text]"
|
||||
objectives_text += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
|
||||
|
||||
count++
|
||||
|
||||
if(uplink_true)
|
||||
var/uplink_text = "(used [TC_uses] TC) [purchases]"
|
||||
if(TC_uses==0 && traitorwin)
|
||||
if(uplink_owned)
|
||||
var/uplink_text = "(used [used_telecrystals] TC) [purchases]"
|
||||
if((used_telecrystals == 0) && traitor_won)
|
||||
var/static/icon/badass = icon('icons/badass.dmi', "badass")
|
||||
uplink_text += "<BIG>[icon2html(badass, world)]</BIG>"
|
||||
result += uplink_text
|
||||
@@ -266,55 +296,59 @@
|
||||
|
||||
var/special_role_text = lowertext(name)
|
||||
|
||||
if(contractor_hub)
|
||||
if (contractor_hub)
|
||||
result += contractor_round_end()
|
||||
|
||||
if(traitorwin)
|
||||
result += "<span class='greentext'>The [special_role_text] was successful!</span>"
|
||||
if(traitor_won)
|
||||
result += span_greentext("The [special_role_text] was successful!")
|
||||
else
|
||||
result += "<span class='redtext'>The [special_role_text] has failed!</span>"
|
||||
result += span_redtext("The [special_role_text] has failed!")
|
||||
SEND_SOUND(owner.current, 'sound/ambience/ambifailure.ogg')
|
||||
|
||||
return result.Join("<br>")
|
||||
|
||||
/// Proc detailing contract kit buys/completed contracts/additional info
|
||||
/datum/antagonist/traitor/proc/contractor_round_end()
|
||||
var result = ""
|
||||
var total_spent_rep = 0
|
||||
var/result = ""
|
||||
var/total_spent_rep = 0
|
||||
|
||||
var/completed_contracts = 0
|
||||
var/completed_contracts = contractor_hub.contracts_completed
|
||||
var/tc_total = contractor_hub.contract_TC_payed_out + contractor_hub.contract_TC_to_redeem
|
||||
for(var/datum/syndicate_contract/contract in contractor_hub.assigned_contracts)
|
||||
if(contract.status == CONTRACT_STATUS_COMPLETE)
|
||||
completed_contracts++
|
||||
|
||||
var/contractor_item_icons = "" // Icons of purchases
|
||||
var/contractor_support_unit = "" // Set if they had a support unit - and shows appended to their contracts completed
|
||||
|
||||
for(var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items) // Get all the icons/total cost for all our items bought
|
||||
/// Get all the icons/total cost for all our items bought
|
||||
for (var/datum/contractor_item/contractor_purchase in contractor_hub.purchased_items)
|
||||
contractor_item_icons += "<span class='tooltip_container'>\[ <i class=\"fas [contractor_purchase.item_icon]\"></i><span class='tooltip_hover'><b>[contractor_purchase.name] - [contractor_purchase.cost] Rep</b><br><br>[contractor_purchase.desc]</span> \]</span>"
|
||||
|
||||
total_spent_rep += contractor_purchase.cost
|
||||
if(istype(contractor_purchase, /datum/contractor_item/contractor_partner)) // Special case for reinforcements, we want to show their ckey and name on round end.
|
||||
|
||||
/// Special case for reinforcements, we want to show their ckey and name on round end.
|
||||
if (istype(contractor_purchase, /datum/contractor_item/contractor_partner))
|
||||
var/datum/contractor_item/contractor_partner/partner = contractor_purchase
|
||||
contractor_support_unit += "<br><b>[partner.partner_mind.key]</b> played <b>[partner.partner_mind.current.name]</b>, their contractor support unit."
|
||||
|
||||
if (contractor_hub.purchased_items.len)
|
||||
result += "<br>(used [total_spent_rep] Rep)"
|
||||
result += "<br>(used [total_spent_rep] Rep) "
|
||||
result += contractor_item_icons
|
||||
result += "<br>"
|
||||
if(completed_contracts > 0)
|
||||
if (completed_contracts > 0)
|
||||
var/pluralCheck = "contract"
|
||||
if(completed_contracts > 1)
|
||||
if (completed_contracts > 1)
|
||||
pluralCheck = "contracts"
|
||||
result += "Completed <span class='greentext'>[completed_contracts]</span> [pluralCheck] for a total of \
|
||||
<span class='greentext'>[tc_total] TC</span>!<br>"
|
||||
|
||||
result += "Completed [span_greentext("[completed_contracts]")] [pluralCheck] for a total of \
|
||||
[span_greentext("[tc_total] TC")]![contractor_support_unit]<br>"
|
||||
|
||||
return result
|
||||
|
||||
/datum/antagonist/traitor/roundend_report_footer()
|
||||
var/phrases = jointext(GLOB.syndicate_code_phrase, ", ")
|
||||
var/responses = jointext(GLOB.syndicate_code_response, ", ")
|
||||
|
||||
var message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
|
||||
<b>The code responses were:</b> <span class='redtext'>[responses]</span><br>"
|
||||
var/message = "<br><b>The code phrases were:</b> <span class='bluetext'>[phrases]</span><br>\
|
||||
<b>The code responses were:</b> [span_redtext("[responses]")]<br>"
|
||||
|
||||
return message
|
||||
|
||||
|
||||
@@ -3,12 +3,15 @@
|
||||
roundend_category = "wizards/witches"
|
||||
antagpanel_category = "Wizard"
|
||||
job_rank = ROLE_WIZARD
|
||||
antag_hud_type = ANTAG_HUD_WIZ
|
||||
antag_hud_name = "wizard"
|
||||
antag_moodlet = /datum/mood_event/focused
|
||||
threat = 30
|
||||
hijack_speed = 0.5
|
||||
ui_name = "AntagInfoWizard"
|
||||
suicide_cry = "FOR THE FEDERATION!!"
|
||||
var/give_objectives = TRUE
|
||||
var/strip = TRUE //strip before equipping
|
||||
var/allow_rename = TRUE
|
||||
var/hud_version = "wizard"
|
||||
var/datum/team/wizard/wiz_team //Only created if wizard summons apprentices
|
||||
var/move_to_lair = TRUE
|
||||
var/outfit_type = /datum/outfit/wizard
|
||||
@@ -50,16 +53,17 @@
|
||||
wiz_team = new(owner)
|
||||
wiz_team.name = "[owner.current.real_name] team"
|
||||
wiz_team.master_wizard = src
|
||||
update_wiz_icons_added(owner.current)
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, owner.current)
|
||||
|
||||
/datum/antagonist/wizard/proc/send_to_lair()
|
||||
if(!owner || !owner.current)
|
||||
if(!owner)
|
||||
CRASH("Antag datum with no owner.")
|
||||
if(!owner.current)
|
||||
return
|
||||
if(!GLOB.wizardstart.len)
|
||||
SSjob.SendToLateJoin(owner.current)
|
||||
to_chat(owner, "HOT INSERTION, GO GO GO")
|
||||
else
|
||||
owner.current.forceMove(pick(GLOB.wizardstart))
|
||||
owner.current.forceMove(pick(GLOB.wizardstart))
|
||||
|
||||
/datum/antagonist/wizard/proc/create_objectives()
|
||||
var/datum/objective/flavor/wizard/new_objective = new
|
||||
@@ -79,7 +83,7 @@
|
||||
|
||||
/datum/antagonist/wizard/proc/equip_wizard()
|
||||
if(!owner)
|
||||
return
|
||||
CRASH("Antag datum with no owner.")
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
@@ -91,18 +95,14 @@
|
||||
H.age = wiz_age
|
||||
H.equipOutfit(outfit_type)
|
||||
|
||||
/datum/antagonist/wizard/greet()
|
||||
to_chat(owner, "<span class='boldannounce'>You are the Space Wizard!</span>")
|
||||
to_chat(owner, "<B>The Space Wizards Federation has given you the following tasks:</B>")
|
||||
owner.announce_objectives()
|
||||
to_chat(owner, "<B>These are merely guidelines! The federation are your masters, but you forge your own path!</B>")
|
||||
to_chat(owner, "You will find a list of available spells in your spell book. Choose your magic arsenal carefully.")
|
||||
to_chat(owner, "The spellbook is bound to you, and others cannot use it.")
|
||||
to_chat(owner, "In your pockets you will find a teleport scroll. Use it as needed.")
|
||||
to_chat(owner,"<B>Remember:</B> do not forget to prepare your spells.")
|
||||
/datum/antagonist/wizard/ui_static_data(mob/user)
|
||||
. = ..()
|
||||
var/list/data = list()
|
||||
data["objectives"] = get_objectives()
|
||||
return data
|
||||
|
||||
/datum/antagonist/wizard/farewell()
|
||||
to_chat(owner, "<span class='userdanger'>You have been brainwashed! You are no longer a wizard!</span>")
|
||||
to_chat(owner, span_userdanger("You have been brainwashed! You are no longer a wizard!"))
|
||||
|
||||
/datum/antagonist/wizard/proc/rename_wizard()
|
||||
set waitfor = FALSE
|
||||
@@ -111,7 +111,7 @@
|
||||
var/wizard_name_second = pick(GLOB.wizard_second)
|
||||
var/randomname = "[wizard_name_first] [wizard_name_second]"
|
||||
var/mob/living/wiz_mob = owner.current
|
||||
var/newname = reject_bad_name(stripped_input(wiz_mob, "You are the [name]. Would you like to change your name to something else?", "Name change", randomname, MAX_NAME_LEN))
|
||||
var/newname = sanitize_name(reject_bad_text(stripped_input(wiz_mob, "You are the [name]. Would you like to change your name to something else?", "Name change", randomname, MAX_NAME_LEN)))
|
||||
|
||||
if (!newname)
|
||||
newname = randomname
|
||||
@@ -120,12 +120,12 @@
|
||||
|
||||
/datum/antagonist/wizard/apply_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_wiz_icons_added(M, wiz_team ? TRUE : FALSE) //Don't bother showing the icon if you're solo wizard
|
||||
add_antag_hud(antag_hud_type, antag_hud_name, M)
|
||||
M.faction |= ROLE_WIZARD
|
||||
|
||||
/datum/antagonist/wizard/remove_innate_effects(mob/living/mob_override)
|
||||
var/mob/living/M = mob_override || owner.current
|
||||
update_wiz_icons_removed(M)
|
||||
remove_antag_hud(antag_hud_type, M)
|
||||
M.faction -= ROLE_WIZARD
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
|
||||
/datum/antagonist/wizard/apprentice
|
||||
name = "Wizard Apprentice"
|
||||
hud_version = "apprentice"
|
||||
antag_hud_name = "apprentice"
|
||||
var/datum/mind/master
|
||||
var/school = APPRENTICE_DESTRUCTION
|
||||
outfit_type = /datum/outfit/wizard/apprentice
|
||||
@@ -157,7 +157,7 @@
|
||||
/datum/antagonist/wizard/apprentice/equip_wizard()
|
||||
. = ..()
|
||||
if(!owner)
|
||||
return
|
||||
CRASH("Antag datum with no owner.")
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
if(!istype(H))
|
||||
return
|
||||
@@ -169,12 +169,12 @@
|
||||
if(APPRENTICE_BLUESPACE)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned reality bending mobility spells. You are able to cast teleport and ethereal jaunt.")
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned reality-bending mobility spells. You are able to cast teleport and ethereal jaunt.")
|
||||
if(APPRENTICE_HEALING)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/charge(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/forcewall(null))
|
||||
H.put_in_hands(new /obj/item/gun/magic/staff/healing(H))
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned livesaving survival spells. You are able to cast charge and forcewall.")
|
||||
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned life-saving survival spells. You are able to cast charge and forcewall.")
|
||||
if(APPRENTICE_ROBELESS)
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/pointed/mind_transfer(null))
|
||||
@@ -194,6 +194,7 @@
|
||||
//Random event wizard
|
||||
/datum/antagonist/wizard/apprentice/imposter
|
||||
name = "Wizard Imposter"
|
||||
show_in_antagpanel = FALSE
|
||||
allow_rename = FALSE
|
||||
move_to_lair = FALSE
|
||||
|
||||
@@ -224,20 +225,11 @@
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(null))
|
||||
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(null))
|
||||
|
||||
/datum/antagonist/wizard/proc/update_wiz_icons_added(mob/living/wiz,join = TRUE)
|
||||
var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ]
|
||||
wizhud.join_hud(wiz)
|
||||
set_antag_hud(wiz, hud_version)
|
||||
|
||||
/datum/antagonist/wizard/proc/update_wiz_icons_removed(mob/living/wiz)
|
||||
var/datum/atom_hud/antag/wizhud = GLOB.huds[ANTAG_HUD_WIZ]
|
||||
wizhud.leave_hud(wiz)
|
||||
set_antag_hud(wiz, null)
|
||||
|
||||
|
||||
/datum/antagonist/wizard/academy
|
||||
name = "Academy Teacher"
|
||||
show_in_antagpanel = FALSE
|
||||
outfit_type = /datum/outfit/wizard/academy
|
||||
move_to_lair = FALSE
|
||||
|
||||
/datum/antagonist/wizard/academy/equip_wizard()
|
||||
. = ..()
|
||||
@@ -250,7 +242,7 @@
|
||||
if(!istype(M))
|
||||
return
|
||||
|
||||
var/obj/item/implant/exile/Implant = new
|
||||
var/obj/item/implant/exile/Implant = new/obj/item/implant/exile(M)
|
||||
Implant.implant(M)
|
||||
|
||||
/datum/antagonist/wizard/academy/create_objectives()
|
||||
@@ -265,25 +257,25 @@
|
||||
parts += printplayer(owner)
|
||||
|
||||
var/count = 1
|
||||
var/wizardwin = 1
|
||||
var/wizardwin = TRUE
|
||||
for(var/datum/objective/objective in objectives)
|
||||
if(objective.completable)
|
||||
var/completion = objective.check_completion()
|
||||
if(completion >= 1)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='greentext'><B>Success!</B></span>"
|
||||
parts += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_greentext("Success!")]"
|
||||
else if(completion <= 0)
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='redtext'>Fail.</span>"
|
||||
parts += "<br><B>Objective #[count]</B>: [objective.explanation_text] [span_redtext("Fail.")]"
|
||||
wizardwin = FALSE
|
||||
else
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
|
||||
parts += "<br><B>Objective #[count]</B>: [objective.explanation_text] <span class='yellowtext'>[completion*100]%</span>"
|
||||
else
|
||||
parts += "<B>Objective #[count]</B>: [objective.explanation_text]"
|
||||
count++
|
||||
|
||||
if(wizardwin)
|
||||
parts += "<span class='greentext'>The wizard was successful!</span>"
|
||||
parts += span_greentext("The wizard was successful!")
|
||||
else
|
||||
parts += "<span class='redtext'>The wizard has failed!</span>"
|
||||
parts += span_redtext("The wizard has failed!")
|
||||
|
||||
if(owner.spell_list.len>0)
|
||||
parts += "<B>[owner.name] used the following spells: </B>"
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
if(spill && R.total_volume >= 5)
|
||||
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
|
||||
if(!turfing)
|
||||
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1))
|
||||
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1), log = TRUE)
|
||||
G.last_orgasmed = world.time
|
||||
R.clear_reagents()
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE))
|
||||
return
|
||||
to_chat(src,"<span class='userlove'>You used your [G.name] to fill [container].</span>")
|
||||
message_admins("[src] used their [G.name] to fill [container].")
|
||||
do_climax(fluid_source, container, G, FALSE)
|
||||
|
||||
/mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE)
|
||||
|
||||
@@ -13,9 +13,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
var/_abstract = /datum/asset
|
||||
var/cached_url_mappings
|
||||
|
||||
/// Whether or not this asset should be loaded in the "early assets" SS
|
||||
var/early = FALSE
|
||||
|
||||
/datum/asset/New()
|
||||
GLOB.asset_datums[type] = src
|
||||
register()
|
||||
@@ -368,28 +365,3 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
/datum/asset/simple/namespaced/proc/get_htmlloader(filename)
|
||||
return url2htmlloader(SSassets.transport.get_asset_url(filename, assets[filename]))
|
||||
|
||||
/// A subtype to generate a JSON file from a list
|
||||
/datum/asset/json
|
||||
_abstract = /datum/asset/json
|
||||
/// The filename, will be suffixed with ".json"
|
||||
var/name
|
||||
|
||||
/datum/asset/json/send(client)
|
||||
return SSassets.transport.send_assets(client, "data/[name].json")
|
||||
|
||||
/datum/asset/json/get_url_mappings()
|
||||
return list(
|
||||
"[name].json" = SSassets.transport.get_asset_url("data/[name].json"),
|
||||
)
|
||||
|
||||
/datum/asset/json/register()
|
||||
var/filename = "data/[name].json"
|
||||
fdel(filename)
|
||||
text2file(json_encode(generate()), filename)
|
||||
SSassets.transport.register_asset(filename, fcopy_rsc(filename))
|
||||
fdel(filename)
|
||||
|
||||
/// Returns the data that will be JSON encoded
|
||||
/datum/asset/json/proc/generate()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
CRASH("generate() not implemented for [type]!")
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
//DEFINITIONS FOR ASSET DATUMS START HERE.
|
||||
|
||||
/datum/asset/simple/tgui_common
|
||||
keep_local_name = TRUE
|
||||
assets = list(
|
||||
"tgui-common.bundle.js" = file("tgui/public/tgui-common.bundle.js"),
|
||||
)
|
||||
|
||||
/datum/asset/simple/tgui
|
||||
keep_local_name = TRUE
|
||||
assets = list(
|
||||
@@ -54,9 +48,14 @@
|
||||
|
||||
/datum/asset/simple/radar_assets
|
||||
assets = list(
|
||||
"ntosradarbackground.png" = 'icons/UI_Icons/tgui/ntosradar_background.png',
|
||||
"ntosradarpointer.png" = 'icons/UI_Icons/tgui/ntosradar_pointer.png',
|
||||
"ntosradarpointerS.png" = 'icons/UI_Icons/tgui/ntosradar_pointer_S.png'
|
||||
"ntosradarbackground.png" = 'icons/ui_icons/tgui/ntosradar_background.png',
|
||||
"ntosradarpointer.png" = 'icons/ui_icons/tgui/ntosradar_pointer.png',
|
||||
"ntosradarpointerS.png" = 'icons/ui_icons/tgui/ntosradar_pointer_S.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/circuit_assets
|
||||
assets = list(
|
||||
"grid_background.png" = 'icons/ui_icons/tgui/grid_background.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/pda
|
||||
@@ -91,6 +90,7 @@
|
||||
"status" = 'icons/pda_icons/pda_status.png',
|
||||
"dronephone" = 'icons/pda_icons/pda_dronephone.png',
|
||||
"emoji" = 'icons/pda_icons/pda_emoji.png'
|
||||
// "droneblacklist" = 'icons/pda_icons/pda_droneblacklist.png',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/paper
|
||||
@@ -116,7 +116,7 @@
|
||||
|
||||
/datum/asset/simple/irv
|
||||
assets = list(
|
||||
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/IRV/jquery-ui.custom-core-widgit-mouse-sortable-min.js',
|
||||
"jquery-ui.custom-core-widgit-mouse-sortable-min.js" = 'html/jquery/jquery-ui.custom-core-widgit-mouse-sortable.min.js',
|
||||
)
|
||||
|
||||
/datum/asset/group/irv
|
||||
@@ -125,35 +125,10 @@
|
||||
/datum/asset/simple/irv
|
||||
)
|
||||
|
||||
/datum/asset/simple/namespaced/changelog
|
||||
assets = list(
|
||||
"88x31.png" = 'html/88x31.png',
|
||||
"bug-minus.png" = 'html/bug-minus.png',
|
||||
"cross-circle.png" = 'html/cross-circle.png',
|
||||
"hard-hat-exclamation.png" = 'html/hard-hat-exclamation.png',
|
||||
"image-minus.png" = 'html/image-minus.png',
|
||||
"image-plus.png" = 'html/image-plus.png',
|
||||
"music-minus.png" = 'html/music-minus.png',
|
||||
"music-plus.png" = 'html/music-plus.png',
|
||||
"tick-circle.png" = 'html/tick-circle.png',
|
||||
"wrench-screwdriver.png" = 'html/wrench-screwdriver.png',
|
||||
"spell-check.png" = 'html/spell-check.png',
|
||||
"burn-exclamation.png" = 'html/burn-exclamation.png',
|
||||
"chevron.png" = 'html/chevron.png',
|
||||
"chevron-expand.png" = 'html/chevron-expand.png',
|
||||
"scales.png" = 'html/scales.png',
|
||||
"coding.png" = 'html/coding.png',
|
||||
"ban.png" = 'html/ban.png',
|
||||
"chrome-wrench.png" = 'html/chrome-wrench.png',
|
||||
"changelog.css" = 'html/changelog.css'
|
||||
)
|
||||
parents = list("changelog.html" = 'html/changelog.html')
|
||||
|
||||
|
||||
/datum/asset/simple/jquery
|
||||
legacy = TRUE
|
||||
assets = list(
|
||||
"jquery.min.js" = 'html/jquery.min.js',
|
||||
"jquery.min.js" = 'html/jquery/jquery.min.js',
|
||||
)
|
||||
|
||||
/datum/asset/simple/namespaced/fontawesome
|
||||
@@ -223,102 +198,102 @@
|
||||
|
||||
/datum/asset/simple/arcade
|
||||
assets = list(
|
||||
"boss1.gif" = 'icons/UI_Icons/Arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/UI_Icons/Arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/UI_Icons/Arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/UI_Icons/Arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/UI_Icons/Arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/UI_Icons/Arcade/boss6.gif',
|
||||
"boss1.gif" = 'icons/ui_icons/arcade/boss1.gif',
|
||||
"boss2.gif" = 'icons/ui_icons/arcade/boss2.gif',
|
||||
"boss3.gif" = 'icons/ui_icons/arcade/boss3.gif',
|
||||
"boss4.gif" = 'icons/ui_icons/arcade/boss4.gif',
|
||||
"boss5.gif" = 'icons/ui_icons/arcade/boss5.gif',
|
||||
"boss6.gif" = 'icons/ui_icons/arcade/boss6.gif',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/achievements
|
||||
name ="achievements"
|
||||
assets = list(
|
||||
"default" = 'icons/UI_Icons/Achievements/default.png',
|
||||
"basemisc" = 'icons/UI_Icons/Achievements/basemisc.png',
|
||||
"baseboss" = 'icons/UI_Icons/Achievements/baseboss.png',
|
||||
"baseskill" = 'icons/UI_Icons/Achievements/baseskill.png',
|
||||
"bbgum" = 'icons/UI_Icons/Achievements/Boss/bbgum.png',
|
||||
"colossus" = 'icons/UI_Icons/Achievements/Boss/colossus.png',
|
||||
"hierophant" = 'icons/UI_Icons/Achievements/Boss/hierophant.png',
|
||||
"drake" = 'icons/UI_Icons/Achievements/Boss/drake.png',
|
||||
"legion" = 'icons/UI_Icons/Achievements/Boss/legion.png',
|
||||
"miner" = 'icons/UI_Icons/Achievements/Boss/miner.png',
|
||||
"swarmer" = 'icons/UI_Icons/Achievements/Boss/swarmer.png',
|
||||
"tendril" = 'icons/UI_Icons/Achievements/Boss/tendril.png',
|
||||
"featofstrength" = 'icons/UI_Icons/Achievements/Misc/featofstrength.png',
|
||||
"helbital" = 'icons/UI_Icons/Achievements/Misc/helbital.png',
|
||||
"jackpot" = 'icons/UI_Icons/Achievements/Misc/jackpot.png',
|
||||
"meteors" = 'icons/UI_Icons/Achievements/Misc/meteors.png',
|
||||
"timewaste" = 'icons/UI_Icons/Achievements/Misc/timewaste.png',
|
||||
"upgrade" = 'icons/UI_Icons/Achievements/Misc/upgrade.png',
|
||||
"clownking" = 'icons/UI_Icons/Achievements/Misc/clownking.png',
|
||||
"clownthanks" = 'icons/UI_Icons/Achievements/Misc/clownthanks.png',
|
||||
"rule8" = 'icons/UI_Icons/Achievements/Misc/rule8.png',
|
||||
"longshift" = 'icons/UI_Icons/Achievements/Misc/longshift.png',
|
||||
"snail" = 'icons/UI_Icons/Achievements/Misc/snail.png',
|
||||
"ascension" = 'icons/UI_Icons/Achievements/Misc/ascension.png',
|
||||
"ashascend" = 'icons/UI_Icons/Achievements/Misc/ashascend.png',
|
||||
"fleshascend" = 'icons/UI_Icons/Achievements/Misc/fleshascend.png',
|
||||
"rustascend" = 'icons/UI_Icons/Achievements/Misc/rustascend.png',
|
||||
"voidascend" = 'icons/UI_Icons/Achievements/Misc/voidascend.png',
|
||||
"toolbox_soul" = 'icons/UI_Icons/Achievements/Misc/toolbox_soul.png',
|
||||
"chem_tut" = 'icons/UI_Icons/Achievements/Misc/chem_tut.png',
|
||||
"mining" = 'icons/UI_Icons/Achievements/Skills/mining.png',
|
||||
"mafia" = 'icons/UI_Icons/Achievements/Mafia/mafia.png',
|
||||
"town" = 'icons/UI_Icons/Achievements/Mafia/town.png',
|
||||
"neutral" = 'icons/UI_Icons/Achievements/Mafia/neutral.png',
|
||||
"hated" = 'icons/UI_Icons/Achievements/Mafia/hated.png',
|
||||
"basemafia" ='icons/UI_Icons/Achievements/basemafia.png',
|
||||
"frenching" = 'icons/UI_Icons/Achievements/Misc/frenchingthebubble.png'
|
||||
"default" = 'icons/ui_icons/achievements/default.png',
|
||||
"basemisc" = 'icons/ui_icons/achievements/basemisc.png',
|
||||
"baseboss" = 'icons/ui_icons/achievements/baseboss.png',
|
||||
"baseskill" = 'icons/ui_icons/achievements/baseskill.png',
|
||||
"bbgum" = 'icons/ui_icons/achievements/Boss/bbgum.png',
|
||||
"colossus" = 'icons/ui_icons/achievements/Boss/colossus.png',
|
||||
"hierophant" = 'icons/ui_icons/achievements/Boss/hierophant.png',
|
||||
"drake" = 'icons/ui_icons/achievements/Boss/drake.png',
|
||||
"legion" = 'icons/ui_icons/achievements/Boss/legion.png',
|
||||
"miner" = 'icons/ui_icons/achievements/Boss/miner.png',
|
||||
"swarmer" = 'icons/ui_icons/achievements/Boss/swarmer.png',
|
||||
"tendril" = 'icons/ui_icons/achievements/Boss/tendril.png',
|
||||
"featofstrength" = 'icons/ui_icons/achievements/Misc/featofstrength.png',
|
||||
"helbital" = 'icons/ui_icons/achievements/Misc/helbital.png',
|
||||
"jackpot" = 'icons/ui_icons/achievements/Misc/jackpot.png',
|
||||
"meteors" = 'icons/ui_icons/achievements/Misc/meteors.png',
|
||||
"timewaste" = 'icons/ui_icons/achievements/Misc/timewaste.png',
|
||||
"upgrade" = 'icons/ui_icons/achievements/Misc/upgrade.png',
|
||||
"clownking" = 'icons/ui_icons/achievements/Misc/clownking.png',
|
||||
"clownthanks" = 'icons/ui_icons/achievements/Misc/clownthanks.png',
|
||||
"rule8" = 'icons/ui_icons/achievements/Misc/rule8.png',
|
||||
"longshift" = 'icons/ui_icons/achievements/Misc/longshift.png',
|
||||
"snail" = 'icons/ui_icons/achievements/Misc/snail.png',
|
||||
"ascension" = 'icons/ui_icons/achievements/Misc/ascension.png',
|
||||
"ashascend" = 'icons/ui_icons/achievements/Misc/ashascend.png',
|
||||
"fleshascend" = 'icons/ui_icons/achievements/Misc/fleshascend.png',
|
||||
"rustascend" = 'icons/ui_icons/achievements/Misc/rustascend.png',
|
||||
"voidascend" = 'icons/ui_icons/achievements/Misc/voidascend.png',
|
||||
"toolbox_soul" = 'icons/ui_icons/achievements/Misc/toolbox_soul.png',
|
||||
"chem_tut" = 'icons/ui_icons/achievements/Misc/chem_tut.png',
|
||||
"mining" = 'icons/ui_icons/achievements/Skills/mining.png',
|
||||
"mafia" = 'icons/ui_icons/achievements/Mafia/mafia.png',
|
||||
"town" = 'icons/ui_icons/achievements/Mafia/town.png',
|
||||
"neutral" = 'icons/ui_icons/achievements/Mafia/neutral.png',
|
||||
"hated" = 'icons/ui_icons/achievements/Mafia/hated.png',
|
||||
"basemafia" ='icons/ui_icons/achievements/basemafia.png',
|
||||
"frenching" = 'icons/ui_icons/achievements/Misc/frenchingthebubble.png'
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/simple/pills
|
||||
name = "pills"
|
||||
assets = list(
|
||||
"pill1" = 'icons/UI_Icons/Pills/pill1.png',
|
||||
"pill2" = 'icons/UI_Icons/Pills/pill2.png',
|
||||
"pill3" = 'icons/UI_Icons/Pills/pill3.png',
|
||||
"pill4" = 'icons/UI_Icons/Pills/pill4.png',
|
||||
"pill5" = 'icons/UI_Icons/Pills/pill5.png',
|
||||
"pill6" = 'icons/UI_Icons/Pills/pill6.png',
|
||||
"pill7" = 'icons/UI_Icons/Pills/pill7.png',
|
||||
"pill8" = 'icons/UI_Icons/Pills/pill8.png',
|
||||
"pill9" = 'icons/UI_Icons/Pills/pill9.png',
|
||||
"pill10" = 'icons/UI_Icons/Pills/pill10.png',
|
||||
"pill11" = 'icons/UI_Icons/Pills/pill11.png',
|
||||
"pill12" = 'icons/UI_Icons/Pills/pill12.png',
|
||||
"pill13" = 'icons/UI_Icons/Pills/pill13.png',
|
||||
"pill14" = 'icons/UI_Icons/Pills/pill14.png',
|
||||
"pill15" = 'icons/UI_Icons/Pills/pill15.png',
|
||||
"pill16" = 'icons/UI_Icons/Pills/pill16.png',
|
||||
"pill17" = 'icons/UI_Icons/Pills/pill17.png',
|
||||
"pill18" = 'icons/UI_Icons/Pills/pill18.png',
|
||||
"pill19" = 'icons/UI_Icons/Pills/pill19.png',
|
||||
"pill20" = 'icons/UI_Icons/Pills/pill20.png',
|
||||
"pill21" = 'icons/UI_Icons/Pills/pill21.png',
|
||||
"pill22" = 'icons/UI_Icons/Pills/pill22.png',
|
||||
"pill1" = 'icons/ui_icons/pills/pill1.png',
|
||||
"pill2" = 'icons/ui_icons/pills/pill2.png',
|
||||
"pill3" = 'icons/ui_icons/pills/pill3.png',
|
||||
"pill4" = 'icons/ui_icons/pills/pill4.png',
|
||||
"pill5" = 'icons/ui_icons/pills/pill5.png',
|
||||
"pill6" = 'icons/ui_icons/pills/pill6.png',
|
||||
"pill7" = 'icons/ui_icons/pills/pill7.png',
|
||||
"pill8" = 'icons/ui_icons/pills/pill8.png',
|
||||
"pill9" = 'icons/ui_icons/pills/pill9.png',
|
||||
"pill10" = 'icons/ui_icons/pills/pill10.png',
|
||||
"pill11" = 'icons/ui_icons/pills/pill11.png',
|
||||
"pill12" = 'icons/ui_icons/pills/pill12.png',
|
||||
"pill13" = 'icons/ui_icons/pills/pill13.png',
|
||||
"pill14" = 'icons/ui_icons/pills/pill14.png',
|
||||
"pill15" = 'icons/ui_icons/pills/pill15.png',
|
||||
"pill16" = 'icons/ui_icons/pills/pill16.png',
|
||||
"pill17" = 'icons/ui_icons/pills/pill17.png',
|
||||
"pill18" = 'icons/ui_icons/pills/pill18.png',
|
||||
"pill19" = 'icons/ui_icons/pills/pill19.png',
|
||||
"pill20" = 'icons/ui_icons/pills/pill20.png',
|
||||
"pill21" = 'icons/ui_icons/pills/pill21.png',
|
||||
"pill22" = 'icons/ui_icons/pills/pill22.png',
|
||||
)
|
||||
|
||||
// /datum/asset/spritesheet/simple/condiments
|
||||
// name = "condiments"
|
||||
// assets = list(
|
||||
// CONDIMASTER_STYLE_FALLBACK = 'icons/UI_Icons/Condiments/emptycondiment.png',
|
||||
// "enzyme" = 'icons/UI_Icons/Condiments/enzyme.png',
|
||||
// "flour" = 'icons/UI_Icons/Condiments/flour.png',
|
||||
// "mayonnaise" = 'icons/UI_Icons/Condiments/mayonnaise.png',
|
||||
// "milk" = 'icons/UI_Icons/Condiments/milk.png',
|
||||
// "blackpepper" = 'icons/UI_Icons/Condiments/peppermillsmall.png',
|
||||
// "rice" = 'icons/UI_Icons/Condiments/rice.png',
|
||||
// "sodiumchloride" = 'icons/UI_Icons/Condiments/saltshakersmall.png',
|
||||
// "soymilk" = 'icons/UI_Icons/Condiments/soymilk.png',
|
||||
// "soysauce" = 'icons/UI_Icons/Condiments/soysauce.png',
|
||||
// "sugar" = 'icons/UI_Icons/Condiments/sugar.png',
|
||||
// "ketchup" = 'icons/UI_Icons/Condiments/ketchup.png',
|
||||
// "capsaicin" = 'icons/UI_Icons/Condiments/hotsauce.png',
|
||||
// "frostoil" = 'icons/UI_Icons/Condiments/coldsauce.png',
|
||||
// "bbqsauce" = 'icons/UI_Icons/Condiments/bbqsauce.png',
|
||||
// "cornoil" = 'icons/UI_Icons/Condiments/oliveoil.png',
|
||||
// CONDIMASTER_STYLE_FALLBACK = 'icons/ui_icons/condiments/emptycondiment.png',
|
||||
// "enzyme" = 'icons/ui_icons/condiments/enzyme.png',
|
||||
// "flour" = 'icons/ui_icons/condiments/flour.png',
|
||||
// "mayonnaise" = 'icons/ui_icons/condiments/mayonnaise.png',
|
||||
// "milk" = 'icons/ui_icons/condiments/milk.png',
|
||||
// "blackpepper" = 'icons/ui_icons/condiments/peppermillsmall.png',
|
||||
// "rice" = 'icons/ui_icons/condiments/rice.png',
|
||||
// "sodiumchloride" = 'icons/ui_icons/condiments/saltshakersmall.png',
|
||||
// "soymilk" = 'icons/ui_icons/condiments/soymilk.png',
|
||||
// "soysauce" = 'icons/ui_icons/condiments/soysauce.png',
|
||||
// "sugar" = 'icons/ui_icons/condiments/sugar.png',
|
||||
// "ketchup" = 'icons/ui_icons/condiments/ketchup.png',
|
||||
// "capsaicin" = 'icons/ui_icons/condiments/hotsauce.png',
|
||||
// "frostoil" = 'icons/ui_icons/condiments/coldsauce.png',
|
||||
// "bbqsauce" = 'icons/ui_icons/condiments/bbqsauce.png',
|
||||
// "cornoil" = 'icons/ui_icons/condiments/oliveoil.png',
|
||||
// )
|
||||
|
||||
//this exists purely to avoid meta by pre-loading all language icons.
|
||||
@@ -410,9 +385,15 @@
|
||||
if (machine)
|
||||
item = machine
|
||||
|
||||
// Check for GAGS support where necessary
|
||||
// var/greyscale_config = initial(item.greyscale_config)
|
||||
// var/greyscale_colors = initial(item.greyscale_colors)
|
||||
// if (greyscale_config && greyscale_colors)
|
||||
// icon_file = SSgreyscale.GetColoredIconByType(greyscale_config, greyscale_colors)
|
||||
// else
|
||||
icon_file = initial(item.icon)
|
||||
icon_state = initial(item.icon_state)
|
||||
|
||||
icon_state = initial(item.icon_state)
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
warning("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
@@ -441,7 +422,11 @@
|
||||
if (!ispath(item, /atom))
|
||||
continue
|
||||
|
||||
var/icon_file = initial(item.icon)
|
||||
var/icon_file
|
||||
// if (initial(item.greyscale_colors) && initial(item.greyscale_config))
|
||||
// icon_file = SSgreyscale.GetColoredIconByType(initial(item.greyscale_config), initial(item.greyscale_colors))
|
||||
// else
|
||||
icon_file = initial(item.icon)
|
||||
var/icon_state = initial(item.icon_state)
|
||||
var/icon/I
|
||||
|
||||
@@ -543,6 +528,35 @@
|
||||
// Insert(id, fish_icon, fish_icon_state)
|
||||
// ..()
|
||||
|
||||
/datum/asset/simple/adventure
|
||||
assets = list(
|
||||
"default" = 'icons/ui_icons/adventure/default.png',
|
||||
"grue" = 'icons/ui_icons/adventure/grue.png',
|
||||
"signal_lost" ='icons/ui_icons/adventure/signal_lost.png',
|
||||
"trade" = 'icons/ui_icons/adventure/trade.png',
|
||||
)
|
||||
|
||||
/datum/asset/simple/inventory
|
||||
assets = list(
|
||||
"inventory-glasses.png" = 'icons/ui_icons/inventory/glasses.png',
|
||||
"inventory-head.png" = 'icons/ui_icons/inventory/head.png',
|
||||
"inventory-neck.png" = 'icons/ui_icons/inventory/neck.png',
|
||||
"inventory-mask.png" = 'icons/ui_icons/inventory/mask.png',
|
||||
"inventory-ears.png" = 'icons/ui_icons/inventory/ears.png',
|
||||
"inventory-uniform.png" = 'icons/ui_icons/inventory/uniform.png',
|
||||
"inventory-suit.png" = 'icons/ui_icons/inventory/suit.png',
|
||||
"inventory-gloves.png" = 'icons/ui_icons/inventory/gloves.png',
|
||||
"inventory-hand_l.png" = 'icons/ui_icons/inventory/hand_l.png',
|
||||
"inventory-hand_r.png" = 'icons/ui_icons/inventory/hand_r.png',
|
||||
"inventory-shoes.png" = 'icons/ui_icons/inventory/shoes.png',
|
||||
"inventory-suit_storage.png" = 'icons/ui_icons/inventory/suit_storage.png',
|
||||
"inventory-id.png" = 'icons/ui_icons/inventory/id.png',
|
||||
"inventory-belt.png" = 'icons/ui_icons/inventory/belt.png',
|
||||
"inventory-back.png" = 'icons/ui_icons/inventory/back.png',
|
||||
"inventory-pocket.png" = 'icons/ui_icons/inventory/pocket.png',
|
||||
"inventory-collar.png" = 'icons/ui_icons/inventory/collar.png',
|
||||
)
|
||||
|
||||
/// Removes all non-alphanumerics from the text, keep in mind this can lead to id conflicts
|
||||
/proc/sanitize_css_class_name(name)
|
||||
var/static/regex/regex = new(@"[^a-zA-Z0-9]","g")
|
||||
@@ -550,5 +564,34 @@
|
||||
|
||||
/datum/asset/simple/tutorial_advisors
|
||||
assets = list(
|
||||
"chem_help_advisor.gif" = 'icons/UI_Icons/Advisors/chem_help_advisor.gif',
|
||||
"chem_help_advisor.gif" = 'icons/ui_icons/advisors/chem_help_advisor.gif',
|
||||
)
|
||||
|
||||
// /datum/asset/spritesheet/moods
|
||||
// name = "moods"
|
||||
// var/iconinserted = 1
|
||||
|
||||
// /datum/asset/spritesheet/moods/register()
|
||||
// for(var/i in 1 to 9)
|
||||
// var/target_to_insert = "mood"+"[iconinserted]"
|
||||
// Insert(target_to_insert, 'icons/hud/screen_gen.dmi', target_to_insert)
|
||||
// iconinserted++
|
||||
// ..()
|
||||
|
||||
// /datum/asset/spritesheet/moods/ModifyInserted(icon/pre_asset)
|
||||
// var/blended_color
|
||||
// switch(iconinserted)
|
||||
// if(1)
|
||||
// blended_color = "#f15d36"
|
||||
// if(2 to 3)
|
||||
// blended_color = "#f38943"
|
||||
// if(4)
|
||||
// blended_color = "#dfa65b"
|
||||
// if(5)
|
||||
// blended_color = "#4b96c4"
|
||||
// if(6)
|
||||
// blended_color = "#86d656"
|
||||
// else
|
||||
// blended_color = "#2eeb9a"
|
||||
// pre_asset.Blend(blended_color, ICON_MULTIPLY)
|
||||
// return pre_asset
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
|
||||
if (unreceived.len)
|
||||
if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT)
|
||||
to_chat(client, "Sending Resources...")
|
||||
to_chat(client, "<span class='infoplain'>Sending Resources...</span>")
|
||||
|
||||
for (var/asset_name in unreceived)
|
||||
var/new_asset_name = asset_name
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
)
|
||||
)
|
||||
fusion_power = 3
|
||||
enthalpy = -393500
|
||||
|
||||
/datum/gas/plasma
|
||||
id = GAS_PLASMA
|
||||
@@ -54,7 +55,10 @@
|
||||
heat_penalty = 15
|
||||
transmit_modifier = 4
|
||||
powermix = 1
|
||||
// no fire info cause it has its own bespoke reaction for trit generation reasons
|
||||
fire_burn_rate = OXYGEN_BURN_RATE_BASE // named when plasma fires were the only fires, surely
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
fire_products = "plasma_fire"
|
||||
enthalpy = FIRE_PLASMA_ENERGY_RELEASED // 3000000, 3 megajoules, 3000 kj
|
||||
|
||||
/datum/gas/water_vapor
|
||||
id = GAS_H2O
|
||||
@@ -64,6 +68,7 @@
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
fusion_power = 8
|
||||
heat_penalty = 8
|
||||
enthalpy = -241800 // FIRE_HYDROGEN_ENERGY_RELEASED is actually what this was supposed to be
|
||||
powermix = 1
|
||||
breath_reagent = /datum/reagent/water
|
||||
|
||||
@@ -84,6 +89,7 @@
|
||||
fire_products = list(GAS_N2 = 1)
|
||||
oxidation_rate = 0.5
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST + 100
|
||||
enthalpy = 81600
|
||||
heat_resistance = 6
|
||||
|
||||
/datum/gas/nitryl
|
||||
@@ -95,8 +101,22 @@
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fusion_power = 15
|
||||
fire_products = list(GAS_N2 = 0.5)
|
||||
enthalpy = 33200
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
|
||||
|
||||
/datum/gas/hydrogen
|
||||
id = GAS_HYDROGEN
|
||||
specific_heat = 10
|
||||
name = "Hydrogen"
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fusion_power = 0
|
||||
powermix = 1
|
||||
heat_penalty = 3
|
||||
transmit_modifier = 10
|
||||
fire_products = list(GAS_H2O = 1)
|
||||
fire_burn_rate = 2
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
|
||||
|
||||
/datum/gas/tritium
|
||||
id = GAS_TRITIUM
|
||||
specific_heat = 10
|
||||
@@ -108,13 +128,11 @@
|
||||
powermix = 1
|
||||
heat_penalty = 10
|
||||
transmit_modifier = 30
|
||||
/*
|
||||
these are for when we add hydrogen, trit gets to keep its hardcoded fire for legacy reasons
|
||||
fire_provides = list(GAS_H2O = 2)
|
||||
fire_products = list(GAS_H2O = 1)
|
||||
enthalpy = 40000
|
||||
fire_burn_rate = 2
|
||||
fire_energy_released = FIRE_HYDROGEN_ENERGY_RELEASED
|
||||
fire_radiation_released = 50 // arbitrary number, basically 60 moles of trit burning will just barely start to harm you
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
|
||||
*/
|
||||
|
||||
/datum/gas/bz
|
||||
id = GAS_BZ
|
||||
@@ -124,6 +142,7 @@
|
||||
fusion_power = 8
|
||||
powermix = 1
|
||||
heat_penalty = 5
|
||||
enthalpy = FIRE_CARBON_ENERGY_RELEASED // it is a mystery
|
||||
transmit_modifier = -2
|
||||
radioactivity_modifier = 5
|
||||
|
||||
@@ -139,7 +158,8 @@
|
||||
name = "Pluoxium"
|
||||
fusion_power = 10
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 1000 // it is VERY stable
|
||||
oxidation_rate = 8
|
||||
oxidation_rate = 8 // when it can oxidize, it can oxidize a LOT
|
||||
enthalpy = -50000 // but it reduces the heat output a bit
|
||||
powermix = -1
|
||||
heat_penalty = -1
|
||||
transmit_modifier = -5
|
||||
@@ -172,7 +192,7 @@
|
||||
alert_type = /atom/movable/screen/alert/too_much_ch4
|
||||
)
|
||||
)
|
||||
fire_energy_released = FIRE_CARBON_ENERGY_RELEASED
|
||||
enthalpy = -74600
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
|
||||
/datum/gas/methyl_bromide
|
||||
@@ -192,7 +212,28 @@
|
||||
alert_type = /atom/movable/screen/alert/too_much_ch3br
|
||||
)
|
||||
)
|
||||
fire_products = list(GAS_CO2 = 1, GAS_H2O = 1.5, GAS_BZ = 0.5)
|
||||
fire_energy_released = FIRE_CARBON_ENERGY_RELEASED
|
||||
fire_burn_rate = 0.5
|
||||
fire_products = list(GAS_CO2 = 1, GAS_H2O = 1.5, GAS_BROMINE = 0.5)
|
||||
enthalpy = -35400
|
||||
fire_burn_rate = 4 / 7 // oh no
|
||||
fire_temperature = 808 // its autoignition, it apparently doesn't spark readily, so i don't put it lower
|
||||
|
||||
/datum/gas/bromine
|
||||
id = GAS_BROMINE
|
||||
specific_heat = 76
|
||||
name = "Bromine"
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
group = GAS_GROUP_CHEMICALS
|
||||
enthalpy = 193 // yeah it's small but it's good to include it
|
||||
breath_reagent = /datum/reagent/bromine
|
||||
|
||||
/datum/gas/ammonia
|
||||
id = GAS_AMMONIA
|
||||
specific_heat = 35
|
||||
name = "Ammonia"
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
group = GAS_GROUP_CHEMICALS
|
||||
enthalpy = -45900
|
||||
breath_reagent = /datum/reagent/ammonia
|
||||
fire_products = list(GAS_H2O = 1.5, GAS_N2 = 0.5)
|
||||
fire_burn_rate = 4/3
|
||||
fire_temperature = 924
|
||||
|
||||
@@ -15,6 +15,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
|
||||
/proc/_auxtools_register_gas(datum/gas/gas) // makes sure auxtools knows stuff about this gas
|
||||
|
||||
/datum/auxgm
|
||||
var/done_initializing = FALSE
|
||||
var/list/datums = list()
|
||||
var/list/specific_heats = list()
|
||||
var/list/names = list()
|
||||
@@ -32,30 +33,34 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
|
||||
var/list/oxidation_temperatures = list()
|
||||
var/list/oxidation_rates = list()
|
||||
var/list/fire_temperatures = list()
|
||||
var/list/fire_enthalpies = list()
|
||||
var/list/enthalpies = list()
|
||||
var/list/fire_products = list()
|
||||
var/list/fire_burn_rates = list()
|
||||
var/list/supermatter = list()
|
||||
|
||||
var/list/groups_by_gas = list()
|
||||
var/list/groups = list()
|
||||
|
||||
/datum/gas
|
||||
var/id = ""
|
||||
var/specific_heat = 0
|
||||
var/name = ""
|
||||
var/gas_overlay = "" //icon_state in icons/effects/atmospherics.dmi
|
||||
var/color = "#ffff"
|
||||
var/moles_visible = null
|
||||
var/flags = NONE //currently used by canisters
|
||||
var/group = null // groups for scrubber/filter listing
|
||||
var/fusion_power = 0 // How much the gas destabilizes a fusion reaction
|
||||
var/breath_results = GAS_CO2 // what breathing this breathes out
|
||||
var/breath_reagent = null // what breathing this adds to your reagents
|
||||
var/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold
|
||||
var/datum/reagent/breath_reagent = null // what breathing this adds to your reagents
|
||||
var/datum/reagent/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold
|
||||
var/list/breath_alert_info = null // list for alerts that pop up when you have too much/not enough of something
|
||||
var/oxidation_temperature = null // temperature above which this gas is an oxidizer; null for none
|
||||
var/oxidation_rate = 1 // how many moles of this can oxidize how many moles of material
|
||||
var/fire_temperature = null // temperature above which gas may catch fire; null for none
|
||||
var/list/fire_products = null // what results when this gas is burned (oxidizer or fuel); null for none
|
||||
var/fire_energy_released = 0 // how much energy is released per mole of fuel burned
|
||||
var/enthalpy = 0 // Standard enthalpy of formation in joules, used for fires
|
||||
var/fire_burn_rate = 1 // how many moles are burned per product released
|
||||
var/fire_radiation_released = 0 // How much radiation is released when this gas burns
|
||||
var/powermix = 0 // how much this gas contributes to the supermatter's powermix ratio
|
||||
var/heat_penalty = 0 // heat and waste penalty from having the supermatter crystal surrounded by this gas; negative numbers reduce
|
||||
var/transmit_modifier = 0 // bonus to supermatter power generation (multiplicative, since it's % based, and divided by 10)
|
||||
@@ -94,21 +99,31 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
|
||||
breath_reagents[g] = gas.breath_reagent
|
||||
if(gas.breath_reagent_dangerous)
|
||||
breath_reagents_dangerous[g] = gas.breath_reagent_dangerous
|
||||
|
||||
if(gas.oxidation_temperature)
|
||||
oxidation_temperatures[g] = gas.oxidation_temperature
|
||||
oxidation_rates[g] = gas.oxidation_rate
|
||||
if(gas.fire_products)
|
||||
fire_products[g] = gas.fire_products
|
||||
fire_enthalpies[g] = gas.fire_energy_released
|
||||
enthalpies[g] = gas.enthalpy
|
||||
else if(gas.fire_temperature)
|
||||
fire_temperatures[g] = gas.fire_temperature
|
||||
fire_burn_rates[g] = gas.fire_burn_rate
|
||||
if(gas.fire_products)
|
||||
fire_products[g] = gas.fire_products
|
||||
fire_enthalpies[g] = gas.fire_energy_released
|
||||
enthalpies[g] = gas.enthalpy
|
||||
if(gas.group)
|
||||
if(!(gas.group in groups))
|
||||
groups[gas.group] = list()
|
||||
groups[gas.group] += gas
|
||||
groups_by_gas[g] = gas.group
|
||||
add_supermatter_properties(gas)
|
||||
_auxtools_register_gas(gas)
|
||||
if(done_initializing)
|
||||
for(var/r in SSair.gas_reactions)
|
||||
var/datum/gas_reaction/R = r
|
||||
R.init_reqs()
|
||||
SSair.auxtools_update_reactions()
|
||||
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NEW_GAS, g)
|
||||
|
||||
/proc/finalize_gas_refs()
|
||||
|
||||
@@ -127,6 +142,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
|
||||
for(var/breathing_class_path in subtypesof(/datum/breathing_class))
|
||||
var/datum/breathing_class/class = new breathing_class_path
|
||||
breathing_classes[breathing_class_path] = class
|
||||
done_initializing = TRUE
|
||||
finalize_gas_refs()
|
||||
|
||||
|
||||
|
||||
@@ -53,23 +53,68 @@
|
||||
id = "vapor"
|
||||
|
||||
/datum/gas_reaction/water_vapor/init_reqs()
|
||||
min_requirements = list(GAS_H2O = MOLES_GAS_VISIBLE)
|
||||
min_requirements = list(
|
||||
GAS_H2O = MOLES_GAS_VISIBLE,
|
||||
"MAX_TEMP" = T0C + 40
|
||||
)
|
||||
|
||||
/datum/gas_reaction/water_vapor/react(datum/gas_mixture/air, datum/holder)
|
||||
var/turf/open/location = isturf(holder) ? holder : null
|
||||
. = NO_REACTION
|
||||
var/turf/open/location = holder
|
||||
if(!istype(location))
|
||||
return NO_REACTION
|
||||
if (air.return_temperature() <= WATER_VAPOR_FREEZE)
|
||||
if(location && location.freon_gas_act())
|
||||
. = REACTING
|
||||
return REACTING
|
||||
else if(location && location.water_vapor_gas_act())
|
||||
air.adjust_moles(GAS_H2O,-MOLES_GAS_VISIBLE)
|
||||
. = REACTING
|
||||
return REACTING
|
||||
|
||||
// no test cause it's entirely based on location
|
||||
|
||||
/datum/gas_reaction/condensation
|
||||
priority = 0
|
||||
name = "Condensation"
|
||||
id = "condense"
|
||||
exclude = TRUE
|
||||
var/datum/reagent/condensing_reagent
|
||||
|
||||
/datum/gas_reaction/condensation/New(datum/reagent/R)
|
||||
. = ..()
|
||||
if(!istype(R))
|
||||
return
|
||||
min_requirements = list(
|
||||
"MAX_TEMP" = initial(R.boiling_point)
|
||||
)
|
||||
min_requirements[R.get_gas()] = MOLES_GAS_VISIBLE
|
||||
name = "[R.name] condensation"
|
||||
id = "[R.type] condensation"
|
||||
condensing_reagent = R
|
||||
exclude = FALSE
|
||||
|
||||
/datum/gas_reaction/condensation/react(datum/gas_mixture/air, datum/holder)
|
||||
. = NO_REACTION
|
||||
var/turf/open/location = holder
|
||||
if(!istype(location))
|
||||
return
|
||||
var/temperature = air.return_temperature()
|
||||
var/static/datum/reagents/reagents_holder = new
|
||||
reagents_holder.clear_reagents()
|
||||
reagents_holder.chem_temp = temperature
|
||||
var/G = condensing_reagent.get_gas()
|
||||
var/amt = air.get_moles(G)
|
||||
air.adjust_moles(G, -min(initial(condensing_reagent.condensation_amount), amt))
|
||||
reagents_holder.add_reagent(condensing_reagent, amt)
|
||||
. = REACTING
|
||||
for(var/atom/movable/AM in location)
|
||||
if(location.intact && AM.level == 1)
|
||||
continue
|
||||
reagents_holder.reaction(AM, TOUCH)
|
||||
reagents_holder.reaction(location, TOUCH)
|
||||
|
||||
//tritium combustion: combustion of oxygen and tritium (treated as hydrocarbons). creates hotspots. exothermic
|
||||
/datum/gas_reaction/tritfire
|
||||
priority = -1 //fire should ALWAYS be last, but tritium fires happen before plasma fires
|
||||
exclude = TRUE // generic fire now takes care of this
|
||||
name = "Tritium Combustion"
|
||||
id = "tritfire"
|
||||
|
||||
@@ -88,9 +133,9 @@
|
||||
item.temperature_expose(air, temperature, CELL_VOLUME)
|
||||
location.temperature_expose(air, temperature, CELL_VOLUME)
|
||||
|
||||
/proc/radiation_burn(turf/open/location, energy_released)
|
||||
/proc/radiation_burn(turf/open/location, rad_power)
|
||||
if(istype(location) && prob(10))
|
||||
radiation_pulse(location, energy_released/TRITIUM_BURN_RADIOACTIVITY_FACTOR)
|
||||
radiation_pulse(location, rad_power)
|
||||
|
||||
/datum/gas_reaction/tritfire/react(datum/gas_mixture/air, datum/holder)
|
||||
var/energy_released = 0
|
||||
@@ -151,6 +196,7 @@
|
||||
/datum/gas_reaction/plasmafire
|
||||
priority = -2 //fire should ALWAYS be last, but plasma fires happen after tritium fires
|
||||
name = "Plasma Combustion"
|
||||
exclude = TRUE // generic fire now takes care of this
|
||||
id = "plasmafire"
|
||||
|
||||
/datum/gas_reaction/plasmafire/init_reqs()
|
||||
@@ -300,7 +346,7 @@
|
||||
fuels[fuel] *= oxidation_ratio
|
||||
fuels += oxidizers
|
||||
var/list/fire_products = GLOB.gas_data.fire_products
|
||||
var/list/fire_enthalpies = GLOB.gas_data.fire_enthalpies
|
||||
var/list/fire_enthalpies = GLOB.gas_data.enthalpies
|
||||
for(var/fuel in fuels + oxidizers)
|
||||
var/amt = fuels[fuel]
|
||||
if(!burn_results[fuel])
|
||||
|
||||
@@ -535,7 +535,7 @@
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"set_filters" = list(GAS_CO2, GAS_MIASMA),
|
||||
"set_filters" = list(GAS_CO2, GAS_MIASMA, GAS_GROUP_CHEMICALS),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 0,
|
||||
))
|
||||
@@ -554,6 +554,7 @@
|
||||
GAS_MIASMA,
|
||||
GAS_PLASMA,
|
||||
GAS_H2O,
|
||||
GAS_HYDROGEN,
|
||||
GAS_HYPERNOB,
|
||||
GAS_NITROUS,
|
||||
GAS_NITRYL,
|
||||
@@ -562,7 +563,8 @@
|
||||
GAS_STIMULUM,
|
||||
GAS_PLUOXIUM,
|
||||
GAS_METHANE,
|
||||
GAS_METHYL_BROMIDE
|
||||
GAS_METHYL_BROMIDE,
|
||||
GAS_GROUP_CHEMICALS
|
||||
),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 1,
|
||||
@@ -582,9 +584,16 @@
|
||||
))
|
||||
for(var/device_id in A.air_vent_names)
|
||||
send_signal(device_id, list(
|
||||
"is_pressurizing" = 1,
|
||||
"power" = 1,
|
||||
"checks" = 1,
|
||||
"set_external_pressure" = ONE_ATMOSPHERE*2
|
||||
"set_external_pressure" = ONE_ATMOSPHERE*1.4
|
||||
))
|
||||
send_signal(device_id, list(
|
||||
"is_siphoning" = 1,
|
||||
"power" = 1,
|
||||
"checks" = 1,
|
||||
"set_external_pressure" = ONE_ATMOSPHERE/1.4
|
||||
))
|
||||
if(AALARM_MODE_REFILL)
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
@@ -596,10 +605,15 @@
|
||||
))
|
||||
for(var/device_id in A.air_vent_names)
|
||||
send_signal(device_id, list(
|
||||
"is_pressurizing" = 1,
|
||||
"power" = 1,
|
||||
"checks" = 1,
|
||||
"set_external_pressure" = ONE_ATMOSPHERE * 3
|
||||
))
|
||||
send_signal(device_id, list(
|
||||
"is_siphoning" = 1,
|
||||
"power" = 0,
|
||||
))
|
||||
if(AALARM_MODE_PANIC,
|
||||
AALARM_MODE_REPLACEMENT)
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
@@ -610,8 +624,14 @@
|
||||
))
|
||||
for(var/device_id in A.air_vent_names)
|
||||
send_signal(device_id, list(
|
||||
"is_pressurizing" = 1,
|
||||
"power" = 0
|
||||
))
|
||||
send_signal(device_id, list(
|
||||
"is_siphoning" = 1,
|
||||
"power" = 1,
|
||||
"checks" = 0
|
||||
))
|
||||
if(AALARM_MODE_SIPHON)
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
@@ -621,9 +641,14 @@
|
||||
))
|
||||
for(var/device_id in A.air_vent_names)
|
||||
send_signal(device_id, list(
|
||||
"is_pressurizing" = 1,
|
||||
"power" = 0
|
||||
))
|
||||
|
||||
send_signal(device_id, list(
|
||||
"is_siphoning" = 1,
|
||||
"power" = 1,
|
||||
"checks" = 0
|
||||
))
|
||||
if(AALARM_MODE_OFF)
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
@@ -641,8 +666,12 @@
|
||||
for(var/device_id in A.air_vent_names)
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"checks" = 2,
|
||||
"set_internal_pressure" = 0
|
||||
"checks" = 0,
|
||||
"is_pressurizing" = 1
|
||||
))
|
||||
send_signal(device_id, list(
|
||||
"power" = 0,
|
||||
"is_siphoning" = 1
|
||||
))
|
||||
|
||||
/obj/machinery/airalarm/update_icon_state()
|
||||
|
||||
@@ -29,13 +29,16 @@ Passive gate is similar to the regular pump except:
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/CtrlClick(mob/user)
|
||||
if(can_interact(user))
|
||||
on = !on
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/AltClick(mob/user)
|
||||
if(can_interact(user))
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
update_icon()
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
balloon_alert(user, "pressure output set to [target_pressure] kPa")
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/passive_gate/Destroy()
|
||||
|
||||
@@ -33,25 +33,19 @@
|
||||
. += "<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>"
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/pump/CtrlClick(mob/user)
|
||||
var/area/A = get_area(src)
|
||||
var/turf/T = get_turf(src)
|
||||
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
|
||||
if(can_interact(user))
|
||||
on = !on
|
||||
update_icon()
|
||||
investigate_log("Pump, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
|
||||
message_admins("Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
return ..()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/pump/AltClick(mob/user)
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
var/turf/T = get_turf(src)
|
||||
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
|
||||
if(can_interact(user))
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
to_chat(user,"<span class='notice'>You maximize the pressure on the [src].</span>")
|
||||
investigate_log("Pump, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
|
||||
message_admins("Pump, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
return TRUE
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
balloon_alert(user, "pressure output set to [target_pressure] kPa")
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/pump/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
|
||||
@@ -33,15 +33,20 @@
|
||||
. += "<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its pressure.</span>"
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/volume_pump/CtrlClick(mob/user)
|
||||
var/area/A = get_area(src)
|
||||
var/turf/T = get_turf(src)
|
||||
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
|
||||
on = !on
|
||||
update_icon()
|
||||
investigate_log("Volume Pump, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
|
||||
message_admins("Volume Pump, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/volume_pump/AltClick(mob/user)
|
||||
if(can_interact(user))
|
||||
transfer_rate = MAX_TRANSFER_RATE
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
balloon_alert(user, "volume output set to [transfer_rate] L/s")
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/binary/volume_pump/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
|
||||
@@ -20,25 +20,19 @@
|
||||
. += "<span class='notice'>You can hold <b>Alt</b> and click on it to maximize its flow rate.</span>"
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/CtrlClick(mob/user)
|
||||
var/area/A = get_area(src)
|
||||
var/turf/T = get_turf(src)
|
||||
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
|
||||
on = !on
|
||||
update_icon()
|
||||
investigate_log("Filter, [src.name], turned on by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
|
||||
message_admins("Filter, [src.name], turned [on ? "on" : "off"] by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/AltClick(mob/user)
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
var/turf/T = get_turf(src)
|
||||
if(user.canUseTopic(src, BE_CLOSE, FALSE,))
|
||||
if(can_interact(user))
|
||||
transfer_rate = MAX_TRANSFER_RATE
|
||||
to_chat(user,"<span class='notice'>You maximize the flow rate on the [src].</span>")
|
||||
investigate_log("Filter, [src.name], was maximized by [key_name(usr)] at [x], [y], [z], [A]", INVESTIGATE_ATMOS)
|
||||
message_admins("Filter, [src.name], was maximized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
return TRUE
|
||||
investigate_log("was set to [transfer_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
balloon_alert(user, "volume output set to [transfer_rate] L/s")
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/proc/set_frequency(new_frequency)
|
||||
SSradio.remove_object(src, frequency)
|
||||
@@ -100,7 +94,10 @@
|
||||
if(transfer_ratio > 0)
|
||||
|
||||
if(filter_type && air2.return_pressure() <= 9000)
|
||||
air1.scrub_into(air2, transfer_ratio, list(filter_type))
|
||||
if(filter_type in GLOB.gas_data.groups)
|
||||
air1.scrub_into(air2, transfer_ratio, GLOB.gas_data.groups[filter_type])
|
||||
else
|
||||
air1.scrub_into(air2, transfer_ratio, list(filter_type))
|
||||
if(air3.return_pressure() <= 9000)
|
||||
air1.transfer_ratio_to(air3, transfer_ratio)
|
||||
|
||||
@@ -125,8 +122,10 @@
|
||||
data["filter_types"] = list()
|
||||
data["filter_types"] += list(list("name" = "Nothing", "id" = "", "selected" = !filter_type))
|
||||
for(var/id in GLOB.gas_data.ids)
|
||||
data["filter_types"] += list(list("name" = GLOB.gas_data.names[id], "id" = id, "selected" = (id == filter_type)))
|
||||
|
||||
if(!(id in GLOB.gas_data.groups_by_gas))
|
||||
data["filter_types"] += list(list("name" = GLOB.gas_data.names[id], "id" = id, "selected" = (id == filter_type)))
|
||||
for(var/group in GLOB.gas_data.groups)
|
||||
data["filter_types"] += list(list("name" = group, "id" = group, "selected" = (group == filter_type)))
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/filter/ui_act(action, params)
|
||||
|
||||
@@ -17,35 +17,27 @@
|
||||
//node 3 is the outlet, nodes 1 & 2 are intakes
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/CtrlClick(mob/user)
|
||||
if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
if(can_interact(user))
|
||||
on = !on
|
||||
update_icon()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/AltClick(mob/user)
|
||||
if(user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
if(can_interact(user))
|
||||
target_pressure = MAX_OUTPUT_PRESSURE
|
||||
update_icon()
|
||||
investigate_log("was set to [target_pressure] kPa by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
balloon_alert(user, "pressure output on set to [target_pressure] kPa")
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
//node 3 is the outlet, nodes 1 & 2 are intakes
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/update_icon()
|
||||
cut_overlays()
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/update_overlays()
|
||||
. = ..()
|
||||
for(var/direction in GLOB.cardinals)
|
||||
if(!(direction & initialize_directions))
|
||||
continue
|
||||
var/obj/machinery/atmospherics/node = findConnecting(direction)
|
||||
|
||||
var/image/cap
|
||||
if(node)
|
||||
cap = getpipeimage(icon, "cap", direction, node.pipe_color, piping_layer = piping_layer)
|
||||
else
|
||||
cap = getpipeimage(icon, "cap", direction, piping_layer = piping_layer)
|
||||
|
||||
add_overlay(cap)
|
||||
|
||||
return ..()
|
||||
. += getpipeimage(icon, "cap", direction, pipe_color, piping_layer, TRUE)
|
||||
|
||||
/obj/machinery/atmospherics/components/trinary/mixer/update_icon_nopipes()
|
||||
var/on_state = on && nodes[1] && nodes[2] && nodes[3] && is_operational()
|
||||
|
||||
@@ -439,7 +439,7 @@
|
||||
return // we don't see the pipe network while inside cryo.
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/get_remote_view_fullscreens(mob/user)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/impaired, 1)
|
||||
user.overlay_fullscreen("remote_view", /atom/movable/screen/fullscreen/scaled/impaired, 1)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/cryo_cell/can_crawl_through()
|
||||
return // can't ventcrawl in or out of cryo.
|
||||
|
||||
@@ -24,13 +24,16 @@
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/CtrlClick(mob/user)
|
||||
if(can_interact(user))
|
||||
on = !on
|
||||
update_icon()
|
||||
investigate_log("was turned [on ? "on" : "off"] by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/AltClick(mob/user)
|
||||
if(can_interact(user))
|
||||
volume_rate = MAX_TRANSFER_RATE
|
||||
update_icon()
|
||||
investigate_log("was set to [volume_rate] L/s by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
balloon_alert(user, "volume output set to [volume_rate] L/s")
|
||||
update_appearance()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/outlet_injector/Destroy()
|
||||
|
||||
@@ -217,16 +217,11 @@
|
||||
min_temperature = max(T0C - (initial(min_temperature) + L * 15), TCMB) //73.15K with T1 stock parts
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
if(!can_interact(user))
|
||||
return
|
||||
target_temperature = min_temperature
|
||||
to_chat(user,"<span class='notice'>You minimize the temperature on the [src].</span>")
|
||||
investigate_log("was set to [target_temperature] K by [key_name(usr)]", INVESTIGATE_ATMOS)
|
||||
message_admins("[src.name] was minimized by [ADMIN_LOOKUPFLW(usr)] at [ADMIN_COORDJMP(T)], [A]")
|
||||
return TRUE
|
||||
investigate_log("was set to [target_temperature] K by [key_name(user)]", INVESTIGATE_ATMOS)
|
||||
balloon_alert(user, "temperature reset to [target_temperature] K")
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/thermomachine/heater
|
||||
name = "heater"
|
||||
|
||||
@@ -178,6 +178,9 @@
|
||||
|
||||
var/mob/signal_sender = signal.data["user"]
|
||||
|
||||
if((("is_siphoning" in signal.data) && pump_direction == RELEASING) || (("is_pressurizing" in signal.data) && pump_direction == SIPHONING))
|
||||
return
|
||||
|
||||
if("purge" in signal.data)
|
||||
pressure_checks &= ~EXT_BOUND
|
||||
pump_direction = SIPHONING
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
var/id_tag = null
|
||||
var/scrubbing = SCRUBBING //0 = siphoning, 1 = scrubbing
|
||||
|
||||
var/filter_types = list(GAS_CO2)
|
||||
var/filter_types = list(GAS_CO2, GAS_MIASMA, GAS_GROUP_CHEMICALS)
|
||||
var/list/clean_filter_types = null
|
||||
var/volume_rate = 200
|
||||
var/widenet = 0 //is this scrubber acting on the 3x3 area around it.
|
||||
var/list/turf/adjacent_turfs = list()
|
||||
@@ -34,6 +35,16 @@
|
||||
..()
|
||||
if(!id_tag)
|
||||
id_tag = assign_uid_vents()
|
||||
generate_clean_filter_types()
|
||||
RegisterSignal(SSdcs,COMSIG_GLOB_NEW_GAS,.proc/generate_clean_filter_types)
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/generate_clean_filter_types()
|
||||
clean_filter_types = list()
|
||||
for(var/id in filter_types)
|
||||
if(id in GLOB.gas_data.groups)
|
||||
clean_filter_types += GLOB.gas_data.groups[id]
|
||||
else
|
||||
clean_filter_types += id
|
||||
|
||||
/obj/machinery/atmospherics/components/unary/vent_scrubber/Destroy()
|
||||
var/area/A = get_base_area(src)
|
||||
@@ -95,7 +106,11 @@
|
||||
|
||||
var/list/f_types = list()
|
||||
for(var/id in GLOB.gas_data.ids)
|
||||
f_types += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.names[id], "enabled" = (id in filter_types)))
|
||||
if(!(id in GLOB.gas_data.groups_by_gas))
|
||||
f_types += list(list("gas_id" = id, "gas_name" = GLOB.gas_data.names[id], "enabled" = (id in filter_types)))
|
||||
|
||||
for(var/group in GLOB.gas_data.groups)
|
||||
f_types += list(list("gas_id" = group, "gas_name" = group, "enabled" = (group in filter_types)))
|
||||
|
||||
var/datum/signal/signal = new(list(
|
||||
"tag" = id_tag,
|
||||
@@ -147,11 +162,11 @@
|
||||
var/datum/gas_mixture/environment = tile.return_air()
|
||||
var/datum/gas_mixture/air_contents = airs[1]
|
||||
|
||||
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE || !islist(filter_types))
|
||||
if(air_contents.return_pressure() >= 50*ONE_ATMOSPHERE || !islist(clean_filter_types))
|
||||
return FALSE
|
||||
|
||||
if(scrubbing & SCRUBBING)
|
||||
environment.scrub_into(air_contents, volume_rate/environment.return_volume(), filter_types)
|
||||
environment.scrub_into(air_contents, volume_rate/environment.return_volume(), clean_filter_types)
|
||||
|
||||
tile.air_update_turf()
|
||||
|
||||
@@ -205,11 +220,13 @@
|
||||
|
||||
if("toggle_filter" in signal.data)
|
||||
filter_types ^= signal.data["toggle_filter"]
|
||||
generate_clean_filter_types()
|
||||
|
||||
if("set_filters" in signal.data)
|
||||
filter_types = list()
|
||||
for(var/gas in signal.data["set_filters"])
|
||||
filter_types += gas
|
||||
generate_clean_filter_types()
|
||||
|
||||
if("init" in signal.data)
|
||||
name = signal.data["init"]
|
||||
|
||||
@@ -70,9 +70,9 @@
|
||||
|
||||
/obj/machinery/atmospherics/pipe/layer_manifold/SetInitDirections()
|
||||
switch(dir)
|
||||
if(NORTH || SOUTH)
|
||||
if(NORTH, SOUTH)
|
||||
initialize_directions = NORTH|SOUTH
|
||||
if(EAST || WEST)
|
||||
if(EAST, WEST)
|
||||
initialize_directions = EAST|WEST
|
||||
|
||||
/obj/machinery/atmospherics/pipe/layer_manifold/isConnectable(obj/machinery/atmospherics/target, given_layer)
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
var/ghost_usable = TRUE
|
||||
var/skip_reentry_check = FALSE //Skips the ghost role blacklist time for people who ghost/suicide/cryo
|
||||
|
||||
///override this to add special spawn conditions to a ghost role
|
||||
/obj/effect/mob_spawn/proc/allow_spawn(mob/user, silent = FALSE)
|
||||
return TRUE
|
||||
|
||||
//ATTACK GHOST IGNORING PARENT RETURN VALUE
|
||||
/obj/effect/mob_spawn/attack_ghost(mob/user, latejoinercalling)
|
||||
if(!SSticker.HasRoundStarted() || !loc || !ghost_usable)
|
||||
@@ -43,6 +47,8 @@
|
||||
if(jobban_isbanned(user, banType))
|
||||
to_chat(user, "<span class='warning'>You are jobanned!</span>")
|
||||
return
|
||||
if(!allow_spawn(user, silent = FALSE))
|
||||
return
|
||||
if(QDELETED(src) || QDELETED(user))
|
||||
return
|
||||
if(isobserver(user))
|
||||
|
||||
90
code/modules/balloon_alert/balloon_alert.dm
Normal file
90
code/modules/balloon_alert/balloon_alert.dm
Normal file
@@ -0,0 +1,90 @@
|
||||
#define BALLOON_TEXT_WIDTH 200
|
||||
#define BALLOON_TEXT_SPAWN_TIME (0.2 SECONDS)
|
||||
#define BALLOON_TEXT_FADE_TIME (0.1 SECONDS)
|
||||
#define BALLOON_TEXT_FULLY_VISIBLE_TIME (0.7 SECONDS)
|
||||
#define BALLOON_TEXT_TOTAL_LIFETIME(mult) (BALLOON_TEXT_SPAWN_TIME + BALLOON_TEXT_FULLY_VISIBLE_TIME*mult + BALLOON_TEXT_FADE_TIME)
|
||||
/// The increase in duration per character in seconds
|
||||
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT (0.05)
|
||||
/// The amount of characters needed before this increase takes into effect
|
||||
#define BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN 10
|
||||
|
||||
/// Creates text that will float from the atom upwards to the viewer.
|
||||
/atom/proc/balloon_alert(mob/viewer, text)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
INVOKE_ASYNC(src, .proc/balloon_alert_perform, viewer, text)
|
||||
|
||||
/// Create balloon alerts (text that floats up) to everything within range.
|
||||
/// Will only display to people who can see.
|
||||
/atom/proc/balloon_alert_to_viewers(message, self_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs)
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
var/list/hearers = get_hearers_in_view(vision_distance, src)
|
||||
hearers -= ignored_mobs
|
||||
|
||||
for (var/mob/hearer in hearers)
|
||||
if (hearer.is_blind())
|
||||
continue
|
||||
|
||||
balloon_alert(hearer, (hearer == src && self_message) || message)
|
||||
|
||||
// Do not use.
|
||||
// MeasureText blocks. I have no idea for how long.
|
||||
// I would've made the maptext_height update on its own, but I don't know
|
||||
// if this would look bad on laggy clients.
|
||||
/atom/proc/balloon_alert_perform(mob/viewer, text)
|
||||
var/client/viewer_client = viewer.client
|
||||
if (isnull(viewer_client))
|
||||
return
|
||||
|
||||
var/bound_width = world.icon_size
|
||||
if (ismovable(src))
|
||||
var/atom/movable/movable_source = src
|
||||
bound_width = movable_source.bound_width
|
||||
|
||||
var/image/balloon_alert = image(loc = get_atom_on_turf(src), layer = ABOVE_MOB_LAYER)
|
||||
balloon_alert.plane = BALLOON_CHAT_PLANE
|
||||
balloon_alert.alpha = 0
|
||||
balloon_alert.appearance_flags = RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM
|
||||
balloon_alert.maptext = MAPTEXT("<span style='text-align: center; -dm-text-outline: 1px #0005'>[text]</span>")
|
||||
balloon_alert.maptext_x = (BALLOON_TEXT_WIDTH - bound_width) * -0.5
|
||||
balloon_alert.maptext_height = WXH_TO_HEIGHT(viewer_client?.MeasureText(text, null, BALLOON_TEXT_WIDTH))
|
||||
balloon_alert.maptext_width = BALLOON_TEXT_WIDTH
|
||||
|
||||
viewer_client?.images += balloon_alert
|
||||
|
||||
var/duration_mult = 1
|
||||
var/duration_length = length(text) - BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN
|
||||
|
||||
if(duration_length > 0)
|
||||
duration_mult += duration_length*BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT
|
||||
|
||||
animate(
|
||||
balloon_alert,
|
||||
pixel_y = world.icon_size * 1.2,
|
||||
time = BALLOON_TEXT_TOTAL_LIFETIME(1),
|
||||
easing = SINE_EASING | EASE_OUT,
|
||||
)
|
||||
|
||||
animate(
|
||||
alpha = 255,
|
||||
time = BALLOON_TEXT_SPAWN_TIME,
|
||||
easing = CUBIC_EASING | EASE_OUT,
|
||||
flags = ANIMATION_PARALLEL,
|
||||
)
|
||||
|
||||
animate(
|
||||
alpha = 0,
|
||||
time = BALLOON_TEXT_FULLY_VISIBLE_TIME*duration_mult,
|
||||
easing = CUBIC_EASING | EASE_IN,
|
||||
)
|
||||
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/remove_image_from_client, balloon_alert, viewer_client), BALLOON_TEXT_TOTAL_LIFETIME(duration_mult))
|
||||
|
||||
#undef BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MIN
|
||||
#undef BALLOON_TEXT_CHAR_LIFETIME_INCREASE_MULT
|
||||
#undef BALLOON_TEXT_FADE_TIME
|
||||
#undef BALLOON_TEXT_FULLY_VISIBLE_TIME
|
||||
#undef BALLOON_TEXT_SPAWN_TIME
|
||||
#undef BALLOON_TEXT_TOTAL_LIFETIME
|
||||
#undef BALLOON_TEXT_WIDTH
|
||||
@@ -52,7 +52,7 @@
|
||||
desc = "Packs of tools waiting to be used for repairing. Contains a tool and engineering vending machine refill. Requires CE access."
|
||||
cost = 5500 //Powerfull
|
||||
access = ACCESS_CE
|
||||
contains = list(/obj/item/vending_refill/tool,
|
||||
contains = list(/obj/item/vending_refill/youtool,
|
||||
/obj/item/vending_refill/engivend)
|
||||
crate_name = "engineering supply crate"
|
||||
crate_type = /obj/structure/closet/crate/secure/engineering
|
||||
|
||||
@@ -648,7 +648,7 @@
|
||||
desc = "This disk provides a firmware update to the Express Supply Console, granting the use of Nanotrasen's Bluespace Drop Pods to the supply department."
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "cargodisk"
|
||||
// inhand_icon_state = "card-id"
|
||||
// item_state = "card-id"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
// let's not.
|
||||
|
||||
@@ -4,6 +4,16 @@
|
||||
//BLACK MAGIC THINGS//
|
||||
//////////////////////
|
||||
parent_type = /datum
|
||||
|
||||
///////////////
|
||||
// Rendering //
|
||||
///////////////
|
||||
|
||||
/// Click catcher
|
||||
var/atom/movable/screen/click_catcher/click_catcher
|
||||
/// Parallax holder
|
||||
var/datum/parallax_holder/parallax_holder
|
||||
|
||||
////////////////
|
||||
//ADMIN THINGS//
|
||||
////////////////
|
||||
@@ -34,6 +44,9 @@
|
||||
var/last_move = 0
|
||||
var/area = null
|
||||
|
||||
/// Timers are now handled by clients, not by doing a mess on the item and multiple people overwriting a single timer on the object, have fun.
|
||||
var/tip_timer = null
|
||||
|
||||
/// Last time we Click()ed. No clicking twice in one tick!
|
||||
var/last_click = 0
|
||||
|
||||
@@ -150,20 +163,6 @@
|
||||
///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns
|
||||
var/cryo_warned = -5 MINUTES
|
||||
|
||||
var/list/parallax_layers
|
||||
var/list/parallax_layers_cached
|
||||
var/atom/movable/movingmob
|
||||
var/turf/previous_turf
|
||||
///world.time of when we can state animate()ing parallax again
|
||||
var/dont_animate_parallax
|
||||
///world.time of last parallax update
|
||||
var/last_parallax_shift
|
||||
///ds between parallax updates
|
||||
var/parallax_throttle = 0
|
||||
var/parallax_movedir = 0
|
||||
var/parallax_layers_max = 3
|
||||
var/parallax_animate_timer
|
||||
|
||||
/**
|
||||
* Assoc list with all the active maps - when a screen obj is added to
|
||||
* a map, it's put in here as well.
|
||||
|
||||
@@ -79,19 +79,16 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
|
||||
// Tgui Topic middleware
|
||||
if(tgui_Topic(href_list))
|
||||
if(CONFIG_GET(flag/emergency_tgui_logging))
|
||||
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
|
||||
return
|
||||
if(href_list["reload_tguipanel"])
|
||||
nuke_chat()
|
||||
if(href_list["reload_statbrowser"])
|
||||
src << browse(file('html/statbrowser.html'), "window=statbrowser")
|
||||
// Log all hrefs
|
||||
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
|
||||
|
||||
last_activity = world.time
|
||||
|
||||
//Logs all hrefs
|
||||
log_href("[src] (usr:[usr]\[[COORD(usr)]\]) : [hsrc ? "[hsrc] " : ""][href]")
|
||||
|
||||
//byond bug ID:2256651
|
||||
if (asset_cache_job && (asset_cache_job in completed_asset_jobs))
|
||||
to_chat(src, "<span class='danger'>An error has been detected in how your client is receiving resources. Attempting to correct.... (If you keep seeing these messages you might want to close byond and reconnect)</span>")
|
||||
@@ -357,13 +354,19 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
return
|
||||
|
||||
// Initialize tgui panel
|
||||
tgui_panel.initialize()
|
||||
src << browse(file('html/statbrowser.html'), "window=statbrowser")
|
||||
addtimer(CALLBACK(src, .proc/check_panel_loaded), 30 SECONDS)
|
||||
tgui_panel.initialize()
|
||||
|
||||
if(alert_mob_dupe_login)
|
||||
spawn()
|
||||
alert(mob, "You have logged in already with another key this round, please log out of this one NOW or risk being banned!")
|
||||
if(alert_mob_dupe_login && !holder)
|
||||
var/dupe_login_message = "Your ComputerID has already logged in with another key this round, please log out of this one NOW or risk being banned!"
|
||||
// if (alert_admin_multikey)
|
||||
// dupe_login_message += "\nAdmins have been informed."
|
||||
// message_admins(span_danger("<B>MULTIKEYING: </B></span><span class='notice'>[key_name_admin(src)] has a matching CID+IP with another player and is clearly multikeying. They have been warned to leave the server or risk getting banned."))
|
||||
// log_admin_private("MULTIKEYING: [key_name(src)] has a matching CID+IP with another player and is clearly multikeying. They have been warned to leave the server or risk getting banned.")
|
||||
spawn(0.5 SECONDS) //needs to run during world init, do not convert to add timer
|
||||
alert(mob, dupe_login_message) //players get banned if they don't see this message, do not convert to tgui_alert (or even tg_alert) please.
|
||||
to_chat(mob, span_danger(dupe_login_message))
|
||||
|
||||
connection_time = world.time
|
||||
connection_realtime = world.realtime
|
||||
@@ -441,8 +444,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
|
||||
send_resources()
|
||||
|
||||
generate_clickcatcher()
|
||||
apply_clickcatcher()
|
||||
update_clickcatcher()
|
||||
|
||||
if(prefs.lastchangelog != GLOB.changelog_hash) //bolds the changelog button on the interface so we know there are updates.
|
||||
to_chat(src, "<span class='info'>You have unread updates in the changelog.</span>")
|
||||
@@ -532,9 +534,6 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
|
||||
send2adminchat("Server", "[cheesy_message] (No admins online)")
|
||||
QDEL_LIST_ASSOC_VAL(char_render_holders)
|
||||
if(movingmob != null)
|
||||
movingmob.client_mobs_in_contents -= mob
|
||||
UNSETEMPTY(movingmob.client_mobs_in_contents)
|
||||
// seen_messages = null
|
||||
Master.UpdateTickRate()
|
||||
. = ..() //Even though we're going to be hard deleted there are still some things that want to know the destroy is happening
|
||||
@@ -1011,7 +1010,8 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
var/list/old_view = getviewsize(view)
|
||||
view = new_size
|
||||
var/list/actualview = getviewsize(view)
|
||||
apply_clickcatcher(actualview)
|
||||
update_clickcatcher()
|
||||
parallax_holder.Reset()
|
||||
mob.reload_fullscreen()
|
||||
if (isliving(mob))
|
||||
var/mob/living/M = mob
|
||||
@@ -1020,33 +1020,31 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
addtimer(CALLBACK(src,.verb/fit_viewport,10)) //Delayed to avoid wingets from Login calls.
|
||||
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_CHANGE_VIEW, src, old_view, actualview)
|
||||
|
||||
/client/proc/generate_clickcatcher()
|
||||
if(!void)
|
||||
void = new()
|
||||
screen += void
|
||||
|
||||
/client/proc/apply_clickcatcher(list/actualview)
|
||||
generate_clickcatcher()
|
||||
if(!actualview)
|
||||
actualview = getviewsize(view)
|
||||
void.UpdateGreed(actualview[1],actualview[2])
|
||||
|
||||
/client/proc/AnnouncePR(announcement)
|
||||
if(prefs && prefs.chat_toggles & CHAT_PULLR)
|
||||
to_chat(src, announcement)
|
||||
|
||||
/client/proc/show_character_previews(mutable_appearance/MA)
|
||||
/client/proc/show_character_previews(mutable_appearance/source)
|
||||
LAZYINITLIST(char_render_holders)
|
||||
if(!LAZYLEN(char_render_holders))
|
||||
for(var/plane_master_path as anything in subtypesof(/atom/movable/screen/plane_master))
|
||||
var/atom/movable/screen/plane_master/plane_master = new plane_master_path()
|
||||
char_render_holders["plane_master-[plane_master.plane]"] = plane_master
|
||||
plane_master.backdrop(mob)
|
||||
screen |= plane_master
|
||||
plane_master.screen_loc = "character_preview_map:0,CENTER"
|
||||
|
||||
var/pos = 0
|
||||
for(var/D in GLOB.cardinals)
|
||||
for(var/dir in GLOB.cardinals)
|
||||
pos++
|
||||
var/atom/movable/screen/O = LAZYACCESS(char_render_holders, "[D]")
|
||||
if(!O)
|
||||
O = new
|
||||
LAZYSET(char_render_holders, "[D]", O)
|
||||
screen |= O
|
||||
O.appearance = MA
|
||||
O.dir = D
|
||||
O.screen_loc = "character_preview_map:0,[pos]"
|
||||
var/atom/movable/screen/preview = char_render_holders["preview-[dir]"]
|
||||
if(!preview)
|
||||
preview = new
|
||||
char_render_holders["preview-[dir]"] = preview
|
||||
screen |= preview
|
||||
preview.appearance = source
|
||||
preview.dir = dir
|
||||
preview.screen_loc = "character_preview_map:0,[pos]"
|
||||
|
||||
/client/proc/clear_character_previews()
|
||||
for(var/index in char_render_holders)
|
||||
@@ -1082,8 +1080,14 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if(IsAdminAdvancedProcCall())
|
||||
return
|
||||
var/list/verblist = list()
|
||||
verb_tabs.Cut()
|
||||
for(var/thing in (verbs + mob?.verbs))
|
||||
var/list/verbstoprocess = verbs.Copy()
|
||||
if(mob)
|
||||
verbstoprocess += mob.verbs
|
||||
for(var/AM in mob.contents)
|
||||
var/atom/movable/thing = AM
|
||||
verbstoprocess += thing.verbs
|
||||
panel_tabs.Cut() // panel_tabs get reset in init_verbs on JS side anyway
|
||||
for(var/thing in verbstoprocess)
|
||||
var/procpath/verb_to_init = thing
|
||||
if(!verb_to_init)
|
||||
continue
|
||||
@@ -1091,9 +1095,9 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
continue
|
||||
if(!istext(verb_to_init.category))
|
||||
continue
|
||||
verb_tabs |= verb_to_init.category
|
||||
panel_tabs |= verb_to_init.category
|
||||
verblist[++verblist.len] = list(verb_to_init.category, verb_to_init.name)
|
||||
src << output("[url_encode(json_encode(verb_tabs))];[url_encode(json_encode(verblist))]", "statbrowser:init_verbs")
|
||||
src << output("[url_encode(json_encode(panel_tabs))];[url_encode(json_encode(verblist))]", "statbrowser:init_verbs")
|
||||
|
||||
/client/proc/check_panel_loaded()
|
||||
if(statbrowser_ready)
|
||||
|
||||
@@ -61,7 +61,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
var/UI_style = null
|
||||
var/outline_enabled = TRUE
|
||||
var/outline_color = COLOR_BLUE_GRAY
|
||||
var/outline_color = COLOR_THEME_MIDNIGHT
|
||||
var/buttons_locked = FALSE
|
||||
var/hotkeys = FALSE
|
||||
|
||||
@@ -164,13 +164,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
var/clientfps = 0
|
||||
|
||||
var/parallax
|
||||
var/parallax = PARALLAX_INSANE
|
||||
|
||||
var/ambientocclusion = TRUE
|
||||
///Should we automatically fit the viewport?
|
||||
var/auto_fit_viewport = FALSE
|
||||
///Should we be in the widescreen mode set by the config?
|
||||
var/widescreenpref = TRUE
|
||||
///Strip menu style
|
||||
var/long_strip_menu = FALSE
|
||||
///What size should pixels be displayed as? 0 is strech to fit
|
||||
var/pixel_size = 0
|
||||
///What scaling method should we use?
|
||||
@@ -785,7 +787,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<h2>General Settings</h2>"
|
||||
dat += "<b>UI Style:</b> <a href='?_src_=prefs;task=input;preference=ui'>[UI_style]</a><br>"
|
||||
dat += "<b>Outline:</b> <a href='?_src_=prefs;preference=outline_enabled'>[outline_enabled ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Outline Color:</b> <span style='border:1px solid #161616; background-color: [outline_color];'> </span> <a href='?_src_=prefs;preference=outline_color'>Change</a><BR>"
|
||||
dat += "<b>Outline Color:</b> [outline_color ? "<span style='border:1px solid #161616; background-color: [outline_color];'>" : "Theme-based (null)"] </span> <a href='?_src_=prefs;preference=outline_color'>Change</a><BR>"
|
||||
dat += "<b>tgui Monitors:</b> <a href='?_src_=prefs;preference=tgui_lock'>[(tgui_lock) ? "Primary" : "All"]</a><br>"
|
||||
dat += "<b>tgui Style:</b> <a href='?_src_=prefs;preference=tgui_fancy'>[(tgui_fancy) ? "Fancy" : "No Frills"]</a><br>"
|
||||
dat += "<b>Show Runechat Chat Bubbles:</b> <a href='?_src_=prefs;preference=chat_on_map'>[chat_on_map ? "Enabled" : "Disabled"]</a><br>"
|
||||
@@ -829,6 +831,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat +="<td width='300px' height='300px' valign='top'>"
|
||||
dat += "<h2>Citadel Preferences</h2>" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe.
|
||||
dat += "<b>Widescreen:</b> <a href='?_src_=prefs;preference=widescreenpref'>[widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]</a><br>"
|
||||
dat += "<b>Long strip menu:</b> <a href='?_src_=prefs;preference=long_strip_menu'>[long_strip_menu ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Auto stand:</b> <a href='?_src_=prefs;preference=autostand'>[autostand ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Auto OOC:</b> <a href='?_src_=prefs;preference=auto_ooc'>[auto_ooc ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Force Slot Storage HUD:</b> <a href='?_src_=prefs;preference=no_tetris_storage'>[no_tetris_storage ? "Enabled" : "Disabled"]</a><br>"
|
||||
@@ -2591,6 +2594,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("widescreenpref")
|
||||
widescreenpref = !widescreenpref
|
||||
user.client.view_size.setDefault(getScreenSize(widescreenpref))
|
||||
if("long_strip_menu")
|
||||
long_strip_menu = !long_strip_menu
|
||||
|
||||
if("pixel_size")
|
||||
switch(pixel_size)
|
||||
@@ -2739,8 +2744,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
outline_enabled = !outline_enabled
|
||||
if("outline_color")
|
||||
var/pickedOutlineColor = input(user, "Choose your outline color.", "General Preference", outline_color) as color|null
|
||||
if(pickedOutlineColor)
|
||||
outline_color = pickedOutlineColor
|
||||
if(pickedOutlineColor != pickedOutlineColor)
|
||||
outline_color = pickedOutlineColor // nullable
|
||||
if("tgui_lock")
|
||||
tgui_lock = !tgui_lock
|
||||
if("winflash")
|
||||
@@ -2811,14 +2816,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
toggles ^= MIDROUND_ANTAG
|
||||
|
||||
if("parallaxup")
|
||||
parallax = WRAP(parallax + 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1)
|
||||
if (parent && parent.mob && parent.mob.hud_used)
|
||||
parent.mob.hud_used.update_parallax_pref(parent.mob)
|
||||
parallax = WRAP(parallax + 1, PARALLAX_DISABLE, PARALLAX_INSANE + 1)
|
||||
parent?.parallax_holder?.Reset()
|
||||
|
||||
if("parallaxdown")
|
||||
parallax = WRAP(parallax - 1, PARALLAX_INSANE, PARALLAX_DISABLE + 1)
|
||||
if (parent && parent.mob && parent.mob.hud_used)
|
||||
parent.mob.hud_used.update_parallax_pref(parent.mob)
|
||||
parallax = WRAP(parallax - 1, PARALLAX_DISABLE, PARALLAX_INSANE + 1)
|
||||
parent?.parallax_holder?.Reset()
|
||||
|
||||
// Citadel edit - Prefs don't work outside of this. :c
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// You do not need to raise this if you are adding new values that have sane defaults.
|
||||
// Only raise this value when changing the meaning/format/name/layout of an existing value
|
||||
// where you would want the updater procs below to run
|
||||
#define SAVEFILE_VERSION_MAX 52
|
||||
#define SAVEFILE_VERSION_MAX 53
|
||||
|
||||
/*
|
||||
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
|
||||
@@ -47,7 +47,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
addtimer(CALLBACK(src, .proc/force_reset_keybindings), 30) //No mob available when this is run, timer allows user choice.
|
||||
if(current_version < 30)
|
||||
outline_enabled = TRUE
|
||||
outline_color = COLOR_BLUE_GRAY
|
||||
outline_color = COLOR_THEME_MIDNIGHT
|
||||
|
||||
/datum/preferences/proc/update_character(current_version, savefile/S)
|
||||
if(current_version < 19)
|
||||
@@ -343,6 +343,9 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
marking_list += list(list(part, old_marking_value, copied_color_list))
|
||||
features["mam_body_markings"] = marking_list
|
||||
|
||||
if(current_version < 53)
|
||||
parallax = PARALLAX_INSANE
|
||||
|
||||
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
|
||||
if(!ckey)
|
||||
return
|
||||
@@ -410,6 +413,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["ambientocclusion"] >> ambientocclusion
|
||||
S["auto_fit_viewport"] >> auto_fit_viewport
|
||||
S["widescreenpref"] >> widescreenpref
|
||||
S["long_strip_menu"] >> long_strip_menu
|
||||
S["pixel_size"] >> pixel_size
|
||||
S["scaling_method"] >> scaling_method
|
||||
S["hud_toggle_flash"] >> hud_toggle_flash
|
||||
@@ -468,10 +472,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
|
||||
toggles = sanitize_integer(toggles, 0, 16777215, initial(toggles))
|
||||
clientfps = sanitize_integer(clientfps, 0, 1000, 0)
|
||||
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
|
||||
parallax = sanitize_integer(parallax, PARALLAX_DISABLE, PARALLAX_INSANE, null)
|
||||
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
|
||||
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
|
||||
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
|
||||
long_strip_menu = sanitize_integer(long_strip_menu, 0, 1, initial(long_strip_menu))
|
||||
pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size))
|
||||
scaling_method = sanitize_text(scaling_method, initial(scaling_method))
|
||||
hud_toggle_flash = sanitize_integer(hud_toggle_flash, 0, 1, initial(hud_toggle_flash))
|
||||
@@ -604,6 +609,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["damagescreenshake"], damagescreenshake)
|
||||
WRITE_FILE(S["arousable"], arousable)
|
||||
WRITE_FILE(S["widescreenpref"], widescreenpref)
|
||||
WRITE_FILE(S["long_strip_menu"], long_strip_menu)
|
||||
WRITE_FILE(S["autostand"], autostand)
|
||||
WRITE_FILE(S["cit_toggles"], cit_toggles)
|
||||
WRITE_FILE(S["preferred_chaos"], preferred_chaos)
|
||||
|
||||
@@ -18,3 +18,12 @@
|
||||
prefs.tip_delay = max(indelay, 0.01)
|
||||
prefs.save_preferences()
|
||||
to_chat(usr, "<span class='danger'>Tooltip delay set to [indelay] milliseconds.</span>")
|
||||
|
||||
/client/verb/toggle_hover_outline()
|
||||
set name = "Toggle hover outline"
|
||||
set desc = "Toggles hover-over item outline"
|
||||
set category = "Preferences"
|
||||
|
||||
prefs.outline_enabled = !prefs.outline_enabled
|
||||
prefs.save_preferences()
|
||||
to_chat(usr, "<span class='danger'>Item outline [prefs.outline_enabled ? "en" : "dis"]abled.</span>")
|
||||
|
||||
@@ -443,7 +443,7 @@ BLIND // can't see anything
|
||||
..()
|
||||
|
||||
//Species-restricted clothing check. - Thanks Oraclestation, BS13, /vg/station etc.
|
||||
/obj/item/clothing/mob_can_equip(mob/M, slot, disable_warning = TRUE)
|
||||
/obj/item/clothing/mob_can_equip(M, equipper, slot, disable_warning = TRUE, bypass_equip_delay_self)
|
||||
|
||||
//if we can't equip the item anyway, don't bother with species_restricted (also cuts down on spam)
|
||||
if(!..())
|
||||
|
||||
@@ -581,3 +581,14 @@
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.update_sight()
|
||||
|
||||
/obj/item/clothing/glasses/osi
|
||||
name = "O.S.I. Sunglasses"
|
||||
desc = "There's no such thing as good news! Just bad news and... weird news.."
|
||||
icon_state = "osi_glasses"
|
||||
item_state = "osi_glasses"
|
||||
|
||||
/obj/item/clothing/glasses/phantom
|
||||
name = "Phantom Thief Mask"
|
||||
desc = "Lookin' cool."
|
||||
icon_state = "phantom_glasses"
|
||||
item_state = "phantom_glasses"
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
desc = "A heads-up display that provides important info in (almost) real time."
|
||||
flags_1 = null //doesn't protect eyes because it's a monocle, duh
|
||||
var/hud_type = null
|
||||
///Used for topic calls. Just because you have a HUD display doesn't mean you should be able to interact with stuff.
|
||||
var/hud_trait = null
|
||||
|
||||
/obj/item/clothing/glasses/hud/CheckParts(list/parts_list)
|
||||
. = ..()
|
||||
@@ -290,3 +292,16 @@
|
||||
if(. & EMP_PROTECT_SELF)
|
||||
return
|
||||
thermal_overload()
|
||||
|
||||
/obj/item/clothing/glasses/hud/spacecop
|
||||
name = "police aviators"
|
||||
desc = "For thinking you look cool while brutalizing protestors and minorities."
|
||||
icon_state = "bigsunglasses"
|
||||
hud_type = ANTAG_HUD_GANGSTER
|
||||
|
||||
/obj/item/clothing/glasses/hud/spacecop/hidden // for the undercover cop
|
||||
name = "sunglasses"
|
||||
desc = "These sunglasses are special, and let you view potential criminals."
|
||||
icon_state = "sun"
|
||||
item_state = "sunglasses"
|
||||
|
||||
|
||||
@@ -133,3 +133,9 @@
|
||||
base_knockdown = 1.75 SECONDS
|
||||
min_distance = 2
|
||||
skill_mod = -1
|
||||
|
||||
/obj/item/clothing/gloves/tackler/football
|
||||
name = "football gloves"
|
||||
desc = "Gloves for football players! Teaches them how to tackle like a pro."
|
||||
icon_state = "tackle_gloves"
|
||||
item_state = "tackle_gloves"
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
armor = list("melee" = 30, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
strip_delay = 80
|
||||
|
||||
/obj/item/clothing/head/spacepolice
|
||||
name = "space police cap"
|
||||
desc = "A blue cap for patrolling the daily beat."
|
||||
icon_state = "policecap_families"
|
||||
item_state = "policecap_families"
|
||||
|
||||
/obj/item/clothing/head/powdered_wig
|
||||
name = "powdered wig"
|
||||
desc = "A powdered wig."
|
||||
@@ -488,3 +494,10 @@
|
||||
desc = "This will scare them. All will know my power."
|
||||
icon_state = "human_leather"
|
||||
item_state = "human_leather"
|
||||
|
||||
/obj/item/clothing/head/jackbros
|
||||
name = "frosty hat"
|
||||
desc = "Hee-ho!"
|
||||
icon_state = "JackFrostHat"
|
||||
item_state = "JackFrostHat"
|
||||
|
||||
|
||||
@@ -90,23 +90,34 @@
|
||||
item_state = "ushankadown"
|
||||
alternate_screams = list('sound/voice/human/cyka1.ogg', 'sound/voice/human/cheekibreeki.ogg')
|
||||
flags_inv = HIDEEARS|HIDEHAIR
|
||||
var/earflaps = 1
|
||||
var/earflaps = TRUE
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
|
||||
///Sprite visible when the ushanka flaps are folded up.
|
||||
var/upsprite = "ushankaup"
|
||||
///Sprite visible when the ushanka flaps are folded down.
|
||||
var/downsprite = "ushankadown"
|
||||
|
||||
dog_fashion = /datum/dog_fashion/head/ushanka
|
||||
|
||||
/obj/item/clothing/head/ushanka/attack_self(mob/user)
|
||||
if(earflaps)
|
||||
src.icon_state = "ushankaup"
|
||||
src.item_state = "ushankaup"
|
||||
earflaps = 0
|
||||
icon_state = upsprite
|
||||
item_state = upsprite
|
||||
to_chat(user, "<span class='notice'>You raise the ear flaps on the ushanka.</span>")
|
||||
else
|
||||
src.icon_state = "ushankadown"
|
||||
src.item_state = "ushankadown"
|
||||
earflaps = 1
|
||||
icon_state = downsprite
|
||||
item_state = downsprite
|
||||
to_chat(user, "<span class='notice'>You lower the ear flaps on the ushanka.</span>")
|
||||
earflaps = !earflaps
|
||||
|
||||
/obj/item/clothing/head/ushanka/soviet
|
||||
name = "soviet ushanka"
|
||||
desc = "For the union!"
|
||||
icon_state = "sovietushankadown"
|
||||
item_state = "sovietushankadown"
|
||||
upsprite = "sovietushankaup"
|
||||
downsprite = "sovietushankadown"
|
||||
|
||||
/*
|
||||
* Pumpkin head
|
||||
@@ -315,3 +326,55 @@
|
||||
|
||||
/datum/component/storage/concrete/pockets/tiny/spacenam
|
||||
attack_hand_interact = TRUE //So you can actually see what you stuff in there
|
||||
|
||||
//families
|
||||
/obj/item/clothing/head/irs
|
||||
name = "internal revenue service cap"
|
||||
icon_state = "irs_hat"
|
||||
item_state = "irs_hat"
|
||||
|
||||
/obj/item/clothing/head/pg
|
||||
name = "powder ganger beanie"
|
||||
icon_state = "pg_hat"
|
||||
item_state = "pg_hat"
|
||||
|
||||
/obj/item/clothing/head/tmc
|
||||
name = "Lost M.C. bandana"
|
||||
icon_state = "tmc_hat"
|
||||
item_state = "tmc_hat"
|
||||
|
||||
/obj/item/clothing/head/deckers
|
||||
name = "Decker headphones"
|
||||
icon_state = "decker_hat"
|
||||
item_state = "decker_hat"
|
||||
|
||||
/obj/item/clothing/head/morningstar
|
||||
name = "Morningstar beret"
|
||||
icon_state = "morningstar_hat"
|
||||
item_state = "morningstar_hat"
|
||||
|
||||
/obj/item/clothing/head/saints
|
||||
name = "Saints hat"
|
||||
icon_state = "saints_hat"
|
||||
item_state = "saints_hat"
|
||||
|
||||
/obj/item/clothing/head/allies
|
||||
name = "allies helmet"
|
||||
icon_state = "allies_helmet"
|
||||
item_state = "allies_helmet"
|
||||
|
||||
/obj/item/clothing/head/yuri
|
||||
name = "yuri initiate helmet"
|
||||
icon_state = "yuri_helmet"
|
||||
item_state = "yuri_helmet"
|
||||
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT
|
||||
|
||||
/obj/item/clothing/head/sybil_slickers
|
||||
name = "sybil slickers helmet"
|
||||
icon_state = "football_helmet_blue"
|
||||
item_state = "football_helmet_blue"
|
||||
|
||||
/obj/item/clothing/head/basil_boys
|
||||
name = "basil boys helmet"
|
||||
icon_state = "football_helmet_red"
|
||||
item_state = "football_helmet_red"
|
||||
|
||||
@@ -119,6 +119,23 @@
|
||||
to_chat(user, "<span class='notice'>Your Clown Mask has now morphed into [choice], all praise the Honkmother!</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/mask/gas/clown_hat_polychromic
|
||||
name = "polychromic clown wig and mask"
|
||||
desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
|
||||
clothing_flags = ALLOWINTERNALS
|
||||
icon_state = "clown"
|
||||
item_state = "clown_hat"
|
||||
dye_color = "clown"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
flags_cover = MASKCOVERSEYES
|
||||
resistance_flags = FLAMMABLE
|
||||
dog_fashion = /datum/dog_fashion/head/clown
|
||||
var/list/poly_colors = list("#FF8000", "#FFFFFF", "#FF0000", "#0000FF", "#FFFF00")
|
||||
|
||||
/obj/item/clothing/mask/gas/clown_hat_polychromic/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/polychromic, poly_colors, 5, names = list("Hair", "Frame", "Mouth", "Eyes", "Markings"))
|
||||
|
||||
/obj/item/clothing/mask/gas/clown_hat/sexy
|
||||
name = "sexy-clown wig and mask"
|
||||
desc = "A feminine clown mask for the dabbling crossdressers or female entertainers."
|
||||
@@ -273,3 +290,11 @@
|
||||
item_state = "hunter"
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
flags_inv = HIDEFACIALHAIR|HIDEFACE|HIDEEYES|HIDEEARS|HIDEHAIR
|
||||
|
||||
/obj/item/clothing/mask/gas/driscoll
|
||||
name = "driscoll mask"
|
||||
desc = "Great for train hijackings. Works like a normal full face gas mask, but won't conceal your identity."
|
||||
icon_state = "driscoll_mask"
|
||||
flags_inv = HIDEFACIALHAIR
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
item_state = "driscoll_mask"
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
worn_y_dimension = world.icon_size
|
||||
|
||||
/obj/item/clothing/shoes/dropped(mob/user)
|
||||
if(our_alert && (our_alert.mob_viewer == user))
|
||||
if(our_alert && (our_alert.owner == user))
|
||||
user.clear_alert("shoealert")
|
||||
if(offset && equipped_before_drop)
|
||||
restore_offsets(user)
|
||||
|
||||
@@ -267,9 +267,15 @@
|
||||
desc = "A specialized pair of combat boots with a built-in propulsion system for rapid foward movement."
|
||||
icon_state = "jetboots"
|
||||
resistance_flags = FIRE_PROOF
|
||||
cold_protection = FEET|LEGS
|
||||
min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT
|
||||
heat_protection = FEET|LEGS
|
||||
max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
actions_types = list(/datum/action/item_action/bhop)
|
||||
permeability_coefficient = 0.05
|
||||
unique_reskin = list("Explorer" = "miningjet",
|
||||
"Jackboot" = "jetboots")
|
||||
var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles
|
||||
var/jumpspeed = 3
|
||||
var/recharging_rate = 60 //default 6 seconds between each dash
|
||||
@@ -417,12 +423,16 @@
|
||||
name = "cowboy boots"
|
||||
desc = "A standard pair of brown cowboy boots."
|
||||
icon_state = "cowboyboots"
|
||||
item_state = "cowboyboots"
|
||||
permeability_coefficient = 0.05 //these are quite tall
|
||||
pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes
|
||||
can_be_tied = FALSE
|
||||
|
||||
/obj/item/clothing/shoes/cowboyboots/black
|
||||
name = "black cowboy boots"
|
||||
desc = "A pair of black cowboy boots, pretty easy to scuff up."
|
||||
icon_state = "cowboyboots_black"
|
||||
item_state = "cowboyboots_black"
|
||||
|
||||
/obj/item/clothing/shoes/wallwalkers
|
||||
name = "wall walking boots"
|
||||
@@ -541,3 +551,59 @@
|
||||
desc = "They got me for my foams!"
|
||||
icon_state = "SwagShoes"
|
||||
item_state = "SwagShoes"
|
||||
|
||||
/obj/item/clothing/shoes/phantom
|
||||
name = "phantom shoes"
|
||||
desc = "Excellent for when you need to do cool flashy flips."
|
||||
icon_state = "phantom_shoes"
|
||||
item_state = "phantom_shoes"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/shoes/saints
|
||||
name = "saints sneakers"
|
||||
desc = "Officially branded Saints sneakers. Incredibly valuable!"
|
||||
icon_state = "saints_shoes"
|
||||
item_state = "saints_shoes"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/shoes/morningstar
|
||||
name = "morningstar boots"
|
||||
desc = "The most expensive boots on this station. Wearing them dropped the value by about 50%."
|
||||
icon_state = "morningstar_shoes"
|
||||
item_state = "morningstar_shoes"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/shoes/deckers
|
||||
name = "deckers rollerskates"
|
||||
desc = "t3h c00L3st sh03z j00'LL 3v3r f1nd."
|
||||
icon_state = "decker_shoes"
|
||||
item_state = "decker_shoes"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/shoes/sybil_slickers
|
||||
name = "sybil slickers shoes"
|
||||
desc = "FOOTBALL! YEAH!"
|
||||
icon_state = "sneakers_blue"
|
||||
item_state = "sneakers_blue"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/shoes/basil_boys
|
||||
name = "basil boys shoes"
|
||||
desc = "FOOTBALL! YEAH!"
|
||||
icon_state = "sneakers_red"
|
||||
item_state = "sneakers_red"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/shoes/yakuza
|
||||
name = "tojo clan shoes"
|
||||
desc = "Steel-toed and intimidating."
|
||||
icon_state = "MajimaShoes"
|
||||
item_state = "MajimaShoes_worn"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/shoes/jackbros
|
||||
name = "frosty boots"
|
||||
desc = "For when you're stepping on up to the plate."
|
||||
icon_state = "JackFrostShoes"
|
||||
item_state = "JackFrostShoes_worn"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
@@ -20,12 +20,16 @@
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/Initialize()
|
||||
. = ..()
|
||||
soundloop = new(list(), FALSE, TRUE)
|
||||
soundloop = new(src, FALSE, TRUE)
|
||||
soundloop.volume = 5
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/Destroy()
|
||||
. = ..()
|
||||
if(!QDELETED(suit))
|
||||
qdel(suit)
|
||||
suit = null
|
||||
QDEL_NULL(soundloop)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/attack_self(mob/user)
|
||||
@@ -633,7 +637,7 @@
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/clown
|
||||
mutantrace_variation = STYLE_DIGITIGRADE
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, slot)
|
||||
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, equipper, slot, disable_warning, bypass_equip_delay_self)
|
||||
if(!..() || !ishuman(M))
|
||||
return FALSE
|
||||
if(M.mind && HAS_TRAIT(M.mind, TRAIT_CLOWN_MENTALITY))
|
||||
|
||||
@@ -234,7 +234,6 @@ Contains:
|
||||
icon_state = "ert_medical"
|
||||
item_state = "ert_medical"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/med
|
||||
species_exception = list(/datum/species/angel)
|
||||
|
||||
//Red alert ERT
|
||||
|
||||
@@ -296,7 +295,6 @@ Contains:
|
||||
icon_state = "ert_medical-alert"
|
||||
item_state = "ert_medical-alert"
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert/med
|
||||
species_exception = list(/datum/species/angel)
|
||||
|
||||
/obj/item/clothing/suit/space/eva
|
||||
name = "EVA suit"
|
||||
|
||||
@@ -1241,3 +1241,132 @@
|
||||
desc = "It looks like someone dragged this out of a muddy lake."
|
||||
icon_state = "bomberalt"
|
||||
item_state = "bomberalt"
|
||||
|
||||
/obj/item/clothing/suit/driscoll
|
||||
name = "driscoll poncho"
|
||||
desc = "Keeping you warm in the harsh cold of space."
|
||||
icon_state = "driscoll_suit"
|
||||
item_state = "driscoll_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/irs
|
||||
name = "internal revenue service jacket"
|
||||
desc = "I'm crazy enough to take on The Owl, but the IRS? Nooo thank you!"
|
||||
icon_state = "irs_suit"
|
||||
item_state = "irs_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/osi
|
||||
name = "\improper O.S.I. body armor"
|
||||
desc = "You're beyond good and evil, super man. You work for the government. And you're a tool, boy, a tool! Built for a single purpose by the United States of shut your third fucking damn eye for a fucking reason! You can't teach a hammer to love nails, son. That dog don't hunt!"
|
||||
icon_state = "osi_suit"
|
||||
item_state = "osi_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/tmc
|
||||
name = "\improper Lost M.C. cut"
|
||||
desc = "Making sure everyone knows you're in the best biker gang this side of Alderney."
|
||||
icon_state = "tmc_suit"
|
||||
item_state = "tmc_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/pg
|
||||
name = "powder ganger jacket"
|
||||
desc = "Remind Security of their mistakes in giving prisoners blasting charges."
|
||||
icon_state = "pg_suit"
|
||||
item_state = "pg_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/deckers
|
||||
name = "decker hoodie"
|
||||
desc = "Based? Based on what?"
|
||||
icon_state = "decker_suit"
|
||||
item_state = "decker_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/morningstar
|
||||
name = "morningstar coat"
|
||||
desc = "This coat costs more than you've ever made in your entire life."
|
||||
icon_state = "morningstar_suit"
|
||||
item_state = "morningstar_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/saints
|
||||
name = "Third Street Saints fur coat"
|
||||
desc = "Rated 10 out of 10 in Cosmo for best coat brand."
|
||||
icon_state = "saints_suit"
|
||||
item_state = "saints_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/phantom
|
||||
name = "phantom thief coat"
|
||||
desc = "Your foes will never see you coming in this stealthy yet stylish getup."
|
||||
icon_state = "phantom_suit"
|
||||
item_state = "phantom_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/allies
|
||||
name = "allies body armor"
|
||||
desc = "How 'bout some action!? Sponsored by DonkSoft Co. for historical reenactment of the Third World War!"
|
||||
icon_state = "allies_armor"
|
||||
item_state = "allies_armor"
|
||||
body_parts_covered = CHEST|GROIN
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/soviet
|
||||
name = "soviet armored coat"
|
||||
desc = "Conscript reporting! Sponsored by DonkSoft Co. for historical reenactment of the Third World War!"
|
||||
icon_state = "soviet_suit"
|
||||
item_state = "soviet_suit"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/yuri
|
||||
name = "yuri initiate coat"
|
||||
desc = "Yuri is master! Sponsored by DonkSoft Co. for historical reenactment of the Third World War!"
|
||||
icon_state = "yuri_coat"
|
||||
item_state = "yuri_coat"
|
||||
body_parts_covered = CHEST|GROIN|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/sybil_slickers
|
||||
name = "sybil slickers protective gear"
|
||||
desc = "Given to members of the Sybil Slickers football team!"
|
||||
icon_state = "football_armor_blue"
|
||||
item_state = "football_armor_blue"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/basil_boys
|
||||
name = "basil boys protective gear"
|
||||
desc = "Given to members of the Basil Boys football team!"
|
||||
icon_state = "football_armor_red"
|
||||
item_state = "football_armor_red"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/yakuza
|
||||
name = "tojo clan jacket"
|
||||
desc = "The jacket of a mad dog."
|
||||
icon_state = "MajimaJacket"
|
||||
item_state = "MajimaJacket"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/suit/dutch
|
||||
name = "dutch's jacket"
|
||||
desc = "For those long nights on the beach in Tahiti."
|
||||
icon_state = "DutchJacket"
|
||||
item_state = "DutchJacket"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|ARMS
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
|
||||
@@ -356,9 +356,131 @@
|
||||
icon_state = "sakura_kimono"
|
||||
item_state = "sakura_kimono"
|
||||
|
||||
/obj/item/clothing/under/costume/irs
|
||||
name = "internal revenue service outfit"
|
||||
icon_state = "irs_jumpsuit"
|
||||
item_state = "irs_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/osi
|
||||
name = "O.S.I. jumpsuit"
|
||||
icon_state = "osi_jumpsuit"
|
||||
item_state = "osi_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/tmc
|
||||
name = "Lost MC clothing"
|
||||
icon_state = "tmc_jumpsuit"
|
||||
item_state = "tmc_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/pg
|
||||
name = "powder ganger prison jumpsuit"
|
||||
icon_state = "pg_jumpsuit"
|
||||
item_state = "pg_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/driscoll
|
||||
name = "O'Driscoll outfit"
|
||||
icon_state = "driscoll_jumpsuit"
|
||||
item_state = "driscoll_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/deckers
|
||||
name = "deckers outfit"
|
||||
icon_state = "decker_jumpsuit"
|
||||
item_state = "decker_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/morningstar
|
||||
name = "Morningstar suit"
|
||||
icon_state = "morningstar_jumpsuit"
|
||||
item_state = "morningstar_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/saints
|
||||
name = "Saints outfit"
|
||||
icon_state = "saints_jumpsuit"
|
||||
item_state = "saints_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/phantom
|
||||
name = "Phantom Thief outfit"
|
||||
icon_state = "phantom_jumpsuit"
|
||||
item_state = "phantom_jumpsuit"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/allies
|
||||
name = "allies tanktop"
|
||||
icon_state = "allies_uniform"
|
||||
item_state = "allies_uniform"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/soviet_families
|
||||
name = "soviet conscript uniform"
|
||||
icon_state = "soviet_uniform"
|
||||
item_state = "soviet_uniform"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/yuri
|
||||
name = "yuri initiate jumpsuit"
|
||||
icon_state = "yuri_uniform"
|
||||
item_state = "yuri_uniform"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/sybil_slickers
|
||||
name = "sybil slickers uniform"
|
||||
icon_state = "football_blue"
|
||||
item_state = "football_blue"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/basil_boys
|
||||
name = "basil boys uniform"
|
||||
icon_state = "football_red"
|
||||
item_state = "football_red"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/swagoutfit
|
||||
name = "Swag outfit"
|
||||
desc = "Why don't you go secure some bitches?"
|
||||
icon_state = "SwagOutfit"
|
||||
item_state = "SwagOutfit"
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/costume/jackbros
|
||||
name = "jack bros outfit"
|
||||
desc = "For when it's time to hee some hos."
|
||||
icon_state = "JackFrostUniform"
|
||||
item_state = "JackFrostUniform"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/yakuza
|
||||
name = "tojo clan pants"
|
||||
desc = "For those long nights under the traffic cone."
|
||||
icon_state = "MajimaPants"
|
||||
item_state = "MajimaPants"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/costume/dutch
|
||||
name = "dutch's suit"
|
||||
desc = "You can feel a <b>god damn plan</b> coming on."
|
||||
icon_state = "DutchUniform"
|
||||
item_state = "DutchUniform"
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
@@ -32,6 +32,20 @@
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE //The clown suit must look funny, no taur alpha masks where possible.
|
||||
|
||||
/obj/item/clothing/under/rank/civilian/polychromic_clown
|
||||
name = "polychromic clown suit"
|
||||
desc = "<i>'HONK!'</i>"
|
||||
icon_state = "clown"
|
||||
item_state = "clown"
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
mutantrace_variation = STYLE_DIGITIGRADE //The clown suit must look funny, no taur alpha masks where possible.
|
||||
var/list/poly_colors = list("#FF0000", "#FF99FF", "#FFFF00", "#FFFFFF")
|
||||
|
||||
/obj/item/clothing/under/rank/civilian/polychromic_clown/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/polychromic, poly_colors, 4)
|
||||
|
||||
/obj/item/clothing/under/rank/civilian/clown/blue
|
||||
name = "blue clown suit"
|
||||
desc = "<i>'BLUE HONK!'</i>"
|
||||
|
||||
@@ -242,3 +242,10 @@
|
||||
icon_state = "spacepol"
|
||||
item_state = "spacepol"
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/rank/security/officer/beatcop
|
||||
name = "space police uniform"
|
||||
desc = "A police uniform often found in the lines at donut shops."
|
||||
icon_state = "spacepolice_families"
|
||||
item_state = "spacepolice_families"
|
||||
can_adjust = FALSE
|
||||
|
||||
@@ -111,6 +111,25 @@
|
||||
body_parts_covered = CHEST|GROIN
|
||||
can_adjust = FALSE
|
||||
|
||||
|
||||
/obj/item/clothing/under/suit/beige
|
||||
name = "beige suit"
|
||||
desc = "An excellent light colored suit, experts in the field stress that it should not to be confused with the inferior tan suit."
|
||||
icon_state = "beige_suit"
|
||||
item_state = "beige_suit"
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/suit/henchmen
|
||||
name = "henchmen jumpsuit"
|
||||
desc = "A very gaudy jumpsuit for a proper Henchman. Guild regulations, you understand."
|
||||
icon = 'icons/obj/clothing/uniforms.dmi'
|
||||
mob_overlay_icon = 'icons/mob/clothing/uniform.dmi'
|
||||
icon_state = "henchmen"
|
||||
item_state = "henchmen"
|
||||
body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS|HEAD
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEEARS|HIDEEYES|HIDEHAIR|HIDETAUR
|
||||
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
|
||||
|
||||
/obj/item/clothing/under/suit/polychromic //enables all three overlays to reduce copypasta and defines basic stuff
|
||||
name = "polychromic suit"
|
||||
desc = "For when you want to show off your horrible colour coordination skills."
|
||||
|
||||
23
code/modules/events/atmos_speed.dm
Normal file
23
code/modules/events/atmos_speed.dm
Normal file
@@ -0,0 +1,23 @@
|
||||
/datum/round_event_control/atmos_flux
|
||||
name = "Atmospheric Flux"
|
||||
typepath = /datum/round_event/atmos_flux
|
||||
max_occurrences = 1
|
||||
weight = 5
|
||||
endWhen = 600
|
||||
var/original_speed
|
||||
|
||||
/datum/round_event/atmos_flux
|
||||
announceWhen = 1
|
||||
|
||||
/datum/round_event/atmos_flux/announce(fake)
|
||||
priority_announce("Atmospheric flux in your sector detected. Sensors show that air may move [(SSair.share_max_steps_target > original_speed) ? "faster" : "slower"] than usual for some time.", "Atmos Alert")
|
||||
|
||||
/datum/round_event/atmos_flux/start()
|
||||
original_speed = SSair.share_max_steps_target
|
||||
if(prob(20))
|
||||
SSair.share_max_steps_target = max(1, original_speed - rand(1,original_speed-1))
|
||||
else
|
||||
SSair.share_max_steps_target += rand(2,10)
|
||||
|
||||
/datum/round_event/atmos_flux/end()
|
||||
SSair.share_max_steps_target = original_speed
|
||||
@@ -58,7 +58,7 @@
|
||||
supernova.power_mod = min(supernova.power_mod*1.2, power)
|
||||
if(activeFor > endWhen-10)
|
||||
supernova.power_mod /= 4
|
||||
if(prob(round(supernova.power_mod)) && prob(3) && storm_count < 5 && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
|
||||
if(prob(round(supernova.power_mod)) && prob(5-storm_count) && !SSweather.get_weather_by_type(/datum/weather/rad_storm))
|
||||
SSweather.run_weather(/datum/weather/rad_storm/supernova)
|
||||
storm_count++
|
||||
|
||||
@@ -73,6 +73,6 @@
|
||||
weather_duration_lower = 50
|
||||
weather_duration_upper = 100
|
||||
telegraph_duration = 200
|
||||
radiation_intensity = 1000
|
||||
radiation_intensity = 500
|
||||
weather_sound = null
|
||||
telegraph_message = "<span class='userdanger'>The air begins to grow very warm!</span>"
|
||||
|
||||
@@ -57,7 +57,11 @@ God bless America.
|
||||
component_parts += new /obj/item/circuitboard/machine/deep_fryer(null)
|
||||
component_parts += new /obj/item/stock_parts/micro_laser(null)
|
||||
RefreshParts()
|
||||
fry_loop = new(list(src), FALSE)
|
||||
fry_loop = new(src, FALSE)
|
||||
|
||||
/obj/machinery/deepfryer/Destroy()
|
||||
QDEL_NULL(fry_loop)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/deepfryer/RefreshParts()
|
||||
var/oil_efficiency
|
||||
|
||||
@@ -13,15 +13,21 @@
|
||||
|
||||
/obj/machinery/grill/Initialize()
|
||||
. = ..()
|
||||
grill_loop = new(list(src), FALSE)
|
||||
grill_loop = new(src, FALSE)
|
||||
|
||||
/obj/machinery/grill/Destroy()
|
||||
QDEL_NULL(grill_loop)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/grill/update_icon_state()
|
||||
if(grilled_item)
|
||||
icon_state = "grill"
|
||||
else if(grill_fuel)
|
||||
return ..()
|
||||
if(grill_fuel > 0)
|
||||
icon_state = "grill_on"
|
||||
else
|
||||
icon_state = "grill_open"
|
||||
return ..()
|
||||
icon_state = "grill_open"
|
||||
return ..()
|
||||
|
||||
/obj/machinery/grill/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/stack/sheet/mineral/coal) || istype(I, /obj/item/stack/sheet/mineral/wood))
|
||||
@@ -60,21 +66,21 @@
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/grill/process()
|
||||
/obj/machinery/grill/process(delta_time)
|
||||
..()
|
||||
update_icon()
|
||||
if(!grill_fuel)
|
||||
update_appearance()
|
||||
if(grill_fuel <= 0)
|
||||
return
|
||||
else
|
||||
grill_fuel -= 1
|
||||
if(prob(1))
|
||||
grill_fuel -= 0.5 * delta_time
|
||||
if(DT_PROB(0.5, delta_time))
|
||||
var/datum/effect_system/smoke_spread/bad/smoke = new
|
||||
smoke.set_up(1, loc)
|
||||
smoke.start()
|
||||
if(grilled_item)
|
||||
grill_time += 1
|
||||
grill_time += delta_time
|
||||
grilled_item.reagents.add_reagent("char", 1)
|
||||
grill_fuel -= 10
|
||||
grill_fuel -= 5 * delta_time
|
||||
grilled_item.AddComponent(/datum/component/sizzle)
|
||||
|
||||
/obj/machinery/grill/Exited(atom/movable/AM)
|
||||
@@ -109,9 +115,9 @@
|
||||
|
||||
/obj/machinery/grill/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(grilled_item)
|
||||
to_chat(user, "<span class='notice'>You take out [grilled_item] from [src].</span>")
|
||||
to_chat(user, span_notice("You take out [grilled_item] from [src]."))
|
||||
grilled_item.forceMove(drop_location())
|
||||
update_icon()
|
||||
update_appearance()
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -36,12 +36,13 @@
|
||||
. = ..()
|
||||
wires = new /datum/wires/microwave(src)
|
||||
create_reagents(100)
|
||||
soundloop = new(list(src), FALSE)
|
||||
soundloop = new(src, FALSE)
|
||||
|
||||
/obj/machinery/microwave/Destroy()
|
||||
eject()
|
||||
if(wires)
|
||||
QDEL_NULL(wires)
|
||||
QDEL_NULL(soundloop)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/microwave/RefreshParts()
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
pop_areas += A
|
||||
|
||||
var/list/targets = list()
|
||||
for(var/H in GLOB.network_holopads)
|
||||
for(var/H in GLOB.the_station_areas)
|
||||
var/area/A = get_area(H)
|
||||
if(!A || findtextEx(A.name, "AI") || !(A in pop_areas) || !is_station_level(H))
|
||||
continue
|
||||
|
||||
@@ -53,31 +53,21 @@
|
||||
|
||||
/obj/item/seeds/replicapod/on_reagent_change(changetype)
|
||||
if(changetype == ADD_REAGENT)
|
||||
var/datum/reagent/blood/B = reagents.has_reagent(/datum/reagent/blood)
|
||||
if(B)
|
||||
if(B.data["mind"] && B.data["cloneable"])
|
||||
mind = B.data["mind"]
|
||||
ckey = B.data["ckey"]
|
||||
realName = B.data["real_name"]
|
||||
blood_gender = B.data["gender"]
|
||||
blood_type = B.data["blood_type"]
|
||||
features = B.data["features"]
|
||||
factions = B.data["factions"]
|
||||
quirks = B.data["quirks"]
|
||||
contains_sample = TRUE
|
||||
visible_message("<span class='notice'>The [src] is injected with a fresh blood sample.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>The [src] rejects the sample!</span>")
|
||||
|
||||
if(!reagents.has_reagent(/datum/reagent/blood))
|
||||
mind = null
|
||||
ckey = null
|
||||
realName = null
|
||||
blood_gender = null
|
||||
blood_type = null
|
||||
features = null
|
||||
factions = null
|
||||
contains_sample = FALSE
|
||||
for(var/datum/reagent/R as anything in reagents.reagent_list)
|
||||
if(R.data["mind"])
|
||||
if(R.data["cloneable"])
|
||||
mind = R.data["mind"]
|
||||
ckey = R.data["ckey"]
|
||||
realName = R.data["real_name"]
|
||||
blood_gender = R.data["gender"]
|
||||
blood_type = R.data["blood_type"]
|
||||
features = R.data["features"]
|
||||
factions = R.data["factions"]
|
||||
quirks = R.data["quirks"]
|
||||
contains_sample = TRUE
|
||||
visible_message("<span class='notice'>The [src] is injected with a fresh blood sample.</span>")
|
||||
else
|
||||
visible_message("<span class='warning'>The [src] rejects the sample!</span>")
|
||||
|
||||
/obj/item/seeds/replicapod/get_analyzer_text()
|
||||
var/text = ..()
|
||||
|
||||
@@ -12,21 +12,16 @@
|
||||
|
||||
|
||||
/obj/machinery/hydroponics/proc/mutation_roll(mob/user)
|
||||
switch(rand(100))
|
||||
switch(rand(1, 100))
|
||||
if(91 to 100)
|
||||
adjustHealth(-10)
|
||||
visible_message("<span class='warning'>\The [myseed.plantname] starts to wilt and burn!</span>")
|
||||
return
|
||||
if(41 to 90)
|
||||
if(myseed && !self_sustaining) //Stability
|
||||
myseed.adjust_instability(5)
|
||||
return
|
||||
if(21 to 40)
|
||||
visible_message("<span class='notice'>\The [myseed.plantname] appears unusually reactive...</span>")
|
||||
return
|
||||
if(11 to 20)
|
||||
mutateweed()
|
||||
return
|
||||
if(1 to 10)
|
||||
mutatepest(user)
|
||||
return
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"light blue" = COLOR_ASSEMBLY_LBLUE,
|
||||
"blue" = COLOR_ASSEMBLY_BLUE,
|
||||
"purple" = COLOR_ASSEMBLY_PURPLE,
|
||||
"pink" = COLOR_ASSEMBLY_PINK,
|
||||
"pink" = LIGHT_COLOR_PINK,
|
||||
"custom" = COLOR_ASSEMBLY_WHITE
|
||||
)
|
||||
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
ui = new(user, src, "TrackedPlaytime")
|
||||
ui.open()
|
||||
|
||||
/datum/job_report_menu/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
data["exemptStatus"] = (owner.prefs?.db_flags & DB_FLAG_EXEMPT)
|
||||
|
||||
return data
|
||||
|
||||
/datum/job_report_menu/ui_static_data()
|
||||
if (!CONFIG_GET(flag/use_exp_tracking))
|
||||
return list("failReason" = JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED)
|
||||
@@ -42,8 +49,39 @@
|
||||
|
||||
data["livingTime"] = play_records[EXP_TYPE_LIVING]
|
||||
data["ghostTime"] = play_records[EXP_TYPE_GHOST]
|
||||
data["adminTime"] = play_records[EXP_TYPE_ADMIN] ? play_records[EXP_TYPE_ADMIN] : 0
|
||||
|
||||
data["isAdmin"] = check_rights(R_ADMIN, show_msg = FALSE)
|
||||
|
||||
return data
|
||||
|
||||
/datum/job_report_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
switch(action)
|
||||
if("toggle_exempt")
|
||||
if(!check_rights(R_ADMIN))
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin rights.")
|
||||
log_admin("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin rights.")
|
||||
to_chat(usr, span_danger("ERROR: Insufficient admin rights."), confidential = TRUE)
|
||||
return TRUE
|
||||
|
||||
var/datum/admins/viewer_admin_datum = GLOB.admin_datums[usr.ckey]
|
||||
|
||||
if(!viewer_admin_datum)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin datum for their ckey.")
|
||||
log_admin("[ADMIN_LOOKUPFLW(usr)] attempted to toggle job playtime exempt status without admin datum for their ckey.")
|
||||
to_chat(usr, span_danger("ERROR: Insufficient admin rights."), confidential = TRUE)
|
||||
return TRUE
|
||||
|
||||
if(QDELETED(owner))
|
||||
to_chat(usr, span_danger("ERROR: Client not found."), confidential = TRUE)
|
||||
return TRUE
|
||||
|
||||
viewer_admin_datum.toggle_exempt_status(owner)
|
||||
return TRUE
|
||||
|
||||
#undef JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED
|
||||
#undef JOB_REPORT_MENU_FAIL_REASON_NO_RECORDS
|
||||
|
||||
@@ -36,3 +36,25 @@
|
||||
/datum/keybinding/living/toggle_resting/down(client/user)
|
||||
var/mob/living/L = user.mob
|
||||
L.lay_down()
|
||||
|
||||
/datum/keybinding/living/cancel_action
|
||||
hotkey_keys = list("Unbound")
|
||||
name = "cancel_action"
|
||||
full_name = "Cancel Action"
|
||||
description = "Cancel the current action."
|
||||
|
||||
/// Technically you shouldn't be doing any actions if you were sleeping either but...
|
||||
/datum/keybinding/living/can_use(client/user)
|
||||
. = ..()
|
||||
var/mob/living/mob = user.mob
|
||||
return . && (mob.stat == CONSCIOUS)
|
||||
|
||||
/datum/keybinding/living/cancel_action/down(client/user)
|
||||
var/mob/M = user.mob
|
||||
if(length(M.do_afters))
|
||||
var/atom/target = M.do_afters[M.do_afters.len]
|
||||
to_chat(M, "<span class='notice'>You stop interacting with \the [target].</span>")
|
||||
LAZYREMOVE(M.do_afters, target)
|
||||
else
|
||||
to_chat(M, "<span class='notice'>There's nothing that you can cancel right now.</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
speech_verb = "chitter"
|
||||
ask_verb = "chitter"
|
||||
exclaim_verb = "chitter"
|
||||
key = "r"
|
||||
key = "c"
|
||||
flags = NO_STUTTER | LANGUAGE_HIDE_ICON_IF_NOT_UNDERSTOOD
|
||||
|
||||
icon_state = "arachnid"
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -5,7 +5,7 @@
|
||||
ask_verb = "queries"
|
||||
exclaim_verb = "declares"
|
||||
whisper_verb = "hushes"
|
||||
key = "k"
|
||||
key = "j"
|
||||
space_chance = 40
|
||||
default_priority = 94
|
||||
flags = TONGUELESS_SPEECH
|
||||
|
||||
@@ -245,6 +245,8 @@
|
||||
those who wish to spit in the eyes of God. Sacrifices outright damage for \
|
||||
a reliance on backstabs and the ability to give fauna concussions on a parry."
|
||||
attack_verb = list("pummeled", "punched", "jabbed", "hammer-fisted", "uppercut", "slammed")
|
||||
hitsound = 'sound/weapons/resonator_blast.ogg'
|
||||
sharpness = SHARP_NONE // use your survival dagger or smth
|
||||
icon_state = "crusher-hands"
|
||||
item_state = "crusher0-fist"
|
||||
unique_reskin = list("Gauntlets" = "crusher-hands",
|
||||
|
||||
96
code/modules/mining/lavaland/ash_tree.dm
Normal file
96
code/modules/mining/lavaland/ash_tree.dm
Normal file
@@ -0,0 +1,96 @@
|
||||
//Houses the ash tree, a lava land tree that has been burning for quite some time making a maple like sweetener.
|
||||
|
||||
/obj/structure/flora/ashtree
|
||||
name = "ashed tree"
|
||||
desc = "A once large tree now burnt like the lands around it."
|
||||
layer = FLY_LAYER
|
||||
gender = PLURAL //same as other tree
|
||||
density = TRUE
|
||||
pixel_x = -16
|
||||
icon = 'icons/obj/lavaland/ash_tree.dmi'
|
||||
icon_state = "ashtree"
|
||||
//Are icon when we are full of honey or other sap
|
||||
var/sap_icon_state = "ashtree_maple"
|
||||
//What we look like when tapping
|
||||
var/tabbed_icon_state = "ashtree_maple"
|
||||
//amout of coal in are tree, simular to logs
|
||||
var/coal_amount = 5
|
||||
//Do we have sap?
|
||||
var/sap = FALSE
|
||||
//What reagent we have
|
||||
var/sap_type = /datum/reagent/consumable/honey
|
||||
//This is in seconds, and now long we wait till are tree is tapped
|
||||
var/harvest_sap_time = 60
|
||||
var/container_used
|
||||
var/sap_amount
|
||||
|
||||
/obj/structure/flora/ashtree/Initialize(mapload)
|
||||
..()
|
||||
if(prob(50))
|
||||
sap = TRUE
|
||||
icon_state = sap_icon_state
|
||||
desc = "A once large tree now burnt like the lands around it. This one seems to have a sap still inside."
|
||||
//If we have sap, we can generate a bit of it
|
||||
sap_amount = rand(5,15)
|
||||
//Random coal or wood amount, so its not bog standered.
|
||||
coal_amount = rand(5,15)
|
||||
//If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
SSblackbox.record_feedback("tally", "Honey Tree", 1, "Trees Spawned")
|
||||
|
||||
//So we dont lose are bowls, stolen form closet code
|
||||
/obj/structure/flora/ashtree/Destroy()
|
||||
dump_contents(override = FALSE)
|
||||
return ..()
|
||||
|
||||
//Override is for not revealing the locker electronics when you open the locker, for example
|
||||
/obj/structure/flora/ashtree/proc/dump_contents(override = TRUE)
|
||||
var/atom/L = drop_location()
|
||||
for(var/atom/movable/AM in src)
|
||||
AM.forceMove(L)
|
||||
|
||||
/obj/structure/flora/ashtree/proc/harvest_sap()
|
||||
desc = "A once large tree now burnt like the lands around it."
|
||||
icon_state = "ashtree"
|
||||
var/obj/item/reagent_containers/RG = container_used
|
||||
//Incase someone was a dumb and used a lidded container
|
||||
if(RG.is_refillable())
|
||||
//Make sure that its not filling something thats full
|
||||
if(!RG.reagents.holder_full())
|
||||
RG.reagents.add_reagent(sap_type, min(RG.volume - RG.reagents.total_volume, sap_amount))
|
||||
//We drop are used beaker and try to fill it with sap
|
||||
RG.forceMove(drop_location())
|
||||
SSblackbox.record_feedback("tally", "Honey Tree", 1, "Harvested Honey") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
//Proc stolen from Trees
|
||||
//If you hit it with a sharp force aboe 0 item it chops it down, unlike trees tho it dosnt give wood as its already charcoal
|
||||
//Also dosnt have a stump
|
||||
/obj/structure/flora/ashtree/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/reagent_containers))
|
||||
if(sap)
|
||||
user.visible_message("<span class='notice'>[user] pokes [src] and places a container under the [W].</span>","<span class='notice'>You set up [src] with [W].</span>")
|
||||
icon_state = tabbed_icon_state
|
||||
sap = FALSE
|
||||
container_used = W
|
||||
//So we dont lose are bowl when cutting it down + needed for the harvest sap proc
|
||||
user.transferItemToLoc(W, src)
|
||||
addtimer(CALLBACK(src, .proc/harvest_sap), harvest_sap_time SECONDS)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There is no sap to collect.</span>")
|
||||
|
||||
if(coal_amount && (!(flags_1 & NODECONSTRUCT_1)))
|
||||
if(!W.sharpness || !W.force)
|
||||
return
|
||||
if(W.hitsound)
|
||||
playsound(get_turf(src), W.hitsound, 100, 0, 0)
|
||||
user.visible_message("<span class='notice'>[user] begins to cut down [src] with [W].</span>","<span class='notice'>You begin to cut down [src] with [W].</span>", "You hear the sound of brittle sawing.")
|
||||
//2.5 seconds with 20 force, 4 seconds with a hatchet, 10 seconds with a shard.
|
||||
if(do_after(user, 500/W.force, target = src))
|
||||
user.visible_message("<span class='notice'>[user] fells [src] with the [W].</span>","<span class='notice'>You fell [src] with the [W].</span>", "You hear the sound of a crumbling tree.")
|
||||
playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 100 , 0, 0)
|
||||
for(var/i=1 to coal_amount)
|
||||
new /obj/item/stack/sheet/mineral/coal(get_turf(src))
|
||||
qdel(src)//If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
SSblackbox.record_feedback("tally", "Honey Tree", 1, "Cutted Tree")
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -694,16 +694,20 @@
|
||||
|
||||
/datum/reagent/flightpotion/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1)
|
||||
if(iscarbon(M) && M.stat != DEAD)
|
||||
if(!ishumanbasic(M) || reac_volume < 5) // implying xenohumans are holy
|
||||
var/mob/living/carbon/C = M
|
||||
if(reac_volume < 5)
|
||||
if(method == INGEST && show_message)
|
||||
to_chat(M, "<span class='notice'><i>You feel nothing but a terrible aftertaste.</i></span>")
|
||||
to_chat(C, "<span class='notice'><i>You feel nothing but a terrible aftertaste.</i></span>")
|
||||
return ..()
|
||||
|
||||
to_chat(M, "<span class='userdanger'>A terrible pain travels down your back as wings burst out!</span>")
|
||||
M.set_species(/datum/species/angel)
|
||||
playsound(M.loc, 'sound/items/poster_ripped.ogg', 50, 1, -1)
|
||||
M.adjustBruteLoss(20)
|
||||
M.emote("scream")
|
||||
var/has_wings = (C.dna.species.mutant_bodyparts["deco_wings"] && C.dna.features["deco_wings"] != "None" || C.dna.species.mutant_bodyparts["insect_wings"] && C.dna.features["insect_wings"] != "None")
|
||||
var/has_functional_wings = (C.dna.species.mutant_bodyparts["wings"] != null)
|
||||
to_chat(C, "<span class='userdanger'>A terrible pain travels down your back as [has_wings || has_functional_wings ? "your wings transform" : "wings burst out"]!</span>")
|
||||
C.dna.species.GiveSpeciesFlight(C, has_functional_wings ? TRUE : FALSE) //give them the full list of wing choices if this is their second flight potion
|
||||
to_chat(C, "<span class='notice'>You feel blessed!</span>")
|
||||
ADD_TRAIT(C, TRAIT_HOLY, SPECIES_TRAIT) //implying anyone is truly holy in a setting where people throw tantrums when things aren't violent
|
||||
playsound(C.loc, 'sound/items/poster_ripped.ogg', 50, TRUE, -1)
|
||||
C.adjustBruteLoss(20)
|
||||
C.emote("scream")
|
||||
..()
|
||||
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
/obj/item/stack/ore/uranium
|
||||
name = "uranium ore"
|
||||
icon_state = "Uranium ore"
|
||||
// inhand_icon_state = "Uranium ore"
|
||||
// item_state = "Uranium ore"
|
||||
singular_name = "uranium ore chunk"
|
||||
points = 30
|
||||
// material_flags = MATERIAL_NO_EFFECTS
|
||||
|
||||
@@ -126,5 +126,5 @@ INITIALIZE_IMMEDIATE(/mob/dead)
|
||||
return ..()
|
||||
|
||||
/mob/dead/onTransitZ(old_z,new_z)
|
||||
..()
|
||||
. = ..()
|
||||
update_z(new_z)
|
||||
|
||||
@@ -578,8 +578,6 @@
|
||||
Spl.Fade(TRUE)
|
||||
character.playsound_local(get_turf(character), 'sound/voice/ApproachingTG.ogg', 25)
|
||||
|
||||
character.update_parallax_teleport()
|
||||
|
||||
job.standard_assign_skills(character.mind)
|
||||
|
||||
SSticker.minds += character.mind
|
||||
@@ -762,6 +760,7 @@
|
||||
|
||||
client.prefs.scars_list["[cur_scar_index]"] = valid_scars
|
||||
client.prefs.save_character()
|
||||
|
||||
client.prefs.copy_to(H, initial_spawn = TRUE)
|
||||
H.dna.update_dna_identity()
|
||||
if(mind)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user