From aa3b7ac6781cec065dd84b4b46c1761c9cb7f0a1 Mon Sep 17 00:00:00 2001 From: Tigercat2000 Date: Sat, 16 Apr 2016 13:51:40 -0700 Subject: [PATCH 1/2] -tg- screen alerts A lot has changed. Major points: - All mobs now use the -tg- thrown alerts system. This is a system where a maximum of 5 "alerts" (which take the apperance of HUD icons like the inventory and modular action buttons) on their HUD. - Alerts are defined as a subtype of /obj/screen/alert. - Alerts are "thrown", or activated on the mob with the proc `mob.throw_alert("alert_id", /obj/screen/alert/path, severity (optional), new_master (optional, overlays the referenced "obj" on the button))` - Alerts are cleared by calling `mob.clear_alert("alert_id")` or by the /obj/screen/alert containing a `timeout` setting, which will automatically clear itself after that period of deciseconds. - Alerts may have functionality beyond appearance: Mousing over them will use the WireWraith tooltip system to generate a themed tooltip, and clicking them may have a function defined on the /obj/screen/alert object. - Shift-clicking an alert will give you it's name and status, in case the tooltips fail to work. - Hunger/Oxygen/Toxin/Nitrogen/Pressure/Etc warnings are now handled via the -tg- thrown alerts system. - Failing to breathe anything will display as an "No O2" warning. - Species breathing has been refactored to accomodate this. Vox are able to breathe the station air without instantly dying, but will be poisoned every time they breathe by the oxygen in the air. Any species with a unique gas breathing type will also display the correct "Choking (no X gas)" instead of just "oxygen". (Unless they have not breathed anything in, it's a quirk.) - Robot cell/temperature alerts also use this. - Aliens, though not harmed by toxins, will have an alert if they breathe in toxins, notifying them that "You'll be toast if this lights up." - More alerts have been added - Buckling - Activated on: Being buckled to an object. - Cleared on: Being unbuckled. - Click functionality: Calls resist(); Will unbuckle from chair instantly if unrestrained, otherwise, there is a delay period. - Hand/Leg cuffs - Activated on: Being handcuffed. - Cleared on: Being unhandcuffed. - Click functionality: Calls resist(); Will attempt to either get out of the handcuffs, or, if you are a xenomorph or hulk, break the handcuffs in 5 seconds. - Blind/High - Activated on: Becoming blinded/becoming high on LSD. - Cleared on: Becoming unblinded/the high wearing off. - Click functionality: None. - Asleep - Activated on: Life() tick detecting sleeping. - Deactivated on: Sleeping being 0 or less. - Click functionality: None. - Weightless - Activated on: Losing gravity. - Deactivated on: Moving back into an area with gravity. - Click functionality: None. - On Fire - Activated on: Catching fire. - Deactivated on: Being extinguished. - Click functionality: Calls resist(); Causes you to stop, drop, and roll, which will reduce firestacks and possibly extinguish you. - Law update (BORG ONLY) - Activated on: Laws being changed. - Deactivated on: Timer, 300 deciseconds. - Click functionality: None. - Hacked (BORG ONLY) - Activated on: Being emagged/given malf tools by the malf AI. - Deactivated on: Emagged status being removed. - Click functionality: None. - Locked (BORG ONLY) - Activated on: Lockdown being set (by emag law rewriting/robotics console/wire being destroyed) - Deactivated on: Movement being unlocked. - Click functionality: None. - Notify Cloning (GHOST ONLY) - Activated on: A human's body being placed in a DNA scanner. - Deactivated on: Timer, 300 deciseconds. - Click functionality: Reenters body. - Notify Jump (MULTIPURPOSE) (GHOST ONLY) - Activated on: Any sort of chance to become a mob (ie, golem rune). - Deactivated on: Timer, 300 deciseconds. - Click functionality: Varies. --- code/_onclick/hud/_defines.dm | 8 + code/_onclick/hud/alert.dm | 400 ++++++++++ code/_onclick/hud/alien.dm | 20 +- code/_onclick/hud/alien_larva.dm | 22 +- code/_onclick/hud/bot.dm | 14 +- code/_onclick/hud/hud.dm | 5 +- code/_onclick/hud/human.dm | 38 +- code/_onclick/hud/monkey.dm | 38 +- code/_onclick/hud/other_mobs.dm | 21 +- code/_onclick/hud/robot.dm | 28 +- code/game/dna/dna_modifier.dm | 5 +- code/game/gamemodes/cult/runes.dm | 2 +- code/game/gamemodes/miniantags/borer/borer.dm | 21 + .../gamemodes/miniantags/bot_swarm/swarmer.dm | 2 +- code/game/objects/buckling.dm | 4 +- code/game/objects/items.dm | 1 + code/game/objects/items/weapons/handcuffs.dm | 113 +-- code/game/objects/items/weapons/legcuffs.dm | 101 ++- code/game/objects/items/weapons/tools.dm | 2 +- code/game/objects/structures/spirit_board.dm | 9 +- code/modules/client/client defines.dm | 5 +- code/modules/client/client procs.dm | 4 + code/modules/mob/dead/observer/observer.dm | 14 + code/modules/mob/living/carbon/alien/alien.dm | 9 +- .../living/carbon/alien/humanoid/humanoid.dm | 4 + code/modules/mob/living/carbon/alien/life.dm | 16 +- .../mob/living/carbon/brain/posibrain.dm | 2 - code/modules/mob/living/carbon/carbon.dm | 130 +++- code/modules/mob/living/carbon/human/human.dm | 9 + code/modules/mob/living/carbon/human/life.dm | 44 +- .../living/carbon/human/species/species.dm | 259 ++++--- .../living/carbon/human/species/station.dm | 13 + .../mob/living/carbon/human/update_icons.dm | 13 +- code/modules/mob/living/carbon/life.dm | 13 +- code/modules/mob/living/life.dm | 11 +- code/modules/mob/living/living.dm | 264 +------ code/modules/mob/living/living_defense.dm | 2 + code/modules/mob/living/silicon/laws.dm | 14 +- code/modules/mob/living/silicon/robot/life.dm | 102 +-- .../modules/mob/living/silicon/robot/robot.dm | 7 +- .../mob/living/simple_animal/bot/bot.dm | 23 +- .../mob/living/simple_animal/bot/ed209bot.dm | 2 +- .../mob/living/simple_animal/bot/secbot.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 24 +- code/modules/mob/mob_defines.dm | 6 - code/modules/mob/mob_helpers.dm | 22 +- code/modules/power/singularity/narsie.dm | 6 +- .../chemical_reaction_slime.dm | 2 +- code/modules/tooltip/tooltip.dm | 116 +++ code/modules/tooltip/tooltip.html | 238 ++++++ icons/effects/effects.dmi | Bin 320448 -> 322480 bytes icons/mob/screen_alert.dmi | Bin 0 -> 35168 bytes interface/skin.dmf | 708 +++++++++--------- paradise.dme | 2 + 54 files changed, 1763 insertions(+), 1177 deletions(-) create mode 100644 code/_onclick/hud/alert.dm create mode 100644 code/modules/tooltip/tooltip.dm create mode 100644 code/modules/tooltip/tooltip.html create mode 100644 icons/mob/screen_alert.dmi diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index b11df7a0f63..50527c33329 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -69,6 +69,14 @@ #define ui_borg_radio "EAST-1:28,SOUTH+1:7" #define ui_borg_intents "EAST-2:26,SOUTH:5" +//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" diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm new file mode 100644 index 00000000000..8fec01be719 --- /dev/null +++ b/code/_onclick/hud/alert.dm @@ -0,0 +1,400 @@ +//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 = PoolOrNew(type) + + if(new_master) + var/old_layer = new_master.layer + new_master.layer = FLOAT_LAYER + alert.overlays += new_master + new_master.layer = old_layer + 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/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 = "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/nitro + name = "Choking (No N)" + desc = "You're not getting enough nitrogen. Find some good air before you pass out!" + icon_state = "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/not_enough_tox + name = "Choking (No Plasma)" + desc = "You're not getting enough plasma. Find some good air before you pass out!" + icon_state = "not_enough_tox" + +/obj/screen/alert/tox_in_air + name = "Choking (Plasma)" + desc = "There's highly flammable, toxic plasma 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 = "tox_in_air" +//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/hungry + name = "Hungry" + desc = "Some food would be good right about now." + icon_state = "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/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/drunk //Not implemented + name = "Drunk" + desc = "All that alcohol you've been drinking is impairing your speech, motor skills, and mental cognition. Make sure to act like it." + icon_state = "drunk" + +/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/dead/observer/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 \ No newline at end of file diff --git a/code/_onclick/hud/alien.dm b/code/_onclick/hud/alien.dm index fa7017fd2d8..2842facc713 100644 --- a/code/_onclick/hud/alien.dm +++ b/code/_onclick/hud/alien.dm @@ -125,24 +125,6 @@ mymob.throw_icon.name = "throw" mymob.throw_icon.screen_loc = ui_drop_throw - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = 'icons/mob/screen1_alien.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_alien_oxygen - - mymob.toxin = new /obj/screen() - mymob.toxin.icon = 'icons/mob/screen1_alien.dmi' - mymob.toxin.icon_state = "tox0" - mymob.toxin.name = "toxin" - mymob.toxin.screen_loc = ui_alien_toxin - - 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_alien_fire - mymob.healths = new /obj/screen() mymob.healths.icon = 'icons/mob/screen1_alien.dmi' mymob.healths.icon_state = "health0" @@ -173,6 +155,6 @@ mymob.client.screen = list() - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, nightvisionicon, mymob.pullin, alien_plasma_display, mymob.pullin) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.healths, nightvisionicon, mymob.pullin, alien_plasma_display, mymob.pullin) //, mymob.hands, 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/alien_larva.dm b/code/_onclick/hud/alien_larva.dm index 8232f2073e2..dca63c7d2ae 100644 --- a/code/_onclick/hud/alien_larva.dm +++ b/code/_onclick/hud/alien_larva.dm @@ -24,26 +24,6 @@ src.adding += using move_intent = using - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = 'icons/mob/screen1_alien.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_alien_oxygen - - mymob.toxin = new /obj/screen() - mymob.toxin.icon = 'icons/mob/screen1_alien.dmi' - mymob.toxin.icon_state = "tox0" - mymob.toxin.name = "toxin" - mymob.toxin.screen_loc = ui_alien_toxin - - - 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_alien_fire - - mymob.healths = new /obj/screen() mymob.healths.icon = 'icons/mob/screen1_alien.dmi' mymob.healths.icon_state = "health0" @@ -68,6 +48,6 @@ mymob.client.screen = list() - mymob.client.screen += list( mymob.zone_sel, mymob.oxygen, mymob.toxin, mymob.fire, mymob.healths, nightvisionicon, mymob.pullin) //, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list( mymob.zone_sel, mymob.healths, nightvisionicon, mymob.pullin) //, 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/bot.dm b/code/_onclick/hud/bot.dm index c4488376309..4f205b04567 100644 --- a/code/_onclick/hud/bot.dm +++ b/code/_onclick/hud/bot.dm @@ -30,18 +30,6 @@ mymob.healths.name = "health" mymob.healths.screen_loc = ui_borg_health - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = 'icons/mob/screen1_bot.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_oxygen - - mymob.fire = new /obj/screen() - mymob.fire.icon = 'icons/mob/screen1_bot.dmi' - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - mymob.pullin = new /obj/screen/pull() mymob.pullin.icon = 'icons/mob/screen1_bot.dmi' mymob.pullin.update_icon(mymob) @@ -49,7 +37,7 @@ mymob.client.screen = list() - mymob.client.screen += list(mymob.oxygen, mymob.fire, mymob.healths, mymob.pullin) + mymob.client.screen += list(mymob.healths, mymob.pullin) mymob.client.screen += adding + other mymob.client.screen += mymob.client.void return \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index fa414ba0dea..3c11b91a9b0 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -127,6 +127,9 @@ datum/hud/New(mob/owner) corgi_hud() reload_fullscreen() + persistant_inventory_update() + mymob.update_action_buttons() + reorganize_alerts() //Triggered when F12 is pressed (Unless someone changed something in the DMF) /mob/verb/button_pressed_F12(var/full = 0 as null) @@ -192,7 +195,7 @@ datum/hud/New(mob/owner) hud_used.hidden_inventory_update() hud_used.persistant_inventory_update() update_action_buttons() - //hud_used.reorganize_alerts() + hud_used.reorganize_alerts() else to_chat(usr, "\red Inventory hiding is currently only supported for human mobs, sorry.") diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 8dabef48583..d75f7c8ad61 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -358,42 +358,12 @@ mymob.throw_icon.alpha = ui_alpha src.hotkeybuttons += mymob.throw_icon - 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 - - 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 - - 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 - mymob.internals = new /obj/screen/internals() mymob.internals.icon = ui_style mymob.internals.icon_state = "internal0" mymob.internals.name = "internal" mymob.internals.screen_loc = ui_internal - 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 - - 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 - mymob.healths = new /obj/screen() mymob.healths.icon = ui_style mymob.healths.icon_state = "health0" @@ -406,12 +376,6 @@ mymob.healthdoll.name = "health doll" mymob.healthdoll.screen_loc = ui_healthdoll - 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 - mymob.pullin = new /obj/screen/pull() mymob.pullin.icon = ui_style mymob.pullin.update_icon(mymob) @@ -454,7 +418,7 @@ mymob.client.screen = list() - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.healthdoll, mymob.nutrition_icon, mymob.pullin, mymob.gun_setting_icon, lingchemdisplay, lingstingdisplay) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) + mymob.client.screen += list(mymob.throw_icon, mymob.zone_sel, mymob.internals, mymob.healths, mymob.healthdoll, mymob.pullin, mymob.gun_setting_icon, lingchemdisplay, lingstingdisplay) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) mymob.client.screen += src.adding + src.hotkeybuttons mymob.client.screen += mymob.client.void inventory_shown = 0 diff --git a/code/_onclick/hud/monkey.dm b/code/_onclick/hud/monkey.dm index b7a9a102116..34d26e77d6d 100644 --- a/code/_onclick/hud/monkey.dm +++ b/code/_onclick/hud/monkey.dm @@ -126,42 +126,12 @@ mymob.throw_icon.alpha = ui_alpha src.hotkeybuttons += mymob.throw_icon - 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 - - 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 - - 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 - mymob.internals = new /obj/screen/internals() mymob.internals.icon = ui_style mymob.internals.icon_state = "internal0" mymob.internals.name = "internal" mymob.internals.screen_loc = ui_internal - 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 - - 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 - mymob.healths = new /obj/screen() mymob.healths.icon = ui_style mymob.healths.icon_state = "health0" @@ -174,12 +144,6 @@ mymob.healthdoll.name = "health doll" mymob.healthdoll.screen_loc = ui_healthdoll - 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 - mymob.pullin = new /obj/screen/pull() mymob.pullin.icon = ui_style mymob.pullin.update_icon(mymob) @@ -223,7 +187,7 @@ mymob.client.screen = list() - mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.healthdoll, mymob.nutrition_icon, mymob.pullin, mymob.gun_setting_icon, lingchemdisplay, lingstingdisplay) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) + mymob.client.screen += list(mymob.throw_icon, mymob.zone_sel, mymob.internals, mymob.healths, mymob.healthdoll, mymob.pullin, mymob.gun_setting_icon, lingchemdisplay, lingstingdisplay) //, mymob.hands, mymob.rest, mymob.sleep) //, mymob.mach ) mymob.client.screen += src.adding + src.hotkeybuttons mymob.client.screen += mymob.client.void diff --git a/code/_onclick/hud/other_mobs.dm b/code/_onclick/hud/other_mobs.dm index e0b1ea11f1a..331c04fc69f 100644 --- a/code/_onclick/hud/other_mobs.dm +++ b/code/_onclick/hud/other_mobs.dm @@ -6,12 +6,6 @@ return /datum/hud/proc/corgi_hud(u) - mymob.fire = new /obj/screen() - mymob.fire.icon = 'icons/mob/screen1_corgi.dmi' - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - mymob.healths = new /obj/screen() mymob.healths.icon = 'icons/mob/screen1_corgi.dmi' mymob.healths.icon_state = "health0" @@ -23,21 +17,8 @@ mymob.pullin.update_icon(mymob) mymob.pullin.screen_loc = ui_construct_pull - mymob.oxygen = new /obj/screen() - mymob.oxygen.icon = 'icons/mob/screen1_corgi.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_oxygen - - mymob.toxin = new /obj/screen() - mymob.toxin.icon = 'icons/mob/screen1_corgi.dmi' - mymob.toxin.icon_state = "tox0" - mymob.toxin.name = "toxin" - mymob.toxin.screen_loc = ui_toxin - mymob.client.screen = list() - - mymob.client.screen += list(mymob.fire, mymob.healths, mymob.pullin, mymob.oxygen, mymob.toxin) + mymob.client.screen += list(mymob.healths, mymob.pullin) /datum/hud/proc/blob_hud(ui_style = 'icons/mob/screen1_Midnight.dmi') diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 8e729546b20..8a0fadf4e26 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -150,13 +150,6 @@ src.adding += using action_intent = using -//Cell - mymob:cells = new /obj/screen() - mymob:cells.icon = 'icons/mob/screen1_robot.dmi' - mymob:cells.icon_state = "charge-empty" - mymob:cells.name = "cell" - mymob:cells.screen_loc = ui_toxin - //Health mymob.healths = new /obj/screen() mymob.healths.icon = 'icons/mob/screen1_robot.dmi' @@ -186,25 +179,6 @@ mymob:lamp_button.name = "Toggle Headlamp" mymob:lamp_button.screen_loc = ui_borg_lamp -//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 = 'icons/mob/screen1_robot.dmi' - mymob.oxygen.icon_state = "oxy0" - mymob.oxygen.name = "oxygen" - mymob.oxygen.screen_loc = ui_oxygen - - mymob.fire = new /obj/screen() - mymob.fire.icon = 'icons/mob/screen1_robot.dmi' - mymob.fire.icon_state = "fire0" - mymob.fire.name = "fire" - mymob.fire.screen_loc = ui_fire - mymob.pullin = new /obj/screen/pull() mymob.pullin.icon = 'icons/mob/screen1_robot.dmi' mymob.pullin.update_icon(mymob) @@ -220,7 +194,7 @@ mymob.client.screen = list() - mymob.client.screen += list(mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.gun_setting_icon, mymob:lamp_button) //, mymob.rest, mymob.sleep, mymob.mach ) + mymob.client.screen += list(mymob.zone_sel, mymob.hands, mymob.healths, mymob.pullin, mymob.gun_setting_icon, mymob:lamp_button) //, mymob.rest, mymob.sleep, mymob.mach ) mymob.client.screen += src.adding + src.other mymob.client.screen += mymob.client.void return diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm index bf4a46134a1..1751df19442 100644 --- a/code/game/dna/dna_modifier.dm +++ b/code/game/dna/dna_modifier.dm @@ -271,10 +271,7 @@ || locate(/obj/machinery/computer/cloning, get_step(src, EAST)) \ || locate(/obj/machinery/computer/cloning, get_step(src, WEST))) - var/mob/dead/observer/ghost = occupant.get_ghost() - if(ghost) - to_chat(ghost, "Your corpse has been placed into a cloning scanner. Return to your body if you want to be cloned! (Verbs -> Ghost -> Re-enter corpse)") - to_chat(ghost, sound('sound/effects/genetics.ogg')) + occupant.notify_ghost_cloning(source = src) return /obj/machinery/dna_scannernew/proc/go_out() diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index c409449dbe4..cdd57853759 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -776,7 +776,7 @@ var/list/sacrificed = list() if (cultist.handcuffed) cultist.handcuffed.loc = cultist.loc cultist.handcuffed = null - cultist.update_inv_handcuffed() + cultist.update_handcuffed() if (cultist.legcuffed) cultist.legcuffed.loc = cultist.loc cultist.legcuffed = null diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 11111cdfc69..472dea17cce 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -36,6 +36,27 @@ /mob/living/captive_brain/emote(var/message) return +/mob/living/captive_brain/resist_borer() + var/mob/living/simple_animal/borer/B = loc + + to_chat(src, "You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).") + to_chat(B.host, "You feel the captive mind of [src] begin to resist your control.") + + spawn(rand(350,450) + B.host.brainloss) + + if(!B || !B.controlling) + return + + B.host.adjustBrainLoss(rand(5,10)) + to_chat(src, "With an immense exertion of will, you regain control of your body!") + to_chat(B.host, "You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.") + + B.detatch() + + verbs -= /mob/living/carbon/proc/release_control + verbs -= /mob/living/carbon/proc/punish_host + verbs -= /mob/living/carbon/proc/spawn_larvae + /mob/living/simple_animal/borer name = "cortical borer" real_name = "cortical borer" diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm index 514ceb4b14e..773e81349a1 100644 --- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm +++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm @@ -6,7 +6,7 @@ icon_state = "swarmer_unactivated" /obj/item/unactivated_swarmer/New() - notify_ghosts("An unactivated swarmer has been created in [get_area(src)]! (Click to enter)") + notify_ghosts("An unactivated swarmer has been created in [get_area(src)]!", enter_link = "(Click to enter)", source = src, attack_not_jump = 1) ..() /obj/item/unactivated_swarmer/Topic(href, href_list) diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 7616df4c119..273a4fe4fe6 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -12,7 +12,7 @@ . = ..() if(can_buckle && buckled_mob) return user_unbuckle_mob(user) - + /atom/movable/attack_robot(mob/living/user) . = ..() if(can_buckle && buckled_mob && Adjacent(user)) // attack_robot is called on all ranges, so the Adjacent check is needed @@ -46,6 +46,7 @@ buckled_mob = M M.update_canmove() post_buckle_mob(M) + M.throw_alert("buckled", /obj/screen/alert/restrained/buckled, new_master = src) return 1 /atom/movable/proc/unbuckle_mob() @@ -54,6 +55,7 @@ buckled_mob.buckled = null buckled_mob.anchored = initial(buckled_mob.anchored) buckled_mob.update_canmove() + buckled_mob.clear_alert("buckled") buckled_mob = null post_buckle_mob(.) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 8c4bf753108..417ad82d46b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -53,6 +53,7 @@ var/strip_delay = DEFAULT_ITEM_STRIP_DELAY var/put_on_delay = DEFAULT_ITEM_PUTON_DELAY + var/breakouttime = 0 /* Species-specific sprites, concept stolen from Paradise//vg/. ex: diff --git a/code/game/objects/items/weapons/handcuffs.dm b/code/game/objects/items/weapons/handcuffs.dm index b111501820f..3ce6fc03130 100644 --- a/code/game/objects/items/weapons/handcuffs.dm +++ b/code/game/objects/items/weapons/handcuffs.dm @@ -12,7 +12,7 @@ throw_range = 5 materials = list(MAT_METAL=500) origin_tech = "materials=1" - var/breakouttime = 600 //Deciseconds = 60s = 1 minutes + breakouttime = 600 //Deciseconds = 60s = 1 minutes var/cuffsound = 'sound/weapons/handcuffs.ogg' var/trashtype = null //For disposable cuffs @@ -50,7 +50,7 @@ else loc = target target.handcuffed = src - target.update_inv_handcuffed(1) + target.update_handcuffed() return /obj/item/weapon/restraints/handcuffs/cable @@ -121,7 +121,7 @@ if(do_mob(user, C, 30)) if(!C.handcuffed) C.handcuffed = new /obj/item/weapon/restraints/handcuffs/cable/zipties/used(C) - C.update_inv_handcuffed(1) + C.update_handcuffed() to_chat(user, "You handcuff [C].") add_logs(C, user, "ziptie-cuffed") else @@ -133,110 +133,3 @@ /obj/item/weapon/restraints/handcuffs/cable/zipties/used/attack() return - -//Legcuffs -/obj/item/weapon/restraints/legcuffs - name = "leg cuffs" - desc = "Use this to keep prisoners in line." - gender = PLURAL - icon = 'icons/obj/items.dmi' - icon_state = "handcuff" - flags = CONDUCT - throwforce = 0 - w_class = 3.0 - origin_tech = "materials=1" - slowdown = 7 - var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute - -/obj/item/weapon/restraints/legcuffs/beartrap - name = "bear trap" - throw_speed = 1 - throw_range = 1 - icon_state = "beartrap0" - desc = "A trap used to catch bears and other legged creatures." - var/armed = 0 - var/obj/item/weapon/grenade/iedcasing/IED = null - -/obj/item/weapon/restraints/legcuffs/beartrap/Destroy() - if(IED) - qdel(IED) - IED = null - return ..() - -/obj/item/weapon/restraints/legcuffs/beartrap/suicide_act(mob/user) - user.visible_message("[user] is sticking \his head in the [src.name]! It looks like \he's trying to commit suicide.") - playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) - return (BRUTELOSS) - -/obj/item/weapon/restraints/legcuffs/beartrap/attack_self(mob/user as mob) - ..() - if(ishuman(user) && !user.stat && !user.restrained()) - armed = !armed - icon_state = "beartrap[armed]" - to_chat(user, "[src] is now [armed ? "armed" : "disarmed"]") - -/obj/item/weapon/restraints/legcuffs/beartrap/attackby(var/obj/item/I, mob/user as mob) //Let's get explosive. - if(istype(I, /obj/item/weapon/grenade/iedcasing)) - if(IED) - to_chat(user, "This beartrap already has an IED hooked up to it!") - return - IED = I - switch(IED.assembled) - if(0,1) //if it's not fueled/hooked up - to_chat(user, "You haven't prepared this IED yet!") - IED = null - return - if(2,3) - user.drop_item(src) - I.forceMove(src) - message_admins("[key_name_admin(user)] has rigged a beartrap with an IED.") - log_game("[key_name(user)] has rigged a beartrap with an IED.") - to_chat(user, "You sneak the [IED] underneath the pressure plate and connect the trigger wire.") - desc = "A trap used to catch bears and other legged creatures. There is an IED hooked up to it." - else - to_chat(user, "You shouldn't be reading this message! Contact a coder or someone, something broke!") - IED = null - return - if(istype(I, /obj/item/weapon/screwdriver)) - if(IED) - IED.forceMove(get_turf(src)) - IED = null - to_chat(user, "You remove the IED from the [src].") - return - ..() - -/obj/item/weapon/restraints/legcuffs/beartrap/Crossed(AM as mob|obj) - if(armed && isturf(src.loc)) - if( (iscarbon(AM) || isanimal(AM)) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator)) - var/mob/living/L = AM - armed = 0 - icon_state = "beartrap0" - playsound(src.loc, 'sound/effects/snap.ogg', 50, 1) - L.visible_message("[L] triggers \the [src].", \ - "You trigger \the [src]!") - - if(IED && isturf(src.loc)) - IED.active = 1 - IED.overlays -= image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_filled") - IED.icon_state = initial(icon_state) + "_active" - IED.assembled = 3 - message_admins("[key_name_admin(usr)] has triggered an IED-rigged [name].") - log_game("[key_name(usr)] has triggered an IED-rigged [name].") - spawn(IED.det_time) - IED.prime() - - if(ishuman(AM)) - var/mob/living/carbon/H = AM - if(H.lying) - H.apply_damage(20,BRUTE,"chest") - else - H.apply_damage(20,BRUTE,(pick("l_leg", "r_leg"))) - if(!H.legcuffed) //beartrap can't cuff you leg if there's already a beartrap or legcuffs. - H.legcuffed = src - src.loc = H - H.update_inv_legcuffed(0) - feedback_add_details("handcuffs","B") //Yes, I know they're legcuffs. Don't change this, no need for an extra variable. The "B" is used to tell them apart. - - else - L.apply_damage(20,BRUTE) - ..() diff --git a/code/game/objects/items/weapons/legcuffs.dm b/code/game/objects/items/weapons/legcuffs.dm index 88c555d8148..fa485cbf93b 100644 --- a/code/game/objects/items/weapons/legcuffs.dm +++ b/code/game/objects/items/weapons/legcuffs.dm @@ -1,5 +1,5 @@ -/obj/item/weapon/legcuffs - name = "legcuffs" +/obj/item/weapon/restraints/legcuffs + name = "leg cuffs" desc = "Use this to keep prisoners in line." gender = PLURAL icon = 'icons/obj/items.dmi' @@ -8,7 +8,102 @@ throwforce = 0 w_class = 3.0 origin_tech = "materials=1" - var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute + slowdown = 7 + breakouttime = 300 //Deciseconds = 30s = 0.5 minute + +/obj/item/weapon/restraints/legcuffs/beartrap + name = "bear trap" + throw_speed = 1 + throw_range = 1 + icon_state = "beartrap0" + desc = "A trap used to catch bears and other legged creatures." + var/armed = 0 + var/obj/item/weapon/grenade/iedcasing/IED = null + +/obj/item/weapon/restraints/legcuffs/beartrap/Destroy() + if(IED) + qdel(IED) + IED = null + return ..() + +/obj/item/weapon/restraints/legcuffs/beartrap/suicide_act(mob/user) + user.visible_message("[user] is sticking \his head in the [src.name]! It looks like \he's trying to commit suicide.") + playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) + return (BRUTELOSS) + +/obj/item/weapon/restraints/legcuffs/beartrap/attack_self(mob/user as mob) + ..() + if(ishuman(user) && !user.stat && !user.restrained()) + armed = !armed + icon_state = "beartrap[armed]" + to_chat(user, "[src] is now [armed ? "armed" : "disarmed"]") + +/obj/item/weapon/restraints/legcuffs/beartrap/attackby(var/obj/item/I, mob/user as mob) //Let's get explosive. + if(istype(I, /obj/item/weapon/grenade/iedcasing)) + if(IED) + to_chat(user, "This beartrap already has an IED hooked up to it!") + return + IED = I + switch(IED.assembled) + if(0,1) //if it's not fueled/hooked up + to_chat(user, "You haven't prepared this IED yet!") + IED = null + return + if(2,3) + user.drop_item(src) + I.forceMove(src) + message_admins("[key_name_admin(user)] has rigged a beartrap with an IED.") + log_game("[key_name(user)] has rigged a beartrap with an IED.") + to_chat(user, "You sneak the [IED] underneath the pressure plate and connect the trigger wire.") + desc = "A trap used to catch bears and other legged creatures. There is an IED hooked up to it." + else + to_chat(user, "You shouldn't be reading this message! Contact a coder or someone, something broke!") + IED = null + return + if(istype(I, /obj/item/weapon/screwdriver)) + if(IED) + IED.forceMove(get_turf(src)) + IED = null + to_chat(user, "You remove the IED from the [src].") + return + ..() + +/obj/item/weapon/restraints/legcuffs/beartrap/Crossed(AM as mob|obj) + if(armed && isturf(src.loc)) + if( (iscarbon(AM) || isanimal(AM)) && !istype(AM, /mob/living/simple_animal/parrot) && !istype(AM, /mob/living/simple_animal/construct) && !istype(AM, /mob/living/simple_animal/shade) && !istype(AM, /mob/living/simple_animal/hostile/viscerator)) + var/mob/living/L = AM + armed = 0 + icon_state = "beartrap0" + playsound(src.loc, 'sound/effects/snap.ogg', 50, 1) + L.visible_message("[L] triggers \the [src].", \ + "You trigger \the [src]!") + + if(IED && isturf(src.loc)) + IED.active = 1 + IED.overlays -= image('icons/obj/grenade.dmi', icon_state = "improvised_grenade_filled") + IED.icon_state = initial(icon_state) + "_active" + IED.assembled = 3 + message_admins("[key_name_admin(usr)] has triggered an IED-rigged [name].") + log_game("[key_name(usr)] has triggered an IED-rigged [name].") + spawn(IED.det_time) + IED.prime() + + if(ishuman(AM)) + var/mob/living/carbon/H = AM + if(H.lying) + H.apply_damage(20,BRUTE,"chest") + else + H.apply_damage(20,BRUTE,(pick("l_leg", "r_leg"))) + if(!H.legcuffed) //beartrap can't cuff you leg if there's already a beartrap or legcuffs. + H.legcuffed = src + src.loc = H + H.update_inv_legcuffed(0) + feedback_add_details("handcuffs","B") //Yes, I know they're legcuffs. Don't change this, no need for an extra variable. The "B" is used to tell them apart. + + else + L.apply_damage(20,BRUTE) + ..() + /obj/item/weapon/legcuffs/bolas name = "bolas" diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index a187dc09b65..2a9b64748dd 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -127,7 +127,7 @@ C.handcuffed = null if(C.buckled && C.buckled.buckle_requires_restraints) C.buckled.unbuckle_mob() - C.update_inv_handcuffed() + C.update_handcuffed() return else ..() diff --git a/code/game/objects/structures/spirit_board.dm b/code/game/objects/structures/spirit_board.dm index cb29dec1926..25fe7f4a134 100644 --- a/code/game/objects/structures/spirit_board.dm +++ b/code/game/objects/structures/spirit_board.dm @@ -10,13 +10,6 @@ var/planchette = "A" var/lastuser = null -/obj/structure/spirit_board/proc/announce_to_ghosts() - for(var/mob/dead/observer/O in player_list) - if(O.client) - var/area/A = get_area(src) - if(A) - to_chat(O, "\blue Someone has begun playing with a [src.name] in [A.name]!. (Teleport)") - /obj/structure/spirit_board/examine(mob/user) ..(user) to_chat(user, "[initial(desc)] The planchette is sitting at \"[planchette]\".") @@ -37,7 +30,7 @@ if(virgin) virgin = 0 - announce_to_ghosts() + notify_ghosts("Someone has begun playing with a [src.name] in [get_area(src)]!", source = src) planchette = input("Choose the letter.", "Seance!") in list("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z") add_logs(M, src, "picked a letter on", addition="which was \"[planchette]\".") diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index fa6d0015399..30e4793c747 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -81,4 +81,7 @@ control_freak = CONTROL_FREAK_ALL | CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS - var/datum/click_intercept/click_intercept = null \ No newline at end of file + var/datum/click_intercept/click_intercept = null + + //datum that controls the displaying and hiding of tooltips + var/datum/tooltip/tooltips \ No newline at end of file diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 31db10045f0..57b7487cbe5 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -317,6 +317,10 @@ to_chat(src, "Unable to access asset cache browser, if you are using a custom skin file, please allow DS to download the updated version, if you are not, then make a bug report. This is not a critical issue but can cause issues with resource downloading, as it is impossible to know when extra resources arrived to you.") + //This is down here because of the browse() calls in tooltip/New() + if(!tooltips) + tooltips = new /datum/tooltip(src) + ////////////// //DISCONNECT// ////////////// diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 82b83db73ef..77afb5e2665 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -248,6 +248,16 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source) if(message) to_chat(src, "[message]") + if(source) + var/obj/screen/alert/A = throw_alert("\ref[source]_notify_cloning", /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) to_chat(src, sound(sound)) @@ -563,6 +573,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return forceMove(T) following = null + + if(href_list["reenter"]) + reenter_corpse() + ..() //END TELEPORT HREF CODE diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index a6bf793abe0..6192b0acc6b 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -102,22 +102,19 @@ // +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt. if(bodytemperature > 360.15) //Body temperature is too hot. - fire_alert = max(fire_alert, 1) + throw_alert("alien_fire", /obj/screen/alert/alien_fire) switch(bodytemperature) if(360 to 400) apply_damage(HEAT_DAMAGE_LEVEL_1, BURN) - fire_alert = max(fire_alert, 2) if(400 to 460) apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 2) if(460 to INFINITY) if(on_fire) apply_damage(HEAT_DAMAGE_LEVEL_3, BURN) - fire_alert = max(fire_alert, 2) else apply_damage(HEAT_DAMAGE_LEVEL_2, BURN) - fire_alert = max(fire_alert, 2) - return + else + clear_alert("alien_fire") /mob/living/carbon/alien/handle_mutations_and_radiation() // Aliens love radiation nom nom nom diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index c50e4603e41..90fe6537759 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -343,6 +343,10 @@ In all, this is a lot like the monkey code. /N /mob/living/carbon/alien/humanoid/canBeHandcuffed() return 1 +/mob/living/carbon/alien/humanoid/cuff_resist(obj/item/I) + playsound(src, 'sound/voice/hiss5.ogg', 40, 1, 1) //Alien roars when starting to break free + ..(I, cuff_break = 1) + /mob/living/carbon/alien/humanoid/get_standard_pixel_y_offset(lying = 0) if(leaping) return -32 diff --git a/code/modules/mob/living/carbon/alien/life.dm b/code/modules/mob/living/carbon/alien/life.dm index 93bf633093f..cf602694233 100644 --- a/code/modules/mob/living/carbon/alien/life.dm +++ b/code/modules/mob/living/carbon/alien/life.dm @@ -7,19 +7,19 @@ return 0 var/toxins_used = 0 - var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME + var/breath_pressure = (breath.total_moles() * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME //Partial pressure of the toxins in our breath - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure + var/Toxins_pp = (breath.toxins / breath.total_moles()) * breath_pressure if(Toxins_pp) // Detect toxins in air adjustPlasma(breath.toxins*250) - toxins_alert = max(toxins_alert, 1) + throw_alert("alien_tox", /obj/screen/alert/alien_tox) toxins_used = breath.toxins else - toxins_alert = 0 + clear_alert("alien_tox") //Breathe in toxins and out oxygen breath.toxins -= toxins_used @@ -30,14 +30,6 @@ return 1 -/mob/living/carbon/alien/handle_breath_temperature(datum/gas_mixture/breath) - if(breath.temperature > (T0C + 66) && !(RESIST_COLD in mutations)) - if(prob(20)) - to_chat(src, "You feel a searing heat in your lungs!") - fire_alert = max(fire_alert, 1) - else - fire_alert = 0 - /mob/living/carbon/alien/update_sight() if(stat == DEAD || (XRAY in mutations)) sight |= SEE_TURFS diff --git a/code/modules/mob/living/carbon/brain/posibrain.dm b/code/modules/mob/living/carbon/brain/posibrain.dm index 07251303a12..f6cdb0362e3 100644 --- a/code/modules/mob/living/carbon/brain/posibrain.dm +++ b/code/modules/mob/living/carbon/brain/posibrain.dm @@ -47,8 +47,6 @@ for(var/mob/dead/observer/O in player_list) if(check_observer(O)) to_chat(O, "\A [src] has been activated. (Teleport | Sign Up)") -// if(ROLE_POSIBRAIN in O.client.prefs.be_special) The Guardian implementation looks cleaner -// question(O.client) /obj/item/device/mmi/posibrain/proc/check_observer(var/mob/dead/observer/O) if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 84348120528..af76142de76 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -607,7 +607,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, handcuffed = null if(buckled && buckled.buckle_requires_restraints) buckled.unbuckle_mob() - update_inv_handcuffed() + update_handcuffed() else if(I == legcuffed) legcuffed = null update_inv_legcuffed() @@ -732,6 +732,132 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, /mob/living/carbon/is_muzzled() return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) +/mob/living/carbon/proc/spin(spintime, speed) + spawn() + var/D = dir + while(spintime >= speed) + sleep(speed) + switch(D) + if(NORTH) + D = EAST + if(SOUTH) + D = WEST + if(EAST) + D = SOUTH + if(WEST) + D = NORTH + dir = D + spintime -= speed + +/mob/living/carbon/resist_buckle() + if(restrained()) + changeNext_move(CLICK_CD_BREAKOUT) + last_special = world.time + CLICK_CD_BREAKOUT + visible_message("[src] attempts to unbuckle themself!", \ + "You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)") + if(do_after(src, 600, 0, target = src)) + if(!buckled) + return + buckled.user_unbuckle_mob(src,src) + else + if(src && buckled) + src << "You fail to unbuckle yourself!" + else + buckled.user_unbuckle_mob(src,src) + +/mob/living/carbon/resist_fire() + fire_stacks -= 5 + weakened = max(weakened, 3)//We dont check for CANWEAKEN, I don't care how immune to weakening you are, if you're rolling on the ground, you're busy. + update_canmove() + 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] has successfully extinguished themselves!", \ + "You extinguish yourself.") + ExtinguishMob() + return + + +/mob/living/carbon/resist_restraints() + var/obj/item/I = null + if(handcuffed) + I = handcuffed + else if(legcuffed) + I = legcuffed + if(I) + changeNext_move(CLICK_CD_BREAKOUT) + last_special = world.time + CLICK_CD_BREAKOUT + cuff_resist(I) + + +/mob/living/carbon/proc/cuff_resist(obj/item/I, breakouttime = 600, cuff_break = 0) + breakouttime = I.breakouttime + + var/displaytime = breakouttime / 600 + if(!cuff_break) + visible_message("[src] attempts to remove [I]!") + to_chat(src, "You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)") + if(do_after(src, breakouttime, 0, target = src)) + if(I.loc != src || buckled) + return + visible_message("[src] manages to remove [I]!") + to_chat(src, "You successfully remove [I].") + + if(I == handcuffed) + handcuffed.loc = loc + handcuffed.dropped(src) + handcuffed = null + if(buckled && buckled.buckle_requires_restraints) + buckled.unbuckle_mob(src) + update_handcuffed() + return + if(I == legcuffed) + legcuffed.loc = loc + legcuffed.dropped() + legcuffed = null + update_inv_legcuffed() + return + return 1 + else + to_chat(src, "You fail to remove [I]!") + + else + breakouttime = 50 + visible_message("[src] is trying to break [I]!") + to_chat(src, "You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)") + if(do_after(src, breakouttime, 0, target = src)) + if(!I.loc || buckled) + return + visible_message("[src] manages to break [I]!") + to_chat(src, "You successfully break [I].") + qdel(I) + + if(I == handcuffed) + handcuffed = null + update_handcuffed() + return + else if(I == legcuffed) + legcuffed = null + update_inv_legcuffed() + return + return 1 + else + to_chat(src, "You fail to break [I]!") + +//called when we get cuffed/uncuffed +/mob/living/carbon/proc/update_handcuffed() + if(handcuffed) + drop_r_hand() + drop_l_hand() + stop_pulling() + throw_alert("handcuffed", /obj/screen/alert/restrained/handcuffed, new_master = src.handcuffed) + else + clear_alert("handcuffed") + update_action_buttons() //some of our action buttons might be unusable when we're handcuffed. + update_inv_handcuffed() + /mob/living/carbon/get_standard_pixel_y_offset(lying = 0) if(lying) if(buckled) return initial(pixel_y) @@ -765,7 +891,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, handcuffed = null if (buckled && buckled.buckle_requires_restraints) buckled.unbuckle_mob() - update_inv_handcuffed() + update_handcuffed() if (client) client.screen -= W if (W) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 5d27605b13c..2319b2e77c5 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1348,6 +1348,15 @@ update_inv_shoes(1) return 1 +/mob/living/carbon/human/cuff_resist(obj/item/I) + if(HULK in mutations) + say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + if(..(I, cuff_break = 1)) + unEquip(I) + else + if(..()) + unEquip(I) + /mob/living/carbon/human/get_visible_implants(var/class = 0) var/list/visible_implants = list() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index bdd22a7e6fb..0f5f6a1a3d2 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -369,8 +369,7 @@ var/obj/item/organ/external/affected = get_organ("chest") affected.add_autopsy_data("Suffocation", oxyloss) - - oxygen_alert = max(oxygen_alert, 1) + throw_alert("oxy", /obj/screen/alert/oxy) return 0 @@ -384,7 +383,7 @@ // to_chat(world, "Loc temp: [loc_temp] - Body temp: [bodytemperature] - Fireloss: [getFireLoss()] - Thermal protection: [get_thermal_protection()] - Fire protection: [thermal_protection + add_fire_protection(loc_temp)] - Heat capacity: [environment_heat_capacity] - Location: [loc] - src: [src]") //Body temperature is adjusted in two steps. Firstly your body tries to stabilize itself a bit. - if(stat != 2) + if(stat != DEAD) stabilize_temperature_from_calories() //After then, it reacts to the surrounding atmosphere based on your thermal protection @@ -403,41 +402,43 @@ // +/- 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 var/mult = species.hot_env_multiplier if(bodytemperature >= species.heat_level_1 && bodytemperature <= species.heat_level_2) + throw_alert("temp", /obj/screen/alert/hot, 1) take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature") - fire_alert = max(fire_alert, 2) if(bodytemperature > species.heat_level_2 && bodytemperature <= species.heat_level_3) + throw_alert("temp", /obj/screen/alert/hot, 2) take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature") - fire_alert = max(fire_alert, 2) if(bodytemperature > species.heat_level_3 && bodytemperature < INFINITY) + throw_alert("temp", /obj/screen/alert/hot, 3) if(on_fire) take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_3, used_weapon = "Fire") - fire_alert = max(fire_alert, 2) else take_overall_damage(burn=mult*HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature") - fire_alert = max(fire_alert, 2) else if(bodytemperature < species.cold_level_1) - fire_alert = max(fire_alert, 1) - if(status_flags & GODMODE) return 1 //godmode - - if(stat == DEAD) return 1 //ZomgPonies -- No need for cold burn damage if dead + if(status_flags & GODMODE) + return 1 + if(stat == DEAD) + return 1 if(!istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) var/mult = species.cold_env_multiplier if(bodytemperature >= species.cold_level_2 && bodytemperature <= species.cold_level_1) + throw_alert("temp", /obj/screen/alert/cold, 1) take_overall_damage(burn=mult*COLD_DAMAGE_LEVEL_1, used_weapon = "Low Body Temperature") - fire_alert = max(fire_alert, 1) if(bodytemperature >= species.cold_level_3 && bodytemperature < species.cold_level_2) + throw_alert("temp", /obj/screen/alert/cold, 2) take_overall_damage(burn=mult*COLD_DAMAGE_LEVEL_2, used_weapon = "Low Body Temperature") - fire_alert = max(fire_alert, 1) if(bodytemperature > -INFINITY && bodytemperature < species.cold_level_3) + throw_alert("temp", /obj/screen/alert/cold, 3) take_overall_damage(burn=mult*COLD_DAMAGE_LEVEL_3, used_weapon = "Low Body Temperature") - fire_alert = max(fire_alert, 1) + else + clear_alert("temp") + else + clear_alert("temp") // 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! @@ -449,21 +450,20 @@ 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(RESIST_COLD in mutations) - pressure_alert = -1 + clear_alert("pressure") else take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure") - pressure_alert = -2 + throw_alert("pressure", /obj/screen/alert/lowpressure, 2) - return ///FIRE CODE /mob/living/carbon/human/handle_fire() diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 9b68e5830cb..3190195746d 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -52,6 +52,19 @@ var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning. var/hazard_low_pressure = HAZARD_LOW_PRESSURE // Dangerously low pressure. + var/list/atmos_requirements = list( + "min_oxy" = 16, + "max_oxy" = INFINITY, + "min_nitro" = 0, + "max_nitro" = INFINITY, + "min_tox" = 0, + "max_tox" = 0.005, + "min_co2" = 0, + "max_co2" = 10, + "sa_para" = 1, + "sa_sleep" = 5 + ) + var/brute_mod = null // Physical damage reduction/malus. var/burn_mod = null // Burn damage reduction/malus. @@ -181,66 +194,105 @@ O.owner = H /datum/species/proc/handle_breath(var/datum/gas_mixture/breath, var/mob/living/carbon/human/H) - var/safe_oxygen_min = 16 // Minimum safe partial pressure of O2, in kPa - //var/safe_oxygen_max = 140 // Maximum safe partial pressure of O2, in kPa (Not used for now) - var/safe_co2_max = 10 // Yes it's an arbitrary value who cares? - var/safe_toxins_max = 0.005 - var/SA_para_min = 1 - var/SA_sleep_min = 5 - var/oxygen_used = 0 - var/nitrogen_used = 0 var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME - var/vox_oxygen_max = 1 // For vox. + + var/O2_used = 0 + var/N2_used = 0 + var/Tox_used = 0 + var/CO2_used = 0 //Partial pressure of the O2 in our breath - var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure - // Same, but for the toxins - var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure - // And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun) - var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure // Tweaking to fit the hacky bullshit I've done with atmo -- TLE - // Nitrogen, for Vox. - var/Nitrogen_pp = (breath.nitrogen/breath.total_moles())*breath_pressure + var/O2_pp = (breath.oxygen/breath.total_moles()) * breath_pressure + // Partial pressure of Nitrogen + var/N2_pp = (breath.nitrogen/breath.total_moles()) * breath_pressure + // Partial pressure of plasma + var/Tox_pp = (breath.toxins/breath.total_moles()) * breath_pressure + // Partial pressure of CO2 + var/CO2_pp = (breath.carbon_dioxide/breath.total_moles()) * breath_pressure - // TODO: Split up into Voxs' own proc. - if(O2_pp < safe_oxygen_min && name != "Vox") // Too little oxygen + if(O2_pp < atmos_requirements["min_oxy"]) if(prob(20)) spawn(0) H.emote("gasp") + + H.failed_last_breath = 1 if(O2_pp > 0) - var/ratio = safe_oxygen_min/O2_pp - H.adjustOxyLoss(min(5*ratio, HUMAN_MAX_OXYLOSS)) // Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!) - H.failed_last_breath = 1 - oxygen_used = breath.oxygen*ratio/6 + var/ratio = atmos_requirements["min_oxy"] / O2_pp + H.adjustOxyLoss(min(5 * ratio, HUMAN_MAX_OXYLOSS)) else H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) - H.failed_last_breath = 1 - H.oxygen_alert = max(H.oxygen_alert, 1) - else if(Nitrogen_pp < safe_oxygen_min && name == "Vox") //Vox breathe nitrogen, not oxygen. + H.throw_alert("oxy", /obj/screen/alert/oxy) + else if(atmos_requirements["max_oxy"] && O2_pp > atmos_requirements["max_oxy"]) + var/ratio = (breath.oxygen / atmos_requirements["max_oxy"]) * 1000 + H.adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) + H.throw_alert("oxy", /obj/screen/alert/too_much_oxy) + else + H.clear_alert("oxy") + if(atmos_requirements["min_oxy"]) //species breathes this gas, so, they got their air + H.failed_last_breath = 0 + H.adjustOxyLoss(-5) + O2_used = breath.oxygen / 6 + if(N2_pp < atmos_requirements["min_nitro"]) if(prob(20)) - spawn(0) H.emote("gasp") - if(Nitrogen_pp > 0) - var/ratio = safe_oxygen_min/Nitrogen_pp - H.adjustOxyLoss(min(5*ratio, HUMAN_MAX_OXYLOSS)) - H.failed_last_breath = 1 - nitrogen_used = breath.nitrogen*ratio/6 + spawn(0) + H.emote("gasp") + + H.failed_last_breath = 1 + if(N2_pp > 0) + var/ratio = atmos_requirements["min_nitro"] / N2_pp + H.adjustOxyLoss(min(5 * ratio, HUMAN_MAX_OXYLOSS)) else H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) - H.failed_last_breath = 1 - H.oxygen_alert = max(H.oxygen_alert, 1) + H.throw_alert("nitro", /obj/screen/alert/nitro) + else if(atmos_requirements["max_nitro"] && N2_pp > atmos_requirements["max_nitro"]) + var/ratio = (breath.nitrogen / atmos_requirements["max_nitro"]) * 1000 + H.adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) + H.throw_alert("nitro", /obj/screen/alert/too_much_nitro) + else + H.clear_alert("nitro") + if(atmos_requirements["min_nitro"]) //species breathes this gas, so they got their air + H.failed_last_breath = 0 + H.adjustOxyLoss(-5) + N2_used = breath.nitrogen / 6 - else // We're in safe limits - H.failed_last_breath = 0 - H.adjustOxyLoss(-5) - oxygen_used = breath.oxygen/6 - H.oxygen_alert = 0 + if(Tox_pp < atmos_requirements["min_tox"]) + if(prob(20)) + spawn(0) + H.emote("gasp") - breath.oxygen -= oxygen_used - breath.nitrogen -= nitrogen_used - breath.carbon_dioxide += oxygen_used + H.failed_last_breath = 1 + if(Tox_pp > 0) + var/ratio = atmos_requirements["min_tox"] / Tox_pp + H.adjustOxyLoss(min(5 * ratio, HUMAN_MAX_OXYLOSS)) + else + H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + H.throw_alert("tox_in_air", /obj/screen/alert/not_enough_tox) + else if(atmos_requirements["max_tox"] && Tox_pp > atmos_requirements["max_tox"]) + var/ratio = (breath.toxins / atmos_requirements["max_tox"]) * 10 + if(H.reagents) + H.reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) + H.throw_alert("tox_in_air", /obj/screen/alert/tox_in_air) + else + H.clear_alert("tox_in_air") + if(atmos_requirements["min_tox"]) //species breathes this gas, so, they got their air + H.failed_last_breath = 0 + H.adjustOxyLoss(-5) + Tox_used = breath.toxins / 6 - //CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2, this will hurt you, but only once per 4 ticks, instead of once per tick. - if(CO2_pp > safe_co2_max) + if(CO2_pp < atmos_requirements["min_co2"]) + if(prob(20)) + spawn(0) + H.emote("gasp") + + H.failed_last_breath = 1 + if(CO2_pp) + var/ratio = atmos_requirements["min_co2"] / CO2_pp + H.adjustOxyLoss(min(5 * ratio, HUMAN_MAX_OXYLOSS)) + else + H.adjustOxyLoss(HUMAN_MAX_OXYLOSS) + H.throw_alert("co2", /obj/screen/alert/not_enough_co2) + else if(atmos_requirements["max_co2"] && CO2_pp > atmos_requirements["max_co2"]) if(!H.co2overloadtime) // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so. H.co2overloadtime = world.time else if(world.time - H.co2overloadtime > 120) @@ -249,38 +301,36 @@ if(world.time - H.co2overloadtime > 300) // They've been in here 30s now, lets start to kill them for their own good! H.adjustOxyLoss(8) if(prob(20)) // Lets give them some chance to know somethings not right though I guess. - spawn(0) H.emote("cough") - + spawn(0) + H.emote("cough") + //throw_alert("co2", /obj/screen/alert/too_much_co2) //we're gonna leave this one as a silent killer for now else - H.co2overloadtime = 0 + H.clear_alert("co2") + if(atmos_requirements["min_co2"]) //species breathes this gas, so they got their air + H.failed_last_breath = 0 + H.adjustOxyLoss(-5) + CO2_used = breath.carbon_dioxide / 6 - if(Toxins_pp > safe_toxins_max) // Too much toxins - var/ratio = (breath.toxins/safe_toxins_max) * 10 - //adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second - if(H.reagents) - H.reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) - H.toxins_alert = max(H.toxins_alert, 1) + breath.oxygen -= O2_used + breath.nitrogen -= N2_used + breath.toxins -= Tox_used + breath.carbon_dioxide -= CO2_used + breath.carbon_dioxide += O2_used - else if(O2_pp > vox_oxygen_max && name == "Vox") //Oxygen is toxic to vox. - var/ratio = (breath.oxygen/vox_oxygen_max) * 1000 - H.adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) - H.toxins_alert = max(H.toxins_alert, 1) - else - H.toxins_alert = 0 if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here. for(var/datum/gas/sleeping_agent/SA in breath.trace_gases) - var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure - if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit + var/SA_pp = (SA.moles / breath.total_moles()) * breath_pressure + if(SA_pp > atmos_requirements["sa_para"]) // Enough to make us paralysed for a bit H.Paralyse(3) // 3 gives them one second to wake up and run away a bit! - if(SA_pp > SA_sleep_min) // Enough to make us sleep as well - H.sleeping = max(H.sleeping+2, 10) + if(SA_pp > atmos_requirements["sa_sleep"]) // Enough to make us sleep as well + H.sleeping = max(H.sleeping + 2, 10) else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning if(prob(20)) - spawn(0) H.emote(pick("giggle", "laugh")) + spawn(0) + H.emote(pick("giggle", "laugh")) handle_temperature(breath, H) - return 1 /datum/species/proc/handle_temperature(datum/gas_mixture/breath, var/mob/living/carbon/human/H) // called by human/life, handles temperatures @@ -288,38 +338,31 @@ if(H.status_flags & GODMODE) return 1 //godmode if(breath.temperature < cold_level_1) if(prob(20)) - to_chat(H, "\red You feel your face freezing and an icicle forming in your lungs!") + to_chat(H, "You feel your face freezing and an icicle forming in your lungs!") else if(breath.temperature > heat_level_1) if(prob(20)) - to_chat(H, "\red You feel your face burning and a searing heat in your lungs!") + to_chat(H, "You feel your face burning and a searing heat in your lungs!") switch(breath.temperature) if(-INFINITY to cold_level_3) H.apply_damage(cold_env_multiplier*COLD_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Cold") - H.fire_alert = max(H.fire_alert, 1) if(cold_level_3 to cold_level_2) H.apply_damage(cold_env_multiplier*COLD_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Cold") - H.fire_alert = max(H.fire_alert, 1) if(cold_level_2 to cold_level_1) H.apply_damage(cold_env_multiplier*COLD_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Cold") - H.fire_alert = max(H.fire_alert, 1) if(heat_level_1 to heat_level_2) H.apply_damage(hot_env_multiplier*HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Heat") - H.fire_alert = max(H.fire_alert, 2) if(heat_level_2 to heat_level_3_breathe) H.apply_damage(hot_env_multiplier*HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Heat") - H.fire_alert = max(H.fire_alert, 2) if(heat_level_3_breathe to INFINITY) H.apply_damage(hot_env_multiplier*HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat") - H.fire_alert = max(H.fire_alert, 2) - return /datum/species/proc/handle_post_spawn(var/mob/living/carbon/C) //Handles anything not already covered by basic species assignment. grant_abilities(C) @@ -528,10 +571,10 @@ if(H.blinded || H.eye_blind) H.overlay_fullscreen("blind", /obj/screen/fullscreen/blind) - //H.throw_alert("blind", /obj/screen/alert/blind) + H.throw_alert("blind", /obj/screen/alert/blind) else H.clear_fullscreen("blind") - //H.clear_alert("blind") + H.clear_alert("blind") if(H.disabilities & NEARSIGHTED) //this looks meh but saves a lot of memory by not requiring to add var/prescription @@ -553,10 +596,10 @@ if(H.druggy) H.overlay_fullscreen("high", /obj/screen/fullscreen/high) - //H.throw_alert("high", /obj/screen/alert/high) + H.throw_alert("high", /obj/screen/alert/high) else H.clear_fullscreen("high") - //H.clear_alert("high") + H.clear_alert("high") /datum/species/proc/handle_hud_icons(mob/living/carbon/human/H) if(H.healths) @@ -603,59 +646,15 @@ if(icon_num) H.healthdoll.overlays += image('icons/mob/screen_gen.dmi',"[O.limb_name][icon_num]") - if(H.nutrition_icon) - switch(H.nutrition) - if(450 to INFINITY) H.nutrition_icon.icon_state = "nutrition0" - if(350 to 450) H.nutrition_icon.icon_state = "nutrition1" - if(250 to 350) H.nutrition_icon.icon_state = "nutrition2" - if(150 to 250) H.nutrition_icon.icon_state = "nutrition3" - else H.nutrition_icon.icon_state = "nutrition4" - - - // BAY SHIT - if(H.pressure) - H.pressure.icon_state = "pressure[H.pressure_alert]" - - if(H.toxin) - if(H.hal_screwyhud == 4 || H.toxins_alert) H.toxin.icon_state = "tox1" - else H.toxin.icon_state = "tox0" - if(H.oxygen) - if(H.hal_screwyhud == 3 || H.oxygen_alert) H.oxygen.icon_state = "oxy1" - else H.oxygen.icon_state = "oxy0" - if(H.fire) - if(H.fire_alert) H.fire.icon_state = "fire[H.fire_alert]" //fire_alert is either 0 if no alert, 1 for cold and 2 for heat. - else H.fire.icon_state = "fire0" - - if(H.bodytemp) - var/temp_step - if(H.bodytemperature >= body_temperature) - temp_step = (heat_level_1 - body_temperature)/4 - - if(H.bodytemperature >= heat_level_1) - H.bodytemp.icon_state = "temp4" - else if(H.bodytemperature >= body_temperature + temp_step*3) - H.bodytemp.icon_state = "temp3" - else if(H.bodytemperature >= body_temperature + temp_step*2) - H.bodytemp.icon_state = "temp2" - else if(H.bodytemperature >= body_temperature + temp_step*1) - H.bodytemp.icon_state = "temp1" - else - H.bodytemp.icon_state = "temp0" - - else if(H.bodytemperature < body_temperature) - temp_step = (body_temperature - cold_level_1)/4 - - if(H.bodytemperature <= cold_level_1) - H.bodytemp.icon_state = "temp-4" - else if(H.bodytemperature <= body_temperature - temp_step*3) - H.bodytemp.icon_state = "temp-3" - else if(H.bodytemperature <= body_temperature - temp_step*2) - H.bodytemp.icon_state = "temp-2" - else if(H.bodytemperature <= body_temperature - temp_step*1) - H.bodytemp.icon_state = "temp-1" - else - H.bodytemp.icon_state = "temp0" - + switch(H.nutrition) + if(450 to INFINITY) + H.throw_alert("nutrition", /obj/screen/alert/fat) + if(350 to 450) + H.clear_alert("nutrition") + if(250 to 350) + H.throw_alert("nutrition", /obj/screen/alert/hungry) + else + H.throw_alert("nutrition", /obj/screen/alert/starving) return 1 /* diff --git a/code/modules/mob/living/carbon/human/species/station.dm b/code/modules/mob/living/carbon/human/species/station.dm index ae20969bc00..26c6ddb0c57 100644 --- a/code/modules/mob/living/carbon/human/species/station.dm +++ b/code/modules/mob/living/carbon/human/species/station.dm @@ -226,6 +226,19 @@ cold_level_2 = 50 cold_level_3 = 0 + atmos_requirements = list( + "min_oxy" = 0, + "max_oxy" = 1, + "min_nitro" = 16, + "max_nitro" = 0, + "min_tox" = 0, + "max_tox" = 0.005, + "min_co2" = 0, + "max_co2" = 10, + "sa_para" = 1, + "sa_sleep" = 5 + ) + eyes = "vox_eyes_s" breath_type = "nitrogen" diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 73bbd5a4281..8834bee35b2 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -989,16 +989,19 @@ var/global/list/damage_icon_parts = list() update_icons() /mob/living/carbon/human/update_inv_legcuffed(var/update_icons=1) + clear_alert("legcuffed") if(legcuffed) overlays_standing[LEGCUFF_LAYER] = image("icon" = 'icons/mob/mob.dmi', "icon_state" = "legcuff1") - if(src.m_intent != "walk") - src.m_intent = "walk" - if(src.hud_used && src.hud_used.move_intent) - src.hud_used.move_intent.icon_state = "walking" + throw_alert("legcuffed", /obj/screen/alert/restrained/legcuffed, new_master = src.legcuffed) + if(m_intent != "walk") + m_intent = "walk" + if(hud_used && hud_used.move_intent) + hud_used.move_intent.icon_state = "walking" else overlays_standing[LEGCUFF_LAYER] = null - if(update_icons) update_icons() + if(update_icons) + update_icons() /mob/living/carbon/human/update_inv_r_hand(var/update_icons=1) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 43794bed7b8..7b3f74ef65f 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -95,8 +95,7 @@ if(!breath || (breath.total_moles() == 0)) adjustOxyLoss(1) failed_last_breath = 1 - - oxygen_alert = max(oxygen_alert, 1) + throw_alert("oxy", /obj/screen/alert/oxy) return 0 var/safe_oxy_min = 16 @@ -125,13 +124,13 @@ else adjustOxyLoss(3) failed_last_breath = 1 - oxygen_alert = max(oxygen_alert, 1) + throw_alert("oxy", /obj/screen/alert/oxy) else //Enough oxygen failed_last_breath = 0 adjustOxyLoss(-5) oxygen_used = breath.oxygen/6 - oxygen_alert = 0 + clear_alert("oxy") breath.oxygen -= oxygen_used breath.carbon_dioxide += oxygen_used @@ -147,9 +146,7 @@ adjustOxyLoss(8) if(prob(20)) spawn(0) emote("cough") - co2_alert = max(co2_alert, 1) else - co2_alert = 0 co2overloadtime = 0 //TOXINS/PLASMA @@ -157,9 +154,9 @@ var/ratio = (breath.toxins/safe_tox_max) * 10 if(reagents) reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) - toxins_alert = max(toxins_alert, 1) + throw_alert("tox_in_air", /obj/screen/alert/tox_in_air) else - toxins_alert = 0 + clear_alert("tox_in_air") //TRACE GASES if(breath.trace_gases.len) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index ebbda839e52..59a208d7c2e 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -155,6 +155,9 @@ /mob/living/proc/handle_sleeping() if(sleeping) AdjustSleeping(-1) + throw_alert("asleep", /obj/screen/alert/asleep) + else + clear_alert("asleep") return sleeping @@ -193,10 +196,10 @@ return if(blinded || eye_blind) overlay_fullscreen("blind", /obj/screen/fullscreen/blind) - //throw_alert("blind", /obj/screen/alert/blind) + throw_alert("blind", /obj/screen/alert/blind) else clear_fullscreen("blind") - //clear_alert("blind") + clear_alert("blind") if(disabilities & NEARSIGHTED) overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1) @@ -210,10 +213,10 @@ if(druggy) overlay_fullscreen("high", /obj/screen/fullscreen/high) - //throw_alert("high", /obj/screen/alert/high) + throw_alert("high", /obj/screen/alert/high) else clear_fullscreen("high") - //clear_alert("high") + clear_alert("high") if(machine) if(!machine.check_eye(src)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 4d5245cbf12..0a2e9fe5e5b 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -522,262 +522,72 @@ set name = "Resist" set category = "IC" - if(!isliving(usr) || usr.next_move > world.time) + if(!isliving(src) || next_move > world.time || stat || weakened || stunned || paralysis) return - usr.changeNext_move(CLICK_CD_RESIST) + changeNext_move(CLICK_CD_RESIST) - var/mob/living/L = usr - - //Resisting control by an alien mind. - if(istype(src.loc,/mob/living/simple_animal/borer)) - resist_borer() - - //resisting grabs (as if it helps anyone...) - if ((!(L.stat) && !(L.restrained()))) - resist_grab(L) //this passes L because the proc requires a typecasted mob/living instead of just 'src' + if(!restrained()) + if(resist_grab()) + return //unbuckling yourself - if(L.buckled && (L.last_special <= world.time) ) - resist_buckle(L) //this passes L because the proc requires a typecasted mob/living instead of just 'src' + if(buckled && last_special <= world.time) + resist_buckle() - //Breaking out of an object? - else if(src.loc && istype(src.loc, /obj) && (!isturf(src.loc))) - if(stat == CONSCIOUS && !stunned && !weakened && !paralysis) - var/obj/C = loc - C.container_resist(L) + //Breaking out of a container (Locker, sleeper, cryo...) + else if(isobj(loc)) + var/obj/C = loc + C.container_resist(src) - //breaking out of handcuffs - else if(iscarbon(L)) - var/mob/living/carbon/CM = L - - if(CM.on_fire && CM.canmove) - resist_stop_drop_roll(CM) //this passes CM because the proc requires a typecasted mob/living/carbon instead of just 'src' - - if(CM.handcuffed && CM.canmove && (CM.last_special <= world.time))//this passes CM because the proc requires a typecasted mob/living/carbon instead of just 'src' - resist_handcuffs(CM) - - else if(CM.legcuffed && CM.canmove && (CM.last_special <= world.time)) //this passes CM because the proc requires a typecasted mob/living/carbon instead of just 'src' - resist_legcuffs(CM) + else if(canmove) + if(on_fire) + resist_fire() //stop, drop, and roll + else if(last_special <= world.time) + resist_restraints() //trying to remove cuffs. /*//////////////////// RESIST SUBPROCS *///////////////////// - -/* resist_borer allows a mob to regain control of their body after a borer has assumed control. -*///// -/mob/living/proc/resist_borer() - var/mob/living/simple_animal/borer/B = src.loc - var/mob/living/captive_brain/H = src - - to_chat(H, "\red You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).") - to_chat(B.host, "\red You feel the captive mind of [src] begin to resist your control.") - - spawn(rand(350,450)+B.host.brainloss) - - if(!B || !B.controlling) - return - - B.host.adjustBrainLoss(rand(5,10)) - to_chat(H, "\red With an immense exertion of will, you regain control of your body!") - to_chat(B.host, "\red You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.") - - B.detatch() - - verbs -= /mob/living/carbon/proc/release_control - verbs -= /mob/living/carbon/proc/punish_host - verbs -= /mob/living/carbon/proc/spawn_larvae - - return - -/* resist_grab allows a mob to resist a grab from another mob when disarming is not an option/neckgrabbed. -*///// -/mob/living/proc/resist_grab(var/mob/living/L) +/mob/living/proc/resist_grab() var/resisting = 0 - - for(var/obj/O in L.requests) - L.requests.Remove(O) + for(var/obj/O in requests) qdel(O) resisting++ - - for(var/obj/item/weapon/grab/G in usr.grabbed_by) + for(var/X in grabbed_by) + var/obj/item/weapon/grab/G = X resisting++ - if (G.state == 1) + if(G.state == GRAB_PASSIVE) qdel(G) - else - if(G.state == 2) - if(prob(60)) - for(var/mob/O in viewers(L, null)) - O.show_message(text("\red [] has broken free of []'s grip!", L, G.assailant), 1) + if(G.state == GRAB_AGGRESSIVE) + if(prob(25)) + visible_message("[src] has broken free of [G.assailant]'s grip!") qdel(G) - else - if(G.state == 3) + if(G.state == GRAB_NECK) if(prob(5)) - for(var/mob/O in viewers(usr, null)) - O.show_message(text("\red [] has broken free of []'s headlock!", L, G.assailant), 1) + visible_message("[src] has broken free of [G.assailant]'s headlock!") qdel(G) - if(resisting) - for(var/mob/O in viewers(usr, null)) - O.show_message(text("\red [] resists!", L), 1) + visible_message("[src] resists!") + return 1 -/* resist_buckle allows a mob that is bucklecuffed to break free of the chair/bed/whatever -*///// -/mob/living/proc/resist_buckle(var/mob/living/L) - if(iscarbon(L)) - var/mob/living/carbon/C = L - - if(C.handcuffed) - C.changeNext_move(CLICK_CD_BREAKOUT) - C.last_special = world.time + CLICK_CD_BREAKOUT - - to_chat(C, "\red You attempt to unbuckle yourself. (This will take around 2 minutes and you need to stay still)") - for(var/mob/O in viewers(L)) - O.show_message("\red [usr] attempts to unbuckle themself!", 1) - - spawn(0) - if(do_after(usr, 1200, target = C)) - if(!C.buckled) - return - for(var/mob/O in viewers(C)) - O.show_message("\red [usr] manages to unbuckle themself!", 1) - to_chat(C, "\blue You successfully unbuckle yourself.") - C.buckled.user_unbuckle_mob(C,C) - - else - L.buckled.user_unbuckle_mob(L,L) - -/* resist_stop_drop_roll allows a mob to stop, drop, and roll in order to put out a fire burning on them. -*///// -/mob/living/proc/resist_stop_drop_roll(var/mob/living/carbon/CM) - CM.fire_stacks -= 5 - CM.weakened = max(CM.weakened, 3)//We dont check for CANWEAKEN, I don't care how immune to weakening you are, if you're rolling on the ground, you're busy. - CM.update_canmove() - CM.spin(32,2) - CM.visible_message("[CM] rolls on the floor, trying to put themselves out!", \ - "You stop, drop, and roll!") - sleep(30) - if(fire_stacks <= 0) - CM.visible_message("[CM] has successfully extinguished themselves!", \ - "You extinguish yourself.") - ExtinguishMob() +/mob/living/proc/resist_borer() return -/* resist_handcuffs allows a mob to break/remove their handcuffs after a delay -*///// -/mob/living/proc/resist_handcuffs(var/mob/living/carbon/CM) - CM.changeNext_move(CLICK_CD_BREAKOUT) - CM.last_special = world.time + CLICK_CD_BREAKOUT - var/obj/item/weapon/restraints/handcuffs/HC = CM.handcuffed +/mob/living/proc/resist_buckle() + buckled.user_unbuckle_mob(src,src) - var/breakouttime = 1200 //A default in case you are somehow handcuffed with something that isn't an obj/item/weapon/restraints/handcuffs type - var/displaytime = 2 //Minutes to display in the "this will take X minutes." +/mob/living/proc/resist_fire() + return - var/hulklien = 0 //variable used to define if someone is a hulk or alien - - if(istype(HC)) //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... - breakouttime = HC.breakouttime - displaytime = breakouttime / 600 //Minutes - - if(isalienadult(CM) || (HULK in usr.mutations)) - hulklien = 1 - breakouttime = 50 - displaytime = 5 - - to_chat(CM, "\red You attempt to remove \the [HC]. (This will take around [displaytime] [hulklien ? "seconds" : "minute[displaytime==1 ? "" : "s"]"] and you need to stand still)") - for(var/mob/O in viewers(CM)) - O.show_message( "\red [usr] attempts to [hulklien ? "break" : "remove"] \the [HC]!", 1) - spawn(0) - if(do_after(CM, breakouttime, target = src)) - if(!CM.handcuffed || CM.buckled) - return // time leniency for lag which also might make this whole thing pointless but the server - - for(var/mob/O in viewers(CM))// lags so hard that 40s isn't lenient enough - Quarxink - O.show_message("\red [CM] manages to [hulklien ? "break" : "remove"] the handcuffs!", 1) - - to_chat(CM, "\blue You successfully [hulklien ? "break" : "remove"] \the [CM.handcuffed].") - - if(hulklien) - CM.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - qdel(CM.handcuffed) - CM.handcuffed = null - if(CM.buckled && CM.buckled.buckle_requires_restraints) - CM.buckled.unbuckle_mob() - CM.update_inv_handcuffed() - return - - CM.unEquip(CM.handcuffed) - -/* resist_legcuffs allows a mob to break/remove their legcuffs after a delay -*///// -/mob/living/proc/resist_legcuffs(var/mob/living/carbon/CM) - var/obj/item/weapon/restraints/legcuffs/HC = CM.legcuffed - - var/breakouttime = 1200 //A default in case you are somehow legcuffed with something that isn't an obj/item/weapon/legcuffs type - var/displaytime = 2 //Minutes to display in the "this will take X minutes." - - var/hulklien = 0 //variable used to define if someone is a hulk or alien - - if(istype(HC)) //If you are legcuffed with actual legcuffs... Well what do I know, maybe someone will want to legcuff you with toilet paper in the future... - breakouttime = HC.breakouttime - displaytime = breakouttime / 600 //Minutes - - if(isalienadult(CM) || (HULK in usr.mutations)) - hulklien = 1 - breakouttime = 50 - displaytime = 5 - - to_chat(CM, "\red You attempt to remove \the [HC]. (This will take around [displaytime] [hulklien ? "seconds" : "minute[displaytime==1 ? "" : "s"]"] and you need to stand still)") - - for(var/mob/O in viewers(CM)) - O.show_message( "\red [usr] attempts to [hulklien ? "break" : "remove"] \the [HC]!", 1) - - spawn(0) - if(do_after(CM, breakouttime, target = src)) - if(!CM.legcuffed || CM.buckled) - return // time leniency for lag which also might make this whole thing pointless but the server - for(var/mob/O in viewers(CM))// lags so hard that 40s isn't lenient enough - Quarxink - O.show_message("\red [CM] manages to [hulklien ? "break" : "remove"] the legcuffs!", 1) - - to_chat(CM, "\blue You successfully [hulklien ? "break" : "remove"] \the [CM.legcuffed].") - - if(!hulklien) - CM.unEquip(CM.legcuffed) - - if(hulklien) - CM.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - qdel(CM.legcuffed) - - CM.legcuffed = null - CM.update_inv_legcuffed() +/mob/living/proc/resist_restraints() + return /*////////////////////// END RESIST PROCS */////////////////////// - - - - -/mob/living/carbon/proc/spin(spintime, speed) - spawn() - var/D = dir - while(spintime >= speed) - sleep(speed) - switch(D) - if(NORTH) - D = EAST - if(SOUTH) - D = WEST - if(EAST) - D = SOUTH - if(WEST) - D = NORTH - dir = D - spintime -= speed - return - /mob/living/proc/Exhaust() to_chat(src, "You're too exhausted to keep going...") Weaken(5) @@ -788,6 +598,10 @@ /mob/living/update_gravity(has_gravity) if(!ticker) return + if(has_gravity) + clear_alert("weightless") + else + throw_alert("weightless", /obj/screen/alert/weightless) float(!has_gravity) /mob/living/proc/float(on) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index b48aa36a64c..47f9b9c6988 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -173,6 +173,7 @@ if(fire_stacks > 0 && !on_fire) on_fire = 1 set_light(light_range + 3,l_color = "#ED9200") + throw_alert("fire", /obj/screen/alert/fire) update_fire() /mob/living/proc/ExtinguishMob() @@ -180,6 +181,7 @@ on_fire = 0 fire_stacks = 0 set_light(max(0,light_range - 3)) + clear_alert("fire") update_fire() /mob/living/proc/update_fire() diff --git a/code/modules/mob/living/silicon/laws.dm b/code/modules/mob/living/silicon/laws.dm index 27e431e1675..30784e61b93 100644 --- a/code/modules/mob/living/silicon/laws.dm +++ b/code/modules/mob/living/silicon/laws.dm @@ -10,6 +10,7 @@ return laws.zeroth_law != null /mob/living/silicon/proc/set_zeroth_law(var/law, var/law_borg) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.set_zeroth_law(law, law_borg) if(!isnull(usr) && law) @@ -21,42 +22,49 @@ to_chat(src, "Internal camera is currently being accessed.") /mob/living/silicon/proc/add_ion_law(var/law) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.add_ion_law(law) if(!isnull(usr) && law) log_and_message_admins("has given [src] the ion law: [law]") /mob/living/silicon/proc/add_inherent_law(var/law) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.add_inherent_law(law) if(!isnull(usr) && law) log_and_message_admins("has given [src] the inherent law: [law]") /mob/living/silicon/proc/add_supplied_law(var/number, var/law) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.add_supplied_law(number, law) if(!isnull(usr) && law) log_and_message_admins("has given [src] the supplied law: [law]") /mob/living/silicon/proc/delete_law(var/datum/ai_law/law) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.delete_law(law) if(!isnull(usr) && law) log_and_message_admins("has deleted a law belonging to [src]: [law.law]") /mob/living/silicon/proc/clear_inherent_laws(var/silent = 0) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.clear_inherent_laws() if(!silent && !isnull(usr)) log_and_message_admins("cleared the inherent laws of [src]") /mob/living/silicon/proc/clear_ion_laws(var/silent = 0) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.clear_ion_laws() if(!silent && !isnull(usr)) log_and_message_admins("cleared the ion laws of [src]") /mob/living/silicon/proc/clear_supplied_laws(var/silent = 0) + throw_alert("newlaw", /obj/screen/alert/newlaw) laws_sanity_check() laws.clear_supplied_laws() if(!silent && !isnull(usr)) @@ -108,10 +116,10 @@ /mob/living/silicon/proc/lawsync() laws_sanity_check() laws.sort_laws() - + /mob/living/silicon/proc/make_laws() switch(config.default_laws) - if(0) + if(0) laws = new /datum/ai_laws/crewsimov() else laws = get_random_lawset() @@ -122,6 +130,6 @@ for(var/law in paths) var/datum/ai_laws/L = new law if(!L.default) - continue + continue law_options += L return pick(law_options) diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index d247d726003..fa534b66123 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -176,6 +176,10 @@ /mob/living/silicon/robot/handle_hud_icons() update_items() update_cell() + if(emagged) + throw_alert("hacked", /obj/screen/alert/hacked) + else + clear_alert("hacked") ..() /mob/living/silicon/robot/handle_hud_icons_health() @@ -196,79 +200,47 @@ else healths.icon_state = "health7" - if(bodytemp) - switch(bodytemperature) //310.055 optimal body temp - if(335 to INFINITY) - bodytemp.icon_state = "temp2" - if(320 to 335) - bodytemp.icon_state = "temp1" - if(300 to 320) - bodytemp.icon_state = "temp0" - if(260 to 300) - bodytemp.icon_state = "temp-1" - else - bodytemp.icon_state = "temp-2" + switch(bodytemperature) //310.055 optimal body temp + if(335 to INFINITY) + throw_alert("temp", /obj/screen/alert/hot/robot, 2) + if(320 to 335) + throw_alert("temp", /obj/screen/alert/hot/robot, 1) + if(300 to 320) + clear_alert("temp") + if(260 to 300) + throw_alert("temp", /obj/screen/alert/cold/robot, 1) + else + throw_alert("temp", /obj/screen/alert/cold/robot, 2) /mob/living/silicon/robot/proc/update_cell() - if(cells) - if(cell) - var/cellcharge = cell.charge/cell.maxcharge - switch(cellcharge) - if(0.75 to INFINITY) - cells.icon_state = "charge4" - if(0.5 to 0.75) - cells.icon_state = "charge3" - if(0.25 to 0.5) - cells.icon_state = "charge2" - if(0 to 0.25) - cells.icon_state = "charge1" - else - cells.icon_state = "charge0" - else - cells.icon_state = "charge-empty" - - -/*/mob/living/silicon/robot/handle_regular_hud_updates() -// if(!client) -// return -// -// switch(sensor_mode) -// if(SEC_HUD) -// process_sec_hud(src,1) -// if(MED_HUD) -// process_med_hud(src,1) - - if(syndicate) - if(ticker.mode.name == "traitor") - for(var/datum/mind/tra in ticker.mode.traitors) - if(tra.current) - var/I = image('icons/mob/mob.dmi', loc = tra.current, icon_state = "traitor") - src.client.images += I - if(connected_ai) - connected_ai.connected_robots -= src - connected_ai = null - if(mind) - if(!mind.special_role) - mind.special_role = "traitor" - ticker.mode.traitors += src.mind - - - ..() - return 1 - */ + 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) + if (client) for(var/obj/I in get_all_slots()) 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 + 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 update_icons() /mob/living/silicon/robot/proc/process_locks() diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index d089eb98467..58f965dad7e 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -17,7 +17,6 @@ var/list/robot_verbs_default = list( //Hud stuff - var/obj/screen/cells = null var/obj/screen/inv1 = null var/obj/screen/inv2 = null var/obj/screen/inv3 = null @@ -786,6 +785,7 @@ var/list/robot_verbs_default = list( else sleep(6) emagged = 1 + SetLockdown(1) //Borgs were getting into trouble because they would attack the emagger before the new laws were shown if(src.hud_used) src.hud_used.update_robot_modules_display() //Shows/hides the emag item if the inventory screen is already open. disconnect_from_ai() @@ -814,6 +814,7 @@ var/list/robot_verbs_default = list( to_chat(src, "Obey these laws:") laws.show_laws(src) to_chat(src, "\red \b ALERT: [M.real_name] is your new master. Obey your new laws and his commands.") + SetLockdown(0) if(src.module && istype(src.module, /obj/item/weapon/robot_module/miner)) for(var/obj/item/weapon/pickaxe/drill/cyborg/D in src.module.modules) qdel(D) @@ -1256,6 +1257,10 @@ var/list/robot_verbs_default = list( // 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") lockcharge = state update_canmove() diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index b9bf9046482..f416d59872d 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -1000,15 +1000,14 @@ Pass a positive integer as an argument to override a bot's default speed. /mob/living/simple_animal/bot/handle_hud_icons_health() ..() - if(bodytemp) - switch(bodytemperature) //310.055 optimal body temp - if(335 to INFINITY) - bodytemp.icon_state = "temp2" - if(320 to 335) - bodytemp.icon_state = "temp1" - if(300 to 320) - bodytemp.icon_state = "temp0" - if(260 to 300) - bodytemp.icon_state = "temp-1" - else - bodytemp.icon_state = "temp-2" \ No newline at end of file + switch(bodytemperature) //310.055 optimal body temp + if(335 to INFINITY) + throw_alert("temp", /obj/screen/alert/hot/robot, 2) + if(320 to 335) + throw_alert("temp", /obj/screen/alert/hot/robot, 1) + if(300 to 320) + clear_alert("temp") + if(260 to 300) + throw_alert("temp", /obj/screen/alert/cold/robot, 1) + else + throw_alert("temp", /obj/screen/alert/cold/robot, 2) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 9f288db21a2..12dd032ba49 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -566,5 +566,5 @@ Auto Patrol[]"}, return if(!C.handcuffed) C.handcuffed = new /obj/item/weapon/restraints/handcuffs/cable/zipties/used(C) - C.update_inv_handcuffed(1) + C.update_handcuffed() back_to_idle() diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index ebe2be5a418..284584406c2 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -227,7 +227,7 @@ Auto Patrol: []"}, return if(!C.handcuffed) C.handcuffed = new /obj/item/weapon/restraints/handcuffs/cable/zipties/used(C) - C.update_inv_handcuffed(1) + C.update_handcuffed() playsound(loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0) back_to_idle() diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index b86a034a69e..23477c2fc18 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -101,18 +101,6 @@ ..() health = Clamp(health, 0, maxHealth) -/mob/living/simple_animal/handle_hud_icons() - ..() - if(fire) - if(fire_alert) fire.icon_state = "fire[fire_alert]" //fire_alert is either 0 if no alert, 1 for heat and 2 for cold. - else fire.icon_state = "fire0" - if(oxygen) - if(oxygen_alert) oxygen.icon_state = "oxy1" - else oxygen.icon_state = "oxy0" - if(toxin) - if(toxins_alert) toxin.icon_state = "tox1" - else toxin.icon_state = "tox0" - /mob/living/simple_animal/handle_hud_icons_health() ..() if(healths && maxHealth > 0) @@ -215,21 +203,21 @@ if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"]) atmos_suitable = 0 - oxygen_alert = 1 + throw_alert("oxy", /obj/screen/alert/oxy) else if(atmos_requirements["max_oxy"] && oxy > atmos_requirements["max_oxy"]) atmos_suitable = 0 - oxygen_alert = 1 + throw_alert("oxy", /obj/screen/alert/too_much_oxy) else - oxygen_alert = 0 + clear_alert("oxy") if(atmos_requirements["min_tox"] && tox < atmos_requirements["min_tox"]) atmos_suitable = 0 - toxins_alert = 1 + throw_alert("tox_in_air", /obj/screen/alert/not_enough_tox) else if(atmos_requirements["max_tox"] && tox > atmos_requirements["max_tox"]) atmos_suitable = 0 - toxins_alert = 1 + throw_alert("tox_in_air", /obj/screen/alert/tox_in_air) else - toxins_alert = 0 + clear_alert("tox_in_air") if(atmos_requirements["min_n2"] && n2 < atmos_requirements["min_n2"]) atmos_suitable = 0 diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 0121905380a..ac459679f10 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -14,16 +14,10 @@ var/obj/screen/hands = null var/obj/screen/pullin = 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/gun/item/item_use_icon = null var/obj/screen/gun/move/gun_move_icon = null var/obj/screen/gun/run/gun_run_icon = null diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 1f2e0e7b456..a967c2df779 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -556,12 +556,28 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM) lname = "[lname] " to_chat(M, "[lname][follow][message]") -/proc/notify_ghosts(var/message, var/ghost_sound = null) //Easy notification of ghosts. +/proc/notify_ghosts(var/message, var/ghost_sound = null, var/enter_link = null, var/atom/source = null, var/image/alert_overlay = null, var/attack_not_jump = 0) //Easy notification of ghosts. for(var/mob/dead/observer/O in player_list) if(O.client) - to_chat(O, "[message]") + to_chat(O, "[message][(enter_link) ? " [enter_link]" : ""]") if(ghost_sound) - to_chat(O, sound(ghost_sound)) + O << sound(ghost_sound) + if(source) + var/obj/screen/alert/notify_jump/A = O.throw_alert("\ref[source]_notify_jump", /obj/screen/alert/notify_jump) + if(A) + if(O.client.prefs && O.client.prefs.UI_style) + A.icon = ui_style2icon(O.client.prefs.UI_style) + A.desc = message + A.attack_not_jump = attack_not_jump + A.jump_target = source + if(!alert_overlay) + var/old_layer = source.layer + source.layer = FLOAT_LAYER + A.overlays += source + source.layer = old_layer + else + alert_overlay.layer = FLOAT_LAYER + A.overlays += alert_overlay /mob/proc/switch_to_camera(var/obj/machinery/camera/C) if (!C.can_use() || stat || (get_dist(C, src) > 1 || machine != src || blinded || !canmove)) diff --git a/code/modules/power/singularity/narsie.dm b/code/modules/power/singularity/narsie.dm index 1c43e1a829d..9dfa9c13993 100644 --- a/code/modules/power/singularity/narsie.dm +++ b/code/modules/power/singularity/narsie.dm @@ -29,7 +29,8 @@ var/area/A = get_area(src) if(A) - notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.") + var/image/alert_overlay = image('icons/effects/effects.dmi', "ghostalertsie") + notify_ghosts("Nar-Sie has risen in \the [A.name]. Reach out to the Geometer to be given a new shell for your soul.", source = src, alert_overlay = alert_overlay, attack_not_jump = 1) narsie_spawn_animation() @@ -37,9 +38,6 @@ shuttle_master.emergency.request(null, 0.3) // Cannot recall /obj/singularity/narsie/large/attack_ghost(mob/dead/observer/user as mob) - if(!(src in view())) - to_chat(user, "Your soul is too far away.") - return makeNewConstruct(/mob/living/simple_animal/construct/harvester, user, null, 1) new /obj/effect/effect/sleep_smoke(user.loc) diff --git a/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm index ee51efe2b1e..3a08a28a741 100644 --- a/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm +++ b/code/modules/reagents/oldchem/chemical_reaction/chemical_reaction_slime.dm @@ -510,7 +510,7 @@ feedback_add_details("slime_cores_used","[type]") var/obj/effect/golemrune/Z = new /obj/effect/golemrune Z.forceMove(get_turf(holder.my_atom)) - notify_ghosts("Golem rune created in [get_area(Z)].", 'sound/effects/ghost2.ogg') + notify_ghosts("Golem rune created in [get_area(Z)].", 'sound/effects/ghost2.ogg', source = Z) //Bluespace /datum/chemical_reaction/slimefloor2 diff --git a/code/modules/tooltip/tooltip.dm b/code/modules/tooltip/tooltip.dm new file mode 100644 index 00000000000..cbe016c5bad --- /dev/null +++ b/code/modules/tooltip/tooltip.dm @@ -0,0 +1,116 @@ +/* +Tooltips v1.1 - 22/10/15 +Developed by Wire (#goonstation on irc.synirc.net) +- Added support for screen_loc pixel offsets. Should work. Maybe. +- Added init function to more efficiently send base vars + +Configuration: +- Set control to the correct skin element (remember to actually place the skin element) +- Set file to the correct path for the .html file (remember to actually place the html file) +- Attach the datum to the user client on login, e.g. + /client/New() + src.tooltips = new /datum/tooltip(src) + +Usage: +- Define mouse event procs on your (probably HUD) object and simply call the show and hide procs respectively: + /obj/screen/hud + MouseEntered(location, control, params) + usr.client.tooltip.show(params, title = src.name, content = src.desc) + + MouseExited() + usr.client.tooltip.hide() + +Customization: +- Theming can be done by passing the theme var to show() and using css in the html file to change the look +- For your convenience some pre-made themes are included + +Notes: +- You may have noticed 90% of the work is done via javascript on the client. Gotta save those cycles man. +- This is entirely untested in any other codebase besides goonstation so I have no idea if it will port nicely. Good luck! + - After testing and discussion (Wire, Remie, MrPerson, AnturK) ToolTips are ok and work for /tg/station13 +*/ + + +/datum/tooltip + var/client/owner + var/control = "mainwindow.tooltip" + var/file = 'code/modules/tooltip/tooltip.html' + var/showing = 0 + var/queueHide = 0 + var/init = 0 + + +/datum/tooltip/New(client/C) + if (C) + owner = C + owner << browse(file2text(file), "window=[control]") + + ..() + + +/datum/tooltip/proc/show(atom/movable/thing, params = null, title = null, content = null, theme = "default", special = "none") + if (!thing || !params || (!title && !content) || !owner || !isnum(world.icon_size)) + return 0 + if (!init) + //Initialize some vars + init = 1 + owner << output(list2params(list(world.icon_size, control)), "[control]:tooltip.init") + + showing = 1 + + if (title && content) + title = "

