diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index fa14c1ca48..bc11bad8bc 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -78,6 +78,13 @@ #define ui_ai_multicam "SOUTH+1:6,WEST+12:16" #define ui_ai_add_multicam "SOUTH+1:6,WEST+13:16" +//Upper-middle right (alerts) +#define ui_alert1 "EAST-1:28,CENTER+5:27" +#define ui_alert2 "EAST-1:28,CENTER+4:25" +#define ui_alert3 "EAST-1:28,CENTER+3:23" +#define ui_alert4 "EAST-1:28,CENTER+2:21" +#define ui_alert5 "EAST-1:28,CENTER+1:19" + //Gun buttons #define ui_gun1 "EAST-2:26,SOUTH+2:7" #define ui_gun2 "EAST-1:28, SOUTH+3:7" @@ -96,13 +103,12 @@ #define ui_alien_oxygen "EAST-1:28,NORTH-4:25" //Middle right (status indicators) -#define ui_nutrition "EAST-1:28,CENTER-2:11" -#define ui_temp "EAST-1:28,CENTER-1:13" -#define ui_health "EAST-1:28,CENTER:15" -#define ui_internal "EAST-1:28,CENTER+1:17" +#define ui_temp "EAST-1:28,CENTER-2:13" +#define ui_health "EAST-1:28,CENTER-1:15" +#define ui_internal "EAST-1:28,CENTER:17" //borgs -#define ui_borg_health "EAST-1:28,CENTER-1:13" //borgs have the health display where humans have the pressure damage indicator. -#define ui_alien_health "EAST-1:28,CENTER-1:13" //aliens have the health display where humans have the pressure damage indicator. +#define ui_borg_health "EAST-1:28,CENTER-2:13" //borgs have the health display where humans have the pressure damage indicator. +#define ui_alien_health "EAST-1:28,CENTER-2:13" //aliens have the health display where humans have the pressure damage indicator. #define ui_ling_chemical_display "EAST-1:28,CENTER-3:15" #define ui_wiz_energy_display "EAST-1:28,CENTER-3:15" diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm new file mode 100644 index 0000000000..3a7727a9f6 --- /dev/null +++ b/code/_onclick/hud/alert.dm @@ -0,0 +1,443 @@ +//A system to manage and display alerts on screen without needing you to do it yourself + +//PUBLIC - call these wherever you want + + +/mob/proc/throw_alert(category, type, severity, obj/new_master) + +/* Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already + category is a text string. Each mob may only have one alert per category; the previous one will be replaced + path is a type path of the actual alert type to throw + severity is an optional number that will be placed at the end of the icon_state for this alert + For example, high pressure's icon_state is "highpressure" and can be serverity 1 or 2 to get "highpressure1" or "highpressure2" + new_master is optional and sets the alert's icon state to "template" in the ui_style icons with the master as an overlay. + Clicks are forwarded to master */ + + if(!category) + return + + var/obj/screen/alert/alert + if(alerts[category]) + alert = alerts[category] + if(new_master && new_master != alert.master) + WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [alert.master]") + clear_alert(category) + return .() + else if(alert.type != type) + clear_alert(category) + return .() + else if(!severity || severity == alert.severity) + if(alert.timeout) + clear_alert(category) + return .() + else //no need to update + return 0 + else + alert = new type + + if(new_master) + var/old_layer = new_master.layer + var/old_plane = new_master.plane + new_master.layer = LAYER_HUD_ABOVE + new_master.plane = PLANE_PLAYER_HUD_ABOVE + alert.overlays += new_master + new_master.layer = old_layer + new_master.plane = old_plane + alert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts() + alert.master = new_master + else + alert.icon_state = "[initial(alert.icon_state)][severity]" + alert.severity = severity + + alerts[category] = alert + if(client && hud_used) + hud_used.reorganize_alerts() + alert.transform = matrix(32, 6, MATRIX_TRANSLATE) + animate(alert, transform = matrix(), time = 2.5, easing = CUBIC_EASING) + + if(alert.timeout) + spawn(alert.timeout) + if(alert.timeout && alerts[category] == alert && world.time >= alert.timeout) + clear_alert(category) + alert.timeout = world.time + alert.timeout - world.tick_lag + return alert + +// Proc to clear an existing alert. +/mob/proc/clear_alert(category) + var/obj/screen/alert/alert = alerts[category] + if(!alert) + return 0 + + alerts -= category + if(client && hud_used) + hud_used.reorganize_alerts() + client.screen -= alert + qdel(alert) + +/obj/screen/alert + icon = 'icons/mob/screen_alert.dmi' + icon_state = "default" + name = "Alert" + desc = "Something seems to have gone wrong with this alert, so report this bug please" + mouse_opacity = 1 + var/timeout = 0 //If set to a number, this alert will clear itself after that many deciseconds + var/severity = 0 + var/alerttooltipstyle = "" + + +/obj/screen/alert/MouseEntered(location,control,params) + openToolTip(usr, src, params, title = name, content = desc, theme = alerttooltipstyle) + + +/obj/screen/alert/MouseExited() + closeToolTip(usr) + + +//Gas alerts +/obj/screen/alert/not_enough_oxy + name = "Choking (No O2)" + desc = "You're not getting enough oxygen. Find some good air before you pass out! \ +The box in your backpack has an oxygen tank and breath mask in it." + icon_state = "not_enough_oxy" + +/obj/screen/alert/too_much_oxy + name = "Choking (O2)" + desc = "There's too much oxygen in the air, and you're breathing it in! Find some good air before you pass out!" + icon_state = "too_much_oxy" + +/obj/screen/alert/not_enough_nitro + name = "Choking (No N)" + desc = "You're not getting enough nitrogen. Find some good air before you pass out!" + icon_state = "not_enough_nitro" + +/obj/screen/alert/too_much_nitro + name = "Choking (N)" + desc = "There's too much nitrogen in the air, and you're breathing it in! Find some good air before you pass out!" + icon_state = "too_much_nitro" + +/obj/screen/alert/not_enough_co2 + name = "Choking (No CO2)" + desc = "You're not getting enough carbon dioxide. Find some good air before you pass out!" + icon_state = "not_enough_co2" + +/obj/screen/alert/too_much_co2 + name = "Choking (CO2)" + desc = "There's too much carbon dioxide in the air, and you're breathing it in! Find some good air before you pass out!" + icon_state = "too_much_co2" + +/obj/screen/alert/too_much_co2/plant + name = "Livin' the good life" + desc = "There's so much carbon dioxide in the air, you're in fucking heaven. Watch out for passed out fleshies, though." + icon_state = "too_much_co2" + +/obj/screen/alert/not_enough_tox + name = "Choking (No Phoron)" + desc = "You're not getting enough phoron. Find some good air before you pass out!" + icon_state = "not_enough_tox" + +/obj/screen/alert/tox_in_air + name = "Choking (Phoron)" + desc = "There's highly flammable, toxic phoron in the air and you're breathing it in. Find some fresh air. \ +The box in your backpack has an oxygen tank and gas mask in it." + icon_state = "too_much_tox" + +/obj/screen/alert/not_enough_fuel + name = "Choking (No Volatile fuel)" + desc = "You're not getting enough volatile fuel. Find some good air before you pass out!" + icon_state = "not_enough_tox" + +/obj/screen/alert/not_enough_n2o + name = "Choking (No Sleeping Gas)" + desc = "You're not getting enough sleeping gas. Find some good air before you pass out!" + icon_state = "not_enough_tox" +//End gas alerts + + +/obj/screen/alert/fat + name = "Fat" + desc = "You ate too much food, lardass. Run around the station and lose some weight." + icon_state = "fat" + +/obj/screen/alert/fat/vampire + desc = "You drank too much blood, lardass. Run around the station and lose some weight." + icon_state = "v_fat" + +/obj/screen/alert/fat/synth + desc = "Your battery is full! Don't overvolt it." + icon_state = "c_fat" + +/obj/screen/alert/hungry + name = "Hungry" + desc = "Some food would be good right about now." + icon_state = "hungry" + +/obj/screen/alert/hungry/vampire + desc = "You could use a bloodsnack or two." + icon_state = "v_hungry" + +/obj/screen/alert/hungry/synth + desc = "Battery's running a bit low, could use a topoff." + icon_state = "c_hungry" + +/obj/screen/alert/starving + name = "Starving" + desc = "You're severely malnourished. The hunger pains make moving around a chore." + icon_state = "starving" + +/obj/screen/alert/starving/vampire + desc = "You *need* blood; go rip out someone's throat already!" + icon_state = "v_starving" + +/obj/screen/alert/starving/synth + desc = "Your battery is about to die! Charge it ASAP!" + icon_state = "c_starving" + +/obj/screen/alert/hot + name = "Too Hot" + desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit." + icon_state = "hot" + +/obj/screen/alert/hot/robot + desc = "The air around you is too hot for a humanoid. Be careful to avoid exposing them to this enviroment." + +/obj/screen/alert/cold + name = "Too Cold" + desc = "You're freezing cold! Get somewhere warmer and take off any insulating clothing like a space suit." + icon_state = "cold" + +/obj/screen/alert/cold/robot + desc = "The air around you is too cold for a humanoid. Be careful to avoid exposing them to this enviroment." + +/obj/screen/alert/lowpressure + name = "Low Pressure" + desc = "The air around you is hazardously thin. A space suit would protect you." + icon_state = "lowpressure" + +/obj/screen/alert/highpressure + name = "High Pressure" + desc = "The air around you is hazardously thick. A fire suit would protect you." + icon_state = "highpressure" + +/obj/screen/alert/blind + name = "Blind" + desc = "You can't see! This may be caused by a genetic defect, eye trauma, being unconscious, \ +or something covering your eyes." + icon_state = "blind" + +/obj/screen/alert/high + name = "High" + desc = "Whoa man, you're tripping balls! Careful you don't get addicted... if you aren't already." + icon_state = "high" + +/obj/screen/alert/embeddedobject + name = "Embedded Object" + desc = "Something got lodged into your flesh and is causing major bleeding. It might fall out with time, but surgery is the safest way. \ +If you're feeling frisky, right click on yourself and select \"Remove embedded object\" to pull the object out." + icon_state = "embeddedobject" + +/obj/screen/alert/embeddedobject/Click() + if(isliving(usr)) + var/mob/living/carbon/human/M = usr + return M.help_shake_act(M) + +/obj/screen/alert/asleep + name = "Asleep" + desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are." + icon_state = "asleep" + +/obj/screen/alert/weightless + name = "Weightless" + desc = "Gravity has ceased affecting you, and you're floating around aimlessly. You'll need something large and heavy, like a \ +wall or lattice, to push yourself off if you want to move. A jetpack would enable free range of motion. A pair of \ +magboots would let you walk around normally on the floor. Barring those, you can throw things, use a fire extinguisher, \ +or shoot a gun to move around via Newton's 3rd Law of Motion." + icon_state = "weightless" + +/obj/screen/alert/fire + name = "On Fire" + desc = "You're on fire. Stop, drop and roll to put the fire out or move to a vacuum area." + icon_state = "fire" + +/obj/screen/alert/fire/Click() + if(isliving(usr)) + var/mob/living/L = usr + return L.resist() + + +//ALIENS + +/obj/screen/alert/alien_tox + name = "Plasma" + desc = "There's flammable plasma in the air. If it lights up, you'll be toast." + icon_state = "alien_tox" + alerttooltipstyle = "alien" + +/obj/screen/alert/alien_fire +// This alert is temporarily gonna be thrown for all hot air but one day it will be used for literally being on fire + name = "Too Hot" + desc = "It's too hot! Flee to space or at least away from the flames. Standing on weeds will heal you." + icon_state = "alien_fire" + alerttooltipstyle = "alien" + +/obj/screen/alert/alien_vulnerable + name = "Severed Matriarchy" + desc = "Your queen has been killed, you will suffer movement penalties and loss of hivemind. A new queen cannot be made until you recover." + icon_state = "alien_noqueen" + alerttooltipstyle = "alien" + +//BLOBS + +/obj/screen/alert/nofactory + name = "No Factory" + desc = "You have no factory, and are slowly dying!" + icon_state = "blobbernaut_nofactory" + alerttooltipstyle = "blob" + +//SILICONS + +/obj/screen/alert/nocell + name = "Missing Power Cell" + desc = "Unit has no power cell. No modules available until a power cell is reinstalled. Robotics may provide assistance." + icon_state = "nocell" + +/obj/screen/alert/emptycell + name = "Out of Power" + desc = "Unit's power cell has no charge remaining. No modules available until power cell is recharged. \ +Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite." + icon_state = "emptycell" + +/obj/screen/alert/lowcell + name = "Low Charge" + desc = "Unit's power cell is running low. Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite." + icon_state = "lowcell" + +//Need to cover all use cases - emag, illegal upgrade module, malf AI hack, traitor cyborg +/obj/screen/alert/hacked + name = "Hacked" + desc = "Hazardous non-standard equipment detected. Please ensure any usage of this equipment is in line with unit's laws, if any." + icon_state = "hacked" + +/obj/screen/alert/locked + name = "Locked Down" + desc = "Unit has been remotely locked down. Usage of a Robotics Control Console like the one in the Research Director's \ +office by your AI master or any qualified human may resolve this matter. Robotics may provide further assistance if necessary." + icon_state = "locked" + +/obj/screen/alert/newlaw + name = "Law Update" + desc = "Laws have potentially been uploaded to or removed from this unit. Please be aware of any changes \ +so as to remain in compliance with the most up-to-date laws." + icon_state = "newlaw" + timeout = 300 + +//MECHS + +/obj/screen/alert/low_mech_integrity + name = "Mech Damaged" + desc = "Mech integrity is low." + icon_state = "low_mech_integrity" + + +//GHOSTS +//TODO: expand this system to replace the pollCandidates/CheckAntagonist/"choose quickly"/etc Yes/No messages +/obj/screen/alert/notify_cloning + name = "Revival" + desc = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!" + icon_state = "template" + timeout = 300 + +/obj/screen/alert/notify_cloning/Click() + if(!usr || !usr.client) return + var/mob/observer/dead/G = usr + G.reenter_corpse() + +// /obj/screen/alert/notify_jump +// name = "Body created" +// desc = "A body was created. You can enter it." +// icon_state = "template" +// timeout = 300 +// var/atom/jump_target = null +// var/attack_not_jump = null + +// /obj/screen/alert/notify_jump/Click() +// if(!usr || !usr.client) return +// if(!jump_target) return +// var/mob/dead/observer/G = usr +// if(!istype(G)) return +// if(attack_not_jump) +// jump_target.attack_ghost(G) +// else +// var/turf/T = get_turf(jump_target) +// if(T && isturf(T)) +// G.loc = T + +//OBJECT-BASED + +/obj/screen/alert/restrained/buckled + name = "Buckled" + desc = "You've been buckled to something. Click the alert to unbuckle unless you're handcuffed." + +/obj/screen/alert/restrained/handcuffed + name = "Handcuffed" + desc = "You're handcuffed and can't act. If anyone drags you, you won't be able to move. Click the alert to free yourself." + +/obj/screen/alert/restrained/legcuffed + name = "Legcuffed" + desc = "You're legcuffed, which slows you down considerably. Click the alert to free yourself." + +/obj/screen/alert/restrained/Click() + if(isliving(usr)) + var/mob/living/L = usr + return L.resist() +// PRIVATE = only edit, use, or override these if you're editing the system as a whole + +// Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there +/datum/hud/proc/reorganize_alerts() + var/list/alerts = mymob.alerts + var/icon_pref + if(!hud_shown) + for(var/i = 1, i <= alerts.len, i++) + mymob.client.screen -= alerts[alerts[i]] + return 1 + for(var/i = 1, i <= alerts.len, i++) + var/obj/screen/alert/alert = alerts[alerts[i]] + if(alert.icon_state == "template") + if(!icon_pref) + icon_pref = ui_style2icon(mymob.client.prefs.UI_style) + alert.icon = icon_pref + switch(i) + if(1) + . = ui_alert1 + if(2) + . = ui_alert2 + if(3) + . = ui_alert3 + if(4) + . = ui_alert4 + if(5) + . = ui_alert5 // Right now there's 5 slots + else + . = "" + alert.screen_loc = . + mymob.client.screen |= alert + return 1 + +/mob + var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly + +/obj/screen/alert/Click(location, control, params) + if(!usr || !usr.client) + return + var/paramslist = params2list(params) + if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat + usr << "[name] - [desc]" + return + if(master) + return usr.client.Click(master, location, control, params) + +/obj/screen/alert/Destroy() + ..() + severity = 0 + master = null + screen_loc = "" + return QDEL_HINT_QUEUE diff --git a/code/_onclick/hud/alien_larva.dm b/code/_onclick/hud/alien_larva.dm index 2ec9da3b27..960582b4b1 100644 --- a/code/_onclick/hud/alien_larva.dm +++ b/code/_onclick/hud/alien_larva.dm @@ -21,13 +21,7 @@ mymob.healths.name = "health" mymob.healths.screen_loc = ui_alien_health - mymob.fire = new /obj/screen() - mymob.fire.icon = 'icons/mob/screen1_alien.dmi' - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - mymob.client.screen = list() - mymob.client.screen += list( mymob.healths, mymob.fire) //, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list( mymob.healths) //, mymob.rest, mymob.sleep, mymob.mach ) mymob.client.screen += src.adding + src.other mymob.client.screen += mymob.client.void \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 6e1b184071..830dd65546 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -324,6 +324,11 @@ datum/hud/New(mob/owner) else mymob.instantiate_hud(src) + persistant_inventory_update() + mymob.reload_fullscreen() // Reload any fullscreen overlays this mob has. + mymob.update_action_buttons() + reorganize_alerts() + /mob/proc/instantiate_hud(var/datum/hud/HUD) return @@ -388,6 +393,7 @@ datum/hud/New(mob/owner) hud_used.hidden_inventory_update() hud_used.persistant_inventory_update() update_action_buttons() + hud_used.reorganize_alerts() //Similar to button_pressed_F12() but keeps zone_sel, gun_setting_icon, and healths. /mob/proc/toggle_zoom_hud() diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index adbee61eb8..173398fda6 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -246,27 +246,6 @@ hud_elements |= mymob.internals if(hud_data.has_warnings) - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = ui_style - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_oxygen - hud_elements |= mymob.oxygen - - mymob.toxin = new /obj/screen() - mymob.toxin.icon = ui_style - mymob.toxin.icon_state = "tox0" - mymob.toxin.name = "toxin" - mymob.toxin.screen_loc = ui_toxin - hud_elements |= mymob.toxin - - mymob.fire = new /obj/screen() - mymob.fire.icon = ui_style - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - hud_elements |= mymob.fire - mymob.healths = new /obj/screen() mymob.healths.icon = ui_style mymob.healths.icon_state = "health0" @@ -274,30 +253,6 @@ mymob.healths.screen_loc = ui_health hud_elements |= mymob.healths - if(hud_data.has_pressure) - mymob.pressure = new /obj/screen() - mymob.pressure.icon = ui_style - mymob.pressure.icon_state = "pressure0" - mymob.pressure.name = "pressure" - mymob.pressure.screen_loc = ui_pressure - hud_elements |= mymob.pressure - - if(hud_data.has_bodytemp) - mymob.bodytemp = new /obj/screen() - mymob.bodytemp.icon = ui_style - mymob.bodytemp.icon_state = "temp1" - mymob.bodytemp.name = "body temperature" - mymob.bodytemp.screen_loc = ui_temp - hud_elements |= mymob.bodytemp - - if(hud_data.has_nutrition) - mymob.nutrition_icon = new /obj/screen() - mymob.nutrition_icon.icon = ui_style - mymob.nutrition_icon.icon_state = "nutrition0" - mymob.nutrition_icon.name = "nutrition" - mymob.nutrition_icon.screen_loc = ui_nutrition - hud_elements |= mymob.nutrition_icon - //VOREStation Addition begin mymob.shadekin_dark_display = new /obj/screen/shadekin/darkness() mymob.shadekin_dark_display.screen_loc = ui_shadekin_dark_display diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 392854742a..c71e0004c8 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -85,15 +85,6 @@ var/obj/screen/robot_inventory src.adding += using action_intent = using -//Cell - mymob:cells = new /obj/screen() - mymob:cells.icon = ui_style - mymob:cells.icon_state = "charge-empty" - mymob:cells.alpha = ui_alpha - mymob:cells.name = "cell" - mymob:cells.screen_loc = ui_toxin - src.other += mymob:cells - //Health mymob.healths = new /obj/screen() mymob.healths.icon = ui_style @@ -142,28 +133,6 @@ var/obj/screen/robot_inventory robot_inventory.screen_loc = ui_borg_inventory src.other += robot_inventory -//Temp - mymob.bodytemp = new /obj/screen() - mymob.bodytemp.icon_state = "temp0" - mymob.bodytemp.name = "body temperature" - mymob.bodytemp.screen_loc = ui_temp - - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = ui_style - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.alpha = ui_alpha - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_oxygen - src.other += mymob.oxygen - - mymob.fire = new /obj/screen() - mymob.fire.icon = ui_style - mymob.fire.icon_state = "fire0" - mymob.fire.alpha = ui_alpha - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - src.other += mymob.fire - mymob.pullin = new /obj/screen() mymob.pullin.icon = ui_style mymob.pullin.icon_state = "pull0" @@ -195,7 +164,7 @@ var/obj/screen/robot_inventory mymob.client.screen = list() - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, robot_inventory, mymob.gun_setting_icon) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.hands, mymob.healths, mymob.pullin, robot_inventory, mymob.gun_setting_icon) mymob.client.screen += src.adding + src.other mymob.client.screen += mymob.client.void diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 7f16c60bde..10a7b4b7b9 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -480,6 +480,19 @@ else return 0 +/datum/mind/proc/get_ghost(even_if_they_cant_reenter) + for(var/mob/observer/dead/G in player_list) + if(G.mind == src) + if(G.can_reenter_corpse || even_if_they_cant_reenter) + return G + break + +/datum/mind/proc/grab_ghost(force) + var/mob/observer/dead/G = get_ghost(even_if_they_cant_reenter = force) + . = G + if(G) + G.reenter_corpse() + //Initialisation procs /mob/living/proc/mind_initialize() if(mind) diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index f403606db2..2dac39e0e7 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -400,6 +400,7 @@ var/list/mob/living/forced_ambiance_list = new if(has_gravity) thunk(M) M.update_floating( M.Check_Dense_Object() ) + M.update_gravity(has_gravity) /area/proc/thunk(mob) if(istype(get_turf(mob), /turf/space)) // Can't fall onto nothing. diff --git a/code/game/gamemodes/changeling/powers/escape_restraints.dm b/code/game/gamemodes/changeling/powers/escape_restraints.dm index 08700b1e04..ced80d35bf 100644 --- a/code/game/gamemodes/changeling/powers/escape_restraints.dm +++ b/code/game/gamemodes/changeling/powers/escape_restraints.dm @@ -34,7 +34,7 @@ C.handcuffed = null if(C.buckled && C.buckled.buckle_require_restraints) C.buckled.unbuckle_mob() - C.update_inv_handcuffed() + C.update_handcuffed() if (C.client) C.client.screen -= W W.forceMove(C.loc) diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm index 420b1173c8..e483498155 100644 --- a/code/game/gamemodes/changeling/powers/revive.dm +++ b/code/game/gamemodes/changeling/powers/revive.dm @@ -50,7 +50,7 @@ H.handcuffed = null if(H.buckled && H.buckled.buckle_require_restraints) H.buckled.unbuckle_mob() - H.update_inv_handcuffed() + H.update_handcuffed() if (H.client) H.client.screen -= W W.forceMove(H.loc) diff --git a/code/game/gamemodes/technomancer/spells/resurrect.dm b/code/game/gamemodes/technomancer/spells/resurrect.dm index 02c072b90d..41dc9ce34f 100644 --- a/code/game/gamemodes/technomancer/spells/resurrect.dm +++ b/code/game/gamemodes/technomancer/spells/resurrect.dm @@ -44,7 +44,7 @@ for(var/mob/observer/dead/ghost in player_list) if(ghost.mind == H.mind) ghost.notify_revive("The Technomancer [user.real_name] is trying to revive you. \ - Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg') + Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg', source = user) break H.adjustBruteLoss(-40) diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 86f3fe93da..0ce27d99bb 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -672,10 +672,10 @@ src.visible_message("The machine states, 'YOU ARE UNDER ARREST, RAIDER!' and shoots handcuffs onto [usr]!", "You hear something say 'YOU ARE UNDER ARREST, RAIDER!' and a clinking sound") var/obj/item/weapon/handcuffs/C = new(src.loc) var/mob/living/carbon/human/H = usr - if(istype(usr)) + if(istype(H)) C.forceMove(H) H.handcuffed = C - H.update_inv_handcuffed() + H.update_handcuffed() else C.throw_at(usr,16,3,src) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 90c09acb44..30c15f6d04 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -323,10 +323,9 @@ if ((!subject.ckey) || (!subject.client)) scantemp = "Error: Mental interface failure." if(subject.stat == DEAD && subject.mind && subject.mind.key) // If they're dead and not in their body, tell them to get in it. - for(var/mob/observer/dead/ghost in player_list) - if(ghost.ckey == ckey(subject.mind.key)) - ghost.notify_revive("Someone is trying to scan your body in the cloner. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg') - break + var/mob/observer/dead/ghost = subject.get_ghost() + if(ghost) + ghost.notify_revive("Someone is trying to scan your body in the cloner. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg', source = src) return if (!isnull(find_record(subject.ckey))) scantemp = "Subject already in database." diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index a5516c4c33..990a99bc05 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -629,6 +629,7 @@ //////////////////////////////////////// /obj/mecha/take_damage(amount, type="brute") + update_damage_alerts() if(amount) var/damage = absorbDamage(amount,type) health -= damage @@ -969,6 +970,7 @@ if(src.healthYou repair some damage to [src.name].") src.health += min(10, initial(src.health)-src.health) + update_damage_alerts() else to_chat(user, "The [src.name] is at full integrity") return @@ -1319,6 +1321,8 @@ src.verbs += /obj/mecha/verb/eject src.log_append_to_last("[H] moved in as pilot.") src.icon_state = src.reset_icon() + update_cell_alerts() + update_damage_alerts() set_dir(dir_in) playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) if(occupant.client && cloaked_selfimage) @@ -1401,6 +1405,8 @@ occupant.loc = mmi mmi.mecha = null occupant.canmove = 0 + occupant.clear_alert("charge") + occupant.clear_alert("mech damage") occupant = null icon_state = src.reset_icon()+"-open" set_dir(dir_in) @@ -1975,12 +1981,14 @@ return call((proc_res["dynusepower"]||src), "dynusepower")(amount) /obj/mecha/proc/dynusepower(amount) + update_cell_alerts() if(get_charge()) cell.use(amount) return 1 return 0 /obj/mecha/proc/give_power(amount) + update_cell_alerts() if(!isnull(get_charge())) cell.give(amount) return 1 @@ -2158,3 +2166,31 @@ //src.check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) return */ + +/obj/mecha/proc/update_cell_alerts() + if(occupant && cell) + var/cellcharge = cell.charge/cell.maxcharge + switch(cellcharge) + if(0.75 to INFINITY) + occupant.clear_alert("charge") + if(0.5 to 0.75) + occupant.throw_alert("charge", /obj/screen/alert/lowcell, 1) + if(0.25 to 0.5) + occupant.throw_alert("charge", /obj/screen/alert/lowcell, 2) + if(0.01 to 0.25) + occupant.throw_alert("charge", /obj/screen/alert/lowcell, 3) + else + occupant.throw_alert("charge", /obj/screen/alert/emptycell) + +/obj/mecha/proc/update_damage_alerts() + if(occupant) + var/integrity = health/initial(health)*100 + switch(integrity) + if(30 to 45) + occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 1) + if(15 to 35) + occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 2) + if(-INFINITY to 15) + occupant.throw_alert("mech damage", /obj/screen/alert/low_mech_integrity, 3) + else + occupant.clear_alert("mech damage") \ No newline at end of file diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index c1e6b9adda..3d4c2ffe37 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -73,6 +73,7 @@ //VOREStation Add End post_buckle_mob(M) + M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src) return TRUE /atom/movable/proc/unbuckle_mob(mob/living/buckled_mob, force = FALSE) @@ -88,6 +89,7 @@ buckled_mob.anchored = initial(buckled_mob.anchored) buckled_mob.update_canmove() buckled_mob.update_floating( buckled_mob.Check_Dense_Object() ) + buckled_mob.clear_alert("buckled") // buckled_mob = null buckled_mobs -= buckled_mob diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 80d9dc081b..8df119f0d5 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -386,11 +386,9 @@ // This proc is used so that we can return out of the revive process while ensuring that busy and update_icon() are handled /obj/item/weapon/shockpaddles/proc/do_revive(mob/living/carbon/human/H, mob/user) - if(!H.client && !H.teleop) - for(var/mob/observer/dead/ghost in player_list) - if(ghost.mind == H.mind) - ghost.notify_revive("Someone is trying to resuscitate you. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg') - break + var/mob/observer/dead/ghost = H.get_ghost() + if(ghost) + ghost.notify_revive("Someone is trying to resuscitate you. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg', source = src) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process user.visible_message("\The [user] begins to place [src] on [H]'s chest.", "You begin to place [src] on [H]'s chest...") diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index 763b89c353..2f7e3d6e08 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -98,7 +98,7 @@ user.drop_from_inventory(cuffs) cuffs.loc = target target.handcuffed = cuffs - target.update_inv_handcuffed() + target.update_handcuffed() target.drop_r_hand() target.drop_l_hand() target.stop_pulling() diff --git a/code/game/objects/items/weapons/implants/implantfreedom.dm b/code/game/objects/items/weapons/implants/implantfreedom.dm index b55274cc92..6e4f5f7a16 100644 --- a/code/game/objects/items/weapons/implants/implantfreedom.dm +++ b/code/game/objects/items/weapons/implants/implantfreedom.dm @@ -27,7 +27,7 @@ source.handcuffed = null if(source.buckled && source.buckled.buckle_require_restraints) source.buckled.unbuckle_mob() - source.update_inv_handcuffed() + source.update_handcuffed() if (source.client) source.client.screen -= W if (W) diff --git a/code/game/objects/items/weapons/tools/wirecutters.dm b/code/game/objects/items/weapons/tools/wirecutters.dm index 28e9e8f6cf..91a48299c6 100644 --- a/code/game/objects/items/weapons/tools/wirecutters.dm +++ b/code/game/objects/items/weapons/tools/wirecutters.dm @@ -37,7 +37,7 @@ C.handcuffed = null if(C.buckled && C.buckled.buckle_require_restraints) C.buckled.unbuckle_mob() - C.update_inv_handcuffed() + C.update_handcuffed() return else ..() diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 2a361f1d46..1d58533771 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -199,4 +199,7 @@ // Test for if stepping on a tile containing this obj is safe to do, used for things like landmines and cliffs. /obj/proc/is_safe_to_step(mob/living/L) - return TRUE \ No newline at end of file + return TRUE + +/obj/proc/container_resist(var/mob/living) + return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 55cb97c3cb..d14ccc602b 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -403,8 +403,7 @@ return 0 //closed but not sealed... return 1 -/obj/structure/closet/proc/mob_breakout(var/mob/living/escapee) - +/obj/structure/closet/container_resist(var/mob/living/escapee) if(breakout || !req_breakout()) return @@ -415,30 +414,31 @@ visible_message("\The [src] begins to shake violently!") - breakout = 1 //can't think of a better way to do this right now. - for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2 - if(!do_after(escapee, 50)) //5 seconds - breakout = 0 - return - if(!escapee || escapee.incapacitated() || escapee.loc != src) - breakout = 0 - return //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened - //Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'... - if(!req_breakout()) - breakout = 0 - return + spawn(0) + breakout = 1 //can't think of a better way to do this right now. + for(var/i in 1 to (6*breakout_time * 2)) //minutes * 6 * 5seconds * 2 + if(!do_after(escapee, 50)) //5 seconds + breakout = 0 + return + if(!escapee || escapee.incapacitated() || escapee.loc != src) + breakout = 0 + return //closet/user destroyed OR user dead/unconcious OR user no longer in closet OR closet opened + //Perform the same set of checks as above for weld and lock status to determine if there is even still a point in 'resisting'... + if(!req_breakout()) + breakout = 0 + return + playsound(src.loc, breakout_sound, 100, 1) + animate_shake() + add_fingerprint(escapee) + + //Well then break it! + breakout = 0 + to_chat(escapee, "You successfully break out!") + visible_message("\The [escapee] successfully broke out of \the [src]!") playsound(src.loc, breakout_sound, 100, 1) + break_open() animate_shake() - add_fingerprint(escapee) - - //Well then break it! - breakout = 0 - to_chat(escapee, "You successfully break out!") - visible_message("\The [escapee] successfully broke out of \the [src]!") - playsound(src.loc, breakout_sound, 100, 1) - break_open() - animate_shake() /obj/structure/closet/proc/break_open() sealed = 0 diff --git a/code/modules/clothing/clothing_vr.dm b/code/modules/clothing/clothing_vr.dm index 470cb94c06..2d708d90b8 100644 --- a/code/modules/clothing/clothing_vr.dm +++ b/code/modules/clothing/clothing_vr.dm @@ -55,6 +55,34 @@ ..() +/obj/item/clothing/shoes/container_resist(mob/living/micro) + var/mob/living/carbon/human/macro = loc + if(!istype(macro)) + to_chat(micro, "You start to climb out of [src]!") + if(do_after(micro, 50, src)) + to_chat(micro, "You climb out of [src]!") + micro.forceMove(loc) + return + + var/escape_message_micro = "You start to climb out of [src]!" + var/escape_message_macro = "Something is trying to climb out of your [src]!" + var/escape_time = 60 + + if(macro.shoes == src) + escape_message_micro = "You start to climb around the larger creature's feet and ankles!" + escape_time = 100 + + to_chat(micro, "[escape_message_micro]") + to_chat(macro, "[escape_message_macro]") + if(!do_after(micro, escape_time, macro)) + to_chat(micro, "You're pinned underfoot!") + to_chat(macro, "You pin the escapee underfoot!") + return + + to_chat(micro, "You manage to escape [src]!") + to_chat(macro, "Someone has climbed out of your [src]!") + micro.forceMove(macro.loc) + /obj/item/clothing/gloves sprite_sheets = list( SPECIES_TESHARI = 'icons/mob/species/seromi/gloves.dmi', diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 349859029f..936f9d85f9 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -827,7 +827,7 @@ mob/observer/dead/MayRespawn(var/feedback = 0) // Lets a ghost know someone's trying to bring them back, and for them to get into their body. // Mostly the same as TG's sans the hud element, since we don't have TG huds. -/mob/observer/dead/proc/notify_revive(var/message, var/sound, flashwindow = TRUE) +/mob/observer/dead/proc/notify_revive(var/message, var/sound, flashwindow = TRUE, var/atom/source) if((last_revive_notification + 2 MINUTES) > world.time) return last_revive_notification = world.time @@ -836,6 +836,16 @@ mob/observer/dead/MayRespawn(var/feedback = 0) window_flash(client) if(message) to_chat(src, "[message]") + 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 to_chat(src, "(Click to re-enter)") if(sound) SEND_SOUND(src, sound(sound)) diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index 0febfdc5c4..1315c94a47 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -89,6 +89,22 @@ var/list/holder_mob_icon_cache = list() else if(H.r_hand == src) H.update_inv_r_hand() +/obj/item/weapon/holder/container_resist(mob/living/held) + var/mob/M = loc + if(istype(M)) + M.drop_from_inventory(src) + to_chat(M, "\The [held] wriggles out of your grip!") + to_chat(held, "You wiggle out of [M]'s grip!") + else if(istype(loc, /obj/item/clothing/accessory/holster)) + var/obj/item/clothing/accessory/holster/holster = loc + if(holster.holstered == src) + holster.clear_holster() + to_chat(held, "You extricate yourself from [holster].") + held.forceMove(get_turf(held)) + else if(isitem(loc)) + to_chat(held, "You struggle free of [loc].") + held.forceMove(get_turf(held)) + //Mob specific holders. /obj/item/weapon/holder/diona origin_tech = list(TECH_MAGNET = 3, TECH_BIO = 5) diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index 3839e2ed85..0c979ba008 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -311,7 +311,7 @@ H.handcuffed = new /obj/item/weapon/handcuffs/cable(H) // Better to be cable cuffed than stun-locked else H.handcuffed = new /obj/item/weapon/handcuffs(H) - H.update_inv_handcuffed() + H.update_handcuffed() busy = FALSE else if(istype(M, /mob/living)) var/mob/living/L = M diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index 0bd0ac89b1..370ec77422 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -148,11 +148,11 @@ if(environment.temperature > (T0C+66)) adjustFireLoss((environment.temperature - (T0C+66))/5) // Might be too high, check in testing. - if (fire) fire.icon_state = "fire2" + throw_alert("alien_fire", /obj/screen/alert/alien_fire) if(prob(20)) to_chat(src, "You feel a searing heat!") else - if (fire) fire.icon_state = "fire0" + clear_alert("alien_fire") /mob/living/carbon/alien/handle_fire() if(..()) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index c11cf6bac0..f5e2f59c89 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -310,7 +310,7 @@ else if (W == handcuffed) handcuffed = null - update_inv_handcuffed() + update_handcuffed() if(buckled && buckled.buckle_require_restraints) buckled.unbuckle_mob() @@ -318,9 +318,8 @@ legcuffed = null update_inv_legcuffed() else - ..() + ..() - return //generates realistic-ish pulse output based on preset levels /mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate @@ -403,3 +402,14 @@ if(does_not_breathe) return FALSE return ..() + +/mob/living/carbon/proc/update_handcuffed() + if(handcuffed) + drop_l_hand() + drop_r_hand() + stop_pulling() + throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = handcuffed) + else + clear_alert("handcuffed") + update_action_buttons() //some of our action buttons might be unusable when we're handcuffed. + update_inv_handcuffed() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 9687bde18f..0af9f90225 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1679,4 +1679,9 @@ if(istype(loc, /turf/simulated)) var/turf/T = loc T.add_blood(src) - . = ..() \ No newline at end of file + . = ..() + +/mob/living/carbon/human/reduce_cuff_time() + if(istype(gloves, /obj/item/clothing/gloves/gauntlets/rig)) + return 2 + return ..() diff --git a/code/modules/mob/living/carbon/human/human_resist.dm b/code/modules/mob/living/carbon/human/human_resist.dm index 56d42c1a15..f9ef85c94b 100644 --- a/code/modules/mob/living/carbon/human/human_resist.dm +++ b/code/modules/mob/living/carbon/human/human_resist.dm @@ -1,30 +1,7 @@ -/mob/living/carbon/human/process_resist() - //drop && roll - if((on_fire || has_modifier_of_type(/datum/modifier/fire)) && !buckled) - adjust_fire_stacks(-1.2) - Weaken(3) - spin(32,2) - visible_message( - "[src] rolls on the floor, trying to put themselves out!", - "You stop, drop, and roll!" - ) - sleep(30) - if(fire_stacks <= 0 && !(has_modifier_of_type(/datum/modifier/fire))) - visible_message( - "[src] has successfully extinguished themselves!", - "You extinguish yourself." - ) - ExtinguishMob() - return TRUE - - if(handcuffed) - spawn() escape_handcuffs() - else if(legcuffed) - spawn() escape_legcuffs() - else if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) - spawn() escape_straight_jacket() - else - ..() +/mob/living/carbon/human/resist_restraints() + if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/straight_jacket)) + return escape_straight_jacket() + return ..() #define RESIST_ATTACK_DEFAULT 0 #define RESIST_ATTACK_CLAWS 1 diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 0d9e58b7cb..379dfd4b8f 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -172,7 +172,7 @@ This saves us from having to call add_fingerprint() any time something is put in handcuffed = null if(buckled && buckled.buckle_require_restraints) buckled.unbuckle_mob() - update_inv_handcuffed() + update_handcuffed() else if (W == legcuffed) legcuffed = null update_inv_legcuffed() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 1856fad689..135c5df17c 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -25,12 +25,6 @@ #define HUMAN_COMBUSTION_TEMP 524 //524k is the sustained combustion temperature of human fat /mob/living/carbon/human - var/oxygen_alert = 0 - var/phoron_alert = 0 - var/co2_alert = 0 - var/fire_alert = 0 - var/pressure_alert = 0 - var/temperature_alert = 0 var/in_stasis = 0 var/heartbeat = 0 @@ -46,7 +40,6 @@ //code. Very ugly. I dont care. Moving this stuff here so its easy //to find it. blinded = 0 - fire_alert = 0 //Reset this here, because both breathe() and handle_environment() have a chance to set it. //TODO: seperate this out // update the current life tick, can be used to e.g. only do something every 4 ticks @@ -384,8 +377,7 @@ if(suiciding) failed_last_breath = 1 adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster - oxygen_alert = max(oxygen_alert, 1) - suiciding -- + suiciding-- return 0 if(does_not_breathe) @@ -405,9 +397,10 @@ if(!L.is_bruised() && prob(8)) rupture_lung() - oxygen_alert = max(oxygen_alert, 1) - + throw_alert("pressure", /obj/screen/alert/lowpressure) return 0 + else + clear_alert("pressure") var/safe_pressure_min = species.minimum_breath_pressure // Minimum safe partial pressure of breathable gas in kPa @@ -466,6 +459,7 @@ var/inhale_pp = (inhaling/breath.total_moles)*breath_pressure var/toxins_pp = (poison/breath.total_moles)*breath_pressure + // To be clear, this isn't how much they're exhaling -- it's the amount of the species exhale_gas that they just var/exhaled_pp = (exhaling/breath.total_moles)*breath_pressure // Not enough to breathe @@ -478,10 +472,23 @@ adjustOxyLoss(max(HUMAN_MAX_OXYLOSS*(1-ratio), 0)) failed_inhale = 1 - oxygen_alert = max(oxygen_alert, 1) + switch(breath_type) + if("oxygen") + throw_alert("oxy", /obj/screen/alert/not_enough_oxy) + if("phoron") + throw_alert("oxy", /obj/screen/alert/not_enough_tox) + if("nitrogen") + throw_alert("oxy", /obj/screen/alert/not_enough_nitro) + if("carbon_dioxide") + throw_alert("oxy", /obj/screen/alert/not_enough_co2) + if("volatile_fuel") + throw_alert("oxy", /obj/screen/alert/not_enough_fuel) + if("sleeping_agent") + throw_alert("oxy", /obj/screen/alert/not_enough_n2o) + else // We're in safe limits - oxygen_alert = 0 + clear_alert("oxy") inhaled_gas_used = inhaling/6 @@ -492,16 +499,15 @@ // Too much exhaled gas in the air if(exhaled_pp > safe_exhaled_max) - if (!co2_alert|| prob(15)) + if (prob(15)) var/word = pick("extremely dizzy","short of breath","faint","confused") to_chat(src, "You feel [word].") adjustOxyLoss(HUMAN_MAX_OXYLOSS) - co2_alert = 1 failed_exhale = 1 else if(exhaled_pp > safe_exhaled_max * 0.7) - if (!co2_alert || prob(1)) + if (!prob(1)) var/word = pick("dizzy","short of breath","faint","momentarily confused") to_chat(src, "You feel [word].") @@ -511,26 +517,22 @@ //give them some oxyloss, up to the limit - we don't want people falling unconcious due to CO2 alone until they're pretty close to safe_exhaled_max. if (getOxyLoss() < 50*ratio) adjustOxyLoss(HUMAN_MAX_OXYLOSS) - co2_alert = 1 failed_exhale = 1 else if(exhaled_pp > safe_exhaled_max * 0.6) - if (prob(0.3)) + if(prob(0.3)) var/word = pick("a little dizzy","short of breath") to_chat(src, "You feel [word].") - else - co2_alert = 0 - // Too much poison in the air. if(toxins_pp > safe_toxins_max) var/ratio = (poison/safe_toxins_max) * 10 if(reagents) reagents.add_reagent("toxin", CLAMP(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) breath.adjust_gas(poison_type, -poison/6, update = 0) //update after - phoron_alert = max(phoron_alert, 1) + throw_alert("tox_in_air", /obj/screen/alert/tox_in_air) else - phoron_alert = 0 + clear_alert("tox_in_air") // If there's some other shit in the air lets deal with it here. if(breath.gas["sleeping_agent"]) @@ -573,25 +575,24 @@ if(breath.temperature >= species.breath_heat_level_1) if(breath.temperature < species.breath_heat_level_2) apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Heat") - fire_alert = max(fire_alert, 2) + throw_alert("temp", /obj/screen/alert/hot, 1) else if(breath.temperature < species.breath_heat_level_3) apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Heat") - fire_alert = max(fire_alert, 2) + throw_alert("temp", /obj/screen/alert/hot, 2) else apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Heat") - fire_alert = max(fire_alert, 2) + throw_alert("temp", /obj/screen/alert/hot, 3) else if(breath.temperature <= species.breath_cold_level_1) if(breath.temperature > species.breath_cold_level_2) apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, BP_HEAD, used_weapon = "Excessive Cold") - fire_alert = max(fire_alert, 1) + throw_alert("temp", /obj/screen/alert/cold, 1) else if(breath.temperature > species.breath_cold_level_3) apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, BP_HEAD, used_weapon = "Excessive Cold") - fire_alert = max(fire_alert, 1) + throw_alert("temp", /obj/screen/alert/cold, 2) else apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, BP_HEAD, used_weapon = "Excessive Cold") - fire_alert = max(fire_alert, 1) - + throw_alert("temp", /obj/screen/alert/cold, 3) //breathing in hot/cold air also heats/cools you a bit var/temp_adj = breath.temperature - bodytemperature @@ -613,6 +614,9 @@ else if(breath.temperature <= species.cold_discomfort_level) species.get_environment_discomfort(src,"cold") + else + clear_alert("temp") + breath.update_values() return 1 @@ -653,7 +657,7 @@ loc_temp = environment.temperature if(adjusted_pressure < species.warning_high_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - bodytemperature) < 20 && bodytemperature < species.heat_level_1 && bodytemperature > species.cold_level_1) - pressure_alert = 0 + clear_alert("pressure") return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp //Body temperature adjusts depending on surrounding atmosphere based on your thermal protection (convection) @@ -674,7 +678,6 @@ // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. if(bodytemperature >= species.heat_level_1) //Body temperature is too hot. - fire_alert = max(fire_alert, 1) if(status_flags & GODMODE) return 1 //godmode @@ -691,11 +694,9 @@ burn_dam = HEAT_DAMAGE_LEVEL_1 take_overall_damage(burn=burn_dam, used_weapon = "High Body Temperature") - fire_alert = max(fire_alert, 2) else if(bodytemperature <= species.cold_level_1) //Body temperature is too cold. - fire_alert = max(fire_alert, 1) if(status_flags & GODMODE) return 1 //godmode @@ -713,7 +714,6 @@ cold_dam = COLD_DAMAGE_LEVEL_1 take_overall_damage(burn=cold_dam, used_weapon = "Low Body Temperature") - fire_alert = max(fire_alert, 1) // Account for massive pressure differences. Done by Polymorph // Made it possible to actually have something that can protect against high pressure... Done by Errorage. Polymorph now has an axe sticking from his head for his previous hardcoded nonsense! @@ -723,13 +723,13 @@ if(adjusted_pressure >= species.hazard_high_pressure) var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure") - pressure_alert = 2 + throw_alert("pressure", /obj/screen/alert/highpressure, 2) else if(adjusted_pressure >= species.warning_high_pressure) - pressure_alert = 1 + throw_alert("pressure", /obj/screen/alert/highpressure, 1) else if(adjusted_pressure >= species.warning_low_pressure) - pressure_alert = 0 + clear_alert("pressure") else if(adjusted_pressure >= species.hazard_low_pressure) - pressure_alert = -1 + throw_alert("pressure", /obj/screen/alert/lowpressure, 1) else if( !(COLD_RESISTANCE in mutations)) if(!isSynthetic() || !nif || !nif.flag_check(NIF_O_PRESSURESEAL,NIF_FLAGS_OTHER)) //VOREStation Edit - NIF pressure seals @@ -747,9 +747,9 @@ // Firesuits (Min protection = 0.2 atmospheres) decrease oxyloss to 1/5 adjustOxyLoss(pressure_dam) - pressure_alert = -2 + throw_alert("pressure", /obj/screen/alert/lowpressure, 2) else - pressure_alert = -1 + clear_alert("pressure") return @@ -1009,12 +1009,14 @@ //Are they SSD? If so we'll keep them asleep but work off some of that sleep var in case of stoxin or similar. if(client || sleeping > 3) AdjustSleeping(-1) + throw_alert("asleep", /obj/screen/alert/asleep) if( prob(2) && health && !hal_crit ) spawn(0) emote("snore") //CONSCIOUS else set_stat(CONSCIOUS) + clear_alert("asleep") //Periodically double-check embedded_flag if(embedded_flag && !(life_tick % 10)) @@ -1046,19 +1048,24 @@ SetBlinded(0) blinded = 0 eye_blurry = 0 + clear_alert("blind") else if(!vision || vision.is_broken()) // Vision organs cut out or broken? Permablind. SetBlinded(1) blinded = 1 eye_blurry = 1 + throw_alert("blind", /obj/screen/alert/blind) else //You have the requisite organs if(sdisabilities & BLIND) // Disabled-blind, doesn't get better on its own blinded = 1 + throw_alert("blind", /obj/screen/alert/blind) else if(eye_blind) // Blindness, heals slowly over time AdjustBlinded(-1) blinded = 1 + throw_alert("blind", /obj/screen/alert/blind) else if(istype(glasses, /obj/item/clothing/glasses/sunglasses/blindfold)) //resting your eyes with a blindfold heals blurry eyes faster eye_blurry = max(eye_blurry-3, 0) blinded = 1 + throw_alert("blind", /obj/screen/alert/blind) //blurry sight if(vision.is_bruised()) // Vision organs impaired? Permablurry. @@ -1213,83 +1220,41 @@ healths_ma.overlays += health_images healths.appearance = healths_ma - if(nutrition_icon) - var/prefix = isSynthetic() ? "c" : null - switch(nutrition) - if(450 to INFINITY) nutrition_icon.icon_state = "[prefix]nutrition0" - if(350 to 450) nutrition_icon.icon_state = "[prefix]nutrition1" - if(250 to 350) nutrition_icon.icon_state = "[prefix]nutrition2" - if(150 to 250) nutrition_icon.icon_state = "[prefix]nutrition3" - else nutrition_icon.icon_state = "[prefix]nutrition4" - if(pressure) - pressure.icon_state = "pressure[pressure_alert]" + var/fat_alert = /obj/screen/alert/fat + var/hungry_alert = /obj/screen/alert/hungry + var/starving_alert = /obj/screen/alert/starving -// if(rest) //Not used with new UI -// if(resting || lying || sleeping) rest.icon_state = "rest1" -// else rest.icon_state = "rest0" - if(toxin) - if(hal_screwyhud == 4 || (phoron_alert && !does_not_breathe)) toxin.icon_state = "tox1" - else toxin.icon_state = "tox0" - if(oxygen) - if(hal_screwyhud == 3 || (oxygen_alert && !does_not_breathe)) oxygen.icon_state = "oxy1" - else oxygen.icon_state = "oxy0" - if(fire) - if(fire_alert) fire.icon_state = "fire[fire_alert]" //fire_alert is either 0 if no alert, 1 for cold and 2 for heat. - else fire.icon_state = "fire0" + if(get_species() == SPECIES_CUSTOM) + var/datum/species/custom/C = species + if(/datum/trait/bloodsucker in C.traits) + fat_alert = /obj/screen/alert/fat/vampire + hungry_alert = /obj/screen/alert/hungry/vampire + starving_alert = /obj/screen/alert/starving/vampire + else if(isSynthetic()) + fat_alert = /obj/screen/alert/fat/synth + hungry_alert = /obj/screen/alert/hungry/synth + starving_alert = /obj/screen/alert/starving/synth - if(bodytemp) - if (!species) - switch(bodytemperature) //310.055 optimal body temp - if(370 to INFINITY) bodytemp.icon_state = "temp4" - if(350 to 370) bodytemp.icon_state = "temp3" - if(335 to 350) bodytemp.icon_state = "temp2" - if(320 to 335) bodytemp.icon_state = "temp1" - if(300 to 320) bodytemp.icon_state = "temp0" - if(295 to 300) bodytemp.icon_state = "temp-1" - if(280 to 295) bodytemp.icon_state = "temp-2" - if(260 to 280) bodytemp.icon_state = "temp-3" - else bodytemp.icon_state = "temp-4" + switch(nutrition) + if(450 to INFINITY) + throw_alert("nutrition", fat_alert) + // if(350 to 450) + // if(250 to 350) // Alternative more-detailed tiers, not used. + if(250 to 450) + clear_alert("nutrition") + if(150 to 250) + throw_alert("nutrition", hungry_alert) else - //TODO: precalculate all of this stuff when the species datum is created - var/base_temperature = species.body_temperature - if(base_temperature == null) //some species don't have a set metabolic temperature - base_temperature = (species.heat_level_1 + species.cold_level_1)/2 - - var/temp_step - if (bodytemperature >= base_temperature) - temp_step = (species.heat_level_1 - base_temperature)/4 - - if (bodytemperature >= species.heat_level_1) - bodytemp.icon_state = "temp4" - else if (bodytemperature >= base_temperature + temp_step*3) - bodytemp.icon_state = "temp3" - else if (bodytemperature >= base_temperature + temp_step*2) - bodytemp.icon_state = "temp2" - else if (bodytemperature >= base_temperature + temp_step*1) - bodytemp.icon_state = "temp1" - else - bodytemp.icon_state = "temp0" - - else if (bodytemperature < base_temperature) - temp_step = (base_temperature - species.cold_level_1)/4 - - if (bodytemperature <= species.cold_level_1) - bodytemp.icon_state = "temp-4" - else if (bodytemperature <= base_temperature - temp_step*3) - bodytemp.icon_state = "temp-3" - else if (bodytemperature <= base_temperature - temp_step*2) - bodytemp.icon_state = "temp-2" - else if (bodytemperature <= base_temperature - temp_step*1) - bodytemp.icon_state = "temp-1" - else - bodytemp.icon_state = "temp0" + throw_alert("nutrition", starving_alert) if(blinded) overlay_fullscreen("blind", /obj/screen/fullscreen/blind) + throw_alert("blind", /obj/screen/alert/blind) else if(!machine) clear_fullscreens() + clear_alert("blind") if(disabilities & NEARSIGHTED) //this looks meh but saves a lot of memory by not requiring to add var/prescription if(glasses) //to every /obj/item @@ -1301,6 +1266,10 @@ set_fullscreen(eye_blurry, "blurry", /obj/screen/fullscreen/blurry) set_fullscreen(druggy, "high", /obj/screen/fullscreen/high) + if(druggy) + throw_alert("high", /obj/screen/alert/high) + else + clear_alert("high") if(config.welder_vision) var/found_welder diff --git a/code/modules/mob/living/carbon/human/species/station/alraune.dm b/code/modules/mob/living/carbon/human/species/station/alraune.dm index f55935ac9e..8a0d93243a 100644 --- a/code/modules/mob/living/carbon/human/species/station/alraune.dm +++ b/code/modules/mob/living/carbon/human/species/station/alraune.dm @@ -146,9 +146,11 @@ else H.adjustOxyLoss(ALRAUNE_CRIT_MAX_OXYLOSS) - H.oxygen_alert = max(H.oxygen_alert, 1) + H.throw_alert("pressure", /obj/screen/alert/lowpressure) return // skip air processing if there's no air + else + H.clear_alert("pressure") // now into the good stuff @@ -188,10 +190,10 @@ H.adjustOxyLoss(max(ALRAUNE_MAX_OXYLOSS*(1-ratio), 0)) failed_inhale = 1 - H.oxygen_alert = max(H.oxygen_alert, 1) + H.throw_alert("oxy", /obj/screen/alert/not_enough_co2) else // We're in safe limits - H.oxygen_alert = 0 + H.clear_alert("oxy") inhaled_gas_used = inhaling/6 breath.adjust_gas("carbon_dioxide", -inhaled_gas_used, update = 0) //update afterwards @@ -199,10 +201,9 @@ //Now we handle CO2. if(inhale_pp > safe_exhaled_max * 0.7) // For a human, this would be too much exhaled gas in the air. But plants don't care. - H.co2_alert = 1 // Give them the alert on the HUD. They'll be aware when the good stuff is present. - + H.throw_alert("co2", /obj/screen/alert/too_much_co2/plant) // Give them the alert on the HUD. They'll be aware when the good stuff is present. else - H.co2_alert = 0 + H.clear_alert("co2") //do the CO2 buff stuff here @@ -225,9 +226,9 @@ if(H.reagents) H.reagents.add_reagent("toxin", CLAMP(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE)) breath.adjust_gas(poison_type, -poison/6, update = 0) //update after - H.phoron_alert = max(H.phoron_alert, 1) + H.throw_alert("tox_in_air", /obj/screen/alert/tox_in_air) else - H.phoron_alert = 0 + H.clear_alert("tox_in_air") // If there's some other shit in the air lets deal with it here. if(breath.gas["sleeping_agent"]) @@ -271,24 +272,18 @@ if(breath.temperature >= breath_heat_level_1) if(breath.temperature < breath_heat_level_2) H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, bodypart, used_weapon = "Excessive Heat") - H.fire_alert = max(H.fire_alert, 2) else if(breath.temperature < breath_heat_level_3) H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, bodypart, used_weapon = "Excessive Heat") - H.fire_alert = max(H.fire_alert, 2) else H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, bodypart, used_weapon = "Excessive Heat") - H.fire_alert = max(H.fire_alert, 2) else if(breath.temperature <= breath_cold_level_1) if(breath.temperature > breath_cold_level_2) H.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, bodypart, used_weapon = "Excessive Cold") - H.fire_alert = max(H.fire_alert, 1) else if(breath.temperature > breath_cold_level_3) H.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, bodypart, used_weapon = "Excessive Cold") - H.fire_alert = max(H.fire_alert, 1) else H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, bodypart, used_weapon = "Excessive Cold") - H.fire_alert = max(H.fire_alert, 1) //breathing in hot/cold air also heats/cools you a bit diff --git a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm index b4e04f745e..5950d069d5 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits_vr/neutral.dm @@ -68,9 +68,6 @@ /datum/trait/bloodsucker/apply(var/datum/species/S,var/mob/living/carbon/human/H) ..(S,H) H.verbs |= /mob/living/carbon/human/proc/bloodsuck - spawn(10 SECONDS) // Ugh! - if(H?.nutrition_icon) - H.nutrition_icon.icon = 'icons/mob/screen/vamp_hunger_vr.dmi' /datum/trait/succubus_drain name = "Succubus Drain" diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 2903bf604f..7b735b0dbe 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -855,11 +855,14 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(QDESTROYING(src)) return + clear_alert("legcuffed") remove_layer(LEGCUFF_LAYER) if(!legcuffed) return //Not legcuffed, why bother. + throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = legcuffed) + overlays_standing[LEGCUFF_LAYER] = legcuffed.make_worn_icon(body_type = species.get_bodytype(src), slot_name = slot_legcuffed_str, default_icon = INV_LCUFF_DEF_ICON, default_layer = LEGCUFF_LAYER) apply_layer(LEGCUFF_LAYER) diff --git a/code/modules/mob/living/carbon/resist.dm b/code/modules/mob/living/carbon/resist.dm index 248fe5c6a6..8af9d9e20d 100644 --- a/code/modules/mob/living/carbon/resist.dm +++ b/code/modules/mob/living/carbon/resist.dm @@ -1,173 +1,99 @@ -/mob/living/carbon/process_resist() - - //drop && roll - if(on_fire && !buckled) - adjust_fire_stacks(-1.2) - Weaken(3) - spin(32,2) +/mob/living/carbon/resist_fire() + adjust_fire_stacks(-1.2) + Weaken(3) + spin(32,2) + visible_message( + "[src] rolls on the floor, trying to put themselves out!", + "You stop, drop, and roll!" + ) + sleep(30) + if(fire_stacks <= 0) visible_message( - "[src] rolls on the floor, trying to put themselves out!", - "You stop, drop, and roll!" + "[src] has successfully extinguished themselves!", + "You extinguish yourself." ) - sleep(30) - if(fire_stacks <= 0) - visible_message( - "[src] has successfully extinguished themselves!", - "You extinguish yourself." - ) - ExtinguishMob() - return TRUE + ExtinguishMob() + return TRUE +/mob/living/carbon/resist_restraints() + var/obj/item/I = null if(handcuffed) - spawn() escape_handcuffs() + I = handcuffed else if(legcuffed) - spawn() escape_legcuffs() - else - ..() + I = legcuffed + + if(I) + setClickCooldown(100) + cuff_resist(I, cuff_break = can_break_cuffs()) -/mob/living/carbon/proc/escape_handcuffs() - //if(!(last_special <= world.time)) return +/mob/living/carbon/proc/reduce_cuff_time() + return FALSE - //This line represent a significant buff to grabs... - // We don't have to check the click cooldown because /mob/living/verb/resist() has done it for us, we can simply set the delay - setClickCooldown(100) +/mob/living/carbon/proc/cuff_resist(obj/item/weapon/handcuffs/I, breakouttime = 1200, cuff_break = 0) + + if(istype(I)) + breakouttime = I.breakouttime - if(can_break_cuffs()) //Don't want to do a lot of logic gating here. - break_handcuffs() + var/displaytime = breakouttime / 10 + + var/reduceCuffTime = reduce_cuff_time() + if(reduceCuffTime) + breakouttime /= reduceCuffTime + displaytime /= reduceCuffTime + + if(cuff_break) + visible_message("[src] is trying to break [I]!", + "You attempt to break your [I]. (This will take around 5 seconds and you need to stand still)") + + if(do_after(src, 5 SECONDS, target = src, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED)) + if(!I || buckled) + return + visible_message("[src] manages to break [I]!", + "You successfully break your [I].") + say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + + if(I == handcuffed) + handcuffed = null + update_handcuffed() + else if(I == legcuffed) + legcuffed = null + update_inv_legcuffed() + + if(buckled && buckled.buckle_require_restraints) + buckled.unbuckle_mob() + + qdel(I) + else + to_chat(src, "You fail to break [I].") + return + + visible_message("[src] attempts to remove [I]!", + "You attempt to remove [I]. (This will take around [displaytime] seconds and you need to stand still)") + if(do_after(src, breakouttime, target = src, incapacitation_flags = INCAPACITATION_DISABLED & INCAPACITATION_KNOCKDOWN)) + visible_message("[src] manages to remove [I]!", + "You successfully remove [I].") + drop_from_inventory(I) + +/mob/living/carbon/resist_buckle() + if(!buckled) return - var/obj/item/weapon/handcuffs/HC = handcuffed + if(!restrained()) + return ..() - //A default in case you are somehow handcuffed with something that isn't an obj/item/weapon/handcuffs type - var/breakouttime = 1200 - var/displaytime = 2 //Minutes to display in the "this will take X minutes." - //If you are handcuffed with actual handcuffs... Well what do I know, maybe someone will want to handcuff you with toilet paper in the future... - if(istype(HC)) - breakouttime = HC.breakouttime - displaytime = breakouttime / 600 //Minutes - - var/mob/living/carbon/human/H = src - if(istype(H) && H.gloves && istype(H.gloves,/obj/item/clothing/gloves/gauntlets/rig)) - breakouttime /= 2 - displaytime /= 2 - - visible_message( - "\The [src] attempts to remove \the [HC]!", - "You attempt to remove \the [HC]. (This will take around [displaytime] minutes and you need to stand still)" - ) - - if(do_after(src, breakouttime, incapacitation_flags = INCAPACITATION_DISABLED & INCAPACITATION_KNOCKDOWN)) - if(!handcuffed) - return - visible_message( - "\The [src] manages to remove \the [handcuffed]!", - "You successfully remove \the [handcuffed]." - ) - drop_from_inventory(handcuffed) - -/mob/living/carbon/proc/escape_legcuffs() - //if(!(last_special <= world.time)) return - - //This line represent a significant buff to grabs... - // We don't have to check the click cooldown because /mob/living/verb/resist() has done it for us, we can simply set the delay setClickCooldown(100) - - if(can_break_cuffs()) //Don't want to do a lot of logic gating here. - break_legcuffs() - return - - var/obj/item/weapon/handcuffs/legcuffs/LC = legcuffed - - //A default in case you are somehow legcuffed with something that isn't an obj/item/weapon/handcuffs/legcuffs type - var/breakouttime = 1200 - var/displaytime = 2 //Minutes to display in the "this will take X minutes." - //If you are legcuffed with actual legcuffs... Well what do I know, maybe someone will want to handcuff you with toilet paper in the future... - if(istype(LC)) - breakouttime = LC.breakouttime - displaytime = breakouttime / 600 //Minutes - - var/mob/living/carbon/human/H = src - if(istype(H) && H.shoes && istype(H.shoes,/obj/item/clothing/shoes/magboots/rig)) - breakouttime /= 2 - displaytime /= 2 - visible_message( - "\The [src] attempts to remove \the [LC]!", - "You attempt to remove \the [LC]. (This will take around [displaytime] minutes and you need to stand still)" + "[src] attempts to unbuckle themself!", + "You attempt to unbuckle yourself. (This will take around 2 minutes and you need to stand still)" ) - if(do_after(src, breakouttime, incapacitation_flags = INCAPACITATION_DISABLED & INCAPACITATION_KNOCKDOWN)) - if(!legcuffed) + if(do_after(src, 2 MINUTES, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY))) + if(!buckled) return - visible_message( - "\The [src] manages to remove \the [legcuffed]!", - "You successfully remove \the [legcuffed]." - ) - drop_from_inventory(legcuffed) - legcuffed = null - update_inv_legcuffed() + visible_message("[src] manages to unbuckle themself!", + "You successfully unbuckle yourself.") + buckled.user_unbuckle_mob(src, src) /mob/living/carbon/proc/can_break_cuffs() if(HULK in mutations) return 1 - -/mob/living/carbon/proc/break_handcuffs() - visible_message( - "[src] is trying to break \the [handcuffed]!", - "You attempt to break your [handcuffed.name]. (This will take around 5 seconds and you need to stand still)" - ) - - if(do_after(src, 5 SECONDS, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED)) - if(!handcuffed || buckled) - return - - visible_message( - "[src] manages to break \the [handcuffed]!", - "You successfully break your [handcuffed.name]." - ) - - say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - - qdel(handcuffed) - handcuffed = null - if(buckled && buckled.buckle_require_restraints) - buckled.unbuckle_mob() - update_inv_handcuffed() - -/mob/living/carbon/proc/break_legcuffs() - to_chat(src, "You attempt to break your legcuffs. (This will take around 5 seconds and you need to stand still)") - visible_message("[src] is trying to break the legcuffs!") - - if(do_after(src, 5 SECONDS, incapacitation_flags = INCAPACITATION_DEFAULT & ~INCAPACITATION_RESTRAINED)) - if(!legcuffed || buckled) - return - - visible_message( - "[src] manages to break the legcuffs!", - "You successfully break your legcuffs." - ) - - say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - - qdel(legcuffed) - legcuffed = null - update_inv_legcuffed() - -/mob/living/carbon/escape_buckle() - if(!buckled) return - - if(!restrained()) - ..() - else - setClickCooldown(100) - visible_message( - "[usr] attempts to unbuckle themself!", - "You attempt to unbuckle yourself. (This will take around 2 minutes and you need to stand still)" - ) - - if(do_after(usr, 2 MINUTES, incapacitation_flags = INCAPACITATION_DEFAULT & ~(INCAPACITATION_RESTRAINED | INCAPACITATION_BUCKLED_FULLY))) - if(!buckled) - return - visible_message("[usr] manages to unbuckle themself!", - "You successfully unbuckle yourself.") - buckled.user_unbuckle_mob(src, src) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index c1ec71a84e..2fdfcf4c56 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -160,9 +160,14 @@ //Eyes if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own SetBlinded(1) + throw_alert("blind", /obj/screen/alert/blind) else if(eye_blind) //blindness, heals slowly over time AdjustBlinded(-1) - else if(eye_blurry) //blurry eyes heal slowly + throw_alert("blind", /obj/screen/alert/blind) + else + clear_alert("blind") + + if(eye_blurry) //blurry eyes heal slowly eye_blurry = max(eye_blurry-1, 0) //Ears diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d74f43bced..316bb2be88 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -860,53 +860,25 @@ default behaviour is: process_resist() /mob/living/proc/process_resist() - //Getting out of someone's inventory. - if(istype(src.loc, /obj/item/weapon/holder)) - escape_inventory(src.loc) - return - //unbuckling yourself if(buckled) - spawn() escape_buckle() + resist_buckle() return TRUE - //Breaking out of a locker? - if( src.loc && (istype(src.loc, /obj/structure/closet)) ) - var/obj/structure/closet/C = loc - spawn() C.mob_breakout(src) + if(isobj(loc)) + var/obj/C = loc + C.container_resist(src) return TRUE - if(istype(loc,/obj/item/clothing)) - spawn() escape_clothes(loc) + else if(canmove) + if(on_fire) + resist_fire() //stop, drop, and roll + else + resist_restraints() if(attempt_vr(src,"vore_process_resist",args)) return TRUE //VOREStation Code -/mob/living/proc/escape_inventory(obj/item/weapon/holder/H) - if(H != src.loc) return - - var/mob/M = H.loc //Get our mob holder (if any). - - if(istype(M)) - M.drop_from_inventory(H) - to_chat(M, "\The [H] wriggles out of your grip!") - to_chat(src, "You wriggle out of \the [M]'s grip!") - - // Update whether or not this mob needs to pass emotes to contents. - for(var/atom/A in M.contents) - if(istype(A,/mob/living/simple_mob/animal/borer) || istype(A,/obj/item/weapon/holder)) - return - - else if(istype(H.loc,/obj/item/clothing/accessory/holster)) - var/obj/item/clothing/accessory/holster/holster = H.loc - if(holster.holstered == H) - holster.clear_holster() - to_chat(src, "You extricate yourself from \the [holster].") - H.forceMove(get_turf(H)) - else if(istype(H.loc,/obj/item)) - to_chat(src, "You struggle free of \the [H.loc].") - H.forceMove(get_turf(H)) - -/mob/living/proc/escape_buckle() +/mob/living/proc/resist_buckle() if(buckled) if(istype(buckled, /obj/vehicle)) var/obj/vehicle/vehicle = buckled @@ -922,6 +894,12 @@ default behaviour is: if(resisting) visible_message("[src] resists!") +/mob/living/proc/resist_fire() + return + +/mob/living/proc/resist_restraints() + return + /mob/living/verb/lay_down() set name = "Rest" set category = "IC" @@ -1335,3 +1313,11 @@ default behaviour is: BRAIN:[getBrainLoss()] "} + +/mob/living/update_gravity(has_gravity) + if(!ticker) + return + if(has_gravity) + clear_alert("weightless") + else + throw_alert("weightless", /obj/screen/alert/weightless) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 428cff3659..b74edbcbba 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -328,6 +328,7 @@ O.loc = src src.embedded += O src.verbs += /mob/proc/yank_out_object + throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) //This is called when the mob is thrown into a dense turf /mob/living/proc/turf_collision(var/turf/T, var/speed) @@ -366,6 +367,7 @@ if(fire_stacks > 0 && !on_fire) on_fire = 1 handle_light() + throw_alert("fire", /obj/screen/alert/fire) update_fire() /mob/living/proc/ExtinguishMob() @@ -373,6 +375,7 @@ on_fire = 0 fire_stacks = 0 handle_light() + clear_alert("fire") update_fire() if(has_modifier_of_type(/datum/modifier/fire)) diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index 0071586458..5de4e9c3e2 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -11,6 +11,7 @@ return laws.zeroth_law != null /mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg, notify = TRUE) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.set_zeroth_law(law, law_borg) if(notify) @@ -76,6 +77,7 @@ log_and_message_admins("cleared the supplied laws of [src]") /mob/living/silicon/proc/notify_of_law_change(message) + throw_alert("newlaw", /obj/screen/alert/newlaw) if((last_law_notification + 1 SECOND) > world.time) return last_law_notification = world.time diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index dbffa182fe..74aad9bae0 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -248,35 +248,22 @@ src.mind.special_role = "traitor" traitors.current_antagonists |= src.mind - if (src.cells) - if (src.cell) - var/cellcharge = src.cell.charge/src.cell.maxcharge - switch(cellcharge) - if(0.75 to INFINITY) - src.cells.icon_state = "charge4" - if(0.5 to 0.75) - src.cells.icon_state = "charge3" - if(0.25 to 0.5) - src.cells.icon_state = "charge2" - if(0 to 0.25) - src.cells.icon_state = "charge1" - else - src.cells.icon_state = "charge0" - else - src.cells.icon_state = "charge-empty" + update_cell() - if(bodytemp) - switch(src.bodytemperature) //310.055 optimal body temp - if(335 to INFINITY) - src.bodytemp.icon_state = "temp2" - if(320 to 335) - src.bodytemp.icon_state = "temp1" - if(300 to 320) - src.bodytemp.icon_state = "temp0" - if(260 to 300) - src.bodytemp.icon_state = "temp-1" + var/turf/T = get_turf(src) + var/datum/gas_mixture/environment = T.return_air() + if(environment) + switch(environment.temperature) //310.055 optimal body temp + if(400 to INFINITY) + throw_alert("temp", /obj/screen/alert/hot/robot, 2) + if(360 to 400) + throw_alert("temp", /obj/screen/alert/hot/robot, 1) + if(260 to 360) + clear_alert("temp") + if(200 to 260) + throw_alert("temp", /obj/screen/alert/cold/robot, 1) else - src.bodytemp.icon_state = "temp-2" + throw_alert("temp", /obj/screen/alert/cold/robot, 2) //Oxygen and fire does nothing yet!! // if (src.oxygen) src.oxygen.icon_state = "oxy[src.oxygen_alert ? 1 : 0]" @@ -298,20 +285,43 @@ if(client && !client.adminobs) reset_view(null) + if(emagged) + throw_alert("hacked", /obj/screen/alert/hacked) + else + clear_alert("hacked") + return 1 +/mob/living/silicon/robot/proc/update_cell() + if(cell) + var/cellcharge = cell.charge/cell.maxcharge + switch(cellcharge) + if(0.75 to INFINITY) + clear_alert("charge") + if(0.5 to 0.75) + throw_alert("charge", /obj/screen/alert/lowcell, 1) + if(0.25 to 0.5) + throw_alert("charge", /obj/screen/alert/lowcell, 2) + if(0.01 to 0.25) + throw_alert("charge", /obj/screen/alert/lowcell, 3) + else + throw_alert("charge", /obj/screen/alert/emptycell) + else + throw_alert("charge", /obj/screen/alert/nocell) + + /mob/living/silicon/robot/proc/update_items() - if (src.client) - src.client.screen -= src.contents - for(var/obj/I in src.contents) + if(client) + client.screen -= contents + for(var/obj/I in contents) if(I && !(istype(I,/obj/item/weapon/cell) || istype(I,/obj/item/device/radio) || istype(I,/obj/machinery/camera) || istype(I,/obj/item/device/mmi))) - src.client.screen += I - if(src.module_state_1) - src.module_state_1:screen_loc = ui_inv1 - if(src.module_state_2) - src.module_state_2:screen_loc = ui_inv2 - if(src.module_state_3) - src.module_state_3:screen_loc = ui_inv3 + client.screen += I + if(module_state_1) + module_state_1:screen_loc = ui_inv1 + if(module_state_2) + module_state_2:screen_loc = ui_inv2 + if(module_state_3) + module_state_3:screen_loc = ui_inv3 updateicon() /mob/living/silicon/robot/proc/process_killswitch() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 9a6c384e0c..63267c6e09 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -34,7 +34,6 @@ //Hud stuff - var/obj/screen/cells = null var/obj/screen/inv1 = null var/obj/screen/inv2 = null var/obj/screen/inv3 = null @@ -935,6 +934,10 @@ // They stay locked down if their wire is cut. if(wires.LockedCut()) state = 1 + if(state) + throw_alert("locked", /obj/screen/alert/locked) + else + clear_alert("locked") lockdown = state lockcharge = state update_canmove() diff --git a/code/modules/mob/living/simple_mob/life.dm b/code/modules/mob/living/simple_mob/life.dm index d4ed684deb..781589dad1 100644 --- a/code/modules/mob/living/simple_mob/life.dm +++ b/code/modules/mob/living/simple_mob/life.dm @@ -52,19 +52,14 @@ healths.icon_state = "health7" //Updates the nutrition while we're here - if(nutrition_icon) - var/food_per = (nutrition / initial(nutrition)) * 100 - switch(food_per) - if(90 to INFINITY) - nutrition_icon.icon_state = "nutrition0" - if(75 to 90) - nutrition_icon.icon_state = "nutrition1" - if(50 to 75) - nutrition_icon.icon_state = "nutrition2" - if(25 to 50) - nutrition_icon.icon_state = "nutrition3" - if(0 to 25) - nutrition_icon.icon_state = "nutrition4" + var/food_per = (nutrition / initial(nutrition)) * 100 + switch(food_per) + if(90 to INFINITY) + clear_alert("nutrition") + if(50 to 90) + throw_alert("nutrition", /obj/screen/alert/hungry) + if(-INFINITY to 50) + throw_alert("nutrition", /obj/screen/alert/starving) // Override for special bullshit. /mob/living/simple_mob/proc/handle_special() @@ -91,54 +86,55 @@ if( abs(Environment.temperature - bodytemperature) > temperature_range ) //VOREStation Edit: heating adjustments bodytemperature += ((Environment.temperature - bodytemperature) / 5) - if(min_oxy) - if(Environment.gas["oxygen"] < min_oxy) - atmos_unsuitable = 1 - if(max_oxy) - if(Environment.gas["oxygen"] > max_oxy) - atmos_unsuitable = 1 - if(min_tox) - if(Environment.gas["phoron"] < min_tox) - atmos_unsuitable = 2 - if(max_tox) - if(Environment.gas["phoron"] > max_tox) - atmos_unsuitable = 2 - if(min_n2) - if(Environment.gas["nitrogen"] < min_n2) - atmos_unsuitable = 1 - if(max_n2) - if(Environment.gas["nitrogen"] > max_n2) - atmos_unsuitable = 1 - if(min_co2) - if(Environment.gas["carbon_dioxide"] < min_co2) - atmos_unsuitable = 1 - if(max_co2) - if(Environment.gas["carbon_dioxide"] > max_co2) - atmos_unsuitable = 1 + if(min_oxy && Environment.gas["oxygen"] < min_oxy) + atmos_unsuitable = 1 + throw_alert("oxy", /obj/screen/alert/not_enough_oxy) + else if(max_oxy && Environment.gas["oxygen"] > max_oxy) + atmos_unsuitable = 1 + throw_alert("oxy", /obj/screen/alert/too_much_oxy) + else + clear_alert("oxy") + + if(min_tox && Environment.gas["phoron"] < min_tox) + atmos_unsuitable = 2 + throw_alert("tox_in_air", /obj/screen/alert/not_enough_tox) + else if(max_tox && Environment.gas["phoron"] > max_tox) + atmos_unsuitable = 2 + throw_alert("tox_in_air", /obj/screen/alert/tox_in_air) + else + clear_alert("tox_in_air") + + if(min_n2 && Environment.gas["nitrogen"] < min_n2) + atmos_unsuitable = 1 + throw_alert("n2o", /obj/screen/alert/not_enough_nitro) + else if(max_n2 && Environment.gas["nitrogen"] > max_n2) + atmos_unsuitable = 1 + throw_alert("n2o", /obj/screen/alert/too_much_nitro) + else + clear_alert("n2o") + + if(min_co2 && Environment.gas["carbon_dioxide"] < min_co2) + atmos_unsuitable = 1 + throw_alert("co2", /obj/screen/alert/not_enough_co2) + else if(max_co2 && Environment.gas["carbon_dioxide"] > max_co2) + atmos_unsuitable = 1 + throw_alert("co2", /obj/screen/alert/too_much_co2) + else + clear_alert("co2") //Atmos effect if(bodytemperature < minbodytemp) - fire_alert = 2 adjustFireLoss(cold_damage_per_tick) - if(fire) - fire.icon_state = "fire1" + throw_alert("temp", /obj/screen/alert/cold, 3) else if(bodytemperature > maxbodytemp) - fire_alert = 1 adjustFireLoss(heat_damage_per_tick) - if(fire) - fire.icon_state = "fire2" + throw_alert("temp", /obj/screen/alert/hot, 3) else - fire_alert = 0 - if(fire) - fire.icon_state = "fire0" + clear_alert("temp") if(atmos_unsuitable) adjustOxyLoss(unsuitable_atoms_damage) - if(oxygen) - oxygen.icon_state = "oxy1" - else if(oxygen) - if(oxygen) - oxygen.icon_state = "oxy0" + else adjustOxyLoss(-unsuitable_atoms_damage) diff --git a/code/modules/mob/living/simple_mob/simple_hud.dm b/code/modules/mob/living/simple_mob/simple_hud.dm index fe851648b4..c16af17ae9 100644 --- a/code/modules/mob/living/simple_mob/simple_hud.dm +++ b/code/modules/mob/living/simple_mob/simple_hud.dm @@ -159,53 +159,7 @@ healths.screen_loc = ui_health hud_elements |= healths - //Oxygen dep icon - oxygen = new /obj/screen() - oxygen.icon = ui_style - oxygen.icon_state = "oxy0" - oxygen.name = "oxygen" - oxygen.screen_loc = ui_oxygen - hud_elements |= oxygen - //Toxins present icon - toxin = new /obj/screen() - toxin.icon = ui_style - toxin.icon_state = "tox0" - toxin.name = "toxin" - toxin.screen_loc = ui_toxin - hud_elements |= toxin - - //Fire warning - fire = new /obj/screen() - fire.icon = ui_style - fire.icon_state = "fire0" - fire.name = "fire" - fire.screen_loc = ui_fire - hud_elements |= fire - - //Pressure warning - pressure = new /obj/screen() - pressure.icon = ui_style - pressure.icon_state = "pressure0" - pressure.name = "pressure" - pressure.screen_loc = ui_pressure - hud_elements |= pressure - - //Body temp warning - bodytemp = new /obj/screen() - bodytemp.icon = ui_style - bodytemp.icon_state = "temp0" - bodytemp.name = "body temperature" - bodytemp.screen_loc = ui_temp - hud_elements |= bodytemp - - //Nutrition status - nutrition_icon = new /obj/screen() - nutrition_icon.icon = ui_style - nutrition_icon.icon_state = "nutrition0" - nutrition_icon.name = "nutrition" - nutrition_icon.screen_loc = ui_nutrition - hud_elements |= nutrition_icon pain = new /obj/screen( null ) diff --git a/code/modules/mob/living/simple_mob/simple_mob.dm b/code/modules/mob/living/simple_mob/simple_mob.dm index 3b063e1ac4..82d16472c1 100644 --- a/code/modules/mob/living/simple_mob/simple_mob.dm +++ b/code/modules/mob/living/simple_mob/simple_mob.dm @@ -67,7 +67,6 @@ var/maxbodytemp = 350 // Maximum of above var/heat_damage_per_tick = 3 // Amount of damage applied if animal's body temperature is higher than maxbodytemp var/cold_damage_per_tick = 2 // Same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp - var/fire_alert = 0 // 0 = fine, 1 = hot, 2 = cold var/min_oxy = 5 // Oxygen in moles, minimum, 0 is 'no minimum' var/max_oxy = 0 // Oxygen in moles, maximum, 0 is 'no maximum' diff --git a/code/modules/mob/login.dm b/code/modules/mob/login.dm index 34a7035d22..e83f10116a 100644 --- a/code/modules/mob/login.dm +++ b/code/modules/mob/login.dm @@ -51,7 +51,6 @@ else client.eye = src client.perspective = MOB_PERSPECTIVE - reload_fullscreen() // Reload any fullscreen overlays this mob has. add_click_catcher() update_client_color() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 6232f90dd7..4d3187bdd2 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -22,16 +22,10 @@ pullin = null purged = null internals = null - oxygen = null i_select = null m_select = null - toxin = null - fire = null - bodytemp = null healths = null throw_icon = null - nutrition_icon = null - pressure = null pain = null item_use_icon = null gun_move_icon = null @@ -962,6 +956,7 @@ mob/proc/yank_out_object() valid_objects = get_visible_implants(0) if(valid_objects.len == 1) //Yanking out last object - removing verb. src.verbs -= /mob/proc/yank_out_object + clear_alert("embeddedobject") if(ishuman(src)) var/mob/living/carbon/human/H = src @@ -1233,3 +1228,11 @@ mob/proc/yank_out_object() /mob/proc/GetAltName() return "" + +/mob/proc/get_ghost(even_if_they_cant_reenter = 0) + if(mind) + return mind.get_ghost(even_if_they_cant_reenter) + +/mob/proc/grab_ghost(force) + if(mind) + return mind.grab_ghost(force = force) \ No newline at end of file diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 111bcab799..375dd0a755 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -16,16 +16,10 @@ var/obj/screen/pullin = null var/obj/screen/purged = null var/obj/screen/internals = null - var/obj/screen/oxygen = null var/obj/screen/i_select = null var/obj/screen/m_select = null - var/obj/screen/toxin = null - var/obj/screen/fire = null - var/obj/screen/bodytemp = null var/obj/screen/healths = null var/obj/screen/throw_icon = null - var/obj/screen/nutrition_icon = null - var/obj/screen/pressure = null var/obj/screen/pain = null var/obj/screen/gun/item/item_use_icon = null var/obj/screen/gun/radio/radio_use_icon = null diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 22249811c8..7f4c48f89f 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -469,6 +469,8 @@ This function completely restores a damaged organ to perfect condition. if(!istype(implanted_object,/obj/item/weapon/implant) && !istype(implanted_object,/obj/item/device/nif)) // We don't want to remove REAL implants. Just shrapnel etc. //VOREStation Edit - NIFs pls implanted_object.loc = get_turf(src) implants -= implanted_object + if(!owner.has_embedded_objects()) + owner.clear_alert("embeddedobject") if(owner && !ignore_prosthetic_prefs) if(owner.client && owner.client.prefs && owner.client.prefs.real_name == owner.real_name) @@ -1184,6 +1186,7 @@ Note that amputating the affected organ does in fact remove the infection from t implants += W owner.embedded_flag = 1 owner.verbs += /mob/proc/yank_out_object + owner.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) W.add_blood(owner) if(ismob(W.loc)) var/mob/living/H = W.loc @@ -1372,4 +1375,11 @@ Note that amputating the affected organ does in fact remove the infection from t if(bling.body_parts_covered & src.body_part) covering_clothing |= bling - return covering_clothing \ No newline at end of file + return covering_clothing + +/mob/living/carbon/human/proc/has_embedded_objects() + . = 0 + for(var/obj/item/organ/external/L in organs) + for(var/obj/item/I in L.implants) + if(!istype(I,/obj/item/weapon/implant) && !istype(I,/obj/item/device/nif)) + return 1 \ No newline at end of file diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index e7e6eb6b4b..624d94443c 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -206,6 +206,8 @@ user.visible_message("[user] takes something out of incision on [target]'s [affected.name] with \the [tool]!", \ "You take [obj] out of incision on [target]'s [affected.name]s with \the [tool]!" ) affected.implants -= obj + if(!target.has_embedded_objects()) + target.clear_alert("embeddedobject") BITSET(target.hud_updateflag, IMPLOYAL_HUD) diff --git a/code/modules/vore/eating/belly_obj_vr.dm b/code/modules/vore/eating/belly_obj_vr.dm index 9cc0dd7224..373da4d551 100644 --- a/code/modules/vore/eating/belly_obj_vr.dm +++ b/code/modules/vore/eating/belly_obj_vr.dm @@ -720,3 +720,6 @@ dupe.emote_lists[K] += I return dupe + +/obj/belly/container_resist(mob/M) + return relay_resist(M) \ No newline at end of file diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index e73eff48f3..492482eb5c 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -185,10 +185,11 @@ // /mob/living/proc/vore_process_resist() //Are we resisting from inside a belly? - if(isbelly(loc)) - var/obj/belly/B = loc - B.relay_resist(src) - return TRUE //resist() on living does this TRUE thing. + // if(isbelly(loc)) + // var/obj/belly/B = loc + // B.relay_resist(src) + // return TRUE //resist() on living does this TRUE thing. + // Note: This is no longer required, as the refactors to resisting allow bellies to just define container_resist //Other overridden resists go here return FALSE @@ -509,51 +510,6 @@ "oxygen" = 21, "nitrogen" = 79) -// Procs for micros stuffed into boots and the like to escape from them -/mob/living/proc/escape_clothes(obj/item/clothing/C) - ASSERT(loc == C) - - if(ishuman(C.loc)) //In a /mob/living/carbon/human - var/mob/living/carbon/human/H = C.loc - if(H.shoes == C) //Being worn - to_chat(src," You start to climb around the larger creature's feet and ankles!") - to_chat(H,"Something is trying to climb out of your [C]!") - var/original_loc = H.loc - for(var/escape_time = 100,escape_time > 0,escape_time--) - if(H.loc != original_loc) - to_chat(src,"You're pinned back underfoot!") - to_chat(H,"You pin the escapee back underfoot!") - return - if(loc != C) - return - sleep(1) - - to_chat(src,"You manage to escape \the [C]!") - to_chat(H,"Somone has climbed out of your [C]!") - forceMove(H.loc) - - else //Being held by a human - to_chat(src,"You start to climb out of \the [C]!") - to_chat(H,"Something is trying to climb out of your [C]!") - for(var/escape_time = 60,escape_time > 0,escape_time--) - if(H.shoes == C) - to_chat(src,"You're pinned underfoot!") - to_chat(H,"You pin the escapee underfoot!") - return - if(loc != C) - return - sleep(1) - to_chat(src,"You manage to escape \the [C]!") - to_chat(H,"Somone has climbed out of your [C]!") - forceMove(H.loc) - - to_chat(src,"You start to climb out of \the [C]!") - sleep(50) - if(loc == C) - to_chat(src,"You climb out of \the [C]!") - forceMove(C.loc) - return - /mob/living/proc/feed_grabbed_to_self_falling_nom(var/mob/living/user, var/mob/living/prey) var/belly = user.vore_selected return perform_the_nom(user, prey, user, belly, delay = 1) //1/10th of a second is probably fine. diff --git a/icons/mob/screen/midnight.dmi b/icons/mob/screen/midnight.dmi index a2519bf1d5..e0ff03e0bf 100644 Binary files a/icons/mob/screen/midnight.dmi and b/icons/mob/screen/midnight.dmi differ diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi new file mode 100644 index 0000000000..32921f3213 Binary files /dev/null and b/icons/mob/screen_alert.dmi differ diff --git a/vorestation.dme b/vorestation.dme index 1b814ea422..e943234da0 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -149,6 +149,7 @@ #include "code\_onclick\hud\ability_screen_objects.dm" #include "code\_onclick\hud\action.dm" #include "code\_onclick\hud\ai.dm" +#include "code\_onclick\hud\alert.dm" #include "code\_onclick\hud\alien_larva.dm" #include "code\_onclick\hud\fullscreen.dm" #include "code\_onclick\hud\gun_mode.dm"