Move some ghosty stuff to async

This commit is contained in:
Aronai Sieyes
2021-06-26 17:37:22 -04:00
parent ec09ddd547
commit faafdcfb5b
4 changed files with 115 additions and 50 deletions
+1
View File
@@ -8,6 +8,7 @@ var/global/list/silicon_mob_list = list() //List of all silicon mobs, includin
var/global/list/ai_list = list() //List of all AIs, including clientless
var/global/list/living_mob_list = list() //List of all alive mobs, including clientless. Excludes /mob/new_player
var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless. Excludes /mob/new_player
var/global/list/observer_mob_list = list() //List of all /mob/observer/dead, including clientless.
var/global/list/listening_objects = list() //List of all objects which care about receiving messages (communicators, radios, etc)
var/global/list/cleanbot_reserved_turfs = list() //List of all turfs currently targeted by some cleanbot
+66 -34
View File
@@ -11,18 +11,13 @@
var/wait_time = 60 SECONDS // How long to wait until returning the list of candidates.
var/cutoff_number = 0 // If above 0, when candidates list reaches this number, further potential candidates are rejected.
/// Begin the ghost asking
/datum/ghost_query/proc/query()
// First, ask all the ghosts who want to be asked.
for(var/mob/observer/dead/D in player_list)
if(!D.MayRespawn())
continue // They can't respawn for whatever reason.
if(D.client)
if(be_special_flag && !(D.client.prefs.be_special & be_special_flag) )
continue // They don't want to see the prompt.
for(var/ban in check_bans)
if(jobban_isbanned(D, ban))
continue // They're banned from this role.
ask_question(D.client)
for(var/mob/observer/dead/D as anything in observer_mob_list)
if(evaluate_candidate(D))
ask_question(D)
// Then wait awhile.
while(!finished)
sleep(1 SECOND)
@@ -31,36 +26,73 @@
finished = TRUE
// Prune the list after the wait, incase any candidates logged out.
for(var/mob/observer/dead/D in candidates)
if(!D.client || !D.key)
candidates.Remove(D)
for(var/mob/observer/dead/D as anything in candidates)
if(!evaluate_candidate(D))
candidates -= D
// Now we're done.
finished = TRUE
return candidates
/datum/ghost_query/proc/ask_question(var/client/C)
spawn(0)
if(!C)
return
window_flash(C)
if(query_sound)
SEND_SOUND(C, sound(query_sound))
var/response = tgui_alert(C, question, "[role_name] request", list("Yes", "No", "Never for this round"))
if(response == "Yes")
response = tgui_alert(C, "Are you sure you want to play as a [role_name]?", "[role_name] request", list("Yes", "No")) // Protection from a misclick.
if(!C || !src)
return
if(response == "Yes")
if(finished || (cutoff_number && candidates.len >= cutoff_number) )
to_chat(C, "<span class='warning'>Unfortunately, you were not fast enough, and there are no more available roles. Sorry.</span>")
return
candidates.Add(C.mob)
if(cutoff_number && candidates.len >= cutoff_number)
finished = TRUE // Finish now if we're full.
else if(response == "Never for this round")
/// Test a candidate for allowance to join as this
/datum/ghost_query/proc/evaluate_candidate(mob/observer/dead/candidate)
if(!istype(candidate))
return FALSE // Changed mobs or something who knows
if(!candidate.client)
return FALSE // No client to ask
if(!candidate.MayRespawn())
return FALSE // They can't respawn for whatever reason.
if(be_special_flag && !(candidate.client.prefs.be_special & be_special_flag) )
return FALSE // They don't want to see the prompt.
for(var/ban in check_bans)
if(jobban_isbanned(candidate, ban))
return FALSE // They're banned from this role.
return TRUE
/// Send async alerts and ask for responses. Expects you to have tested D for client and type already
/datum/ghost_query/proc/ask_question(var/mob/observer/dead/D)
var/client/C = D.client
window_flash(C)
if(query_sound)
SEND_SOUND(C, sound(query_sound))
tgui_alert_async(D, question, "[role_name] request", list("Yes", "No", "Never for this round"), CALLBACK(src, .proc/get_reply), wait_time SECONDS)
/// Process an async alert response
/datum/ghost_query/proc/get_reply(response)
var/mob/observer/dead/D = usr
if(!D?.client)
return
// Unhandled are "No" and "Nevermind" responses, which should just do nothing
// This response is always fine, doesn't warrant retesting
switch(response)
if("Never for this round")
if(be_special_flag)
C.prefs.be_special ^= be_special_flag
D.client.prefs.be_special ^= be_special_flag
to_chat(D, "<span class='notice'>You will not be prompted to join similar roles to [role_name] for the rest of this round. Note: If you save your character now, it will save this permanently.</span>")
else
to_chat(D, "<span class='warning'>This type of ghost-joinable role doesn't have a role type flag associated with it, so I can't prevent future requests, sorry. Bug a dev!</span>")
if("Yes")
if(!evaluate_candidate(D)) // Failed revalidation
to_chat(D, "<span class='warning'>Unfortunately, you no longer qualify for this role. Sorry.</span>")
else if(finished) // Already finished candidate list
to_chat(D, "<span class='warning'>Unfortunately, you were not fast enough, and there are no more available roles. Sorry.</span>")
else // Prompt a second time
tgui_alert_async(D, "Are you sure you want to play as a [role_name]?", "[role_name] request", list("I'm Sure", "Nevermind"), CALLBACK(src, .proc/get_reply), wait_time SECONDS)
if("I'm Sure")
if(!evaluate_candidate(D)) // Failed revalidation
to_chat(D, "<span class='warning'>Unfortunately, you no longer qualify for this role. Sorry.</span>")
else if(finished) // Already finished candidate list
to_chat(D, "<span class='warning'>Unfortunately, you were not fast enough, and there are no more available roles. Sorry.</span>")
else // Accept their nomination
candidates.Add(D)
if(cutoff_number && candidates.len >= cutoff_number)
finished = TRUE // Finish now if we're full.
// Normal things.
/datum/ghost_query/promethean
@@ -16,33 +16,63 @@
/mob/living/simple_mob/animal/giant_spider/carrier //or the ones who fart babies when they die
ic_revivable = 0
//WHEN GHOSTS ATTACK!!!!!
/// A ghost has clicked us
/mob/living/simple_mob/attack_ghost(mob/observer/dead/user as mob)
if(!ghostjoin)
return ..()
var/reply = tgui_alert(usr, "Would you like to become [src]? It is bound to [revivedby].","Bind To",list("Yes","No"))
if(reply == "No")
return
if(!evaluate_ghost_join(user))
return ..()
if(ckey) //FIRST ONE TO CLICK YES GETS IT!!!!!! Channel your inner youtube commenter.
to_chat(src, "<span class='notice'>Sorry, someone else has already inhabited [src].</span>")
return
log_and_message_admins("[key_name_admin(user)] joined [src] as a ghost [ADMIN_FLW(src)]")
tgui_alert_async(usr, "Would you like to become [src]? It is bound to [revivedby].", "Become Mob", list("Yes","No"), CALLBACK(src, .proc/reply_ghost_join), 20 SECONDS)
/// A reply to an async alert request was received
/mob/living/simple_mob/proc/reply_ghost_join(response)
if(response != "Yes")
return // ok
var/mob/observer/dead/D = usr
if(evaluate_ghost_join(D))
ghost_join(D)
/// Inject a ghost into this mob. Assumes you've done all sanity before this point.
/mob/living/simple_mob/proc/ghost_join(mob/observer/dead/D)
log_and_message_admins("[key_name_admin(D)] joined [src] as a ghost [ADMIN_FLW(src)]")
active_ghost_pods -= src
if(user.mind)
user.mind.active = TRUE
user.mind.transfer_to(src)
// Move the ghost in
if(D.mind)
D.mind.active = TRUE
D.mind.transfer_to(src)
else
src.ckey = user.ckey
qdel(user)
ghostjoin = 0
src.ckey = D.ckey
qdel(D)
// Clean up the simplemob
ghostjoin = FALSE
ghostjoin_icon()
if(revivedby != "no one")
to_chat(src, "<span class='notice'>Where once your life had been rough and scary, you have been assisted by [revivedby]. They seem to be the reason you are on your feet again... so perhaps you should help them out.</span> <span class= warning> Being as you were revived, you are allied with the station. Do not attack anyone unless they are threatening the one who revived you. And try to listen to the one who revived you within reason. Of course, you may do scenes as you like, but you must still respect preferences.</span>")
visible_message("[src]'s eyes flicker with a curious intelligence.")
visible_message("[src]'s eyes flicker with a curious intelligence.", runemessage = "looks around")
/// Evaluate someone for being allowed to join as this mob from being a ghost
/mob/living/simple_mob/proc/evaluate_ghost_join(mob/observer/dead/D)
if(!istype(D) || !D.client)
stack_trace("A non-ghost mob was evaluated for joining into a simplemob...")
return FALSE
// At this point we can at least send them messages as to why they can't join, since they are a mob with a client
if(!ghostjoin)
to_chat(D, "<span class='notice'>Sorry, [src] is no longer ghost-joinable.</span>")
return FALSE
if(ckey)
to_chat(D, "<span class='notice'>Sorry, someone else has already inhabited [src].</span>")
return FALSE
// Insert whatever ban checks you want here if we ever add simplemob bans
return TRUE
/obj/item/device/denecrotizer //Away map reward. FOR TRAINED NECROMANCERS ONLY. >:C
name = "experimental denecrotizer"
@@ -130,6 +130,7 @@
name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
real_name = name
animate(src, pixel_y = 2, time = 10, loop = -1)
observer_mob_list += src
..()
/mob/observer/dead/Topic(href, href_list)
@@ -504,6 +505,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/mob/M = following
M.following_mobs -= src
stop_following()
observer_mob_list -= src
return ..()
/mob/Moved(atom/old_loc, direction, forced = FALSE)