[title]

" + content = "

[content]

" + else if (title && !content) + title = "

[title]

" + else if (!title && content) + content = "

[content]

" + + //Make our dumb param object + params = {"{ "cursor": "[params]", "screenLoc": "[thing.screen_loc]" }"} + + //Send stuff to the tooltip + owner << output(list2params(list(params, owner.view, "[title][content]", theme, special)), "[control]:tooltip.update") + + //If a hide() was hit while we were showing, run hide() again to avoid stuck tooltips + showing = 0 + if (queueHide) + hide() + + return 1 + + +/datum/tooltip/proc/hide() + if(queueHide) + spawn(1) + winshow(owner, control, 0) + else + winshow(owner, control, 0) + + queueHide = showing ? 1 : 0 + + return 1 + + +/* TG SPECIFIC CODE */ + + +//Open a tooltip for user, at a location based on params +//Theme is a CSS class in tooltip.html, by default this wrapper chooses a CSS class based on the user's UI_style (Midnight, Plasmafire, Retro, etc) +//Includes sanity.checks +/proc/openToolTip(mob/user = null, atom/movable/tip_src = null, params = null, title = "", content = "", theme = "") + if(istype(user)) + if(user.client && user.client.tooltips) + if(!theme && user.client.prefs && user.client.prefs.UI_style) + theme = lowertext(user.client.prefs.UI_style) + if(!theme) + theme = "default" + user.client.tooltips.show(tip_src, params, title, content, theme) + + +//Arbitrarily close a user's tooltip +//Includes sanity checks. +/proc/closeToolTip(mob/user) + if(istype(user)) + if(user.client && user.client.tooltips) + user.client.tooltips.hide() diff --git a/code/modules/tooltip/tooltip.html b/code/modules/tooltip/tooltip.html new file mode 100644 index 00000000000..9fa0702a2b3 --- /dev/null +++ b/code/modules/tooltip/tooltip.html @@ -0,0 +1,238 @@ + + + + Tooltip + + + + + +
+
+
+ + + + diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 7d87c3d7557486c3a022669381c2d70b4c7660e5..695d701dba35bd337c733c0e37fd10d5c365122f 100644 GIT binary patch delta 13972 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 P@IMs=b@@tJ(~$oI1xNyu delta 11924 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 JPDHLkV1hwGaFqZ6 literal 0 HcmV?d00001 diff --git a/interface/skin.dmf b/interface/skin.dmf index c3d9f693726..d3ba4e0efc5 100644 --- a/interface/skin.dmf +++ b/interface/skin.dmf @@ -1,351 +1,351 @@ macro "AZERTYoff" - elem + elem name = "TAB" command = ".Toggle-hotkey-mode" is-disabled = false - elem + elem name = "CENTER+REP" command = ".center" is-disabled = false - elem + elem name = "NORTHEAST" command = ".northeast" is-disabled = false - elem + elem name = "SOUTHEAST" command = ".southeast" is-disabled = false - elem + elem name = "SOUTHWEST" command = ".southwest" is-disabled = false - elem + elem name = "NORTHWEST" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+WEST" command = "westface" is-disabled = false - elem + elem name = "WEST+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+NORTH" command = "northface" is-disabled = false - elem + elem name = "NORTH+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+EAST" command = "eastface" is-disabled = false - elem + elem name = "EAST+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+SOUTH" command = "southface" is-disabled = false - elem + elem name = "SOUTH+REP" command = ".south" is-disabled = false - elem + elem name = "INSERT" command = "a-intent right" is-disabled = false - elem + elem name = "DELETE" command = "delete-key-pressed" is-disabled = false - elem + elem name = "CTRL+1" command = "a-intent help" is-disabled = false - elem + elem name = "CTRL+2" command = "a-intent disarm" is-disabled = false - elem + elem name = "CTRL+3" command = "a-intent grab" is-disabled = false - elem + elem name = "CTRL+4" command = "a-intent harm" is-disabled = false - elem + elem name = "CTRL+A" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+D+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+B" command = "resist" is-disabled = false - elem + elem name = "CTRL+E" command = "quick-equip" is-disabled = false - elem + elem name = "CTRL+F" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+G" command = "a-intent right" is-disabled = false - elem + elem name = "CTRL+Q+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+R" command = ".southwest" is-disabled = false - elem + elem name = "CTRL+S+REP" command = ".south" is-disabled = false - elem + elem name = "CTRL+W" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+X" command = ".northeast" is-disabled = false - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Z+REP" command = ".north" is-disabled = false - elem + elem name = "F1" command = "adminhelp" is-disabled = false - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" is-disabled = false - elem + elem name = "F2" command = "ooc" is-disabled = false - elem + elem name = "F2+REP" command = ".screenshot auto" is-disabled = false - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" is-disabled = false - elem + elem name = "F3" command = ".say" is-disabled = false - elem + elem name = "F4" command = ".me" is-disabled = false - elem + elem name = "F5" command = "asay" is-disabled = false - elem + elem name = "F6" command = "Aghost" is-disabled = false - elem + elem name = "F7" command = "player-panel-new" is-disabled = false - elem + elem name = "F8" command = "admin-pm-key" is-disabled = false - elem + elem name = "F9" command = "Invisimin" is-disabled = false - elem + elem name = "F12" command = "F12" is-disabled = false macro "AZERTYon" - elem + elem name = "TAB" command = ".Toggle-hotkey-mode" is-disabled = false - elem + elem name = "CENTER+REP" command = ".center" is-disabled = false - elem + elem name = "NORTHEAST" command = ".northeast" is-disabled = false - elem + elem name = "SOUTHEAST" command = ".southeast" is-disabled = false - elem + elem name = "SOUTHWEST" command = ".southwest" is-disabled = false - elem + elem name = "NORTHWEST" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+WEST" command = "westface" is-disabled = false - elem + elem name = "WEST+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+NORTH" command = "northface" is-disabled = false - elem + elem name = "NORTH+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+EAST" command = "eastface" is-disabled = false - elem + elem name = "EAST+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+SOUTH" command = "southface" is-disabled = false - elem + elem name = "SOUTH+REP" command = ".south" is-disabled = false - elem + elem name = "INSERT" command = "a-intent right" is-disabled = false - elem + elem name = "DELETE" command = "delete-key-pressed" is-disabled = false - elem + elem name = "1" command = "a-intent help" is-disabled = false - elem + elem name = "CTRL+1" command = "a-intent help" is-disabled = false - elem + elem name = "2" command = "a-intent disarm" is-disabled = false - elem + elem name = "CTRL+2" command = "a-intent disarm" is-disabled = false - elem + elem name = "3" command = "a-intent grab" is-disabled = false - elem + elem name = "CTRL+3" command = "a-intent grab" is-disabled = false - elem + elem name = "4" command = "a-intent harm" is-disabled = false - elem + elem name = "CTRL+4" command = "a-intent harm" is-disabled = false - elem + elem name = "A" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+A" command = ".northwest" is-disabled = false - elem + elem name = "D+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+D+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+B" command = "resist" is-disabled = false - elem + elem name = "E" command = "quick-equip" is-disabled = false - elem + elem name = "CTRL+E" command = "quick-equip" is-disabled = false - elem + elem name = "F" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+F" command = "a-intent left" is-disabled = false - elem + elem name = "G" command = "a-intent right" is-disabled = false - elem + elem name = "CTRL+G" command = "a-intent right" is-disabled = false - elem + elem name = "H" command = "holster" is-disabled = false - elem + elem name = "CTRL+H" command = "holster" is-disabled = false - elem + elem name = "Q+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+Q+REP" command = ".west" is-disabled = false - elem + elem name = "R" command = ".southwest" is-disabled = false - elem + elem name = "CTRL+R" command = ".southwest" is-disabled = false @@ -353,43 +353,43 @@ macro "AZERTYon" name = "S+REP" command = ".south" is-disabled = false - elem + elem name = "CTRL+S+REP" command = ".south" is-disabled = false - elem + elem name = "T" command = ".say" is-disabled = false - elem + elem name = "O" command = "ooc" is-disabled = false - elem + elem name = "M" command = ".me" is-disabled = false - elem + elem name = "W" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+W" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "X" command = ".northeast" is-disabled = false - elem + elem name = "CTRL+X" command = ".northeast" is-disabled = false - elem + elem name = "Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" is-disabled = false @@ -397,217 +397,217 @@ macro "AZERTYon" name = "Z+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+Z+REP" command = ".north" is-disabled = false - elem + elem name = "F1" command = "adminhelp" is-disabled = false - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" is-disabled = false - elem + elem name = "F2" command = "ooc" is-disabled = false - elem + elem name = "F2+REP" command = ".screenshot auto" is-disabled = false - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" is-disabled = false - elem + elem name = "F3" command = ".say" is-disabled = false - elem + elem name = "F4" command = ".me" is-disabled = false - elem + elem name = "F5" command = "asay" is-disabled = false - elem + elem name = "F6" command = "Aghost" is-disabled = false - elem + elem name = "F7" command = "player-panel-new" is-disabled = false - elem + elem name = "F8" command = "admin-pm-key" is-disabled = false - elem + elem name = "F9" command = "Invisimin" is-disabled = false - elem + elem name = "F12" command = "F12" is-disabled = false macro "borghotkeymode" - elem + elem name = "TAB" command = ".winset \"mainwindow.macro=borgmacro hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5\"" is-disabled = false - elem + elem name = "CENTER+REP" command = ".center" is-disabled = false - elem + elem name = "NORTHEAST" command = ".northeast" is-disabled = false - elem + elem name = "SOUTHEAST" command = ".southeast" is-disabled = false - elem + elem name = "NORTHWEST" command = "unequip-module" is-disabled = false - elem + elem name = "CTRL+WEST" command = "westface" is-disabled = false - elem + elem name = "WEST+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+NORTH" command = "northface" is-disabled = false - elem + elem name = "NORTH+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+EAST" command = "eastface" is-disabled = false - elem + elem name = "EAST+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+SOUTH" command = "southface" is-disabled = false - elem + elem name = "SOUTH+REP" command = ".south" is-disabled = false - elem + elem name = "INSERT" command = "a-intent right" is-disabled = false - elem + elem name = "DELETE" command = "delete-key-pressed" is-disabled = false - elem + elem name = "1" command = "toggle-module 1" is-disabled = false - elem + elem name = "CTRL+1" command = "toggle-module 1" is-disabled = false - elem + elem name = "2" command = "toggle-module 2" is-disabled = false - elem + elem name = "CTRL+2" command = "toggle-module 2" is-disabled = false - elem + elem name = "3" command = "toggle-module 3" is-disabled = false - elem + elem name = "CTRL+3" command = "toggle-module 3" is-disabled = false - elem + elem name = "4" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+4" command = "a-intent left" is-disabled = false - elem + elem name = "A+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+A+REP" command = ".west" is-disabled = false - elem + elem name = "B" command = "resist" is-disabled = false - elem + elem name = "CTRL+B" command = "resist" is-disabled = false - elem + elem name = "T" command = ".say" is-disabled = false - elem + elem name = "O" command = "ooc" is-disabled = false - elem + elem name = "M" command = ".me" is-disabled = false - elem + elem name = "CTRL+O" command = "ooc" is-disabled = false - elem + elem name = "D+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+D+REP" command = ".east" is-disabled = false - elem + elem name = "F" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+F" command = "a-intent left" is-disabled = false - elem + elem name = "G" command = "a-intent right" is-disabled = false - elem + elem name = "CTRL+G" command = "a-intent right" is-disabled = false - elem + elem name = "Q" command = "unequip-module" is-disabled = false - elem + elem name = "CTRL+Q" command = "unequip-module" is-disabled = false @@ -615,7 +615,7 @@ macro "borghotkeymode" name = "S+REP" command = ".south" is-disabled = false - elem + elem name = "CTRL+S+REP" command = ".south" is-disabled = false @@ -623,451 +623,451 @@ macro "borghotkeymode" name = "W+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+W+REP" command = ".north" is-disabled = false - elem + elem name = "X" command = ".northeast" is-disabled = false - elem + elem name = "CTRL+X" command = ".northeast" is-disabled = false - elem + elem name = "Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "Z" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "F1" command = "adminhelp" is-disabled = false - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" is-disabled = false - elem + elem name = "F2" command = "ooc" is-disabled = false - elem + elem name = "F2+REP" command = ".screenshot auto" is-disabled = false - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" is-disabled = false - elem + elem name = "F3" command = ".say" is-disabled = false - elem + elem name = "F4" command = ".me" is-disabled = false - elem + elem name = "F5" command = "asay" is-disabled = false - elem + elem name = "F6" command = "Aghost" is-disabled = false - elem + elem name = "F7" command = "player-panel-new" is-disabled = false - elem + elem name = "F8" command = "admin-pm-key" is-disabled = false - elem + elem name = "F9" command = "Invisimin" is-disabled = false - elem + elem name = "F12" command = "F12" - is-disabled = false - + is-disabled = false + macro "macro" - elem + elem name = "TAB" command = ".Toggle-hotkey-mode" is-disabled = false - elem + elem name = "CENTER+REP" command = ".center" is-disabled = false - elem + elem name = "NORTHEAST" command = ".northeast" is-disabled = false - elem + elem name = "SOUTHEAST" command = ".southeast" is-disabled = false - elem + elem name = "SOUTHWEST" command = ".southwest" is-disabled = false - elem + elem name = "NORTHWEST" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+WEST" command = "westface" is-disabled = false - elem + elem name = "WEST+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+NORTH" command = "northface" is-disabled = false - elem + elem name = "NORTH+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+EAST" command = "eastface" is-disabled = false - elem + elem name = "EAST+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+SOUTH" command = "southface" is-disabled = false - elem + elem name = "SOUTH+REP" command = ".south" is-disabled = false - elem + elem name = "INSERT" command = "a-intent right" is-disabled = false - elem + elem name = "DELETE" command = "delete-key-pressed" is-disabled = false - elem + elem name = "CTRL+1" command = "a-intent help" is-disabled = false - elem + elem name = "CTRL+2" command = "a-intent disarm" is-disabled = false - elem + elem name = "CTRL+3" command = "a-intent grab" is-disabled = false - elem + elem name = "CTRL+4" command = "a-intent harm" is-disabled = false - elem + elem name = "CTRL+A+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+D+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+B" command = "resist" is-disabled = false - elem + elem name = "CTRL+E" command = "quick-equip" is-disabled = false - elem + elem name = "CTRL+F" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+G" command = "a-intent right" is-disabled = false - elem + elem name = "CTRL+Q" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+R" command = ".southwest" is-disabled = false - elem + elem name = "CTRL+S+REP" command = ".south" is-disabled = false - elem + elem name = "CTRL+W+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+X" command = ".northeast" is-disabled = false - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "F1" command = "adminhelp" is-disabled = false - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" is-disabled = false - elem + elem name = "F2" command = "ooc" is-disabled = false - elem + elem name = "F2+REP" command = ".screenshot auto" is-disabled = false - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" is-disabled = false - elem + elem name = "F3" command = ".say" is-disabled = false - elem + elem name = "F4" command = ".me" is-disabled = false - elem + elem name = "F5" command = "asay" is-disabled = false - elem + elem name = "F6" command = "Aghost" is-disabled = false - elem + elem name = "F7" command = "player-panel-new" is-disabled = false - elem + elem name = "F8" command = "admin-pm-key" is-disabled = false - elem + elem name = "F9" command = "Invisimin" is-disabled = false - elem + elem name = "F12" command = "F12" is-disabled = false macro "hotkeymode" - elem + elem name = "TAB" command = ".Toggle-hotkey-mode" is-disabled = false - elem + elem name = "CENTER+REP" command = ".center" is-disabled = false - elem + elem name = "NORTHEAST" command = ".northeast" is-disabled = false - elem + elem name = "SOUTHEAST" command = ".southeast" is-disabled = false - elem + elem name = "SOUTHWEST" command = ".southwest" is-disabled = false - elem + elem name = "NORTHWEST" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+WEST" command = "westface" is-disabled = false - elem + elem name = "WEST+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+NORTH" command = "northface" is-disabled = false - elem + elem name = "NORTH+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+EAST" command = "eastface" is-disabled = false - elem + elem name = "EAST+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+SOUTH" command = "southface" is-disabled = false - elem + elem name = "SOUTH+REP" command = ".south" is-disabled = false - elem + elem name = "INSERT" command = "a-intent right" is-disabled = false - elem + elem name = "DELETE" command = "delete-key-pressed" is-disabled = false - elem + elem name = "1" command = "a-intent help" is-disabled = false - elem + elem name = "CTRL+1" command = "a-intent help" is-disabled = false - elem + elem name = "2" command = "a-intent disarm" is-disabled = false - elem + elem name = "CTRL+2" command = "a-intent disarm" is-disabled = false - elem + elem name = "3" command = "a-intent grab" is-disabled = false - elem + elem name = "CTRL+3" command = "a-intent grab" is-disabled = false - elem + elem name = "4" command = "a-intent harm" is-disabled = false - elem + elem name = "CTRL+4" command = "a-intent harm" is-disabled = false - elem + elem name = "T" command = ".say" is-disabled = false - elem + elem name = "O" command = "ooc" is-disabled = false - elem + elem name = "M" command = ".me" is-disabled = false - elem + elem name = "A+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+A+REP" command = ".west" is-disabled = false - elem + elem name = "D+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+D+REP" command = ".east" is-disabled = false - elem + elem name = "B" command = "resist" is-disabled = false - elem + elem name = "CTRL+B" command = "resist" is-disabled = false - elem + elem name = "E" command = "quick-equip" is-disabled = false - elem + elem name = "CTRL+E" command = "quick-equip" is-disabled = false - elem + elem name = "F" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+F" command = "a-intent left" is-disabled = false - elem + elem name = "G" command = "a-intent right" is-disabled = false - elem + elem name = "CTRL+G" command = "a-intent right" is-disabled = false - elem + elem name = "H" command = "holster" is-disabled = false - elem + elem name = "CTRL+H" command = "holster" is-disabled = false - elem + elem name = "Q" command = ".northwest" is-disabled = false - elem + elem name = "CTRL+Q" command = ".northwest" is-disabled = false - elem + elem name = "R" command = ".southwest" is-disabled = false - elem + elem name = "CTRL+R" command = ".southwest" is-disabled = false @@ -1075,11 +1075,11 @@ macro "hotkeymode" name = "S+REP" command = ".south" is-disabled = false - elem + elem name = "CTRL+S+REP" command = ".south" is-disabled = false - elem + elem name = "T" command = ".say" is-disabled = false @@ -1087,267 +1087,267 @@ macro "hotkeymode" name = "W+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+W+REP" command = ".north" is-disabled = false - elem + elem name = "X" command = ".northeast" is-disabled = false - elem + elem name = "CTRL+X" command = ".northeast" is-disabled = false - elem + elem name = "Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "Z" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "F1" command = "adminhelp" is-disabled = false - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" is-disabled = false - elem + elem name = "F2" command = "ooc" is-disabled = false - elem + elem name = "F2+REP" command = ".screenshot auto" is-disabled = false - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" is-disabled = false - elem + elem name = "F3" command = ".say" is-disabled = false - elem + elem name = "F4" command = ".me" is-disabled = false - elem + elem name = "F5" command = "asay" is-disabled = false - elem + elem name = "F6" command = "Aghost" is-disabled = false - elem + elem name = "F7" command = "player-panel-new" is-disabled = false - elem + elem name = "F8" command = "admin-pm-key" is-disabled = false - elem + elem name = "F9" command = "Invisimin" is-disabled = false - elem + elem name = "F12" command = "F12" is-disabled = false macro "borgmacro" - elem + elem name = "TAB" command = ".winset \"mainwindow.macro=borghotkeymode hotkey_toggle.is-checked=true mapwindow.map.focus=true input.background-color=#F0F0F0\"" is-disabled = false - elem + elem name = "CENTER+REP" command = ".center" is-disabled = false - elem + elem name = "NORTHEAST" command = ".northeast" is-disabled = false - elem + elem name = "SOUTHEAST" command = ".southeast" is-disabled = false - elem + elem name = "NORTHWEST" command = "unequip-module" is-disabled = false - elem + elem name = "CTRL+WEST" command = "westface" is-disabled = false - elem + elem name = "WEST+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+NORTH" command = "northface" is-disabled = false - elem + elem name = "NORTH+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+EAST" command = "eastface" is-disabled = false - elem + elem name = "EAST+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+SOUTH" command = "southface" is-disabled = false - elem + elem name = "SOUTH+REP" command = ".south" is-disabled = false - elem + elem name = "INSERT" command = "a-intent right" is-disabled = false - elem + elem name = "DELETE" command = "delete-key-pressed" is-disabled = false - elem + elem name = "CTRL+1" command = "toggle-module 1" is-disabled = false - elem + elem name = "CTRL+2" command = "toggle-module 2" is-disabled = false - elem + elem name = "CTRL+3" command = "toggle-module 3" is-disabled = false - elem + elem name = "CTRL+4" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+A+REP" command = ".west" is-disabled = false - elem + elem name = "CTRL+B" command = "resist" is-disabled = false - elem + elem name = "CTRL+O" command = "ooc" is-disabled = false - elem + elem name = "CTRL+D+REP" command = ".east" is-disabled = false - elem + elem name = "CTRL+F" command = "a-intent left" is-disabled = false - elem + elem name = "CTRL+G" command = "a-intent right" is-disabled = false - elem + elem name = "CTRL+Q" command = "unequip-module" is-disabled = false - elem + elem name = "CTRL+S+REP" command = ".south" is-disabled = false - elem + elem name = "CTRL+W+REP" command = ".north" is-disabled = false - elem + elem name = "CTRL+X" command = ".northeast" is-disabled = false - elem + elem name = "CTRL+Y" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "CTRL+Z" command = "Activate-Held-Object" is-disabled = false - elem + elem name = "F1" command = "adminhelp" is-disabled = false - elem + elem name = "CTRL+SHIFT+F1+REP" command = ".options" is-disabled = false - elem + elem name = "F2" command = "ooc" is-disabled = false - elem + elem name = "F2+REP" command = ".screenshot auto" is-disabled = false - elem + elem name = "SHIFT+F2+REP" command = ".screenshot" is-disabled = false - elem + elem name = "F3" command = ".say" is-disabled = false - elem + elem name = "F4" command = ".me" is-disabled = false - elem + elem name = "F5" command = "asay" is-disabled = false - elem + elem name = "F6" command = "Aghost" is-disabled = false - elem + elem name = "F7" command = "player-panel-new" is-disabled = false - elem + elem name = "F8" command = "admin-pm-key" is-disabled = false - elem + elem name = "F9" command = "Invisimin" is-disabled = false - elem + elem name = "F12" command = "F12" - is-disabled = false + is-disabled = false menu "menu" - elem + elem name = "&File" command = "" category = "" @@ -1356,7 +1356,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Quick screenshot\tF2" command = ".screenshot auto" category = "&File" @@ -1365,7 +1365,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Save screenshot as...\tShift+F2" command = ".screenshot" category = "&File" @@ -1374,7 +1374,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Reconnect" command = ".reconnect" category = "&File" @@ -1383,7 +1383,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "" command = "" category = "&File" @@ -1392,7 +1392,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Quit" command = ".quit" category = "&File" @@ -1401,7 +1401,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Icons" command = "" category = "" @@ -1464,7 +1464,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Help" command = "" category = "" @@ -1473,7 +1473,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Admin help\tF1" command = "adminhelp" category = "&Help" @@ -1482,7 +1482,7 @@ menu "menu" group = "" is-disabled = false saved-params = "is-checked" - elem + elem name = "&Hotkeys" command = "hotkeys-help" category = "&Help" @@ -2256,6 +2256,32 @@ window "mainwindow" is-checked = false group = "" button-type = pushbox + elem "tooltip" + type = BROWSER + pos = 0,0 + size = 999x999 + anchor1 = none + anchor2 = none + font-family = "" + font-size = 0 + font-style = "" + text-color = #ffffff + background-color = #000000 + is-visible = false + is-disabled = false + is-transparent = false + is-default = false + border = none + drop-zone = false + right-click = false + saved-params = "" + on-size = "" + show-history = false + show-url = false + auto-format = false + use-title = false + on-show = "" + on-hide = "" window "mapwindow" elem "mapwindow" diff --git a/paradise.dme b/paradise.dme index 5493536e2b0..3955e96cb9d 100644 --- a/paradise.dme +++ b/paradise.dme @@ -98,6 +98,7 @@ #include "code\_onclick\hud\_defines.dm" #include "code\_onclick\hud\action.dm" #include "code\_onclick\hud\ai.dm" +#include "code\_onclick\hud\alert.dm" #include "code\_onclick\hud\alien.dm" #include "code\_onclick\hud\alien_larva.dm" #include "code\_onclick\hud\bot.dm" @@ -1983,6 +1984,7 @@ #include "code\modules\telesci\gps.dm" #include "code\modules\telesci\telepad.dm" #include "code\modules\telesci\telesci_computer.dm" +#include "code\modules\tooltip\tooltip.dm" #include "code\modules\tram\tram.dm" #include "code\modules\tram\tram_control_pad.dm" #include "code\modules\tram\tram_floor.dm" From 88f3414d4c40668bf48bd470b91396a5a3cdefb1 Mon Sep 17 00:00:00 2001 From: Tigercat2000 Date: Sat, 16 Apr 2016 16:35:06 -0700 Subject: [PATCH 2/2] PoolOrNew is ugly, carbon trailing returns, oh my --- code/_onclick/hud/alert.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 1 - .../living/carbon/human/species/species.dm | 5 ++--- code/modules/mob/living/living.dm | 22 ++++++++++--------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 8fec01be719..ca3f223c80d 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -33,7 +33,7 @@ else //no need to update return 0 else - alert = PoolOrNew(type) + alert = new type if(new_master) var/old_layer = new_master.layer diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index af76142de76..26def9b6520 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -777,7 +777,6 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump, visible_message("[src] has successfully extinguished themselves!", \ "You extinguish yourself.") ExtinguishMob() - return /mob/living/carbon/resist_restraints() diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 3190195746d..28da2348c23 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -54,9 +54,9 @@ var/list/atmos_requirements = list( "min_oxy" = 16, - "max_oxy" = INFINITY, + "max_oxy" = 0, "min_nitro" = 0, - "max_nitro" = INFINITY, + "max_nitro" = 0, "min_tox" = 0, "max_tox" = 0.005, "min_co2" = 0, @@ -303,7 +303,6 @@ if(prob(20)) // Lets give them some chance to know somethings not right though I guess. spawn(0) H.emote("cough") - //throw_alert("co2", /obj/screen/alert/too_much_co2) //we're gonna leave this one as a silent killer for now else H.clear_alert("co2") if(atmos_requirements["min_co2"]) //species breathes this gas, so they got their air diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 0a2e9fe5e5b..e29444641c4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -556,18 +556,20 @@ for(var/X in grabbed_by) var/obj/item/weapon/grab/G = X resisting++ - if(G.state == GRAB_PASSIVE) - qdel(G) - else - if(G.state == GRAB_AGGRESSIVE) - if(prob(25)) + switch(G.state) + if(GRAB_PASSIVE) + qdel(G) + + if(GRAB_AGGRESSIVE) + if(prob(60)) visible_message("[src] has broken free of [G.assailant]'s grip!") qdel(G) - else - if(G.state == GRAB_NECK) - if(prob(5)) - visible_message("[src] has broken free of [G.assailant]'s headlock!") - qdel(G) + + if(GRAB_NECK) + if(prob(5)) + visible_message("[src] has broken free of [G.assailant]'s headlock!") + qdel(G) + if(resisting) visible_message("[src] resists!") return 1