Port lots of things that had to wait on alerts

Adds a HUD for observers
Adds a HUD for rigs and mechs
Adds up/down buttons for AI hud
Add more tg style alerts
Fix some bugs with the tg alerts
Improve icon_states usage by caching it
Redo how respawning works, add a button to ghost hud for it
This commit is contained in:
Rykka
2020-07-30 16:23:32 -04:00
parent c742c44668
commit 28a7698b9e
63 changed files with 1438 additions and 831 deletions
+3
View File
@@ -6,3 +6,6 @@
plane_holder.set_vis(VIS_CLOAKED, TRUE)
plane_holder.set_vis(VIS_AI_EYE, TRUE)
plane = PLANE_GHOSTS
if(cleanup_timer)
deltimer(cleanup_timer)
cleanup_timer = null
+2
View File
@@ -3,3 +3,5 @@
spawn(0)
if(src && !key) //we've transferred to another mob. This ghost should be deleted.
qdel(src)
else
cleanup_timer = QDEL_IN(src, 10 MINUTES)
+91 -40
View File
@@ -86,6 +86,7 @@
"Beepsky" = "secbot"
)
var/last_revive_notification = null // world.time of last notification, used to avoid spamming players from defibs or cloners.
var/cleanup_timer // Refernece to a timer that will delete this mob if no client returns
/mob/observer/dead/New(mob/body)
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
@@ -129,6 +130,7 @@
if(!name) //To prevent nameless ghosts
name = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
real_name = name
animate(src, pixel_y = 2, time = 10, loop = -1)
..()
/mob/observer/dead/Topic(href, href_list)
@@ -152,6 +154,13 @@
if(new_stat != DEAD)
CRASH("It is best if observers stay dead, thank you.")
/mob/observer/dead/examine_icon()
var/icon/I = get_cached_examine_icon(src)
if(!I)
I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE)
set_cached_examine_icon(src, I, 200 SECONDS)
return I
/*
Transfer_mind is there to check if mob is being deleted/not going to have a body.
Works together with spawning an observer, noted above.
@@ -220,6 +229,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/mob/observer/dead/ghost = ghostize(0) // 0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
if(ghost)
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
ghost.set_respawn_timer()
announce_ghost_joinleave(ghost)
/mob/observer/dead/can_use_hands() return 0
@@ -290,6 +300,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/response = alert(src, "If you turn this on, you will not be able to take any part in the round.","Are you sure you want to turn this feature on?","Yes","No")
if(response == "No") return
can_reenter_corpse = FALSE
set_respawn_timer(-1) // Foreeeever
if(!has_enabled_antagHUD && !client.holder)
has_enabled_antagHUD = TRUE
@@ -306,6 +317,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, "Not when you're not dead!")
return
if(!A)
A = input(usr, "Select an area:", "Ghost Teleport") as null|anything in return_sorted_areas()
if(!A)
return
usr.forceMove(pick(get_area_turfs(A)))
usr.on_mob_jump()
@@ -314,6 +330,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Follow" // "Haunt"
set desc = "Follow and haunt a mob."
if(!input)
input = input(usr, "Select a mob:", "Ghost Follow") as null|anything in getmobs()
if(!input)
return
var/target = getmobs()[input]
if(!target) return
ManualFollow(target)
@@ -347,6 +368,45 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
forceMove(T)
sleep(15)
var/icon/I = icon(target.icon,target.icon_state,target.dir)
var/orbitsize = (I.Width()+I.Height())*0.5
orbitsize -= (orbitsize/world.icon_size)*(world.icon_size*0.25)
var/rot_seg
/* We don't have this pref yet
switch(ghost_orbit)
if(GHOST_ORBIT_TRIANGLE)
rot_seg = 3
if(GHOST_ORBIT_SQUARE)
rot_seg = 4
if(GHOST_ORBIT_PENTAGON)
rot_seg = 5
if(GHOST_ORBIT_HEXAGON)
rot_seg = 6
else //Circular
rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle
*/
orbit(target, orbitsize, FALSE, 20, rot_seg)
/mob/observer/dead/orbit()
set_dir(2) //reset dir so the right directional sprites show up
return ..()
/mob/observer/dead/stop_orbit(datum/component/orbiter/orbits)
. = ..()
//restart our floating animation after orbit is done.
pixel_y = 0
pixel_x = 0
transform = null
animate(src, pixel_y = 2, time = 10, loop = -1)
/mob/observer/dead/proc/stop_following()
following = null
stop_orbit()
/mob/proc/update_following()
. = get_turf(src)
for(var/mob/observer/dead/M in following_mobs)
@@ -361,7 +421,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/Destroy()
for(var/mob/observer/dead/M in following_mobs)
M.following = null
M.stop_following()
following_mobs = null
return ..()
@@ -369,7 +429,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(ismob(following))
var/mob/M = following
M.following_mobs -= src
following = null
stop_following()
return ..()
/mob/Moved(atom/old_loc, direction, forced = FALSE)
@@ -394,35 +454,28 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set category = "Ghost"
set name = "Jump to Mob"
set desc = "Teleport to a mob"
set popup_menu = FALSE
if(istype(usr, /mob/observer/dead)) //Make sure they're an observer!
var/target = getmobs()[input]
if (!target)//Make sure we actually have a target
return
else
var/mob/M = target //Destination mob
var/turf/T = get_turf(M) //Turf of the destination mob
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
forceMove(T)
following = null
else
to_chat(src, "This mob is not located in the game world.")
/*
/mob/observer/dead/verb/boo()
set category = "Ghost"
set name = "Boo!"
set desc= "Scare your crew members because of boredom!"
if(bootime > world.time) return
var/obj/machinery/light/L = locate(/obj/machinery/light) in view(1, src)
if(L)
L.flicker()
bootime = world.time + 600
if(!istype(usr, /mob/observer/dead)) //Make sure they're an observer!
return
//Maybe in the future we can add more <i>spooky</i> code here!
return
*/
if(!input)
input = input(usr, "Select a mob:", "Ghost Jump") as null|anything in getmobs()
if(!input)
return
var/target = getmobs()[input]
if (!target)//Make sure we actually have a target
return
else
var/mob/M = target //Destination mob
var/turf/T = get_turf(M) //Turf of the destination mob
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
forceMove(T)
stop_following()
else
to_chat(src, "This mob is not located in the game world.")
/mob/observer/dead/memory()
set hidden = 1
@@ -433,7 +486,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(src, "<font color='red'>You are dead! You have no mind to store memory!</font>")
/mob/observer/dead/Post_Incorpmove()
following = null
stop_following()
/mob/observer/dead/verb/analyze_air()
set name = "Analyze Air"
@@ -801,13 +854,19 @@ mob/observer/dead/MayRespawn(var/feedback = 0)
set category = "Ghost"
set name = "Blank pAI alert"
set desc = "Flash an indicator light on available blank pAI devices for a smidgen of hope."
if(usr.client.prefs.be_special & BE_PAI)
if(usr.client.prefs?.be_special & BE_PAI)
var/count = 0
for(var/obj/item/device/paicard/p in all_pai_cards)
var/obj/item/device/paicard/PP = p
if(PP.pai == null)
count++
PP.overlays += "pai-ghostalert"
spawn(54)
PP.overlays.Cut()
to_chat(usr,"<span class='notice'>Flashing the displays of [count] unoccupied PAIs.</span>")
else
to_chat(usr,"<span class='warning'>You have 'Be pAI' disabled in your character prefs, so we can't help you.</span>")
/mob/observer/dead/speech_bubble_appearance()
return "ghost"
@@ -824,15 +883,7 @@ mob/observer/dead/MayRespawn(var/feedback = 0)
if(message)
to_chat(src, "<span class='ghostalert'><font size=4>[message]</font></span>")
if(source)
var/obj/screen/alert/A = throw_alert("\ref[source]_notify_revive", /obj/screen/alert/notify_cloning)
if(A)
if(client && client.prefs && client.prefs.UI_style)
A.icon = ui_style2icon(client.prefs.UI_style)
A.desc = message
var/old_layer = source.layer
source.layer = FLOAT_LAYER
A.overlays += source
source.layer = old_layer
throw_alert("\ref[source]_notify_revive", /obj/screen/alert/notify_cloning, new_master = source)
to_chat(src, "<span class='ghostalert'><a href=?src=[REF(src)];reenter=1>(Click to re-enter)</a></span>")
if(sound)
SEND_SOUND(src, sound(sound))
+2 -1
View File
@@ -100,7 +100,8 @@
if(mind) mind.store_memory("Time of death: [stationtime2text()]", 0)
living_mob_list -= src
dead_mob_list |= src
set_respawn_timer()
updateicon()
handle_regular_hud_updates()
handle_vision()
@@ -1566,6 +1566,13 @@
else
layer = HIDING_LAYER
/mob/living/carbon/human/examine_icon()
var/icon/I = get_cached_examine_icon(src)
if(!I)
I = getFlatIcon(src, defdir = SOUTH, no_anim = TRUE)
set_cached_examine_icon(src, I, 50 SECONDS)
return I
/mob/living/carbon/human/proc/get_display_species()
//Shows species in tooltip
//Beepboops get special text if obviously beepboop
@@ -309,7 +309,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
base_icon.MapColors(rgb(tone[1],0,0),rgb(0,tone[2],0),rgb(0,0,tone[3]))
//Handle husk overlay.
if(husk && ("overlay_husk" in icon_states(species.icobase)))
if(husk && ("overlay_husk" in cached_icon_states(species.icobase)))
var/icon/mask = new(base_icon)
var/icon/husk_over = new(species.icobase,"overlay_husk")
mask.MapColors(0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0)
+15
View File
@@ -118,11 +118,17 @@
/mob/living/proc/handle_stunned()
if(stunned)
AdjustStunned(-1)
throw_alert("stunned", /obj/screen/alert/stunned)
else
clear_alert("stunned")
return stunned
/mob/living/proc/handle_weakened()
if(weakened)
AdjustWeakened(-1)
throw_alert("weakened", /obj/screen/alert/weakened)
else
clear_alert("weakened")
return weakened
/mob/living/proc/handle_stuttering()
@@ -138,6 +144,9 @@
/mob/living/proc/handle_drugged()
if(druggy)
druggy = max(druggy-1, 0)
throw_alert("high", /obj/screen/alert/high)
else
clear_alert("high")
return druggy
/mob/living/proc/handle_slurring()
@@ -148,11 +157,17 @@
/mob/living/proc/handle_paralysed()
if(paralysis)
AdjustParalysis(-1)
throw_alert("paralyzed", /obj/screen/alert/paralyzed)
else
clear_alert("paralyzed")
return paralysis
/mob/living/proc/handle_confused()
if(confused)
AdjustConfused(-1)
throw_alert("confused", /obj/screen/alert/confused)
else
clear_alert("confused")
return confused
/mob/living/proc/handle_disabilities()
@@ -29,4 +29,5 @@ var/global/list/empty_playable_ai_cores = list()
global_announcer.autosay("[src] has been moved to intelligence storage.", "Artificial Intelligence Oversight")
//Handle job slot/tater cleanup.
set_respawn_timer()
clear_client()
@@ -1,6 +1,5 @@
/mob/living/simple_mob/instantiate_hud(var/datum/hud/hud)
if(!client)
return //Why bother.
/mob/living/simple_mob/create_mob_hud(datum/hud/HUD)
..()
var/ui_style = 'icons/mob/screen1_animal.dmi'
if(ui_icons)
@@ -14,9 +13,9 @@
var/list/hotkeybuttons = list()
var/list/slot_info = list()
hud.adding = adding
hud.other = other
hud.hotkeybuttons = hotkeybuttons
HUD.adding = adding
HUD.other = other
HUD.hotkeybuttons = hotkeybuttons
var/list/hud_elements = list()
var/obj/screen/using
@@ -65,8 +64,8 @@
using.screen_loc = ui_acti
using.color = ui_color
using.alpha = ui_alpha
hud.adding += using
hud.action_intent = using
HUD.adding += using
HUD.action_intent = using
hud_elements |= using
@@ -82,8 +81,8 @@
using.screen_loc = ui_acti
using.alpha = ui_alpha
using.layer = LAYER_HUD_ITEM //These sit on the intent box
hud.adding += using
hud.help_intent = using
HUD.adding += using
HUD.help_intent = using
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
@@ -94,8 +93,8 @@
using.screen_loc = ui_acti
using.alpha = ui_alpha
using.layer = LAYER_HUD_ITEM
hud.adding += using
hud.disarm_intent = using
HUD.adding += using
HUD.disarm_intent = using
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
@@ -106,8 +105,8 @@
using.screen_loc = ui_acti
using.alpha = ui_alpha
using.layer = LAYER_HUD_ITEM
hud.adding += using
hud.grab_intent = using
HUD.adding += using
HUD.grab_intent = using
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
@@ -118,8 +117,8 @@
using.screen_loc = ui_acti
using.alpha = ui_alpha
using.layer = LAYER_HUD_ITEM
hud.adding += using
hud.hurt_intent = using
HUD.adding += using
HUD.hurt_intent = using
//Move intent (walk/run)
using = new /obj/screen()
@@ -129,8 +128,8 @@
using.screen_loc = ui_movi
using.color = ui_color
using.alpha = ui_alpha
hud.adding += using
hud.move_intent = using
HUD.adding += using
HUD.move_intent = using
//Resist button
using = new /obj/screen()
@@ -140,7 +139,7 @@
using.screen_loc = ui_pull_resist
using.color = ui_color
using.alpha = ui_alpha
hud.hotkeybuttons += using
HUD.hotkeybuttons += using
//Pull button
pullin = new /obj/screen()
@@ -148,7 +147,7 @@
pullin.icon_state = "pull0"
pullin.name = "pull"
pullin.screen_loc = ui_pull_resist
hud.hotkeybuttons += pullin
HUD.hotkeybuttons += pullin
hud_elements |= pullin
//Health status
@@ -159,8 +158,6 @@
healths.screen_loc = ui_health
hud_elements |= healths
pain = new /obj/screen( null )
zone_sel = new /obj/screen/zone_sel( null )
@@ -181,7 +178,7 @@
using.screen_loc = ui_drop_throw
using.color = ui_color
using.alpha = ui_alpha
hud.hotkeybuttons += using
HUD.hotkeybuttons += using
//Equip detail
using = new /obj/screen()
@@ -191,7 +188,7 @@
using.screen_loc = ui_equip
using.color = ui_color
using.alpha = ui_alpha
hud.adding += using
HUD.adding += using
//Hand slots themselves
inv_box = new /obj/screen/inventory/hand()
@@ -205,8 +202,8 @@
inv_box.slot_id = slot_r_hand
inv_box.color = ui_color
inv_box.alpha = ui_alpha
hud.r_hand_hud_object = inv_box
hud.adding += inv_box
HUD.r_hand_hud_object = inv_box
HUD.adding += inv_box
slot_info["[slot_r_hand]"] = inv_box.screen_loc
inv_box = new /obj/screen/inventory/hand()
@@ -220,8 +217,8 @@
inv_box.slot_id = slot_l_hand
inv_box.color = ui_color
inv_box.alpha = ui_alpha
hud.l_hand_hud_object = inv_box
hud.adding += inv_box
HUD.l_hand_hud_object = inv_box
HUD.adding += inv_box
slot_info["[slot_l_hand]"] = inv_box.screen_loc
//Swaphand titlebar
@@ -232,7 +229,7 @@
using.screen_loc = ui_swaphand1
using.color = ui_color
using.alpha = ui_alpha
hud.adding += using
HUD.adding += using
using = new /obj/screen/inventory()
using.name = "hand"
@@ -241,7 +238,7 @@
using.screen_loc = ui_swaphand2
using.color = ui_color
using.alpha = ui_alpha
hud.adding += using
HUD.adding += using
//Throw button
throw_icon = new /obj/screen()
@@ -251,15 +248,13 @@
throw_icon.screen_loc = ui_drop_throw
throw_icon.color = ui_color
throw_icon.alpha = ui_alpha
hud.hotkeybuttons += throw_icon
HUD.hotkeybuttons += throw_icon
hud_elements |= throw_icon
extra_huds(hud,ui_style,hud_elements)
extra_huds(HUD, HUD.ui_style, hud_elements)
client.screen = list()
client.screen += hud_elements
client.screen += adding + hotkeybuttons
client.screen += client.void
return
if(client)
client.screen = list()
client.screen += hud_elements
client.screen += adding + hotkeybuttons
client.screen += client.void
+43 -33
View File
@@ -333,46 +333,56 @@
return
*/
/mob/proc/set_respawn_timer(var/time)
// Try to figure out what time to use
// Special cases, can never respawn
if(ticker?.mode?.deny_respawn)
time = -1
else if(!config.abandon_allowed)
time = -1
else if(!config.respawn)
time = -1
// Special case for observing before game start
else if(ticker?.current_state <= GAME_STATE_SETTING_UP)
time = 1 MINUTE
// Wasn't given a time, use the config time
else if(!time)
time = config.respawn_time
var/keytouse = ckey
// Try harder to find a key to use
if(!keytouse && key)
keytouse = ckey(key)
else if(!keytouse && mind?.key)
keytouse = ckey(mind.key)
GLOB.respawn_timers[keytouse] = world.time + time
/mob/observer/dead/set_respawn_timer()
if(config.antag_hud_restricted && has_enabled_antagHUD)
..(-1)
else
return // Don't set it, no need
/mob/verb/abandon_mob()
set name = "Respawn"
set name = "Return to Menu"
set category = "OOC"
if (!( config.abandon_allowed ))
to_chat(usr, "<span class='notice'>Respawn is disabled.</span>")
return
if ((stat != 2 || !( ticker )))
if(stat != DEAD || !ticker)
to_chat(usr, "<span class='notice'><B>You must be dead to use this!</B></span>")
return
if (ticker.mode && ticker.mode.deny_respawn) //BS12 EDIT
to_chat(usr, "<span class='notice'>Respawn is disabled for this roundtype.</span>")
return
else
var/deathtime = world.time - src.timeofdeath
if(istype(src,/mob/observer/dead))
var/mob/observer/dead/G = src
if(G.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
to_chat(usr, "<font color='blue'><B>By using the antagHUD you forfeit the ability to join the round.</B></font>")
return
var/deathtimeminutes = round(deathtime / 600)
var/pluralcheck = "minute"
if(deathtimeminutes == 0)
pluralcheck = ""
else if(deathtimeminutes == 1)
pluralcheck = " [deathtimeminutes] minute and"
else if(deathtimeminutes > 1)
pluralcheck = " [deathtimeminutes] minutes and"
var/deathtimeseconds = round((deathtime - deathtimeminutes * 600) / 10,1)
to_chat(usr, "You have been dead for[pluralcheck] [deathtimeseconds] seconds.")
if ((deathtime < (5 * 600)) && (ticker && ticker.current_state > GAME_STATE_PREGAME))
to_chat(usr, "You must wait 5 minutes to respawn!")
// Final chance to abort "respawning"
if(mind && timeofdeath) // They had spawned before
var/choice = alert(usr, "Returning to the menu will prevent your character from being revived in-round. Are you sure?", "Confirmation", "No, wait", "Yes, leave")
if(choice == "No, wait")
return
else
to_chat(usr, "You can respawn now, enjoy your new life!")
log_game("[usr.name]/[usr.key] used abandon mob.")
to_chat(usr, "<font color='blue'><B>Make sure to play a different character, and please roleplay correctly!</B></font>")
// Beyond this point, you're going to respawn
to_chat(usr, config.respawn_message)
if(!client)
log_game("[usr.key] AM failed due to disconnect.")
+1 -1
View File
@@ -9,7 +9,7 @@ var/obj/effect/lobby_image = new /obj/effect/lobby_image
/obj/effect/lobby_image/Initialize()
icon = using_map.lobby_icon
var/known_icon_states = icon_states(icon)
var/known_icon_states = cached_icon_states(icon)
for(var/lobby_screen in using_map.lobby_screens)
if(!(lobby_screen in known_icon_states))
error("Lobby screen '[lobby_screen]' did not exist in the icon set [icon].")
+26 -2
View File
@@ -120,8 +120,9 @@
new_player_panel_proc()
if(href_list["observe"])
var/alert_time = ticker?.current_state <= GAME_STATE_SETTING_UP ? 1 : round(config.respawn_time/10/60)
if(alert(src,"Are you sure you wish to observe? You will have to wait 5 minutes before being able to respawn!","Player Setup","Yes","No") == "Yes")
if(alert(src,"Are you sure you wish to observe? You will have to wait up to [alert_time] minute\s before being able to spawn into the game!","Player Setup","Yes","No") == "Yes")
if(!client) return 1
//Make a new mannequin quickly, and allow the observer to take the appearance
@@ -143,7 +144,6 @@
observer.forceMove(O.loc)
else
to_chat(src, "<span class='danger'>Could not locate an observer spawn point. Use the Teleport verb to jump to the station map.</span>")
observer.timeofdeath = world.time // Set the time of death so that the respawn timer works correctly.
announce_ghost_joinleave(src)
@@ -154,6 +154,7 @@
if(!client.holder && !config.antag_hud_allowed) // For new ghosts we remove the verb from even showing up if it's not allowed.
observer.verbs -= /mob/observer/dead/verb/toggle_antagHUD // Poor guys, don't know what they are missing!
observer.key = key
observer.set_respawn_timer(time_till_respawn()) // Will keep their existing time if any, or return 0 and pass 0 into set_respawn_timer which will use the defaults
qdel(src)
return 1
@@ -163,6 +164,12 @@
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
to_chat(usr, "<font color='red'>The round is either not ready, or has already finished...</font>")
return
var/time_till_respawn = time_till_respawn()
if(time_till_respawn == -1) // Special case, never allowed to respawn
to_chat(usr, "<span class='warning'>Respawning is not allowed!</span>")
else if(time_till_respawn) // Nonzero time to respawn
to_chat(usr, "<span class='warning'>You can't respawn yet! You need to wait another [round(time_till_respawn/10/60, 0.1)] minutes.</span>")
return
LateChoices()
if(href_list["manifest"])
@@ -331,6 +338,23 @@
popup.set_content(dat)
popup.open()
/mob/new_player/proc/time_till_respawn()
if(!ckey)
return -1 // What?
var/timer = GLOB.respawn_timers[ckey]
// No timer at all
if(!timer)
return 0
// Special case, infinite timer
if(timer == -1)
return -1
// Timer expired
if(timer <= world.time)
GLOB.respawn_timers -= ckey
return 0
// Timer still going
return timer - world.time
/mob/new_player/proc/IsJobAvailable(rank)
var/datum/job/job = job_master.GetJob(rank)