* Ghost bar initial changes

* more changes

* we ball again brothers

* we are (once again) SO back

* Update code/modules/admin/verbs/debug.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>

* Update code/_onclick/hud/alert.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>

* Update code/_onclick/hud/alert.dm

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>

* Update code/modules/ruins/ghost_bar.dm

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* Update code/modules/ruins/ghost_bar.dm

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* Update code/modules/ruins/ghost_bar.dm

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* Update code/modules/ruins/ghost_bar.dm

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* Update code/modules/ruins/ghost_bar.dm

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* Update code/game/objects/items/weapons/cards_ids.dm

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* deck of cards and shittt

* global placement

* Update code/modules/ruins/ghost_bar.dm

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* readded

* hotfix

* zamn

* fixes

* greyfix

* last of the fixes

* can't stop me baby

* bam

---------

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>
This commit is contained in:
GDN
2023-10-09 19:47:17 +01:00
committed by GitHub
co-authored by Luc Henri215
parent b02ce067bf
commit 6df2c2e3d2
72 changed files with 2640 additions and 1123 deletions
File diff suppressed because it is too large Load Diff
+3
View File
@@ -135,6 +135,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
*/
//***** MOB TRAITS *****//
#define TRAIT_RESPAWNABLE "can_respawn_as_ghost_roles"
#define TRAIT_BLIND "blind"
#define TRAIT_MUTE "mute"
#define TRAIT_DEAF "deaf"
@@ -263,6 +264,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define SLIME_TRAIT "slime"
#define BERSERK_TRAIT "berserk"
#define EYES_OF_GOD "eyes_of_god"
#define GHOSTED "isghost"
#define GHOST_ROLE "ghost_role"
// unique trait sources
#define STATUE_MUTE "statue"
-1
View File
@@ -23,7 +23,6 @@ GLOBAL_LIST_EMPTY(human_list) //all instances of /mob/living/carbon/human and
GLOBAL_LIST_EMPTY(spirits) //List of all the spirits, including Masks
GLOBAL_LIST_EMPTY(alive_mob_list) //List of all alive mobs, including clientless. Excludes /mob/new_player
GLOBAL_LIST_EMPTY(dead_mob_list) //List of all dead mobs, including clientless. Excludes /mob/new_player
GLOBAL_LIST_EMPTY(respawnable_list) //List of all mobs, dead or in mindless creatures that still be respawned.
GLOBAL_LIST_EMPTY(non_respawnable_keys) //List of ckeys that are excluded from respawning for remainder of round.
GLOBAL_LIST_INIT(simple_animals, list(list(), list(), list(), list())) //One for each AI_* status define, List of all simple animals, including clientless
GLOBAL_LIST_EMPTY(bots_list) //List of all bots(beepsky, medibots,etc)
+8 -2
View File
@@ -612,8 +612,6 @@ so as to remain in compliance with the most up-to-date laws."
if(!usr || !usr.client)
return
var/mob/dead/observer/G = usr
if(!istype(G))
return
if(poll)
var/success
@@ -631,8 +629,16 @@ so as to remain in compliance with the most up-to-date laws."
if(NOTIFY_JUMP)
var/turf/T = get_turf(target)
if(T && isturf(T))
if(!istype(G))
var/mob/dead/observer/actual_ghost = G.ghostize(TRUE)
actual_ghost.forceMove(T)
return
G.forceMove(T)
if(NOTIFY_FOLLOW)
if(!istype(G))
var/mob/dead/observer/actual_ghost = G.ghostize(TRUE)
actual_ghost.ManualFollow(target)
return
G.ManualFollow(target)
/obj/screen/alert/notify_action/Topic(href, href_list)
+17 -8
View File
@@ -60,7 +60,7 @@ SUBSYSTEM_DEF(ghost_spawns)
var/category = "[P.hash]_notify_action"
var/notice_sound = sound('sound/misc/notice2.ogg')
for(var/mob/dead/observer/M in (ignore_respawnability ? GLOB.player_list : GLOB.respawnable_list))
for(var/mob/M in (GLOB.player_list))
if(!is_eligible(M, role, antag_age_check, role, min_hours, check_antaghud))
continue
@@ -140,7 +140,14 @@ SUBSYSTEM_DEF(ghost_spawns)
// Sleep until the time is up
UNTIL(P.finished)
return P.signed_up
if(!ignore_respawnability)
var/list/eligable_mobs = list()
for(var/mob/signed_up in P.signed_up)
if(HAS_TRAIT(signed_up, TRAIT_RESPAWNABLE))
eligable_mobs += signed_up
return eligable_mobs
else
return P.signed_up
/**
* Returns whether an observer is eligible to be an event mob
@@ -153,10 +160,12 @@ SUBSYSTEM_DEF(ghost_spawns)
* * min_hours - The amount of minimum hours the client needs before being eligible
* * check_antaghud - Whether to consider a client who enabled AntagHUD ineligible or not
*/
/datum/controller/subsystem/ghost_spawns/proc/is_eligible(mob/M, role, antag_age_check, role_text, min_hours, check_antaghud)
/datum/controller/subsystem/ghost_spawns/proc/is_eligible(mob/M, role, antag_age_check, role_text, min_hours, check_antaghud, ignore_respawnability)
. = FALSE
if(!M.key || !M.client)
return
if(!ignore_respawnability && !HAS_TRAIT(M, TRAIT_RESPAWNABLE))
return
if(role)
if(!(role in M.client.prefs.be_special))
return
@@ -213,7 +222,7 @@ SUBSYSTEM_DEF(ghost_spawns)
var/role // The role the poll is for
var/question // The question asked to observers
var/duration // The duration of the poll
var/list/mob/dead/observer/signed_up // The players who signed up to this poll
var/list/signed_up // The players who signed up to this poll
var/time_started // The world.time at which the poll was created
var/finished = FALSE // Whether the polling is finished
var/hash // Used to categorize in the alerts system
@@ -236,9 +245,9 @@ SUBSYSTEM_DEF(ghost_spawns)
* * M - The (controlled) mob to sign up
* * silent - Whether no messages should appear or not. If not TRUE, signing up to this poll will also sign the mob up for identical polls
*/
/datum/candidate_poll/proc/sign_up(mob/dead/observer/M, silent = FALSE)
/datum/candidate_poll/proc/sign_up(mob/M, silent = FALSE)
. = FALSE
if(!istype(M) || !M.key || !M.client)
if(!HAS_TRAIT(M, TRAIT_RESPAWNABLE) || !M.key || !M.client)
return
if(M in signed_up)
if(!silent)
@@ -269,9 +278,9 @@ SUBSYSTEM_DEF(ghost_spawns)
* * M - The mob to remove from the poll, if present.
* * silent - If TRUE, no messages will be sent to M about their removal.
*/
/datum/candidate_poll/proc/remove_candidate(mob/dead/observer/M, silent = FALSE)
/datum/candidate_poll/proc/remove_candidate(mob/M, silent = FALSE)
. = FALSE
if(!istype(M) || !M.key || !M.client)
if(!HAS_TRAIT(M, TRAIT_RESPAWNABLE) || !M.key || !M.client)
return
if(!(M in signed_up))
if(!silent)
+4 -1
View File
@@ -16,6 +16,7 @@
var/list/data = list()
data["spawners"] = list()
for(var/spawner in GLOB.mob_spawners)
var/is_perm_spawner = FALSE
var/list/this = list()
this["name"] = spawner
this["desc"] = ""
@@ -30,10 +31,12 @@
this["desc"] = MS.description
this["important_info"] = MS.important_info
this["fluff"] = MS.flavour_text
if(MS.permanent)
is_perm_spawner = TRUE
else
var/obj/O = spawner_obj
this["desc"] = O.desc
this["amount_left"] = LAZYLEN(GLOB.mob_spawners[spawner])
this["amount_left"] = is_perm_spawner ? "Infinite uses" : LAZYLEN(GLOB.mob_spawners[spawner])
data["spawners"] += list(this)
return data
+1 -1
View File
@@ -67,7 +67,7 @@ Also, you never added distance checking after target is selected. I've went ahea
ghost.mind.transfer_to(caster)
if(ghost.key)
GLOB.non_respawnable_keys -= ghost.ckey //ghostizing with an argument of 0 will make them unable to respawn forever, which is bad
GLOB.non_respawnable_keys -= ghost.ckey
caster.key = ghost.key //have to transfer the key since the mind was not active
qdel(ghost)
+7
View File
@@ -136,3 +136,10 @@
/area/trader_station/sol
name = "Jupiter Station 6"
/area/ghost_bar
name = "Ghost Bar"
icon_state = "observatory"
requires_power = FALSE
has_gravity = TRUE
hide_attacklogs = TRUE
+1
View File
@@ -666,6 +666,7 @@ structure_check() searches for nearby cultist structures required for the invoca
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(mob_to_revive)]) to replace an AFK player.")
mob_to_revive.ghostize(FALSE)
mob_to_revive.key = C.key
dust_if_respawnable(C)
else
fail_invoke()
return
+1
View File
@@ -416,6 +416,7 @@
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)]) to replace a jobbanned player.")
M.ghostize()
M.key = theghost.key
dust_if_respawnable(theghost)
else
message_admins("[M] ([M.key] has been converted into [role_type] with an active antagonist jobban for said role since no ghost has volunteered to take [M.p_their()] place.")
to_chat(M, "<span class='biggerdanger'>You have been converted into [role_type] with an active jobban. Any further violations of the rules on your part are likely to result in a permanent ban.</span>")
@@ -144,6 +144,7 @@
var/client/C = M.client
S.key = C.key
dust_if_respawnable(M)
S.mind.assigned_role = "Harbinger of the Slaughter"
S.mind.special_role = "Harbinger of the Slaughter"
to_chat(S, playstyle_string)
@@ -310,6 +310,7 @@
to_chat(user, "You already have a [mob_name]!")
used = FALSE
return
dust_if_respawnable(theghost)
spawn_guardian(user, theghost.key, guardian_type)
else
to_chat(user, "[failure_message]")
@@ -99,6 +99,7 @@
message_admins("[key_name_admin(new_stand)] has taken control of ([key_name_admin(guardian)])")
guardian.ghostize()
guardian.key = new_stand.key
dust_if_respawnable(new_stand)
qdel(src)
/**
@@ -23,6 +23,7 @@
var/mob/living/simple_animal/hostile/morph/S = new /mob/living/simple_animal/hostile/morph(pick(GLOB.xeno_spawn))
player_mind.transfer_to(S)
S.make_morph_antag()
dust_if_respawnable(C)
message_admins("[key_of_morph] has been made into morph by an event.")
log_game("[key_of_morph] was spawned as a morph by an event.")
@@ -34,5 +34,6 @@
player_mind.active = TRUE
player_mind.transfer_to(new_morph)
new_morph.make_morph_antag()
dust_if_respawnable(C)
user.create_log(MISC_LOG, "Made a new morph using [src]", new_morph)
user.ventcrawler = initial(user.ventcrawler) // re enable the crawling
@@ -10,7 +10,8 @@
var/mob/C = pick(candidates)
key_of_pulsedemon = C.key
dust_if_respawnable(C)
if(!key_of_pulsedemon)
kill()
return
@@ -168,6 +168,7 @@
key = theghost.key
giveObjectivesandGoals()
giveSpells()
dust_if_respawnable(theghost)
else
message_admins("No ghost was willing to take control of a mindless revenant. Deleting...")
qdel(src)
@@ -397,7 +398,7 @@
else if(reforming)
. += "<span class='revenwarning'>It is shifting and distorted. It would be wise to destroy this.</span>"
/obj/item/ectoplasm/revenant/proc/reform()
/obj/item/ectoplasm/revenant/proc/reform() // Unused proc, production doesn't have revenants revive
if(inert || !src)
return
var/key_of_revenant
@@ -37,6 +37,7 @@
return
var/mob/living/simple_animal/revenant/revvie = new /mob/living/simple_animal/revenant/(pick(spawn_locs))
player_mind.transfer_to(revvie)
dust_if_respawnable(C)
player_mind.assigned_role = SPECIAL_ROLE_REVENANT
player_mind.special_role = SPECIAL_ROLE_REVENANT
SSticker.mode.traitors |= player_mind
+2
View File
@@ -88,6 +88,7 @@
SSticker.mode.apprentices += M.mind
M.mind.special_role = SPECIAL_ROLE_WIZARD_APPRENTICE
SSticker.mode.update_wiz_icons_added(M.mind)
dust_if_respawnable(C)
M.faction = list("wizard")
SStgui.close_uis(src)
else
@@ -369,6 +370,7 @@ GLOBAL_LIST_EMPTY(multiverse)
var/mob/C = pick(candidates)
spawn_copy(C.client, get_turf(user.loc), user)
to_chat(user, "<span class='warning'><B>The sword flashes, and you find yourself face to face with...you!</B></span>")
dust_if_respawnable(C)
else
to_chat(user, "You fail to summon any copies of yourself. Perhaps you should try again in a bit.")
+1
View File
@@ -120,6 +120,7 @@
var/mob/living/carbon/human/new_character= makeBody(harry)
new_character.mind.make_Wizard() // This puts them at the wizard spawn, worry not
mages_made++
dust_if_respawnable(harry)
return TRUE
else
. = FALSE
+1
View File
@@ -505,5 +505,6 @@
if(length(contents)) //If they used the soulstone on someone else in the meantime
return FALSE
M.ckey = chosen_ghost.ckey
dust_if_respawnable(chosen_ghost)
init_shade(M, user)
return TRUE
+1 -1
View File
@@ -581,7 +581,7 @@
time_entered = world.time
if(findtext("[E.key]","@",1,2))
var/FT = replacetext(E.key, "@", "")
for(var/mob/dead/observer/Gh in GLOB.respawnable_list) //this may not be foolproof but it seemed like a better option than 'in world'
for(var/mob/dead/observer/Gh in GLOB.player_list) //this may not be foolproof but it seemed like a better option than 'in world'
if(Gh.key == FT)
if(Gh.client && Gh.client.holder) //just in case someone has a byond name with @ at the start, which I don't think is even possible but whatever
to_chat(Gh, "<span style='color: #800080;font-weight: bold;font-size:4;'>Warning: Your body has entered cryostorage.</span>")
@@ -303,6 +303,18 @@
opacity = FALSE
glass = TRUE
/obj/machinery/door/airlock/external_no_weld
name = "external airlock"
icon = 'icons/obj/doors/airlocks/external/external.dmi'
overlays_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
note_overlay_file = 'icons/obj/doors/airlocks/external/overlays.dmi'
assemblytype = /obj/structure/door_assembly/door_assembly_ext
doorOpen = 'sound/machines/airlock_ext_open.ogg'
doorClose = 'sound/machines/airlock_ext_close.ogg'
/obj/machinery/door/airlock/external_no_weld/welder_act(mob/user, obj/item/I)
return
//////////////////////////////////
/*
CentCom Airlocks
+1
View File
@@ -113,6 +113,7 @@
return
var/mob/dead/observer/O = pick(candidates)
R.key = O.key
dust_if_respawnable(O)
/obj/machinery/transformer/mime
name = "Mimetech Greyscaler"
+7 -2
View File
@@ -1026,7 +1026,7 @@
* * crit - if true, some special damage effects might happen.
* * from_combat - If true, hold off on some of the additional damage and extra effects.
*/
/obj/machinery/economy/vending/proc/tilt(atom/victim, crit = FALSE, from_combat = FALSE)
/obj/machinery/economy/vending/proc/tilt(atom/victim, crit = FALSE, from_combat = FALSE, from_anywhere = FALSE)
if(QDELETED(src) || !has_gravity(src) || !tiltable || tilted)
return
@@ -1037,6 +1037,8 @@
. = FALSE
if(from_anywhere)
forceMove(get_turf(victim))
if(!victim || !in_range(victim, src))
tilt_over()
return
@@ -1118,7 +1120,10 @@
if(HAS_TRAIT(target, TRAIT_FLATTENED))
return
add_attack_logs(attacker, target, "shoved into a vending machine ([src])")
tilt(target, from_combat = TRUE)
if(!HAS_TRAIT(attacker, TRAIT_PACIFISM))
tilt(target, from_combat = TRUE)
else
tilt(attacker, crit = TRUE, from_anywhere = TRUE) // get fucked
return TRUE
/obj/machinery/economy/vending/hit_by_thrown_carbon(mob/living/carbon/human/C, datum/thrownthing/throwingdatum, damage, mob_hurt, self_hurt)
+1
View File
@@ -361,6 +361,7 @@
var/mob/dead/observer/chosen = pick(candidates)
S.key = chosen.key
S.mind.special_role = SPECIAL_ROLE_PYROCLASTIC_SLIME
dust_if_respawnable(chosen)
log_game("[key_name(S.key)] was made into a slime by pyroclastic anomaly at [AREACOORD(T)].")
/////////////////////
+1
View File
@@ -198,6 +198,7 @@
var/mob/C = pick(candidates)
if(C)
S.key = C.key
dust_if_respawnable(C)
if(S.master_commander)
to_chat(S, "<span class='biggerdanger'>You are a spider who is loyal to [S.master_commander], obey [S.master_commander]'s every order and assist [S.master_commander.p_them()] in completing [S.master_commander.p_their()] goals at any cost.</span>")
qdel(src)
@@ -20,6 +20,8 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
num2text(MED_I_FREQ) = list(ACCESS_MEDICAL)
))
GLOBAL_LIST_EMPTY(deadsay_radio_systems)
/obj/item/radio
icon = 'icons/obj/radio.dmi'
name = "station bounced radio"
@@ -795,3 +797,48 @@ GLOBAL_LIST_INIT(default_medbay_channels, list(
/obj/item/radio/phone/medbay/New()
..()
internal_channels = GLOB.default_medbay_channels.Copy()
/obj/item/radio/proc/attempt_send_deadsay_message(mob/subject, message)
return
/obj/item/radio/headset/deadsay
name = "spectral radio"
ks2type = /obj/item/encryptionkey/centcom
/obj/item/radio/headset/deadsay/New()
..()
GLOB.deadsay_radio_systems.Add(src)
make_syndie()
/obj/item/radio/headset/deadsay/Destroy()
GLOB.deadsay_radio_systems.Remove(src)
return ..()
/obj/item/radio/headset/deadsay/screwdriver_act(mob/user, obj/item/I)
return
/obj/item/radio/headset/deadsay/attempt_send_deadsay_message(mob/subject, message)
if(!listening)
return
var/mob/hearer = loc // if people want dchat to shut up, they shouldn't need to deal with other people's headsets
if(!istype(hearer) || hearer.stat || !hearer.can_hear())
return
if(!hearer.get_preference(PREFTOGGLE_CHAT_DEAD))
return
var/speaker_name
if(!subject || subject.client.prefs.toggles2 & PREFTOGGLE_2_ANON)
subject ? (speaker_name = "<i>Anon</i> ([subject.mind.name])") : (speaker_name = "<i>Anon</i>")
else
speaker_name = "[subject.client.key] ([subject.mind.name])"
to_chat(hearer, "<span class='deadsay'><b>[speaker_name]</b> ([ghost_follow_link(subject, hearer)]) [message]</span>")
/obj/item/radio/headset/deadsay/talk_into(mob/living/M, list/message_pieces, channel, verbage)
var/message = sanitize(copytext(multilingual_to_message(message_pieces), 1, MAX_MESSAGE_LEN))
if(!message)
return
return M.say_dead(message)
@@ -385,6 +385,12 @@
name = "agent card"
initial_access = list(ACCESS_MAINT_TUNNELS, ACCESS_VOX, ACCESS_EXTERNAL_AIRLOCKS)
/obj/item/card/id/syndicate/ghost_bar
name = "ghost bar identification card"
assignment = "Ghost Bar Occupant"
initial_access = list() // This is for show, they don't need actual accesses
icon_state = "assistant"
/obj/item/card/id/syndicate/command
initial_access = list(ACCESS_MAINT_TUNNELS, ACCESS_SYNDICATE, ACCESS_SYNDICATE_LEADER, ACCESS_SYNDICATE_COMMAND, ACCESS_EXTERNAL_AIRLOCKS)
icon_state = "commander"
+1
View File
@@ -296,6 +296,7 @@
var/mob/dead/observer/C = pick(candidates)
message_admins("[ADMIN_LOOKUPFLW(C)] was spawned as Dice Servant")
H.key = C.key
dust_if_respawnable(C)
to_chat(H, "<span class='notice'>You are a servant of [user.real_name]. You must do everything in your power to follow their orders.</span>")
var/obj/effect/proc_holder/spell/summonmob/S = new
@@ -294,6 +294,7 @@
S.real_name = name
S.name = name
S.ckey = theghost.ckey
dust_if_respawnable(theghost)
var/input = stripped_input(S, "What are you named?", null, "", MAX_NAME_LEN)
if(src && input)
@@ -78,6 +78,9 @@
if(istype(I, /obj/item/grab))
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/grab/G = I
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='danger'>Swirling [G.affecting] might hurt them!</span>")
return
if(!G.confirm())
return
if(isliving(G.affecting))
@@ -204,6 +207,9 @@
var/obj/item/grab/G = I
if(!G.confirm())
return
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='danger'>Slamming [G.affecting] into [src] might hurt them!</span>")
return
if(isliving(G.affecting))
var/mob/living/GM = G.affecting
if(G.state >= GRAB_AGGRESSIVE)
+2
View File
@@ -2001,6 +2001,7 @@
var/mob/living/simple_animal/pet/P = new petchoice(H.loc)
theghost = pick(candidates)
P.key = theghost.key
dust_if_respawnable(theghost)
P.master_commander = H
P.universal_speak = TRUE
P.universal_understand = TRUE
@@ -3473,6 +3474,7 @@
hunter_mind.active = TRUE
var/mob/living/carbon/human/hunter_mob = new /mob/living/carbon/human(pick(GLOB.latejoin))
hunter_mind.transfer_to(hunter_mob)
dust_if_respawnable(C)
hunter_mob.equipOutfit(O, FALSE)
var/obj/item/pinpointer/advpinpointer/N = new /obj/item/pinpointer/advpinpointer(hunter_mob)
hunter_mob.equip_to_slot_or_del(N, SLOT_HUD_IN_BACKPACK)
+2
View File
@@ -146,6 +146,7 @@ GLOBAL_VAR_INIT(deathsquad_sent, FALSE)
SSticker.minds += R.mind
SSticker.mode.traitors += R.mind
R.key = ghost_mob.key
dust_if_respawnable(ghost_mob)
if(nuke_code)
R.mind.store_memory("<b>Nuke Code:</b> <span class='warning'>[nuke_code].</span>")
R.mind.store_memory("<b>Mission:</b> <span class='warning'>[mission].</span>")
@@ -154,6 +155,7 @@ GLOBAL_VAR_INIT(deathsquad_sent, FALSE)
var/mob/living/carbon/human/new_commando = create_deathsquad_commando(L, is_leader)
new_commando.mind.key = ghost_mob.key
new_commando.key = ghost_mob.key
dust_if_respawnable(ghost_mob)
new_commando.update_action_buttons_icon()
if(nuke_code)
new_commando.mind.store_memory("<b>Nuke Code:</b> <span class='warning'>[nuke_code].</span>")
+5 -1
View File
@@ -776,7 +776,11 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
if("Clients")
to_chat(usr, jointext(GLOB.clients, ","))
if("Respawnable Mobs")
to_chat(usr, jointext(GLOB.respawnable_list, ","))
var/list/respawnable_mobs
for(var/mob/potential_respawnable in GLOB.player_list)
if(HAS_TRAIT(potential_respawnable, TRAIT_RESPAWNABLE))
respawnable_mobs += potential_respawnable
to_chat(usr, jointext(respawnable_mobs, ", "))
/client/proc/cmd_display_del_log()
set category = "Debug"
+1
View File
@@ -75,6 +75,7 @@
H.mind.offstation_role = TRUE
H.key = thisplayer.key
dust_if_respawnable(thisplayer)
H.equipOutfit(O, FALSE)
@@ -85,6 +85,7 @@ GLOBAL_VAR_INIT(sent_syndicate_infiltration_team, 0)
new_syndicate_infiltrator.key = theguy.key
new_syndicate_infiltrator.internal = new_syndicate_infiltrator.s_store
new_syndicate_infiltrator.update_action_buttons_icon()
dust_if_respawnable(theguy)
infiltrators -= theguy
to_chat(new_syndicate_infiltrator, "<span class='danger'>You are a [!syndicate_leader_selected?"Infiltrator":"<B>Lead Infiltrator</B>"] in the service of the Syndicate. \nYour current mission is: <B>[input]</B></span>")
to_chat(new_syndicate_infiltrator, "<span class='notice'>You are equipped with an uplink bio-chip to help you achieve your objectives. ((activate it via button in top left of screen))</span>")
@@ -148,6 +148,7 @@
var/mob/living/carbon/human/new_character = makeBody(selected)
new_character.mind.make_Wizard()
dust_if_respawnable(selected)
return 1
return 0
@@ -330,3 +331,4 @@
to_chat(new_thunderdome_member, "You are a member of the <font color='red'><b>RED</b></font> Thunderdome team! Gear up and help your team destroy the green team!")
new_thunderdome_member.mind.offstation_role = TRUE
team_to_assign_to = "Green"
dust_if_respawnable(candidate_to_spawn)
@@ -300,6 +300,7 @@ GLOBAL_LIST_EMPTY(antagonists)
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(owner.current)]) to replace a jobbaned player.")
owner.current.ghostize(FALSE)
owner.current.key = C.key
dust_if_respawnable(C)
return TRUE
/**
@@ -59,6 +59,7 @@
used = TRUE
var/mob/dead/observer/G = pick(nuke_candidates)
spawn_antag(G.client, get_turf(src), user.mind)
dust_if_respawnable(G)
do_sparks(4, TRUE, src)
qdel(src)
else
@@ -204,6 +205,7 @@
if(candidates.len > 0)
var/mob/C = pick(candidates)
spawn_antag(C, get_turf(src.loc), initial(demon_type.name), user)
dust_if_respawnable(C)
to_chat(user, "[shatter_msg]")
to_chat(user, "[veil_msg]")
playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, 1)
@@ -291,6 +293,7 @@
if(candidates.len > 0)
var/mob/C = pick(candidates)
spawn_antag(C, get_turf(src.loc), initial(morph_type.name), user)
dust_if_respawnable(C)
to_chat(user, "[shatter_msg]")
to_chat(user, "[veil_msg]")
playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, 1)
@@ -351,6 +354,7 @@
var/mob/C = pick(candidates)
spawn_antag(C, get_turf(src), initial(revenant.name), user)
dust_if_respawnable(C)
to_chat(user, "[shatter_msg]")
to_chat(user, "[veil_msg]")
playsound(user.loc, 'sound/effects/glassbr1.ogg', 100, TRUE)
@@ -411,6 +415,7 @@
var/mob/C = pick(candidates)
spawn_antag(C, T, user)
dust_if_respawnable(C)
to_chat(user, shatter_msg)
to_chat(user, veil_msg)
playsound(T, 'sound/effects/glassbr1.ogg', 100, TRUE)
@@ -57,7 +57,7 @@
user.mind.transfer_to(target)
if(ghost && ghost.mind)
ghost.mind.transfer_to(user)
GLOB.non_respawnable_keys -= ghost.ckey //they have a new body, let them be able to re-enter their corpse if they die
GLOB.non_respawnable_keys -= ghost.ckey // Better make sure they can re-enter their new body
user.key = ghost.key
qdel(ghost)
if(ghosted)
+21 -16
View File
@@ -36,29 +36,17 @@
var/death_cooldown = 0 // How long you have to wait after dying before using it again, in deciseconds. People that join as observers are not included.
/obj/effect/mob_spawn/attack_ghost(mob/user)
if(SSticker.current_state != GAME_STATE_PLAYING || !loc || !ghost_usable)
return
if(!uses)
to_chat(user, "<span class='warning'>This spawner is out of charges!</span>")
return
if(jobban_isbanned(user, banType) || jobban_isbanned(user, ROLE_SYNDICATE))
to_chat(user, "<span class='warning'>You are jobanned!</span>")
return
if(cannotPossess(user))
to_chat(user, "<span class='warning'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
return
if(time_check(user))
if(!valid_to_spawn(user))
return
var/ghost_role = alert("Become [mob_name]? (Warning, You can no longer be cloned!)",,"Yes","No")
if(ghost_role == "No")
return
if(!species_prompt())
return
if(!loc || !uses || QDELETED(src) || QDELETED(user))
if(!loc || !uses && !permanent || QDELETED(src) || QDELETED(user))
to_chat(user, "<span class='warning'>The [name] is no longer usable!</span>")
return
log_game("[user.ckey] became [mob_name]")
create(ckey = user.ckey)
create(ckey = user.ckey, user = user)
/obj/effect/mob_spawn/Initialize(mapload)
. = ..()
@@ -85,6 +73,22 @@
/obj/effect/mob_spawn/proc/equip(mob/M)
return
/obj/effect/mob_spawn/proc/valid_to_spawn(mob/user)
if(SSticker.current_state != GAME_STATE_PLAYING || !loc || !ghost_usable)
return FALSE
if(!uses && !permanent)
to_chat(user, "<span class='warning'>This spawner is out of charges!</span>")
return FALSE
if(jobban_isbanned(user, banType) || jobban_isbanned(user, ROLE_SYNDICATE))
to_chat(user, "<span class='warning'>You are jobanned!</span>")
return FALSE
if(cannotPossess(user))
to_chat(user, "<span class='warning'>Upon using the antagHUD you forfeited the ability to join the round.</span>")
return FALSE
if(time_check(user))
return FALSE
return TRUE
/obj/effect/mob_spawn/proc/time_check(mob/user)
var/deathtime = world.time - user.timeofdeath
var/joinedasobserver = FALSE
@@ -109,7 +113,8 @@
return TRUE
return FALSE
/obj/effect/mob_spawn/proc/create(ckey, flavour = TRUE, name)
/obj/effect/mob_spawn/proc/create(ckey, flavour = TRUE, name, mob/user = usr)
log_game("[ckey] became [mob_name]")
var/mob/living/M = new mob_type(get_turf(src)) //living mobs only
if(!random)
M.real_name = mob_name ? mob_name : M.name
+4 -2
View File
@@ -21,9 +21,9 @@
else
temp = new
var/agent_mind = pick(candidates)
var/mob/agent_mind = pick(candidates)
candidates -= agent_mind
var/scientist_mind = pick(candidates)
var/mob/scientist_mind = pick(candidates)
var/mob/living/carbon/human/agent=makeBody(agent_mind)
var/mob/living/carbon/human/scientist=makeBody(scientist_mind)
@@ -41,6 +41,8 @@
temp.abductors |= list(agent_mind,scientist_mind)
temp.make_abductor_team(number,preset_scientist=scientist_mind,preset_agent=agent_mind)
temp.post_setup_team(number)
dust_if_respawnable(agent_mind)
dust_if_respawnable(scientist)
SSticker.mode.abductor_teams++
+1 -1
View File
@@ -30,10 +30,10 @@
var/obj/vent = pick_n_take(vents)
var/mob/C = pick_n_take(candidates)
if(C)
C.remove_from_respawnable_list()
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
new_xeno.amount_grown += (0.75 * new_xeno.max_grown) //event spawned larva start off almost ready to evolve.
new_xeno.key = C.key
dust_if_respawnable(C)
new_xeno.forceMove(vent)
new_xeno.add_ventcrawl(vent)
if(SSticker && SSticker.mode)
+1
View File
@@ -240,6 +240,7 @@
var/mob/C = pick(candidates)
if(C)
blobber.key = C.key
dust_if_respawnable(C)
to_chat(blobber, "<span class='biggerdanger'>You are a blobbernaut! You must assist all blob lifeforms in their mission to consume everything!</span>")
to_chat(blobber, "<span class='danger'>You heal while standing on blob structures, however you will decay slowly if you are damaged outside of the blob.</span>")
if(!blobber.ckey)
@@ -119,6 +119,7 @@
var/mob/camera/blob/B = new(loc)
B.is_offspring = is_offspring
B.key = C.key
dust_if_respawnable(C)
B.blob_core = src
overmind = B
color = overmind.blob_reagent_datum.color
+1
View File
@@ -25,6 +25,7 @@
var/mob/living/simple_animal/mouse/blobinfected/B = new(vent.loc)
var/mob/M = pick(candidates)
B.key = M.key
dust_if_respawnable(M)
B.mind.special_role = SPECIAL_ROLE_BLOB
B.forceMove(vent)
B.add_ventcrawl(vent)
+1
View File
@@ -24,6 +24,7 @@
var/mob/SG = pick(candidates)
SA.key = SG.key
dust_if_respawnable(SG)
SA.universal_speak = TRUE
SA.sentience_act()
SA.can_collar = TRUE
+1
View File
@@ -17,6 +17,7 @@
var/datum/mind/player_mind = new /datum/mind(key_of_slaughter)
player_mind.active = TRUE
dust_if_respawnable(C)
var/turf/spawn_loc = get_spawn_loc(player_mind.current)
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(spawn_loc)
var/mob/living/simple_animal/demon/S = new demon(holder)
+1
View File
@@ -64,6 +64,7 @@
var/mob/living/simple_animal/hostile/poison/terror_spider/S = new spider_type(vent.loc)
var/mob/M = pick_n_take(candidates)
S.key = M.key
dust_if_respawnable(M)
if(infestation_type != PRINCE_SPIDER)
S.forceMove(vent)
S.add_ventcrawl(vent)
+1 -1
View File
@@ -53,9 +53,9 @@ GLOBAL_LIST_INIT(unused_trade_stations, list("sol"))
var/mob/C = pick_n_take(candidates)
spawn_count--
if(C)
C.remove_from_respawnable_list()
var/mob/living/carbon/human/M = new /mob/living/carbon/human(picked_loc)
M.ckey = C.ckey // must be before equipOutfit, or that will runtime due to lack of mind
dust_if_respawnable(C)
M.equipOutfit(/datum/outfit/admin/sol_trader)
M.dna.species.after_equip_job(null, M)
for(var/datum/objective/O in trader_objectives)
@@ -83,6 +83,9 @@
return FALSE
if(!istype(G))
return FALSE
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='danger'>Slamming [G.affecting] into [src] might hurt them!</span>")
return FALSE
if(!iscarbon(G.affecting))
if(verbose)
to_chat(user, "<span class='warning'>You can't shove that in there!</span>")
@@ -117,6 +117,9 @@
return TRUE
else if(istype(O, /obj/item/grab))
var/obj/item/grab/G = O
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='danger'>Slamming [G.affecting] into [src] might hurt them!</span>")
return
return special_attack_grab(G, user)
else
to_chat(user, "<span class='alert'>You have no idea what you can cook with [O].</span>")
@@ -93,6 +93,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
..()
plane = GAME_PLANE
add_observer_verbs()
ADD_TRAIT(src, TRAIT_RESPAWNABLE, GHOSTED)
/mob/dead/observer/Destroy()
toggle_all_huds_off()
@@ -178,9 +179,8 @@ Works together with spawning an observer, noted above.
flags &= ~GHOST_CAN_REENTER
var/mob/dead/observer/ghost = new(src, flags) //Transfer safety to observer spawning proc.
ghost.timeofdeath = src.timeofdeath //BS12 EDIT
remove_from_respawnable_list()
if(ghost.can_reenter_corpse)
ghost.add_to_respawnable_list()
ADD_TRAIT(ghost, TRAIT_RESPAWNABLE, GHOSTED)
else
GLOB.non_respawnable_keys[ckey] = 1
ghost.key = key
@@ -203,6 +203,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
message_admins("[key_name_admin(src)] tried to ghost while admin frozen")
return
if(HAS_TRAIT(M, TRAIT_RESPAWNABLE))
ghostize(1)
return
if(P)
if(TOO_EARLY_TO_GHOST)
warningmsg = "It's too early in the shift to enter cryo"
@@ -280,7 +283,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
statpanel("Status")
if(client.statpanel == "Status")
show_stat_emergency_shuttle_eta()
stat(null, "Respawnability: [(src in GLOB.respawnable_list) ? "Yes" : "No"]")
stat(null, "Respawnability: [HAS_TRAIT(src, TRAIT_RESPAWNABLE) ? "Yes" : "No"]")
/mob/dead/observer/verb/reenter_corpse()
set category = "Ghost"
@@ -6,4 +6,4 @@
if(GLOB.non_respawnable_keys[ckey])
can_reenter_corpse = 0
remove_from_respawnable_list()
REMOVE_TRAIT(src, TRAIT_RESPAWNABLE, GHOSTED)
@@ -100,6 +100,7 @@
owner.cut_overlay(overlay)
var/mob/living/carbon/alien/larva/new_xeno = new(owner.drop_location())
new_xeno.key = C.key
dust_if_respawnable(C)
if(SSticker && SSticker.mode)
SSticker.mode.xenos += new_xeno.mind
new_xeno.mind.name = new_xeno.name
+2 -2
View File
@@ -52,9 +52,9 @@
B.brainmob = null
brainmob.container = src
brainmob.forceMove(src)
REMOVE_TRAIT(brainmob, TRAIT_RESPAWNABLE, GHOSTED)
brainmob.set_stat(CONSCIOUS)
brainmob.see_invisible = initial(brainmob.see_invisible)
brainmob.remove_from_respawnable_list()
GLOB.dead_mob_list -= brainmob//Update dem lists
GLOB.alive_mob_list += brainmob
@@ -159,7 +159,7 @@
brainmob.container = null//Reset brainmob mmi var.
brainmob.forceMove(held_brain) //Throw mob into brain.
brainmob.add_to_respawnable_list()
ADD_TRAIT(brainmob, TRAIT_RESPAWNABLE, GHOSTED)
GLOB.alive_mob_list -= brainmob//Get outta here
held_brain.brainmob = brainmob//Set the brain to use the brainmob
held_brain.brainmob.cancel_camera()
+1 -1
View File
@@ -78,7 +78,7 @@
GLOB.dead_mob_list += src
if(mind)
mind.store_memory("Time of death: [station_time_timestamp("hh:mm:ss", timeofdeath)]", 0)
add_to_respawnable_list()
ADD_TRAIT(src, TRAIT_RESPAWNABLE, GHOSTED)
if(mind.name && !isbrain(src)) // !isbrain() is to stop it from being called twice
var/turf/T = get_turf(src)
@@ -49,7 +49,7 @@ GLOBAL_DATUM_INIT(paiController, /datum/paiController, new) // Global handler fo
var/mob/dead/observer/O = locate(href_list["signup"])
if(!O)
return
if(!(O in GLOB.respawnable_list))
if(!HAS_TRAIT(O, TRAIT_RESPAWNABLE))
to_chat(O, "You've given up your ability to respawn!")
return
if(!check_recruit(O))
@@ -232,7 +232,7 @@ GLOBAL_DATUM_INIT(paiController, /datum/paiController, new) // Global handler fo
var/list/available = list()
for(var/datum/pai_save/c in GLOB.paiController.pai_candidates)
var/found = 0
for(var/mob/o in GLOB.respawnable_list)
for(var/mob/dead/observer/o in GLOB.player_list)
if(o.ckey == c.owner.ckey)
found = 1
if(found)
@@ -357,7 +357,7 @@ GLOBAL_DATUM_INIT(paiController, /datum/paiController, new) // Global handler fo
return 0
if(cannotPossess(O))
return 0
if(!(O in GLOB.respawnable_list))
if(!HAS_TRAIT(O, TRAIT_RESPAWNABLE))
return 0
if(O.client)
return 1
@@ -63,7 +63,7 @@
ghost_can_reenter = 1
break
for(var/mob/living/simple_animal/S in GLOB.player_list)
if(S in GLOB.respawnable_list)
if(HAS_TRAIT(S, TRAIT_RESPAWNABLE))
ghost_can_reenter = 1
break
if(!ghost_can_reenter)
@@ -234,6 +234,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
if(boosted)
mychild.key = elitemind.key
mychild.sentience_act()
dust_if_respawnable(elitemind)
notify_ghosts("\A [mychild] has been awakened in \the [get_area(src)]!", enter_link="<a href=?src=[UID()];follow=1>(Click to help)</a>", source = mychild, action = NOTIFY_FOLLOW)
icon_state = "tumor_popped"
RegisterSignal(mychild, COMSIG_PARENT_QDELETING, PROC_REF(onEliteLoss))
@@ -1,9 +1,9 @@
/mob/living/simple_animal/hostile/poison/terror_spider/Topic(href, href_list)
if(href_list["activate"])
var/mob/dead/observer/ghost = usr
if(istype(ghost))
humanize_spider(ghost)
var/mob/user = usr
if(HAS_TRAIT(user, TRAIT_RESPAWNABLE))
humanize_spider(user)
/mob/living/simple_animal/hostile/poison/terror_spider/attack_ghost(mob/user)
humanize_spider(user)
@@ -24,7 +24,7 @@
error_on_humanize = "Dying spiders are not player-controllable."
else if(stat == DEAD)
error_on_humanize = "Dead spiders are not player-controllable."
else if(!(user in GLOB.respawnable_list))
else if(!HAS_TRAIT(user, TRAIT_RESPAWNABLE))
error_on_humanize = "You are not able to rejoin the round."
if(jobban_isbanned(user, ROLE_SYNDICATE) || jobban_isbanned(user, ROLE_TSPIDER))
to_chat(user, "<span class='warning'>You are jobbanned from role of syndicate and/or terror spider.</span>")
+1 -3
View File
@@ -62,9 +62,7 @@
GLOB.dead_mob_list -= src
GLOB.alive_mob_list |= src
if(mind)
remove_from_respawnable_list()
REMOVE_TRAIT(src, TRAIT_RESPAWNABLE, GHOSTED)
timeofdeath = null
if(updating)
+2 -12
View File
@@ -1148,14 +1148,6 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
/mob/proc/activate_hand(selhand)
return
/mob/proc/add_to_respawnable_list()
GLOB.respawnable_list += src
RegisterSignal(src, COMSIG_PARENT_QDELETING, PROC_REF(remove_from_respawnable_list))
/mob/proc/remove_from_respawnable_list()
GLOB.respawnable_list -= src
UnregisterSignal(src, COMSIG_PARENT_QDELETING)
/mob/dead/observer/verb/respawn()
set name = "Respawn as NPC"
set category = "Ghost"
@@ -1168,7 +1160,7 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
to_chat(src, "<span class='warning'>You can't respawn as an NPC before the game starts!</span>")
return
if((usr in GLOB.respawnable_list) && (stat == DEAD || isobserver(usr)))
if((HAS_TRAIT(usr, TRAIT_RESPAWNABLE)) && (stat == DEAD || isobserver(usr)))
var/list/creatures = list("Mouse")
for(var/mob/living/simple_animal/L in GLOB.alive_mob_list)
if(!(is_station_level(L.z) || is_admin_level(L.z))) // Prevents players from spawning in space
@@ -1178,12 +1170,10 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
var/picked = input("Please select an NPC to respawn as", "Respawn as NPC") as null|anything in creatures
switch(picked)
if("Mouse")
if(become_mouse()) // Only remove respawnability if the player successfully becomes a mouse
remove_from_respawnable_list()
become_mouse()
else
var/mob/living/NPC = picked
if(istype(NPC) && !NPC.key)
remove_from_respawnable_list()
NPC.key = key
else
to_chat(usr, "You are not dead or you have given up your right to be respawned!")
+2
View File
@@ -308,6 +308,8 @@
return
if(INTENT_HARM) //This checks that the user is on harm intent.
if(HAS_TRAIT(user, TRAIT_PACIFISM))
return
if(last_hit_zone == "head") //This checks the hitzone the user has selected. In this specific case, they have the head selected.
if(IS_HORIZONTAL(affecting))
return
+9 -2
View File
@@ -184,6 +184,7 @@
message_admins("[key_name_admin(theghost)] has taken control of ([key_name_admin(M)])")
M.ghostize()
M.key = theghost.key
dust_if_respawnable(theghost)
else
to_chat(M, "There were no ghosts willing to take control.")
message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
@@ -521,6 +522,9 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
else
name = realname
for(var/obj/item/radio/deadsay_radio_system as anything in GLOB.deadsay_radio_systems)
deadsay_radio_system.attempt_send_deadsay_message(subject, message)
for(var/mob/M in GLOB.player_list)
if(M.client && ((!isnewplayer(M) && M.stat == DEAD) || check_rights(R_ADMIN|R_MOD,0,M)) && M.get_preference(PREFTOGGLE_CHAT_DEAD))
var/follow
@@ -547,8 +551,8 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
to_chat(M, "<span class='deadsay'>[lname][follow][message]</span>")
/proc/notify_ghosts(message, ghost_sound = null, enter_link = null, title = null, atom/source = null, image/alert_overlay = null, flashwindow = TRUE, action = NOTIFY_JUMP, role = null) //Easy notification of ghosts.
for(var/mob/dead/observer/O in GLOB.player_list)
if(O.client && (!role || (role in O.client.prefs.be_special)))
for(var/mob/O in GLOB.player_list)
if(O.client && HAS_TRAIT(O, TRAIT_RESPAWNABLE) && (!role || (role in O.client.prefs.be_special)))
to_chat(O, "<span class='ghostalert'>[message][(enter_link) ? " [enter_link]" : ""]</span>")
if(ghost_sound)
SEND_SOUND(O, sound(ghost_sound))
@@ -797,3 +801,6 @@ GLOBAL_LIST_INIT(intents, list(INTENT_HELP,INTENT_DISARM,INTENT_GRAB,INTENT_HARM
return "unconscious"
if(DEAD)
return "dead"
/mob/proc/attempt_listen_to_deadsay()
+1 -1
View File
@@ -203,7 +203,7 @@
observer.real_name = client.prefs.active_character.real_name
observer.name = observer.real_name
observer.key = key
observer.add_to_respawnable_list()
ADD_TRAIT(observer, TRAIT_RESPAWNABLE, GHOSTED)
qdel(src)
return TRUE
return FALSE
@@ -240,6 +240,7 @@
if(candidates.len)
var/mob/C = pick(candidates)
SM.key = C.key
dust_if_respawnable(C)
SM.universal_speak = TRUE
SM.faction = user.faction
SM.master_commander = user
+8 -8
View File
@@ -34,7 +34,7 @@ GLOBAL_LIST_EMPTY(ert_request_messages)
E.ui_interact(usr)
/mob/dead/observer/proc/JoinResponseTeam()
/mob/proc/JoinResponseTeam()
if(!GLOB.send_emergency_team)
to_chat(src, "<span class='warning'>No emergency response team is currently being sent.</span>")
return FALSE
@@ -68,18 +68,18 @@ GLOBAL_LIST_EMPTY(ert_request_messages)
return
// Respawnable players get first dibs
for(var/mob/dead/observer/M in ert_candidates)
for(var/mob/M in ert_candidates)
if(jobban_isbanned(M, ROLE_TRAITOR) || jobban_isbanned(M, "Security Officer") || jobban_isbanned(M, "Captain") || jobban_isbanned(M, "Cyborg"))
continue
if((M in GLOB.respawnable_list) && M.JoinResponseTeam())
if((HAS_TRAIT(M, TRAIT_RESPAWNABLE)) && M.JoinResponseTeam())
GLOB.response_team_members |= M
M.RegisterSignal(M, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/mob/dead/observer, remove_from_ert_list), TRUE)
M.RegisterSignal(M, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/mob, remove_from_ert_list), TRUE)
// If there's still open slots, non-respawnable players can fill them
for(var/mob/dead/observer/M in (ert_candidates - GLOB.respawnable_list))
for(var/mob/M in (ert_candidates - GLOB.response_team_members))
if(M.JoinResponseTeam())
GLOB.response_team_members |= M
M.RegisterSignal(M, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/mob/dead/observer, remove_from_ert_list), TRUE)
M.RegisterSignal(M, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/mob, remove_from_ert_list), TRUE)
if(!length(GLOB.response_team_members))
GLOB.active_team.cannot_send_team()
@@ -133,6 +133,7 @@ GLOBAL_LIST_EMPTY(ert_request_messages)
break
new_commando.mind.key = M.key
new_commando.key = M.key
dust_if_respawnable(M)
new_commando.update_icons()
break
GLOB.send_emergency_team = FALSE
@@ -220,10 +221,9 @@ GLOBAL_LIST_EMPTY(ert_request_messages)
return M
/mob/dead/observer/proc/remove_from_ert_list(ghost)
/mob/proc/remove_from_ert_list(ghost)
SIGNAL_HANDLER
GLOB.response_team_members -= src
remove_from_respawnable_list()
/datum/response_team
var/list/slots = list(
+108
View File
@@ -0,0 +1,108 @@
/obj/effect/mob_spawn/human/alive/ghost_bar
name = "ghastly rejuvenator"
mob_name = "ghost bar occupant"
permanent = TRUE
icon = 'icons/obj/closet.dmi'
icon_state = "coffin"
important_info = "Don't randomly attack people in the ghost bar, stay inside the ghost bar. You will still be able to roll for ghost roles."
description = "Relax, get a beer, watch the station destroy itself and burst into flames."
flavour_text = "You are a ghost bar occupant. You've gotten sick of being dead and decided to meet up with some of your fellow haunting brothers. Take a seat, grab a beer, and chat it out."
assignedrole = "Ghost Bar Occupant"
death_cooldown = 1 MINUTES
/obj/effect/mob_spawn/human/alive/ghost_bar/create(ckey, flavour = TRUE, name, mob/user = usr) // So divorced from the normal proc it's just being overriden
var/datum/character_save/save_to_load
if(alert(user, "Would you like to use one of your saved characters in your character creator?",, "Yes", "No") == "Yes")
var/list/our_characters_names = list()
var/list/our_character_saves = list()
for(var/datum/character_save/saves in user.client.prefs.character_saves)
our_characters_names += saves.real_name
our_character_saves += list(saves.real_name = saves)
var/character_name = input("Select a character", "Character selection") as null|anything in our_characters_names
if(!character_name)
return
if(QDELETED(user))
return
save_to_load = our_character_saves[character_name]
else
if(QDELETED(user))
return
save_to_load = new
save_to_load.randomise()
var/mob/living/carbon/human/H = new(get_turf(src))
save_to_load.copy_to(H)
if(!H.back)
equip_item(H, /obj/item/storage/backpack, SLOT_HUD_BACK)
equip_item(H, /obj/item/radio/headset/deadsay, SLOT_HUD_LEFT_EAR)
H.dna.species.before_equip_job(/datum/job/assistant, H)
H.dna.species.remains_type = /obj/effect/decal/cleanable/ash
var/obj/item/implant/dust/I = new
I.implant(H, null)
for(var/gear in save_to_load.loadout_gear)
var/datum/gear/G = GLOB.gear_datums[text2path(gear) || gear]
if(G.allowed_roles) // Fix due to shitty HUD code
continue
if(G.slot)
if(H.equip_to_slot_or_del(G.spawn_item(H), G.slot, TRUE))
to_chat(H, "<span class='notice'>Equipping you with [G.display_name]!</span>")
else
H.equip_or_collect(G.spawn_item(null, save_to_load.loadout_gear[G.display_name]))
if(!H.w_uniform)
equip_item(H, /obj/item/clothing/under/color/random, SLOT_HUD_JUMPSUIT)
if(!H.shoes)
equip_item(H, /obj/item/clothing/shoes/black, SLOT_HUD_SHOES)
equip_item(H, /obj/item/stack/spacecash/c100, SLOT_HUD_LEFT_STORE)
var/obj/item/card/id/syndicate/our_id = equip_item(H, /obj/item/card/id/syndicate/ghost_bar, SLOT_HUD_WEAR_ID)
our_id.assignment = assignedrole
our_id.registered_name = H.real_name
our_id.sex = capitalize(H.gender)
our_id.age = H.age
our_id.name = "[our_id.registered_name]'s ID Card ([our_id.assignment])"
our_id.photo = get_id_photo(H)
our_id.owner_uid = H.UID()
our_id.owner_ckey = H.ckey
H.job = assignedrole
H.dna.ready_dna(H)
H.mind_initialize()
H.mind.assigned_role = assignedrole
H.mind.special_role = assignedrole
H.mind.offstation_role = TRUE
ADD_TRAIT(H, TRAIT_PACIFISM, GHOST_ROLE)
ADD_TRAIT(H, TRAIT_RESPAWNABLE, GHOST_ROLE)
H.key = ckey
H.dna.species.after_equip_job(/datum/job/assistant, H)
if(isgrey(H))
var/obj/item/organ/internal/cyberimp/brain/speech_translator/implant = new
implant.insert(H)
log_game("[ckey] has entered the ghost bar")
playsound(src, 'sound/machines/wooden_closet_open.ogg', 50)
/obj/effect/mob_spawn/human/alive/ghost_bar/proc/equip_item(mob/living/carbon/human/H, path, slot)
var/obj/item/I = new path(H)
H.equip_or_collect(I, slot, TRUE)
return I
/obj/structure/ghost_bar_cryopod
name = "returning sarcophagus"
desc = "Returns you back to the world of the dead."
icon = 'icons/obj/closet.dmi'
icon_state = "coffin_open"
/obj/structure/ghost_bar_cryopod/MouseDrop_T(mob/living/carbon/human/mob_to_delete, mob/living/user)
if(!istype(mob_to_delete) || !istype(user) || !Adjacent(user))
return
if(mob_to_delete.client)
if(alert(mob_to_delete , "Would you like to return to the realm of spirits? (This will delete your current character, but you can rejoin later)",, "Yes", "No") == "No")
return
mob_to_delete.visible_message("<span class='notice'>[mob_to_delete.name] climbs into [src]...</span>")
playsound(src, 'sound/machines/wooden_closet_close.ogg', 50)
qdel(mob_to_delete)
/proc/dust_if_respawnable(mob/M)
if(HAS_TRAIT_FROM(M, TRAIT_RESPAWNABLE, GHOST_ROLE))
M.dust()
+1 -1
View File
@@ -69,7 +69,7 @@ GLOBAL_DATUM_INIT(ghost_hud_panel, /datum/ui_module/ghost_hud_panel, new)
ghost.has_enabled_antagHUD = TRUE
ghost.can_reenter_corpse = FALSE
ghost.remove_from_respawnable_list()
REMOVE_TRAIT(ghost, TRAIT_RESPAWNABLE, GHOSTED)
ghost.antagHUD = TRUE
for(var/datum/atom_hud/antag/H in GLOB.huds)
+1
View File
@@ -2578,6 +2578,7 @@
#include "code\modules\research\xenobiology\xenobiology.dm"
#include "code\modules\response_team\ert.dm"
#include "code\modules\response_team\ert_outfits.dm"
#include "code\modules\ruins\ghost_bar.dm"
#include "code\modules\ruins\ruin_areas.dm"
#include "code\modules\ruins\syndicate_space_base.dm"
#include "code\modules\ruins\lavalandruin_code\ash_walker_den.dm"