mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-15 00:53:23 +01:00
Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into Kungfu
This commit is contained in:
@@ -749,6 +749,10 @@ var/global/nologevent = 0
|
||||
if (ticker.mode.config_tag == "changeling")
|
||||
return 2
|
||||
return 1
|
||||
if(M.mind in ticker.mode.abductors)
|
||||
if (ticker.mode.config_tag == "abduction")
|
||||
return 2
|
||||
return 1
|
||||
if(isrobot(M))
|
||||
var/mob/living/silicon/robot/R = M
|
||||
if(R.emagged)
|
||||
|
||||
@@ -515,6 +515,12 @@
|
||||
if(ticker.mode.shadowling_thralls.len)
|
||||
dat += check_role_table("Shadowling Thralls", ticker.mode.shadowling_thralls, src)
|
||||
|
||||
if(ticker.mode.abductors.len)
|
||||
dat += check_role_table("Abductors", ticker.mode.abductors, src)
|
||||
|
||||
if(ticker.mode.abductees.len)
|
||||
dat += check_role_table("Abductees", ticker.mode.abductees, src)
|
||||
|
||||
if(ticker.mode.vampires.len)
|
||||
dat += check_role_table("Vampires", ticker.mode.vampires, src)
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@
|
||||
log_admin("[key_name(usr)] has spawned vox raiders.")
|
||||
if(!src.makeVoxRaiders())
|
||||
to_chat(usr, "\red Unfortunately there weren't enough candidates available.")
|
||||
if("9")
|
||||
log_admin("[key_name(usr)] has spawned an abductor team.")
|
||||
if(!src.makeAbductorTeam())
|
||||
to_chat(usr, "\red Unfortunately there weren't enough candidates available.")
|
||||
|
||||
else if(href_list["dbsearchckey"] || href_list["dbsearchadmin"] || href_list["dbsearchip"] || href_list["dbsearchcid"] || href_list["dbsearchbantype"])
|
||||
var/adminckey = href_list["dbsearchadmin"]
|
||||
|
||||
@@ -682,7 +682,6 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(M), slot_glasses)
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/head/det_hat(M), slot_head)
|
||||
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/cloaking_device(M), slot_r_store)
|
||||
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/proto(M), slot_r_hand)
|
||||
M.equip_to_slot_or_del(new /obj/item/ammo_box/a357(M), slot_l_store)
|
||||
@@ -814,7 +813,6 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/sunglasses(M), slot_glasses)
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/suit/wcoat(M), slot_wear_suit)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword/saber(M), slot_l_store)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/cloaking_device(M), slot_r_store)
|
||||
|
||||
var/obj/item/weapon/storage/secure/briefcase/sec_briefcase = new(M)
|
||||
for(var/obj/item/briefcase_item in sec_briefcase)
|
||||
|
||||
@@ -21,6 +21,7 @@ client/proc/one_click_antag()
|
||||
<a href='?src=\ref[src];makeAntag=6'>Make Wizard (Requires Ghosts)</a><br>
|
||||
<a href='?src=\ref[src];makeAntag=7'>Make Vampires</a><br>
|
||||
<a href='?src=\ref[src];makeAntag=8'>Make Vox Raiders (Requires Ghosts)</a><br>
|
||||
<a href='?src=\ref[src];makeAntag=9'>Make Abductor Team (Requires Ghosts)</a><br>
|
||||
"}
|
||||
usr << browse(dat, "window=oneclickantag;size=400x400")
|
||||
return
|
||||
@@ -308,8 +309,10 @@ client/proc/one_click_antag()
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
|
||||
//Abductors
|
||||
/datum/admins/proc/makeAbductorTeam()
|
||||
new /datum/event/abductor
|
||||
return 1
|
||||
|
||||
/datum/admins/proc/makeAliens()
|
||||
alien_infestation(3)
|
||||
@@ -396,7 +399,7 @@ client/proc/one_click_antag()
|
||||
//First we spawn a dude.
|
||||
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
|
||||
|
||||
var/datum/preferences/A = new()
|
||||
var/datum/preferences/A = new(G_found.client)
|
||||
A.copy_to(new_character)
|
||||
|
||||
new_character.dna.ready_dna(new_character)
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
if(href_list["send"])
|
||||
spawn( 0 )
|
||||
signal()
|
||||
signal()
|
||||
|
||||
if(usr)
|
||||
attack_self(usr)
|
||||
@@ -169,6 +169,7 @@
|
||||
desc = "The neutralized core of an anomaly. It'd probably be valuable for research."
|
||||
icon_state = "anomaly core"
|
||||
item_state = "electronic"
|
||||
receiving = 1
|
||||
|
||||
/obj/item/device/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
|
||||
..()
|
||||
|
||||
@@ -81,4 +81,7 @@
|
||||
|
||||
control_freak = CONTROL_FREAK_ALL | CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
|
||||
|
||||
var/datum/click_intercept/click_intercept = null
|
||||
var/datum/click_intercept/click_intercept = null
|
||||
|
||||
//datum that controls the displaying and hiding of tooltips
|
||||
var/datum/tooltip/tooltips
|
||||
@@ -317,6 +317,10 @@
|
||||
to_chat(src, "<span class='warning'>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.</span>")
|
||||
|
||||
|
||||
//This is down here because of the browse() calls in tooltip/New()
|
||||
if(!tooltips)
|
||||
tooltips = new /datum/tooltip(src)
|
||||
|
||||
//////////////
|
||||
//DISCONNECT//
|
||||
//////////////
|
||||
|
||||
@@ -25,6 +25,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
|
||||
ROLE_NINJA = 21,
|
||||
ROLE_MUTINEER = 21,
|
||||
ROLE_MALF = 30,
|
||||
ROLE_ABDUCTOR = 30,
|
||||
)
|
||||
|
||||
/proc/player_old_enough_antag(client/C, role)
|
||||
|
||||
@@ -190,112 +190,217 @@
|
||||
piece.flags &= ~(STOPSPRESSUREDMAGE|AIRTIGHT)
|
||||
update_icon(1)
|
||||
|
||||
/obj/item/weapon/rig/proc/toggle_seals(var/mob/living/carbon/human/M, var/mob/living/user, var/instant)
|
||||
|
||||
if(sealing) return
|
||||
|
||||
if(!check_power_cost(M, 1)) //costs tiny amount of power to unseal/seal
|
||||
/obj/item/weapon/rig/proc/seal(mob/living/user)
|
||||
if(sealing)
|
||||
return 0
|
||||
|
||||
deploy(M, instant)
|
||||
if(!wearer || !user)
|
||||
return
|
||||
|
||||
var/seal_target = (flags & NODROP)
|
||||
var/failed_to_seal
|
||||
var/sealed = (flags & NODROP)
|
||||
if(sealed)
|
||||
to_chat(user, "<span class='danger'>\The [src] is already sealed!</span>")
|
||||
return 0
|
||||
|
||||
flags |= NODROP // No removing the suit while unsealing.
|
||||
sealing = 1
|
||||
if(!check_power_cost(user, 1)) //need power to seal the suit
|
||||
return 0
|
||||
|
||||
if(!seal_target && !suit_is_deployed())
|
||||
M.visible_message("<span class='danger'>[M]'s suit flashes an error light.</span>","<span class='danger'>Your suit flashes an error light. It can't function properly without being fully deployed.</span>")
|
||||
failed_to_seal = 1
|
||||
var/failed_to_seal = FALSE
|
||||
|
||||
if(!suit_is_deployed())
|
||||
to_chat(user, "<span class='danger'>\The [src] cannot seal, as it is not fully deployed!</span>")
|
||||
return 0
|
||||
|
||||
flags |= NODROP
|
||||
sealing = TRUE
|
||||
|
||||
to_chat(user, "<span class='notice'>\The [src] begins to tighten it's seals.</span>")
|
||||
wearer.visible_message("<span class='notice'>\The [wearer]'s suit emits a quiet hum as it begins to tighten it's seals.</span>",
|
||||
"<span class='notice'>With a quiet hum, your suit begins to seal.")
|
||||
|
||||
if(seal_delay && !do_after(user, seal_delay, target = wearer))
|
||||
to_chat(user, "<span class='warning'>You must remain still to seal \the [src]!</span>")
|
||||
failed_to_seal = TRUE
|
||||
|
||||
if(!failed_to_seal)
|
||||
deploy(user)
|
||||
|
||||
if(!instant)
|
||||
M.visible_message("<font color='blue'>[M]'s suit emits a quiet hum as it begins to adjust its seals.</font>","<font color='blue'>With a quiet hum, the suit begins running checks and adjusting components.</font>")
|
||||
if(seal_delay && !do_after(user, seal_delay, target = M))
|
||||
if(user)
|
||||
to_chat(user, "<span class='warning'>You must remain still while the suit is adjusting the components.</span>")
|
||||
failed_to_seal = 1
|
||||
var/list/pieces_data = list(list(wearer.shoes, boots, "boots", boot_type),
|
||||
list(wearer.gloves, gloves, "gloves", glove_type),
|
||||
list(wearer.head, helmet, "helmet", helm_type),
|
||||
list(wearer.wear_suit, chest, "chest", chest_type))
|
||||
|
||||
if(!M)
|
||||
failed_to_seal = 1
|
||||
else
|
||||
for(var/list/piece_data in list(list(M.shoes,boots,"boots",boot_type),list(M.gloves,gloves,"gloves",glove_type),list(M.head,helmet,"helmet",helm_type),list(M.wear_suit,chest,"chest",chest_type)))
|
||||
for(var/list/piece_data in pieces_data)
|
||||
var/obj/item/user_piece = piece_data[1]
|
||||
var/obj/item/correct_piece = piece_data[2]
|
||||
var/msg_type = piece_data[3]
|
||||
var/piece_type = piece_data[4]
|
||||
|
||||
var/obj/item/piece = piece_data[1]
|
||||
var/obj/item/compare_piece = piece_data[2]
|
||||
var/msg_type = piece_data[3]
|
||||
var/piece_type = piece_data[4]
|
||||
if(!user_piece || !piece_type)
|
||||
continue
|
||||
|
||||
if(!piece || !piece_type)
|
||||
continue
|
||||
if(user_piece != correct_piece)
|
||||
to_chat(user, "<span class='danger'>\The [user_piece] is blocking \the [src] from deploying.</span>")
|
||||
failed_to_seal = TRUE
|
||||
|
||||
if(!istype(M) || !istype(piece) || !istype(compare_piece) || !msg_type)
|
||||
if(M)
|
||||
to_chat(M, "<span class='warning'>You must remain still while the suit is adjusting the components.</span>")
|
||||
failed_to_seal = 1
|
||||
break
|
||||
if(seal_delay && !do_after(user, seal_delay, needhand = 0, target = wearer))
|
||||
to_chat(user, "<span class='warning'>You must remain still to seal \the [src]!</span>")
|
||||
failed_to_seal = TRUE
|
||||
|
||||
if(!failed_to_seal && M.back == src && piece == compare_piece)
|
||||
if(failed_to_seal)
|
||||
break
|
||||
|
||||
if(seal_delay && !instant && !do_after(user, seal_delay, needhand = 0, target = M))
|
||||
failed_to_seal = 1
|
||||
correct_piece.icon_state = "[initial(icon_state)]_sealed"
|
||||
switch(msg_type)
|
||||
if("boots")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] seal around your feet.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been sealed.</span>")
|
||||
wearer.update_inv_shoes()
|
||||
if("gloves")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] tighten around your fingers and wrists.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been sealed.</span>")
|
||||
wearer.update_inv_gloves()
|
||||
if("chest")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] cinches tight again your chest.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been sealed.</span>")
|
||||
wearer.update_inv_wear_suit()
|
||||
if("helmet")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] hisses closed.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been sealed.</span>")
|
||||
wearer.update_inv_head()
|
||||
if(helmet)
|
||||
helmet.update_light(wearer)
|
||||
|
||||
piece.icon_state = "[initial(icon_state)][!seal_target ? "_sealed" : ""]"
|
||||
switch(msg_type)
|
||||
if("boots")
|
||||
to_chat(M, "<font color='blue'>\The [piece] [!seal_target ? "seal around your feet" : "relax their grip on your legs"].</font>")
|
||||
M.update_inv_shoes()
|
||||
if("gloves")
|
||||
to_chat(M, "<font color='blue'>\The [piece] [!seal_target ? "tighten around your fingers and wrists" : "become loose around your fingers"].</font>")
|
||||
M.update_inv_gloves()
|
||||
if("chest")
|
||||
to_chat(M, "<font color='blue'>\The [piece] [!seal_target ? "cinches tight again your chest" : "releases your chest"].</font>")
|
||||
M.update_inv_wear_suit()
|
||||
if("helmet")
|
||||
to_chat(M, "<font color='blue'>\The [piece] hisses [!seal_target ? "closed" : "open"].</font>")
|
||||
M.update_inv_head()
|
||||
if(helmet)
|
||||
helmet.update_light(wearer)
|
||||
correct_piece.armor["bio"] = 100
|
||||
|
||||
//sealed pieces become airtight, protecting against diseases
|
||||
if (!seal_target)
|
||||
piece.armor["bio"] = 100
|
||||
else
|
||||
piece.armor["bio"] = src.armor["bio"]
|
||||
|
||||
else
|
||||
failed_to_seal = 1
|
||||
|
||||
if((M && !(istype(M) && M.back == src) && !istype(M,/mob/living/silicon)) || (!seal_target && !suit_is_deployed()))
|
||||
failed_to_seal = 1
|
||||
|
||||
sealing = null
|
||||
sealing = FALSE
|
||||
|
||||
if(failed_to_seal)
|
||||
for(var/obj/item/piece in list(helmet,boots,gloves,chest))
|
||||
if(!piece) continue
|
||||
piece.icon_state = "[initial(icon_state)][!seal_target ? "" : "_sealed"]"
|
||||
if(seal_target)
|
||||
flags |= NODROP
|
||||
else
|
||||
flags &= ~NODROP
|
||||
for(var/obj/item/piece in list(helmet, boots, gloves, chest))
|
||||
if(!piece)
|
||||
continue
|
||||
piece.icon_state = "[initial(icon_state)]"
|
||||
flags &= ~NODROP
|
||||
if(airtight)
|
||||
update_component_sealed()
|
||||
update_icon(1)
|
||||
return 0
|
||||
|
||||
// Success!
|
||||
if(seal_target)
|
||||
flags &= ~NODROP
|
||||
else
|
||||
flags |= NODROP
|
||||
to_chat(M, "<font color='blue'><b>Your entire suit [!(flags & NODROP) ? "loosens as the components relax" : "tightens around you as the components lock into place"].</b></font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been loosened.</span>")
|
||||
to_chat(wearer, "<span class='notice'>Your entire suit tightens around you as the components lock into place.</span>")
|
||||
if(airtight)
|
||||
update_component_sealed()
|
||||
update_icon(1)
|
||||
|
||||
/obj/item/weapon/rig/proc/unseal(mob/living/user)
|
||||
if(sealing)
|
||||
return 0
|
||||
|
||||
if(!wearer || !user)
|
||||
return
|
||||
|
||||
var/sealed = (flags & NODROP)
|
||||
if(!sealed)
|
||||
to_chat(user, "<span class='danger'>\The [src] is already unsealed!</span>")
|
||||
return 0
|
||||
|
||||
sealing = TRUE
|
||||
|
||||
var/failed_to_seal = FALSE
|
||||
|
||||
if(!suit_is_deployed())
|
||||
to_chat(user, "<span class='danger'>\The [src] cannot unseal, as it is not fully deployed!</span>")
|
||||
failed_to_seal = TRUE
|
||||
|
||||
if(!failed_to_seal)
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [src] begins to loosen it's seals.</span>")
|
||||
wearer.visible_message("<span class='notice'>\The [wearer]'s suit emits a quiet hum as it begins to loosen it's seals.</span>",
|
||||
"<span class='notice'>With a quiet hum, your suit begins to unseal.")
|
||||
|
||||
if(seal_delay && !do_after(user, seal_delay, target = wearer))
|
||||
to_chat(user, "<span class='warning'>You must remain still to unseal \the [src]!</span>")
|
||||
failed_to_seal = TRUE
|
||||
|
||||
if(!failed_to_seal)
|
||||
var/list/pieces_data = list(list(wearer.shoes, boots, "boots", boot_type),
|
||||
list(wearer.gloves, gloves, "gloves", glove_type),
|
||||
list(wearer.head, helmet, "helmet", helm_type),
|
||||
list(wearer.wear_suit, chest, "chest", chest_type))
|
||||
|
||||
for(var/list/piece_data in pieces_data)
|
||||
var/obj/item/user_piece = piece_data[1]
|
||||
var/obj/item/correct_piece = piece_data[2]
|
||||
var/msg_type = piece_data[3]
|
||||
var/piece_type = piece_data[4]
|
||||
|
||||
if(!correct_piece || !piece_type)
|
||||
continue
|
||||
|
||||
if(user_piece != correct_piece)
|
||||
to_chat(user, "<span class='danger'>\The [user_piece] is blocking \the [src] from deploying.</span>")
|
||||
failed_to_seal = TRUE
|
||||
|
||||
if(seal_delay && !do_after(user, seal_delay, needhand = 0, target = wearer))
|
||||
to_chat(user, "<span class='warning'>You must remain still to unseal \the [src]!</span>")
|
||||
failed_to_seal = TRUE
|
||||
|
||||
if(failed_to_seal)
|
||||
break
|
||||
|
||||
correct_piece.icon_state = "[initial(icon_state)]"
|
||||
switch(msg_type)
|
||||
if("boots")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] relax their grip on your legs.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been unsealed.</span>")
|
||||
wearer.update_inv_shoes()
|
||||
if("gloves")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] become loose around your fingers.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been unsealed.</span>")
|
||||
wearer.update_inv_gloves()
|
||||
if("chest")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] releases your chest.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been unsealed.</span>")
|
||||
wearer.update_inv_wear_suit()
|
||||
if("helmet")
|
||||
to_chat(wearer, "<font color='blue'>\The [correct_piece] hisses open.</font>")
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [correct_piece] has been unsealed.</span>")
|
||||
wearer.update_inv_head()
|
||||
if(helmet)
|
||||
helmet.update_light(wearer)
|
||||
|
||||
correct_piece.armor["bio"] = armor["bio"]
|
||||
|
||||
sealing = FALSE
|
||||
|
||||
if(failed_to_seal)
|
||||
for(var/obj/item/piece in list(helmet, boots, gloves, chest))
|
||||
if(!piece)
|
||||
continue
|
||||
piece.icon_state = "[initial(icon_state)]_sealed"
|
||||
if(airtight)
|
||||
update_component_sealed()
|
||||
update_icon(1)
|
||||
return 0
|
||||
|
||||
if(user != wearer)
|
||||
to_chat(user, "<span class='notice'>\The [src] has been unsealed.</span>")
|
||||
to_chat(wearer, "<span class='notice'>Your entire suit loosens as the components relax.</span>")
|
||||
|
||||
flags &= ~NODROP
|
||||
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
module.deactivate()
|
||||
|
||||
if(!(flags & NODROP))
|
||||
for(var/obj/item/rig_module/module in installed_modules)
|
||||
module.deactivate()
|
||||
if(airtight)
|
||||
update_component_sealed()
|
||||
update_icon(1)
|
||||
@@ -310,7 +415,6 @@
|
||||
piece.flags |= AIRTIGHT
|
||||
|
||||
/obj/item/weapon/rig/process()
|
||||
|
||||
// If we've lost any parts, grab them back.
|
||||
var/mob/living/M
|
||||
for(var/obj/item/piece in list(gloves,boots,helmet,chest))
|
||||
@@ -367,7 +471,6 @@
|
||||
cell.use(module.process()*10)
|
||||
|
||||
/obj/item/weapon/rig/proc/check_power_cost(var/mob/living/user, var/cost, var/use_unconcious, var/obj/item/rig_module/mod, var/user_is_ai)
|
||||
|
||||
if(!istype(user))
|
||||
return 0
|
||||
|
||||
@@ -524,7 +627,6 @@
|
||||
|
||||
return 1
|
||||
|
||||
//TODO: Fix Topic vulnerabilities for malfunction and AI override.
|
||||
/obj/item/weapon/rig/Topic(href,href_list)
|
||||
if(!check_suit_access(usr))
|
||||
return 0
|
||||
@@ -532,11 +634,13 @@
|
||||
if(href_list["toggle_piece"])
|
||||
if(ishuman(usr) && (usr.stat || usr.stunned || usr.lying))
|
||||
return 0
|
||||
toggle_piece(href_list["toggle_piece"], wearer, user = usr)
|
||||
toggle_piece(href_list["toggle_piece"], usr)
|
||||
else if(href_list["toggle_seals"])
|
||||
toggle_seals(wearer, usr)
|
||||
if(flags & NODROP)
|
||||
unseal(usr)
|
||||
else
|
||||
seal(usr)
|
||||
else if(href_list["interact_module"])
|
||||
|
||||
var/module_index = text2num(href_list["interact_module"])
|
||||
|
||||
if(module_index > 0 && module_index <= installed_modules.len)
|
||||
@@ -559,7 +663,7 @@
|
||||
locked = !locked
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
add_fingerprint(usr)
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/rig/proc/notify_ai(var/message)
|
||||
@@ -570,8 +674,11 @@
|
||||
if(ai && ai.client && !ai.stat)
|
||||
to_chat(ai, "[message]")
|
||||
|
||||
/obj/item/weapon/rig/equipped(mob/living/carbon/human/M)
|
||||
/obj/item/weapon/rig/equipped(mob/living/carbon/human/M, slot)
|
||||
..()
|
||||
if(!istype(M) || slot != slot_back)
|
||||
return //we don't care about picking up/nonhumans
|
||||
|
||||
spawn(1) //equipped() is called BEFORE the item is actually set as the slot
|
||||
|
||||
if(seal_delay > 0 && istype(M) && M.back == src)
|
||||
@@ -588,115 +695,108 @@
|
||||
wearer.wearing_rig = src
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/rig/proc/toggle_piece(var/piece, var/mob/living/carbon/human/H, var/deploy_mode, var/force, var/mob/living/user)
|
||||
/obj/item/weapon/rig/proc/toggle_piece(var/piece, var/mob/living/user, var/deploy_mode, var/force)
|
||||
if(!istype(wearer) || wearer.back != src)
|
||||
if(force) //can only force retracting sorry
|
||||
for(var/obj/item/uneq_piece in list(helmet, gloves, boots, chest))
|
||||
if(uneq_piece)
|
||||
if(isliving(uneq_piece.loc))
|
||||
var/mob/living/L = uneq_piece.loc
|
||||
L.unEquip(uneq_piece, 1)
|
||||
uneq_piece.flags &= ~NODROP
|
||||
uneq_piece.forceMove(src)
|
||||
return 0
|
||||
|
||||
if(!force) //forces the hardsuit to ignore most checks, as the suit being dropped should retract all pieces regardless of power status
|
||||
if(sealing || !cell || !cell.charge) //or else you have issues with shit getting stuck
|
||||
return
|
||||
if(sealing || !cell || !cell.charge)
|
||||
return 0
|
||||
|
||||
if(!istype(wearer) || !wearer.back == src)
|
||||
return
|
||||
|
||||
if(usr == wearer && (usr.stat||usr.paralysis||usr.stunned)) // If the usr isn't wearing the suit it's probably an AI.
|
||||
return
|
||||
if(user == wearer && user.incapacitated()) // If the user isn't wearing the suit it's probably an AI.
|
||||
return 0
|
||||
|
||||
var/obj/item/check_slot
|
||||
var/equip_to
|
||||
var/obj/item/use_obj
|
||||
|
||||
if(!H)
|
||||
return
|
||||
|
||||
switch(piece)
|
||||
if("helmet")
|
||||
equip_to = slot_head
|
||||
use_obj = helmet
|
||||
check_slot = H.head
|
||||
check_slot = wearer.head
|
||||
if("gauntlets")
|
||||
equip_to = slot_gloves
|
||||
use_obj = gloves
|
||||
check_slot = H.gloves
|
||||
check_slot = wearer.gloves
|
||||
if("boots")
|
||||
equip_to = slot_shoes
|
||||
use_obj = boots
|
||||
check_slot = H.shoes
|
||||
check_slot = wearer.shoes
|
||||
if("chest")
|
||||
equip_to = slot_wear_suit
|
||||
use_obj = chest
|
||||
check_slot = H.wear_suit
|
||||
check_slot = wearer.wear_suit
|
||||
|
||||
if(use_obj)
|
||||
if(check_slot == use_obj && deploy_mode != ONLY_DEPLOY)
|
||||
|
||||
var/mob/living/carbon/human/holder
|
||||
|
||||
if(use_obj)
|
||||
holder = use_obj.loc
|
||||
if(istype(holder))
|
||||
if(use_obj && check_slot == use_obj)
|
||||
to_chat(H, "<font color='blue'><b>Your [use_obj.name] [use_obj.gender == PLURAL ? "retract" : "retracts"] swiftly.</b></font>")
|
||||
use_obj.flags &= ~NODROP
|
||||
holder.unEquip(use_obj, 1)
|
||||
use_obj.forceMove(src)
|
||||
|
||||
else if (deploy_mode != ONLY_RETRACT)
|
||||
if(check_slot)
|
||||
if(check_slot != use_obj)
|
||||
to_chat(H, "<span class='danger'>You are unable to deploy \the [piece] as \the [check_slot] [check_slot.gender == PLURAL ? "are" : "is"] in the way.</span>")
|
||||
if(check_slot == use_obj && deploy_mode != ONLY_DEPLOY) //user is wearing it, retract it if not forced to deploy
|
||||
if((flags & NODROP) && equip_to != slot_head && !force) //you can only retract the helmet if the suit isn't unsealed
|
||||
to_chat(user, "<span class='warning'>You can't retract \the [use_obj] while the suit is sealed!</span>")
|
||||
return
|
||||
|
||||
var/mob/living/to_strip
|
||||
if(wearer)
|
||||
to_strip = wearer
|
||||
else if(isliving(use_obj.loc))
|
||||
to_strip = use_obj.loc
|
||||
|
||||
if(to_strip)
|
||||
to_strip.unEquip(use_obj, 1)
|
||||
|
||||
use_obj.flags &= ~NODROP
|
||||
use_obj.forceMove(src)
|
||||
if(wearer)
|
||||
to_chat(wearer, "<span class='notice'>Your [use_obj] [use_obj.gender == PLURAL ? "retract" : "retracts"] swiftly.")
|
||||
|
||||
else if(deploy_mode != ONLY_RETRACT)
|
||||
if(check_slot && check_slot != use_obj)
|
||||
to_chat(wearer, "<span class='danger'>You are unable to deploy \the [piece] as \the [check_slot] [check_slot.gender == PLURAL ? "are" : "is"] in the way.</span>")
|
||||
return
|
||||
use_obj.forceMove(wearer)
|
||||
use_obj.flags &= ~NODROP
|
||||
if(!wearer.equip_to_slot_if_possible(use_obj, equip_to, 0, 1))
|
||||
use_obj.forceMove(src)
|
||||
else
|
||||
use_obj.forceMove(H)
|
||||
use_obj.flags &= ~NODROP
|
||||
if(!H.equip_to_slot_if_possible(use_obj, equip_to, 0, 1))
|
||||
use_obj.forceMove(src)
|
||||
else
|
||||
to_chat(H, "<span class='notice'>Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.</span>")
|
||||
use_obj.flags |= NODROP
|
||||
if(wearer)
|
||||
to_chat(wearer, "<span class='notice'>Your [use_obj.name] [use_obj.gender == PLURAL ? "deploy" : "deploys"] swiftly.</span>")
|
||||
use_obj.flags |= NODROP
|
||||
|
||||
if(piece == "helmet" && helmet)
|
||||
helmet.update_light(H)
|
||||
helmet.update_light(wearer)
|
||||
|
||||
/obj/item/weapon/rig/proc/deploy(mob/M,var/sealed, mob/user)
|
||||
/obj/item/weapon/rig/proc/deploy(mob/user)
|
||||
if(!wearer || !user)
|
||||
return 0
|
||||
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(flags & NODROP)
|
||||
if(wearer.head && wearer.head != helmet)
|
||||
to_chat(user, "<span class='danger'>\The [wearer.head] is blocking \the [src] from deploying!</span>")
|
||||
return 0
|
||||
if(wearer.gloves && wearer.gloves != gloves)
|
||||
to_chat(user, "<span class='danger'>\The [wearer.gloves] is preventing \the [src] from deploying!</span>")
|
||||
return 0
|
||||
if(wearer.shoes && wearer.shoes != boots)
|
||||
to_chat(user, "<span class='danger'>\The [wearer.shoes] is preventing \the [src] from deploying!</span>")
|
||||
return 0
|
||||
if(wearer.wear_suit && wearer.wear_suit != chest)
|
||||
to_chat(user, "<span class='danger'>\The [wearer.wear_suit] is preventing \the [src] from deploying!</span>")
|
||||
return 0
|
||||
|
||||
if(!H || !istype(H)) return
|
||||
|
||||
if(H.back != src)
|
||||
return
|
||||
|
||||
if(sealed)
|
||||
if(H.head)
|
||||
var/obj/item/garbage = H.head
|
||||
H.unEquip(garbage)
|
||||
H.head = null
|
||||
qdel(garbage)
|
||||
|
||||
if(H.gloves)
|
||||
var/obj/item/garbage = H.gloves
|
||||
H.unEquip(garbage)
|
||||
H.gloves = null
|
||||
qdel(garbage)
|
||||
|
||||
if(H.shoes)
|
||||
var/obj/item/garbage = H.shoes
|
||||
H.unEquip(garbage)
|
||||
H.shoes = null
|
||||
qdel(garbage)
|
||||
|
||||
if(H.wear_suit)
|
||||
var/obj/item/garbage = H.wear_suit
|
||||
H.unEquip(garbage)
|
||||
H.wear_suit = null
|
||||
qdel(garbage)
|
||||
|
||||
for(var/piece in list("helmet","gauntlets","chest","boots"))
|
||||
toggle_piece(piece, wearer, ONLY_DEPLOY, user = user)
|
||||
for(var/piece in list("helmet", "gauntlets", "chest", "boots"))
|
||||
toggle_piece(piece, user, ONLY_DEPLOY)
|
||||
|
||||
/obj/item/weapon/rig/dropped(var/mob/user)
|
||||
..()
|
||||
for(var/piece in list("helmet","gauntlets","chest","boots"))
|
||||
toggle_piece(piece, wearer, ONLY_RETRACT, 1, user = user)
|
||||
toggle_piece(piece, user, ONLY_RETRACT, 1)
|
||||
if(wearer)
|
||||
wearer.wearing_rig = null
|
||||
wearer = null
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Interface for humans.
|
||||
/obj/item/weapon/rig/verb/hardsuit_interface()
|
||||
|
||||
set name = "Open Hardsuit Interface"
|
||||
set desc = "Open the hardsuit system interface."
|
||||
set category = "Hardsuit"
|
||||
@@ -10,7 +9,6 @@
|
||||
ui_interact(usr)
|
||||
|
||||
/obj/item/weapon/rig/verb/toggle_vision()
|
||||
|
||||
set name = "Toggle Visor"
|
||||
set desc = "Turns your rig visor off or on."
|
||||
set category = "Hardsuit"
|
||||
@@ -44,7 +42,6 @@
|
||||
visor.deactivate()
|
||||
|
||||
/obj/item/weapon/rig/proc/toggle_helmet()
|
||||
|
||||
set name = "Toggle Helmet"
|
||||
set desc = "Deploys or retracts your helmet."
|
||||
set category = "Hardsuit"
|
||||
@@ -61,10 +58,9 @@
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("helmet",wearer, user = usr)
|
||||
toggle_piece("helmet", usr)
|
||||
|
||||
/obj/item/weapon/rig/proc/toggle_chest()
|
||||
|
||||
set name = "Toggle Chestpiece"
|
||||
set desc = "Deploys or retracts your chestpiece."
|
||||
set category = "Hardsuit"
|
||||
@@ -77,10 +73,9 @@
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("chest",wearer, user = usr)
|
||||
toggle_piece("chest", usr)
|
||||
|
||||
/obj/item/weapon/rig/proc/toggle_gauntlets()
|
||||
|
||||
set name = "Toggle Gauntlets"
|
||||
set desc = "Deploys or retracts your gauntlets."
|
||||
set category = "Hardsuit"
|
||||
@@ -97,10 +92,9 @@
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("gauntlets",wearer, user = usr)
|
||||
toggle_piece("gauntlets", usr)
|
||||
|
||||
/obj/item/weapon/rig/proc/toggle_boots()
|
||||
|
||||
set name = "Toggle Boots"
|
||||
set desc = "Deploys or retracts your boots."
|
||||
set category = "Hardsuit"
|
||||
@@ -117,10 +111,9 @@
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_piece("boots",wearer, user = usr)
|
||||
toggle_piece("boots", usr)
|
||||
|
||||
/obj/item/weapon/rig/verb/deploy_suit()
|
||||
|
||||
set name = "Deploy Hardsuit"
|
||||
set desc = "Deploys helmet, gloves and boots."
|
||||
set category = "Hardsuit"
|
||||
@@ -143,7 +136,6 @@
|
||||
deploy(wearer, usr)
|
||||
|
||||
/obj/item/weapon/rig/verb/toggle_seals_verb()
|
||||
|
||||
set name = "Toggle Hardsuit"
|
||||
set desc = "Activates or deactivates your rig."
|
||||
set category = "Hardsuit"
|
||||
@@ -160,10 +152,12 @@
|
||||
if(M.incapacitated())
|
||||
return
|
||||
|
||||
toggle_seals(wearer)
|
||||
if(flags & NODROP)
|
||||
unseal(usr)
|
||||
else
|
||||
seal(usr)
|
||||
|
||||
/obj/item/weapon/rig/verb/switch_vision_mode()
|
||||
|
||||
set name = "Switch Vision Mode"
|
||||
set desc = "Switches between available vision modes."
|
||||
set category = "Hardsuit"
|
||||
@@ -197,7 +191,6 @@
|
||||
visor.engage()
|
||||
|
||||
/obj/item/weapon/rig/verb/alter_voice()
|
||||
|
||||
set name = "Configure Voice Synthesiser"
|
||||
set desc = "Toggles or configures your voice synthesizer."
|
||||
set category = "Hardsuit"
|
||||
@@ -225,7 +218,6 @@
|
||||
speech.engage()
|
||||
|
||||
/obj/item/weapon/rig/verb/select_module()
|
||||
|
||||
set name = "Select Module"
|
||||
set desc = "Selects a module as your primary system."
|
||||
set category = "Hardsuit"
|
||||
@@ -265,7 +257,6 @@
|
||||
to_chat(usr, "<font color='blue'><b>Primary system is now: [selected_module.interface_name].</b></font>")
|
||||
|
||||
/obj/item/weapon/rig/verb/toggle_module()
|
||||
|
||||
set name = "Toggle Module"
|
||||
set desc = "Toggle a system module."
|
||||
set category = "Hardsuit"
|
||||
@@ -307,7 +298,6 @@
|
||||
module.activate()
|
||||
|
||||
/obj/item/weapon/rig/verb/engage_module()
|
||||
|
||||
set name = "Engage Module"
|
||||
set desc = "Engages a system module."
|
||||
set category = "Hardsuit"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/datum/event/abductor
|
||||
|
||||
/datum/event/abductor/start()
|
||||
//spawn abductor team
|
||||
processing = 0 //so it won't fire again in next tick
|
||||
if(!makeAbductorTeam())
|
||||
message_admins("Abductor event failed to find players. Retrying in 30s.")
|
||||
spawn(300)
|
||||
makeAbductorTeam()
|
||||
|
||||
/datum/event/abductor/proc/makeAbductorTeam()
|
||||
var/list/mob/dead/observer/candidates = pollCandidates("Do you wish to be considered for an Abductor Team?", ROLE_ABDUCTOR, 1)
|
||||
|
||||
if(candidates.len >= 2)
|
||||
//Oh god why we can't have static functions
|
||||
var/number = ticker.mode.abductor_teams + 1
|
||||
|
||||
var/datum/game_mode/abduction/temp
|
||||
if(ticker.mode.config_tag == "abduction")
|
||||
temp = ticker.mode
|
||||
else
|
||||
temp = new
|
||||
|
||||
var/agent_mind = pick(candidates)
|
||||
candidates -= agent_mind
|
||||
var/scientist_mind = pick(candidates)
|
||||
|
||||
var/mob/living/carbon/human/agent=makeBody(agent_mind)
|
||||
var/mob/living/carbon/human/scientist=makeBody(scientist_mind)
|
||||
|
||||
agent_mind = agent.mind
|
||||
scientist_mind = scientist.mind
|
||||
|
||||
temp.scientists.len = number
|
||||
temp.agents.len = number
|
||||
temp.abductors.len = 2*number
|
||||
temp.team_objectives.len = number
|
||||
temp.team_names.len = number
|
||||
temp.scientists[number] = scientist_mind
|
||||
temp.agents[number] = agent_mind
|
||||
temp.abductors |= list(agent_mind,scientist_mind)
|
||||
temp.make_abductor_team(number,preset_scientist=scientist_mind,preset_agent=agent_mind)
|
||||
temp.post_setup_team(number)
|
||||
|
||||
ticker.mode.abductor_teams++
|
||||
|
||||
if(ticker.mode.config_tag != "abduction")
|
||||
ticker.mode.abductors |= temp.abductors
|
||||
processing = 1 //So it will get gc'd
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
@@ -48,6 +48,7 @@
|
||||
return 0*/
|
||||
|
||||
/datum/event //NOTE: Times are measured in master controller ticks!
|
||||
var/processing = 1
|
||||
var/startWhen = 0 //When in the lifetime to call start().
|
||||
var/announceWhen = 0 //When in the lifetime to call announce().
|
||||
var/endWhen = 0 //When in the lifetime the event should end.
|
||||
@@ -105,6 +106,9 @@
|
||||
//Do not override this proc, instead use the appropiate procs.
|
||||
//This proc will handle the calls to the appropiate procs.
|
||||
/datum/event/proc/process()
|
||||
if(!processing)
|
||||
return
|
||||
|
||||
if(activeFor > startWhen && activeFor < endWhen || noAutoEnd)
|
||||
tick()
|
||||
|
||||
|
||||
@@ -178,10 +178,11 @@ var/list/event_last_fired = list()
|
||||
severity = EVENT_LEVEL_MAJOR
|
||||
available_events = list(
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Nothing", /datum/event/nothing, 1320),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 3), 1),
|
||||
//new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ANY = 5)),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 30), 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 3), 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Carp Migration", /datum/event/carp_migration, 0, list(ASSIGNMENT_SECURITY = 3), 1),
|
||||
//new /datum/event_meta(EVENT_LEVEL_MAJOR, "Containment Breach", /datum/event/prison_break/station, 0, list(ASSIGNMENT_ANY = 5)),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Blob", /datum/event/blob, 0, list(ASSIGNMENT_ENGINEER = 30), 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Meteor Wave", /datum/event/meteor_wave, 0, list(ASSIGNMENT_ENGINEER = 3), 1),
|
||||
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Abductor Visit", /datum/event/abductor, 80, is_one_shot = 1),
|
||||
new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 30), 1),
|
||||
)
|
||||
|
||||
|
||||
@@ -334,8 +334,7 @@
|
||||
var/turf/simulated/location = get_turf(M)
|
||||
if(istype(location)) location.add_blood_floor(M)
|
||||
if("fire")
|
||||
if (!(RESIST_COLD in M.mutations))
|
||||
M.take_organ_damage(0, force)
|
||||
M.take_organ_damage(0, force)
|
||||
M.updatehealth()
|
||||
|
||||
if(seed && seed.get_trait(TRAIT_CARNIVOROUS))
|
||||
|
||||
@@ -121,7 +121,7 @@ var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "A
|
||||
var/sqlid = text2num(id)
|
||||
if(!sqlid)
|
||||
return
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id, author, title, category, ckey, flagged FROM [format_table_name("library")] WHERE id=[sqlid]")
|
||||
var/DBQuery/query = dbcon.NewQuery("SELECT id, author, title, category, content, ckey, flagged FROM [format_table_name("library")] WHERE id=[sqlid]")
|
||||
query.Execute()
|
||||
|
||||
var/list/results=list()
|
||||
@@ -132,8 +132,9 @@ var/global/list/library_section_names = list("Any", "Fiction", "Non-Fiction", "A
|
||||
"author" =query.item[2],
|
||||
"title" =query.item[3],
|
||||
"category"=query.item[4],
|
||||
"ckey" =query.item[5],
|
||||
"flagged" =query.item[6]
|
||||
"content" =query.item[5],
|
||||
"ckey" =query.item[6],
|
||||
"flagged" =query.item[7]
|
||||
))
|
||||
results += CB
|
||||
cached_books["[id]"]=CB
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
/**********************Mineral deposits**************************/
|
||||
|
||||
var/global/list/rockTurfEdgeCache
|
||||
#define NORTH_EDGING "north"
|
||||
#define SOUTH_EDGING "south"
|
||||
#define EAST_EDGING "east"
|
||||
#define WEST_EDGING "west"
|
||||
|
||||
var/global/list/rockTurfEdgeCache = list(
|
||||
NORTH_EDGING = image('icons/turf/mining.dmi', "rock_side_n", layer = 6),
|
||||
SOUTH_EDGING = image('icons/turf/mining.dmi', "rock_side_s"),
|
||||
EAST_EDGING = image('icons/turf/mining.dmi', "rock_side_e", layer = 6),
|
||||
WEST_EDGING = image('icons/turf/mining.dmi', "rock_side_w", layer = 6))
|
||||
|
||||
/turf/simulated/mineral //wall piece
|
||||
name = "Rock"
|
||||
icon = 'icons/turf/mining.dmi'
|
||||
@@ -50,32 +55,8 @@ var/global/list/rockTurfEdgeCache
|
||||
return
|
||||
|
||||
/turf/simulated/mineral/New()
|
||||
if(!rockTurfEdgeCache || !rockTurfEdgeCache.len)
|
||||
rockTurfEdgeCache = list()
|
||||
rockTurfEdgeCache.len = 4
|
||||
rockTurfEdgeCache[NORTH_EDGING] = image('icons/turf/mining.dmi', "rock_side_n", layer = 6)
|
||||
rockTurfEdgeCache[SOUTH_EDGING] = image('icons/turf/mining.dmi', "rock_side_s")
|
||||
rockTurfEdgeCache[EAST_EDGING] = image('icons/turf/mining.dmi', "rock_side_e", layer = 6)
|
||||
rockTurfEdgeCache[WEST_EDGING] = image('icons/turf/mining.dmi', "rock_side_w", layer = 6)
|
||||
|
||||
spawn(1)
|
||||
var/turf/T
|
||||
if((istype(get_step(src, NORTH), /turf/simulated/floor)) || (istype(get_step(src, NORTH), /turf/space)))
|
||||
T = get_step(src, NORTH)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[SOUTH_EDGING]
|
||||
if((istype(get_step(src, SOUTH), /turf/simulated/floor)) || (istype(get_step(src, SOUTH), /turf/space)))
|
||||
T = get_step(src, SOUTH)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[NORTH_EDGING]
|
||||
if((istype(get_step(src, EAST), /turf/simulated/floor)) || (istype(get_step(src, EAST), /turf/space)))
|
||||
T = get_step(src, EAST)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[WEST_EDGING]
|
||||
if((istype(get_step(src, WEST), /turf/simulated/floor)) || (istype(get_step(src, WEST), /turf/space)))
|
||||
T = get_step(src, WEST)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[EAST_EDGING]
|
||||
..()
|
||||
mineral_turfs += src
|
||||
|
||||
if (mineralType && mineralAmt && spread && spreadChance)
|
||||
for(var/dir in cardinal)
|
||||
@@ -85,7 +66,6 @@ var/global/list/rockTurfEdgeCache
|
||||
Spread(T)
|
||||
|
||||
HideRock()
|
||||
return
|
||||
|
||||
/turf/simulated/mineral/proc/HideRock()
|
||||
if(hidden)
|
||||
@@ -96,6 +76,33 @@ var/global/list/rockTurfEdgeCache
|
||||
/turf/simulated/mineral/proc/Spread(var/turf/T)
|
||||
new src.type(T)
|
||||
|
||||
/hook/startup/proc/add_mineral_edges()
|
||||
var/watch = start_watch()
|
||||
log_startup_progress("Reticulating splines...")
|
||||
for(var/turf/simulated/mineral/M in mineral_turfs)
|
||||
M.add_edges()
|
||||
log_startup_progress(" Splines reticulated in [stop_watch(watch)]s.")
|
||||
return 1
|
||||
|
||||
/turf/simulated/mineral/proc/add_edges()
|
||||
var/turf/T
|
||||
if((istype(get_step(src, NORTH), /turf/simulated/floor)) || (istype(get_step(src, NORTH), /turf/space)))
|
||||
T = get_step(src, NORTH)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[SOUTH_EDGING]
|
||||
if((istype(get_step(src, SOUTH), /turf/simulated/floor)) || (istype(get_step(src, SOUTH), /turf/space)))
|
||||
T = get_step(src, SOUTH)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[NORTH_EDGING]
|
||||
if((istype(get_step(src, EAST), /turf/simulated/floor)) || (istype(get_step(src, EAST), /turf/space)))
|
||||
T = get_step(src, EAST)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[WEST_EDGING]
|
||||
if((istype(get_step(src, WEST), /turf/simulated/floor)) || (istype(get_step(src, WEST), /turf/space)))
|
||||
T = get_step(src, WEST)
|
||||
if (T)
|
||||
T.overlays += rockTurfEdgeCache[EAST_EDGING]
|
||||
|
||||
/turf/simulated/mineral/random
|
||||
name = "mineral deposit"
|
||||
icon_state = "rock"
|
||||
|
||||
@@ -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, "<span class='ghostalert'>[message]</span>")
|
||||
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, "<span class='ghostalert'><a href=?src=\ref[src];reenter=1>(Click to re-enter)</a></span>")
|
||||
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
|
||||
|
||||
|
||||
@@ -107,10 +107,10 @@
|
||||
to_chat(player, msg_dead)
|
||||
continue
|
||||
|
||||
else if(istype(player,/mob/dead) || ((src in player.languages) && check_special_condition(player)))
|
||||
else if(istype(player,/mob/dead) || ((src in player.languages) && check_special_condition(player, speaker)))
|
||||
to_chat(player, msg)
|
||||
|
||||
/datum/language/proc/check_special_condition(var/mob/other)
|
||||
/datum/language/proc/check_special_condition(var/mob/other, var/mob/living/speaker)
|
||||
return 1
|
||||
|
||||
/datum/language/proc/get_spoken_verb(var/msg_end)
|
||||
@@ -409,6 +409,7 @@
|
||||
key = "8"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
|
||||
|
||||
/datum/language/shadowling/broadcast(var/mob/living/speaker, var/message, var/speaker_mask)
|
||||
if(speaker.mind && speaker.mind.special_role)
|
||||
..(speaker, message, "([speaker.mind.special_role]) [speaker]")
|
||||
@@ -422,6 +423,25 @@
|
||||
else
|
||||
..(speaker,message)
|
||||
|
||||
/datum/language/abductor
|
||||
name = "Abductor Mindlink"
|
||||
desc = "Abductors are incapable of speech, but have a psychic link attuned to their own team."
|
||||
speech_verb = "gibbers"
|
||||
ask_verb = "gibbers"
|
||||
exclaim_verb = "gibbers"
|
||||
colour = "abductor"
|
||||
key = "zw" //doesn't matter, this is their default and only language
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
|
||||
/datum/language/abductor/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
|
||||
..(speaker,message,speaker.real_name)
|
||||
|
||||
/datum/language/abductor/check_special_condition(var/mob/living/carbon/human/other, var/mob/living/carbon/human/speaker)
|
||||
if(other.mind && other.mind.abductor)
|
||||
if(other.mind.abductor.team == speaker.mind.abductor.team)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/language/corticalborer
|
||||
name = "Cortical Link"
|
||||
desc = "Cortical borers possess a strange link between their tiny minds."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, "<span class='danger'>You feel a searing heat in your lungs!</span>")
|
||||
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
|
||||
|
||||
@@ -47,8 +47,6 @@
|
||||
for(var/mob/dead/observer/O in player_list)
|
||||
if(check_observer(O))
|
||||
to_chat(O, "<span class='boldnotice'>\A [src] has been activated. (<a href='?src=\ref[O];jump=\ref[src]'>Teleport</a> | <a href='?src=\ref[src];signup=\ref[O]'>Sign Up</a>)</span>")
|
||||
// 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)
|
||||
|
||||
@@ -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,131 @@ 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("<span class='warning'>[src] attempts to unbuckle themself!</span>", \
|
||||
"<span class='notice'>You attempt to unbuckle yourself... (This will take around one minute and you need to stay still.)</span>")
|
||||
if(do_after(src, 600, 0, target = src))
|
||||
if(!buckled)
|
||||
return
|
||||
buckled.user_unbuckle_mob(src,src)
|
||||
else
|
||||
if(src && buckled)
|
||||
src << "<span class='warning'>You fail to unbuckle yourself!</span>"
|
||||
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("<span class='danger'>[src] rolls on the floor, trying to put themselves out!</span>", \
|
||||
"<span class='notice'>You stop, drop, and roll!</span>")
|
||||
sleep(30)
|
||||
if(fire_stacks <= 0)
|
||||
visible_message("<span class='danger'>[src] has successfully extinguished themselves!</span>", \
|
||||
"<span class='notice'>You extinguish yourself.</span>")
|
||||
ExtinguishMob()
|
||||
|
||||
|
||||
/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("<span class='warning'>[src] attempts to remove [I]!</span>")
|
||||
to_chat(src, "<span class='notice'>You attempt to remove [I]... (This will take around [displaytime] minutes and you need to stand still.)</span>")
|
||||
if(do_after(src, breakouttime, 0, target = src))
|
||||
if(I.loc != src || buckled)
|
||||
return
|
||||
visible_message("<span class='danger'>[src] manages to remove [I]!</span>")
|
||||
to_chat(src, "<span class='notice'>You successfully remove [I].</span>")
|
||||
|
||||
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, "<span class='warning'>You fail to remove [I]!</span>")
|
||||
|
||||
else
|
||||
breakouttime = 50
|
||||
visible_message("<span class='warning'>[src] is trying to break [I]!</span>")
|
||||
to_chat(src, "<span class='notice'>You attempt to break [I]... (This will take around 5 seconds and you need to stand still.)</span>")
|
||||
if(do_after(src, breakouttime, 0, target = src))
|
||||
if(!I.loc || buckled)
|
||||
return
|
||||
visible_message("<span class='danger'>[src] manages to break [I]!</span>")
|
||||
to_chat(src, "<span class='notice'>You successfully break [I].</span>")
|
||||
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, "<span class='warning'>You fail to break [I]!</span>")
|
||||
|
||||
//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 +890,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)
|
||||
|
||||
@@ -114,6 +114,9 @@
|
||||
/mob/living/carbon/human/grey/New(var/new_loc)
|
||||
..(new_loc, "Grey")
|
||||
|
||||
/mob/living/carbon/human/abductor/New(var/new_loc)
|
||||
..(new_loc, "Abductor")
|
||||
|
||||
/mob/living/carbon/human/human/New(var/new_loc)
|
||||
..(new_loc, "Human")
|
||||
|
||||
@@ -690,6 +693,8 @@
|
||||
|
||||
//repurposed proc. Now it combines get_id_name() and get_face_name() to determine a mob's name variable. Made into a seperate proc as it'll be useful elsewhere
|
||||
/mob/living/carbon/human/get_visible_name()
|
||||
if(name_override)
|
||||
return name_override
|
||||
if(wear_mask && (wear_mask.flags_inv & HIDEFACE)) //Wearing a mask which hides our face, use id-name if possible
|
||||
return get_id_name("Unknown")
|
||||
if(head && (head.flags_inv & HIDEFACE))
|
||||
@@ -1350,6 +1355,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()
|
||||
|
||||
@@ -81,6 +81,8 @@ var/global/default_martial_art = new/datum/martial_art
|
||||
|
||||
var/hand_blood_color
|
||||
|
||||
var/name_override //For temporary visible name changes
|
||||
|
||||
var/xylophone = 0 //For the spoooooooky xylophone cooldown
|
||||
|
||||
var/mob/remoteview_target = null
|
||||
|
||||
@@ -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!
|
||||
@@ -447,28 +448,32 @@
|
||||
if(status_flags & GODMODE) return 1 //godmode
|
||||
|
||||
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
|
||||
if(!(RESIST_HEAT in mutations))
|
||||
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")
|
||||
throw_alert("pressure", /obj/screen/alert/highpressure, 2)
|
||||
else
|
||||
clear_alert("pressure")
|
||||
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()
|
||||
if(..())
|
||||
return
|
||||
if(RESIST_HEAT in mutations)
|
||||
return
|
||||
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
|
||||
if(wear_suit)
|
||||
if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)
|
||||
@@ -547,11 +552,13 @@
|
||||
return thermal_protection_flags
|
||||
|
||||
/mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
|
||||
|
||||
if(RESIST_HEAT in mutations)
|
||||
return 1
|
||||
|
||||
var/thermal_protection_flags = get_heat_protection_flags(temperature)
|
||||
|
||||
var/thermal_protection = 0.0
|
||||
if(RESIST_HEAT in mutations)
|
||||
return 1
|
||||
if(thermal_protection_flags)
|
||||
if(thermal_protection_flags & HEAD)
|
||||
thermal_protection += THERMAL_PROTECTION_HEAD
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/datum/species/abductor
|
||||
name = "Abductor"
|
||||
name_plural = "Abductors"
|
||||
icobase = 'icons/mob/human_races/r_abductor.dmi'
|
||||
deform = 'icons/mob/human_races/r_abductor.dmi'
|
||||
path = /mob/living/carbon/human/abductor
|
||||
language = "Abductor Mindlink"
|
||||
default_language = "Abductor Mindlink"
|
||||
unarmed_type = /datum/unarmed_attack/punch
|
||||
darksight = 3
|
||||
eyes = "blank_eyes"
|
||||
|
||||
flags = HAS_LIPS | NO_BLOOD | NO_BREATHE
|
||||
virus_immune = 1
|
||||
clothing_flags = HAS_UNDERWEAR | HAS_UNDERSHIRT | HAS_SOCKS
|
||||
dietflags = DIET_OMNI
|
||||
reagent_tag = PROCESS_ORG
|
||||
blood_color = "#FF5AFF"
|
||||
|
||||
/datum/species/abductor/can_understand(var/mob/other) //Abductors can understand everyone, but they can only speak over their mindlink to another team-member
|
||||
return 1
|
||||
|
||||
/datum/species/abductor/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
H.gender = NEUTER
|
||||
if(H.mind)
|
||||
H.mind.abductor = new /datum/abductor
|
||||
return ..()
|
||||
@@ -186,7 +186,7 @@
|
||||
H.emote(pick("giggle", "laugh"))
|
||||
SA.moles = 0
|
||||
|
||||
if( (abs(310.15 - breath.temperature) > 50) && !(RESIST_HEAT in H.mutations)) // Hot air hurts :(
|
||||
if(abs(310.15 - breath.temperature) > 50) // Hot air hurts :(
|
||||
if(H.status_flags & GODMODE)
|
||||
return 1 //godmode
|
||||
if(breath.temperature < cold_level_1)
|
||||
|
||||
@@ -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" = 0,
|
||||
"min_nitro" = 0,
|
||||
"max_nitro" = 0,
|
||||
"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,77 +301,67 @@
|
||||
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")
|
||||
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
|
||||
if( (abs(310.15 - breath.temperature) > 50) && !(RESIST_HEAT in H.mutations)) // Hot air hurts :(
|
||||
if(abs(310.15 - breath.temperature) > 50) // Hot air hurts :(
|
||||
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, "<span class='warning'>You feel your face freezing and an icicle forming in your lungs!</span>")
|
||||
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, "<span class='warning'>You feel your face burning and a searing heat in your lungs!</span>")
|
||||
|
||||
|
||||
|
||||
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 +570,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 +595,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 +645,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
|
||||
|
||||
/*
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -104,41 +104,6 @@ If you have any questions/constructive-comments/bugs-to-report/or have a massivl
|
||||
Please contact me on #coderbus IRC. ~Carn x
|
||||
*/
|
||||
|
||||
//Human Overlays Indexes/////////
|
||||
#define MUTANTRACE_LAYER 1
|
||||
#define TAIL_UNDERLIMBS_LAYER 2
|
||||
#define LIMBS_LAYER 3
|
||||
#define MARKINGS_LAYER 4
|
||||
#define UNDERWEAR_LAYER 5
|
||||
#define MUTATIONS_LAYER 6
|
||||
#define DAMAGE_LAYER 7
|
||||
#define UNIFORM_LAYER 8
|
||||
#define ID_LAYER 9
|
||||
#define SHOES_LAYER 10
|
||||
#define GLOVES_LAYER 11
|
||||
#define EARS_LAYER 12
|
||||
#define SUIT_LAYER 13
|
||||
#define GLASSES_LAYER 14
|
||||
#define BELT_LAYER 15 //Possible make this an overlay of somethign required to wear a belt?
|
||||
#define SUIT_STORE_LAYER 16
|
||||
#define BACK_LAYER 17
|
||||
#define TAIL_LAYER 18 //bs12 specific. this hack is probably gonna come back to haunt me
|
||||
#define HAIR_LAYER 19 //TODO: make part of head layer?
|
||||
#define HEAD_ACCESSORY_LAYER 20
|
||||
#define FHAIR_LAYER 21
|
||||
#define FACEMASK_LAYER 22
|
||||
#define HEAD_LAYER 23
|
||||
#define COLLAR_LAYER 24
|
||||
#define HANDCUFF_LAYER 25
|
||||
#define LEGCUFF_LAYER 26
|
||||
#define L_HAND_LAYER 27
|
||||
#define R_HAND_LAYER 28
|
||||
#define TARGETED_LAYER 29 //BS12: Layer for the target overlay from weapon targeting system
|
||||
#define FIRE_LAYER 30 //If you're on fire
|
||||
#define TOTAL_LAYERS 30
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human
|
||||
var/list/overlays_standing[TOTAL_LAYERS]
|
||||
var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed
|
||||
@@ -163,18 +128,26 @@ Please contact me on #coderbus IRC. ~Carn x
|
||||
update_hud() //TODO: remove the need for this
|
||||
|
||||
var/stealth = 0
|
||||
for(var/obj/item/weapon/cloaking_device/S in list(l_hand,r_hand,belt,l_store,r_store))
|
||||
if(S.active)
|
||||
var/obj/item/clothing/suit/armor/abductor/vest/V // Begin the most snowflakey bullshit code I've ever written. I'm so sorry, but there was no other way.
|
||||
for(V in list(wear_suit))
|
||||
if(V.stealth_active)
|
||||
stealth = 1
|
||||
break
|
||||
|
||||
if(stealth)
|
||||
icon = 'icons/mob/human.dmi'
|
||||
icon_state = "body_cloaked"
|
||||
var/image/I = overlays_standing[L_HAND_LAYER]
|
||||
if(istype(I)) overlays += I
|
||||
I = overlays_standing[R_HAND_LAYER]
|
||||
if(istype(I)) overlays += I
|
||||
icon = V.disguise.icon //if the suit is active, reference the suit's current loaded icon and overlays; this does not include hand overlays
|
||||
overlays.Cut()
|
||||
|
||||
for(var/thing in V.disguise.overlays)
|
||||
if(thing)
|
||||
overlays += thing
|
||||
|
||||
var/image/I = overlays_standing[L_HAND_LAYER] //manually add both left and right hand, so its independently updated
|
||||
if(istype(I))
|
||||
overlays += I
|
||||
I = overlays_standing[R_HAND_LAYER]
|
||||
if(istype(I))
|
||||
overlays += I
|
||||
else
|
||||
icon = stand_icon
|
||||
overlays.Cut()
|
||||
@@ -533,23 +506,6 @@ var/global/list/damage_icon_parts = list()
|
||||
add_image = 1
|
||||
for(var/mut in mutations)
|
||||
switch(mut)
|
||||
/*
|
||||
if(HULK)
|
||||
if(fat)
|
||||
standing.underlays += "hulk_[fat]_s"
|
||||
else
|
||||
standing.underlays += "hulk_[g]_s"
|
||||
add_image = 1
|
||||
if(RESIST_COLD)
|
||||
standing.underlays += "fire[fat]_s"
|
||||
add_image = 1
|
||||
if(RESIST_HEAT)
|
||||
standing.underlays += "cold[fat]_s"
|
||||
add_image = 1
|
||||
if(TK)
|
||||
standing.underlays += "telekinesishead[fat]_s"
|
||||
add_image = 1
|
||||
*/
|
||||
if(LASER)
|
||||
standing.overlays += "lasereyes_s"
|
||||
add_image = 1
|
||||
@@ -989,16 +945,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)
|
||||
@@ -1237,34 +1196,11 @@ var/global/list/damage_icon_parts = list()
|
||||
O.sync_colour_to_human(src)
|
||||
update_body(0)
|
||||
|
||||
//Human Overlays Indexes/////////
|
||||
#undef MUTANTRACE_LAYER
|
||||
#undef TAIL_UNDERLIMBS_LAYER
|
||||
#undef LIMBS_LAYER
|
||||
#undef MARKINGS_LAYER
|
||||
#undef MUTATIONS_LAYER
|
||||
#undef DAMAGE_LAYER
|
||||
#undef UNIFORM_LAYER
|
||||
#undef ID_LAYER
|
||||
#undef SHOES_LAYER
|
||||
#undef GLOVES_LAYER
|
||||
#undef EARS_LAYER
|
||||
#undef SUIT_LAYER
|
||||
#undef GLASSES_LAYER
|
||||
#undef FACEMASK_LAYER
|
||||
#undef BELT_LAYER
|
||||
#undef SUIT_STORE_LAYER
|
||||
#undef BACK_LAYER
|
||||
#undef TAIL_LAYER
|
||||
#undef HAIR_LAYER
|
||||
#undef HEAD_LAYER
|
||||
#undef HEAD_ACCESSORY_LAYER
|
||||
#undef FHAIR_LAYER
|
||||
#undef COLLAR_LAYER
|
||||
#undef HANDCUFF_LAYER
|
||||
#undef LEGCUFF_LAYER
|
||||
#undef L_HAND_LAYER
|
||||
#undef R_HAND_LAYER
|
||||
#undef TARGETED_LAYER
|
||||
#undef FIRE_LAYER
|
||||
#undef TOTAL_LAYERS
|
||||
/mob/living/carbon/human/proc/get_overlays_copy(list/unwantedLayers)
|
||||
var/list/out = new
|
||||
for(var/i=1;i<=TOTAL_LAYERS;i++)
|
||||
if(overlays_standing[i])
|
||||
if(i in unwantedLayers)
|
||||
continue
|
||||
out += overlays_standing[i]
|
||||
return out
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
if(BRUTE)
|
||||
adjustBruteLoss(damage * blocked)
|
||||
if(BURN)
|
||||
if(RESIST_HEAT in mutations) damage = 0
|
||||
adjustFireLoss(damage * blocked)
|
||||
if(TOX)
|
||||
adjustToxLoss(damage * blocked)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -92,9 +92,6 @@
|
||||
//sort of a legacy burn method for /electrocute, /shock, and the e_chair
|
||||
/mob/living/proc/burn_skin(burn_amount)
|
||||
if(istype(src, /mob/living/carbon/human))
|
||||
// to_chat(world, "DEBUG: burn_skin(), mutations=[mutations]")
|
||||
if (RESIST_HEAT in src.mutations) //fireproof
|
||||
return 0
|
||||
var/mob/living/carbon/human/H = src //make this damage method divide the damage to be done among all the body parts, then burn each body part for that much damage. will have better effect then just randomly picking a body part
|
||||
var/divided_damage = (burn_amount)/(H.organs.len)
|
||||
var/extradam = 0 //added to when organ is at max dam
|
||||
@@ -522,262 +519,74 @@
|
||||
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 <B>You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).</B>")
|
||||
to_chat(B.host, "\red <B>You feel the captive mind of [src] begin to resist your control.</B>")
|
||||
|
||||
spawn(rand(350,450)+B.host.brainloss)
|
||||
|
||||
if(!B || !B.controlling)
|
||||
return
|
||||
|
||||
B.host.adjustBrainLoss(rand(5,10))
|
||||
to_chat(H, "\red <B>With an immense exertion of will, you regain control of your body!</B>")
|
||||
to_chat(B.host, "\red <B>You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.</b>")
|
||||
|
||||
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)
|
||||
qdel(G)
|
||||
switch(G.state)
|
||||
if(GRAB_PASSIVE)
|
||||
qdel(G)
|
||||
|
||||
else
|
||||
if(G.state == 2)
|
||||
if(GRAB_AGGRESSIVE)
|
||||
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)
|
||||
visible_message("<span class='danger'>[src] has broken free of [G.assailant]'s grip!</span>")
|
||||
qdel(G)
|
||||
|
||||
else
|
||||
if(G.state == 3)
|
||||
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)
|
||||
qdel(G)
|
||||
if(GRAB_NECK)
|
||||
if(prob(5))
|
||||
visible_message("<span class='danger'>[src] has broken free of [G.assailant]'s headlock!</span>")
|
||||
qdel(G)
|
||||
|
||||
if(resisting)
|
||||
for(var/mob/O in viewers(usr, null))
|
||||
O.show_message(text("\red <B>[] resists!</B>", L), 1)
|
||||
visible_message("<span class='danger'>[src] resists!</span>")
|
||||
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)</span>")
|
||||
for(var/mob/O in viewers(L))
|
||||
O.show_message("\red <B>[usr] attempts to unbuckle themself!</B>", 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 <B>[usr] manages to unbuckle themself!</B>", 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("<span class='danger'>[CM] rolls on the floor, trying to put themselves out!</span>", \
|
||||
"<span class='notice'>You stop, drop, and roll!</span>")
|
||||
sleep(30)
|
||||
if(fire_stacks <= 0)
|
||||
CM.visible_message("<span class='danger'>[CM] has successfully extinguished themselves!</span>", \
|
||||
"<span class='notice'>You extinguish yourself.</span>")
|
||||
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 <B>[usr] attempts to [hulklien ? "break" : "remove"] \the [HC]!</B>", 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 <B>[CM] manages to [hulklien ? "break" : "remove"] the handcuffs!</B>", 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 <B>[usr] attempts to [hulklien ? "break" : "remove"] \the [HC]!</B>", 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 <B>[CM] manages to [hulklien ? "break" : "remove"] the legcuffs!</B>", 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, "<span class='notice'>You're too exhausted to keep going...</span>")
|
||||
Weaken(5)
|
||||
@@ -788,6 +597,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)
|
||||
|
||||
@@ -39,14 +39,6 @@
|
||||
|
||||
|
||||
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone)
|
||||
//Being hit while using a cloaking device
|
||||
var/obj/item/weapon/cloaking_device/C = locate((/obj/item/weapon/cloaking_device) in src)
|
||||
if(C && C.active)
|
||||
C.attack_self(src)//Should shut it off
|
||||
update_icons()
|
||||
to_chat(src, "\blue Your [C.name] was disrupted!")
|
||||
Stun(2)
|
||||
|
||||
//Armor
|
||||
var/armor = run_armor_check(def_zone, P.flag, armour_penetration = P.armour_penetration)
|
||||
var/proj_sharp = is_sharp(P)
|
||||
@@ -173,6 +165,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 +173,7 @@
|
||||
on_fire = 0
|
||||
fire_stacks = 0
|
||||
set_light(max(0,light_range - 3))
|
||||
clear_alert("fire")
|
||||
update_fire()
|
||||
|
||||
/mob/living/proc/update_fire()
|
||||
|
||||
@@ -334,6 +334,10 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
|
||||
whisper_say(message, speaking)
|
||||
|
||||
// for weird circumstances where you're inside an atom that is also you, like pai's
|
||||
/mob/living/proc/get_whisper_loc()
|
||||
return src
|
||||
|
||||
/mob/living/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/verb="whispers")
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
@@ -382,7 +386,8 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
if(!message || message=="")
|
||||
return
|
||||
|
||||
var/list/listening = hearers(message_range, src)
|
||||
var/atom/whisper_loc = get_whisper_loc()
|
||||
var/list/listening = hearers(message_range, whisper_loc)
|
||||
listening |= src
|
||||
|
||||
//ghosts
|
||||
@@ -399,16 +404,16 @@ proc/get_radio_key_from_channel(var/channel)
|
||||
listening += C
|
||||
|
||||
//pass on the message to objects that can hear us.
|
||||
for(var/obj/O in view(message_range, src))
|
||||
for(var/obj/O in view(message_range, whisper_loc))
|
||||
spawn(0)
|
||||
if(O)
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
|
||||
var/list/eavesdropping = hearers(eavesdropping_range, src)
|
||||
var/list/eavesdropping = hearers(eavesdropping_range, whisper_loc)
|
||||
eavesdropping -= src
|
||||
eavesdropping -= listening
|
||||
|
||||
var/list/watching = hearers(watching_range, src)
|
||||
var/list/watching = hearers(watching_range, whisper_loc)
|
||||
watching -= src
|
||||
watching -= listening
|
||||
watching -= eavesdropping
|
||||
|
||||
@@ -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, "<span class='warning'>Internal camera is currently being accessed.</span>")
|
||||
|
||||
/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)
|
||||
|
||||
@@ -2,4 +2,12 @@
|
||||
if(silence_time)
|
||||
to_chat(src, "<font color=green>Communication circuits remain uninitialized.</font>")
|
||||
else
|
||||
..(msg)
|
||||
..(msg)
|
||||
|
||||
/mob/living/silicon/pai/get_whisper_loc()
|
||||
if(loc == card) // currently in its card?
|
||||
if(istype(card.loc, /mob/living))
|
||||
return card.loc // allow a pai being held or in pocket to whisper
|
||||
else
|
||||
return card // allow a pai in its card to whisper
|
||||
return ..()
|
||||
@@ -38,10 +38,9 @@
|
||||
set desc = "Activate a low power omnidirectional LED. Toggled on or off."
|
||||
set category = "Drone"
|
||||
|
||||
if(luminosity)
|
||||
set_light(0)
|
||||
return
|
||||
set_light(2)
|
||||
if(lamp_intensity)
|
||||
lamp_intensity = lamp_max // setting this to lamp_max will make control_headlamp shutoff the lamp
|
||||
control_headlamp()
|
||||
|
||||
//Actual picking-up event.
|
||||
/mob/living/silicon/robot/drone/attack_hand(mob/living/carbon/human/M as mob)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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, "<b>Obey these laws:</b>")
|
||||
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()
|
||||
|
||||
|
||||
@@ -30,7 +30,10 @@
|
||||
/mob/living/silicon/pai/handle_message_mode(message_mode, message, verb, speaking, used_radios, alt_name)
|
||||
if(..())
|
||||
return 1
|
||||
if(message_mode)
|
||||
else if(message_mode == "whisper")
|
||||
whisper_say(message, speaking, alt_name)
|
||||
return 1
|
||||
else if(message_mode)
|
||||
if(message_mode == "general")
|
||||
message_mode = null
|
||||
return radio.talk_into(src,message,message_mode,verb,speaking)
|
||||
|
||||
@@ -84,6 +84,20 @@
|
||||
|
||||
hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD) //Diagnostic HUD views
|
||||
|
||||
/obj/item/device/radio/headset/bot
|
||||
subspace_transmission = 1
|
||||
canhear_range = 0
|
||||
|
||||
/obj/item/device/radio/headset/bot/recalculateChannels()
|
||||
var/mob/living/simple_animal/bot/B = loc
|
||||
if(istype(B))
|
||||
if(!B.radio_config)
|
||||
B.radio_config = list("AI Private" = 1)
|
||||
if(!(B.radio_channel in B.radio_config)) // put it first so it's the :h channel
|
||||
B.radio_config.Insert(1, "[B.radio_channel]")
|
||||
B.radio_config["[B.radio_channel]"] = 1
|
||||
config(B.radio_config)
|
||||
|
||||
/mob/living/simple_animal/bot/proc/get_mode()
|
||||
if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player.
|
||||
if(paicard)
|
||||
@@ -123,15 +137,7 @@
|
||||
//This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first.
|
||||
access_card.access += access_robotics
|
||||
set_custom_texts()
|
||||
Radio = new/obj/item/device/radio/headset(src)
|
||||
Radio.subspace_transmission = 1
|
||||
Radio.canhear_range = 0 // anything greater will have the bot broadcast the channel as if it were saying it out loud.
|
||||
if(!radio_config)
|
||||
radio_config = list("AI Private" = 1)
|
||||
if(!(radio_channel in radio_config)) // put it first so it's the :h channel
|
||||
radio_config.Insert(1, "[radio_channel]")
|
||||
radio_config["[radio_channel]"] = 1
|
||||
Radio.config(radio_config)
|
||||
Radio = new/obj/item/device/radio/headset/bot(src)
|
||||
|
||||
add_language("Galactic Common", 1)
|
||||
add_language("Sol Common", 1)
|
||||
@@ -1000,15 +1006,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"
|
||||
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)
|
||||
@@ -38,6 +38,7 @@
|
||||
var/arrest_type = 0 //If true, don't handcuff
|
||||
var/projectile = /obj/item/projectile/energy/electrode //Holder for projectile type
|
||||
var/shoot_sound = 'sound/weapons/Taser.ogg'
|
||||
allow_pai = 0
|
||||
|
||||
|
||||
/mob/living/simple_animal/bot/ed209/New(loc,created_name,created_lasercolor)
|
||||
@@ -565,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()
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
var/harmbaton = 0 //If true, beat instead of stun
|
||||
var/flashing_lights = 0 //If true, flash lights
|
||||
var/prev_flashing_lights = 0
|
||||
allow_pai = 0
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky
|
||||
name = "Officer Beepsky"
|
||||
@@ -40,7 +41,6 @@
|
||||
idcheck = 0
|
||||
weaponscheck = 0
|
||||
auto_patrol = 1
|
||||
allow_pai = 0
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/beepsky/explode()
|
||||
var/turf/Tsec = get_turf(src)
|
||||
@@ -54,7 +54,6 @@
|
||||
name = "Officer Pingsky"
|
||||
desc = "It's Officer Pingsky! Delegated to satellite guard duty for harbouring anti-human sentiment."
|
||||
radio_channel = "AI Private"
|
||||
allow_pai = 0
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/ofitser
|
||||
name = "Prison Ofitser"
|
||||
@@ -62,7 +61,6 @@
|
||||
idcheck = 0
|
||||
weaponscheck = 1
|
||||
auto_patrol = 1
|
||||
allow_pai = 0
|
||||
|
||||
/mob/living/simple_animal/bot/secbot/buzzsky
|
||||
name = "Officer Buzzsky"
|
||||
@@ -229,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()
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/Life()
|
||||
. = ..()
|
||||
if(ranged)
|
||||
ranged_cooldown--
|
||||
if(!.)
|
||||
walk(src, 0)
|
||||
return 0
|
||||
@@ -46,8 +48,6 @@
|
||||
/mob/living/simple_animal/hostile/handle_automated_action()
|
||||
if(AIStatus == AI_OFF)
|
||||
return 0
|
||||
if(ranged)
|
||||
ranged_cooldown--
|
||||
var/list/possible_targets = ListTargets() //we look around for potential targets and make it a list for later use.
|
||||
if(environment_smash)
|
||||
EscapeConfinement()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -556,12 +556,28 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
|
||||
lname = "<span class='name'>[lname]</span> "
|
||||
to_chat(M, "<span class='deadsay'>[lname][follow][message]</span>")
|
||||
|
||||
/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, "<span class='ghostalert'>[message]<span>")
|
||||
to_chat(O, "<span class='ghostalert'>[message][(enter_link) ? " [enter_link]" : ""]<span>")
|
||||
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))
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
frequency.post_signal(src, signal, filter = s_filter)
|
||||
|
||||
/obj/item/radio/integrated/receive_signal(datum/signal/signal)
|
||||
if (signal.data["type"] == bot_type)
|
||||
if (bot_type && istype(signal.source, /obj/machinery/bot_core) && signal.data["type"] == bot_type)
|
||||
if(!botlist)
|
||||
botlist = new()
|
||||
|
||||
|
||||
@@ -337,7 +337,6 @@
|
||||
continue
|
||||
M.show_message("[user.name] smashed the light!", 3, "You hear a tinkle of breaking glass", 2)
|
||||
if(on && (W.flags & CONDUCT))
|
||||
//if(!user.mutations & RESIST_COLD)
|
||||
if (prob(12))
|
||||
electrocute_mob(user, get_area(src), src, 0.3)
|
||||
broken()
|
||||
@@ -374,7 +373,6 @@
|
||||
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
//if(!user.mutations & RESIST_COLD)
|
||||
if (prob(75))
|
||||
electrocute_mob(user, get_area(src), src, rand(0.7,1.0))
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
name = "glass"
|
||||
desc = "Your standard drinking glass."
|
||||
icon_state = "glass_empty"
|
||||
item_state = "drinking_glass"
|
||||
amount_per_transfer_from_this = 10
|
||||
volume = 50
|
||||
lefthand_file = 'icons/goonstation/mob/inhands/items_lefthand.dmi'
|
||||
righthand_file = 'icons/goonstation/mob/inhands/items_righthand.dmi'
|
||||
materials = list(MAT_GLASS=500)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass
|
||||
name = "shot glass"
|
||||
desc = "No glasses were shot in the making of this glass."
|
||||
icon_state = "shotglass"
|
||||
amount_per_transfer_from_this = 15
|
||||
volume = 15
|
||||
materials = list(MAT_GLASS=100)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change()
|
||||
overlays.Cut()
|
||||
|
||||
if(reagents.total_volume)
|
||||
var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]1")
|
||||
switch(reagents.total_volume)
|
||||
if(0 to 4) filling.icon_state = "[icon_state]1"
|
||||
if(5 to 11) filling.icon_state = "[icon_state]5"
|
||||
if(12 to INFINITY) filling.icon_state = "[icon_state]12"
|
||||
|
||||
filling.icon += mix_color_from_reagents(reagents.reagent_list)
|
||||
overlays += filling
|
||||
name = "shot glass of " + reagents.get_master_reagent_name() //No matter what, the glass will tell you the reagent's name. Might be too abusable in the future.
|
||||
else
|
||||
name = "shot glass"
|
||||
@@ -96,14 +96,12 @@
|
||||
return
|
||||
|
||||
|
||||
var/time = 30 //Injecting through a hardsuit takes longer due to needing to find a port.
|
||||
var/time = 30
|
||||
if(istype(target,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = T
|
||||
if(H.species.flags & NO_BLOOD)
|
||||
to_chat(usr, "<span class='warning'>You are unable to locate any blood.</span>")
|
||||
return
|
||||
if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space))
|
||||
time = 60
|
||||
if(target == user)
|
||||
time = 0
|
||||
else
|
||||
@@ -185,18 +183,10 @@
|
||||
return */
|
||||
|
||||
if(ismob(target) && target != user)
|
||||
var/time = 30 //Injecting through a hardsuit takes longer due to needing to find a port.
|
||||
if(istype(target,/mob/living/carbon/human))
|
||||
if(H.wear_suit && istype(H.wear_suit,/obj/item/clothing/suit/space))
|
||||
time = 60
|
||||
|
||||
for(var/mob/O in viewers(world.view, user))
|
||||
if(time == 30)
|
||||
O.show_message(text("\red <B>[] is trying to inject []!</B>", user, target), 1)
|
||||
else
|
||||
O.show_message(text("\red <B>[] begins hunting for an injection port on []'s suit!</B>", user, target), 1)
|
||||
O.show_message(text("\red <B>[] is trying to inject []!</B>", user, target), 1)
|
||||
|
||||
if(!do_mob(user, target, time)) return
|
||||
if(!do_mob(user, target, 30)) return
|
||||
|
||||
for(var/mob/O in viewers(world.view, user))
|
||||
O.show_message(text("\red [] injects [] with the syringe!", user, target), 1)
|
||||
|
||||
@@ -230,4 +230,14 @@
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 15000, MAT_GLASS = 5000, MAT_SILVER = 2500) //hardcore
|
||||
build_path = /obj/item/weapon/storage/part_replacer/bluespace
|
||||
category = list("Stock Parts")
|
||||
|
||||
/datum/design/alienalloy
|
||||
name = "Alien Alloy"
|
||||
desc = "A sheet of reverse-engineered alien alloy."
|
||||
id = "alienalloy"
|
||||
req_tech = list("abductor" = 1, "materials" = 7, "plasmatech" = 2)
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 4000, MAT_PLASMA = 4000)
|
||||
build_path = /obj/item/stack/sheet/mineral/abductor
|
||||
category = list("Stock Parts")
|
||||
@@ -438,8 +438,9 @@ proc/CallMaterialName(ID)
|
||||
if( new_item.type == /obj/item/weapon/storage/backpack/holding )
|
||||
new_item.investigate_log("built by [key]","singulo")
|
||||
new_item.reliability = 100
|
||||
new_item.materials[MAT_METAL] /= coeff
|
||||
new_item.materials[MAT_GLASS] /= coeff
|
||||
if(!istype(new_item, /obj/item/stack/sheet)) // To avoid materials dupe glitches
|
||||
new_item.materials[MAT_METAL] /= coeff
|
||||
new_item.materials[MAT_GLASS] /= coeff
|
||||
if(O)
|
||||
var/obj/item/weapon/storage/lockbox/L = new/obj/item/weapon/storage/lockbox(linked_lathe.loc)
|
||||
new_item.loc = L
|
||||
@@ -706,6 +707,8 @@ proc/CallMaterialName(ID)
|
||||
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A>"
|
||||
dat += "<h3>Current Research Levels:</h3><BR><div class='statusDisplay'>"
|
||||
for(var/datum/tech/T in files.known_tech)
|
||||
if(T.level <= 0)
|
||||
continue
|
||||
dat += "[T.name]<BR>"
|
||||
dat += "* Level: [T.level]<BR>"
|
||||
dat += "* Summary: [T.desc]<HR>"
|
||||
@@ -733,6 +736,8 @@ proc/CallMaterialName(ID)
|
||||
dat += "<A href='?src=\ref[src];menu=1.2'>Return to Disk Operations</A><div class='statusDisplay'>"
|
||||
dat += "<h3>Load Technology to Disk:</h3><BR>"
|
||||
for(var/datum/tech/T in files.known_tech)
|
||||
if(T.level <= 0)
|
||||
continue
|
||||
dat += "[T.name] "
|
||||
dat += "<A href='?src=\ref[src];copy_tech=1;copy_tech_ID=[T.id]'>Copy to Disk</A><BR>"
|
||||
dat += "</div>"
|
||||
|
||||
@@ -117,7 +117,7 @@ research holder datum.
|
||||
if(DesignHasReqs(PD))
|
||||
AddDesign2Known(PD)
|
||||
for(var/datum/tech/T in known_tech)
|
||||
T = Clamp(T.level, 1, 20)
|
||||
T = Clamp(T.level, 0, 20)
|
||||
for(var/datum/design/D in known_designs)
|
||||
D.CalcReliability(known_tech)
|
||||
return
|
||||
@@ -242,6 +242,13 @@ datum/tech/syndicate
|
||||
max_level = 0 // Don't count towards maxed research, since it's illegal.
|
||||
rare = 4
|
||||
|
||||
/datum/tech/abductor
|
||||
name = "Alien Technologies Research"
|
||||
desc = "The study of technologies used by the advanced alien race known as Abductors."
|
||||
id = "abductor"
|
||||
rare = 5
|
||||
level = 0
|
||||
|
||||
/*
|
||||
datum/tech/arcane
|
||||
name = "Arcane Research"
|
||||
@@ -278,8 +285,7 @@ datum/tech/robotics
|
||||
return 0
|
||||
|
||||
var/cost = 0
|
||||
var/i
|
||||
for(i=current_level+1, i<=level, i++)
|
||||
for(var/i=current_level+1, i<=level, i++)
|
||||
if(i == initial(level))
|
||||
continue
|
||||
cost += i*5*rare
|
||||
|
||||
@@ -315,6 +315,8 @@
|
||||
dat += "[temp_server.name] Data ManagementP<BR><BR>"
|
||||
dat += "Known Technologies<BR>"
|
||||
for(var/datum/tech/T in temp_server.files.known_tech)
|
||||
if(T.level <= 0)
|
||||
continue
|
||||
dat += "* [T.name] "
|
||||
dat += "<A href='?src=\ref[src];reset_tech=[T.id]'>(Reset)</A><BR>" //FYI, these are all strings.
|
||||
dat += "Known Designs<BR>"
|
||||
|
||||
@@ -242,9 +242,9 @@
|
||||
height = 4
|
||||
|
||||
/obj/docking_port/mobile/pod/New()
|
||||
..()
|
||||
if(id == "pod")
|
||||
WARNING("[type] id has not been changed from the default. Use the id convention \"pod1\" \"pod2\" etc.")
|
||||
..()
|
||||
|
||||
/obj/docking_port/mobile/pod/cancel()
|
||||
return
|
||||
|
||||
@@ -302,10 +302,6 @@
|
||||
//rotate our direction
|
||||
dir = angle2dir(rotation+dir2angle(dir))
|
||||
|
||||
//resmooth if need be.
|
||||
if(smooth)
|
||||
smooth_icon(src)
|
||||
|
||||
//rotate the pixel offsets too.
|
||||
if (pixel_x || pixel_y)
|
||||
if (rotation < 0)
|
||||
@@ -316,6 +312,9 @@
|
||||
pixel_x = oldPY
|
||||
pixel_y = (oldPX*(-1))
|
||||
|
||||
/atom/proc/postDock()
|
||||
if(smooth)
|
||||
smooth_icon(src)
|
||||
|
||||
|
||||
//this is the main proc. It instantly moves our mobile port to stationary port S1
|
||||
@@ -368,7 +367,7 @@
|
||||
|
||||
var/list/door_unlock_list = list()
|
||||
|
||||
for(var/i=1, i<=L0.len, ++i)
|
||||
for(var/i in 1 to L0.len)
|
||||
var/turf/T0 = L0[i]
|
||||
if(!T0)
|
||||
continue
|
||||
@@ -443,6 +442,12 @@
|
||||
T0.CalculateAdjacentTurfs()
|
||||
air_master.add_to_active(T0,1)
|
||||
|
||||
for(var/A1 in L1)
|
||||
var/turf/T1 = A1
|
||||
T1.postDock()
|
||||
for(var/atom/movable/M in T1)
|
||||
M.postDock()
|
||||
|
||||
loc = S1.loc
|
||||
dir = S1.dir
|
||||
|
||||
|
||||
@@ -329,7 +329,12 @@
|
||||
/datum/surgery_step/remove_object
|
||||
name = "remove embedded objects"
|
||||
time = 32
|
||||
accept_hand = 1
|
||||
allowed_tools = list(
|
||||
/obj/item/weapon/scalpel/manager = 120, \
|
||||
/obj/item/weapon/hemostat = 100, \
|
||||
/obj/item/stack/cable_coil = 75, \
|
||||
/obj/item/device/assembly/mousetrap = 20
|
||||
)
|
||||
var/obj/item/organ/external/L = null
|
||||
|
||||
|
||||
@@ -368,4 +373,4 @@
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't find [target]'s [target_zone], let alone any objects embedded in it!</span>")
|
||||
|
||||
return 1
|
||||
return 1
|
||||
|
||||
@@ -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 = "<h1>[title]</h1>"
|
||||
content = "<p>[content]</p>"
|
||||
else if (title && !content)
|
||||
title = "<p>[title]</p>"
|
||||
else if (!title && content)
|
||||
content = "<p>[content]</p>"
|
||||
|
||||
//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()
|
||||
@@ -0,0 +1,238 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tooltip</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<style type="text/css">
|
||||
body, html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
max-width: 298px;
|
||||
border: 2px solid #1B2967;
|
||||
}
|
||||
|
||||
.content {
|
||||
font: bold 12px Arial, 'Helvetica Neue', Helvetica, sans-serif;
|
||||
color: #ffffff;
|
||||
padding: 8px;
|
||||
border: 2px solid #0033CC;
|
||||
background: #005CB8;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: -5px 0 2px 0;
|
||||
font-size: 1.2em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
/* Custom Themes */
|
||||
.blob .wrap {border-color: #2E2E2E;}
|
||||
.blob .content {color: #82ED00; border-color: #4E4C4A; background-color: #191918;}
|
||||
|
||||
.parasite .wrap {border-color: #88868D;}
|
||||
.parasite .content {color: #EFEEEF; border-color: #35333A; background-color: #636169;}
|
||||
|
||||
.alien .wrap {border-color: #33165B;}
|
||||
.alien .content {color: #25004A; border-color: #5A3076; background-color: #6D3A8E;}
|
||||
|
||||
.wraith .wrap {border-color: #492136;}
|
||||
.wraith .content {border-color: #331726; background-color: #471962;}
|
||||
|
||||
.cult .wrap {border-color: #610002;}
|
||||
.cult .content {color: #0F0B0C; border-color: #A10000; background-color: #4A363B;}
|
||||
|
||||
.pod .wrap {border-color: #052401;}
|
||||
.pod .content {border-color: #326D29; background-color: #569F4B;}
|
||||
|
||||
.colo-pod .wrap {border-color: #256fb9;}
|
||||
.colo-pod .content {border-color: #000000; background-color: #000000;}
|
||||
|
||||
/* TG: Themes */
|
||||
/* ScreenUI */
|
||||
.midnight .wrap {border-color: #2B2B33;}
|
||||
.midnight .content {color: #6087A0; border-color: #2B2B33; background-color: #36363C;}
|
||||
|
||||
.plasmafire .wrap {border-color: #21213D;}
|
||||
.plasmafire .content {color: #FFA800 ; border-color: #21213D; background-color:#1D1D36;}
|
||||
|
||||
.retro .wrap {border-color: #005E00;}
|
||||
.retro .content {color: #003366; border-color: #005E00; background-color: #00BD00;}
|
||||
|
||||
.slimecore .wrap {border-color: #18640E;}
|
||||
.slimecore .content {color: #6EA161; border-color: #11450B; background-color: #354E35;}
|
||||
|
||||
.operative .wrap {border-color: #1E0101;}
|
||||
.operative .content {color: #FFFFFF; border-color: #750000; background-color: #350000;}
|
||||
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap" class="wrap">
|
||||
<div id="content" class="content"></div>
|
||||
</div>
|
||||
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
var tooltip = {
|
||||
'tileSize': 32,
|
||||
'control': '',
|
||||
'params': {},
|
||||
'clientView': 0,
|
||||
'text': '',
|
||||
'theme': '',
|
||||
'padding': 2,
|
||||
init: function(tileSize, control) {
|
||||
tooltip.tileSize = parseInt(tileSize);
|
||||
tooltip.control = control;
|
||||
},
|
||||
hide: function() {
|
||||
window.location = 'byond://winset?id='+tooltip.control+';is-visible=false';
|
||||
},
|
||||
updateCallback: function(map) {
|
||||
if (typeof map === 'undefined' || !map) {return false;}
|
||||
|
||||
//alert(tooltip.params+' | '+tooltip.clientView+' | '+tooltip.text+' | '+tooltip.theme); //DEBUG
|
||||
|
||||
//Some reset stuff to avoid fringe issues with sizing
|
||||
window.location = 'byond://winset?id='+tooltip.control+';anchor1=0,0;size=999x999';
|
||||
|
||||
//Get the real icon size according to the client view
|
||||
var mapWidth = map['view-size'].x,
|
||||
mapHeight = map['view-size'].y,
|
||||
tilesShown = (tooltip.clientView * 2) + 1,
|
||||
realIconSize = mapWidth / tilesShown,
|
||||
resizeRatio = realIconSize / tooltip.tileSize,
|
||||
//Calculate letterboxing offsets
|
||||
leftOffset = (map.size.x - mapWidth) / 2,
|
||||
topOffset = (map.size.y - mapHeight) / 2;
|
||||
|
||||
//alert(realIconSize + ' | ' +tooltip.tileSize + ' | ' + resizeRatio); //DEBUG
|
||||
|
||||
//Parse out the tile and cursor locations from params (e.g. "icon-x=32;icon-y=29;screen-loc=3:10,15:29")
|
||||
var paramsA = tooltip.params.cursor.split(';');
|
||||
if (paramsA.length < 3) {return false;} //Sometimes screen-loc is never sent ahaha fuck you byond
|
||||
//icon-x
|
||||
var iconX = paramsA[0];
|
||||
iconX = iconX.split('=');
|
||||
iconX = parseInt(iconX[1]);
|
||||
//icon-y
|
||||
var iconY = paramsA[1];
|
||||
iconY = iconY.split('=');
|
||||
iconY = parseInt(iconY[1]);
|
||||
//screen-loc
|
||||
var screenLoc = paramsA[2];
|
||||
screenLoc = screenLoc.split('=');
|
||||
screenLoc = screenLoc[1].split(',');
|
||||
if (screenLoc.length < 2) {return false;}
|
||||
var left = screenLoc[0];
|
||||
var top = screenLoc[1];
|
||||
if (!left || !top) {return false;}
|
||||
screenLoc = left.split(':');
|
||||
left = parseInt(screenLoc[0]);
|
||||
var enteredX = parseInt(screenLoc[1]);
|
||||
screenLoc = top.split(':');
|
||||
top = parseInt(screenLoc[0]);
|
||||
var enteredY = parseInt(screenLoc[1]);
|
||||
|
||||
//Screen loc offsets on objects (e.g. "WEST+0:6,NORTH-1:26") can royally mess with positioning depending on where the cursor enters
|
||||
//This is a giant bitch to parse. Note that it only expects screen_loc in the format <west>,<north>.
|
||||
var oScreenLoc = tooltip.params.screenLoc.split(','); //o for original ok
|
||||
|
||||
var west = oScreenLoc[0].split(':');
|
||||
if (west.length > 1) { //Only if west has a pixel offset
|
||||
var westOffset = parseInt(west[1]);
|
||||
if (westOffset !== 0) {
|
||||
if ((iconX + westOffset) !== enteredX) { //Cursor entered on the offset tile
|
||||
left = left + (westOffset < 0 ? 1 : -1);
|
||||
}
|
||||
leftOffset = leftOffset + (westOffset * resizeRatio);
|
||||
}
|
||||
}
|
||||
|
||||
if (oScreenLoc.length > 1) { //If north is given
|
||||
var north = oScreenLoc[1].split(':');
|
||||
if (north.length > 1) { //Only if north has a pixel offset
|
||||
var northOffset = parseInt(north[1]);
|
||||
if (northOffset !== 0) {
|
||||
if ((iconY + northOffset) === enteredY) { //Cursor entered on the original tile
|
||||
top--;
|
||||
topOffset = topOffset - ((tooltip.tileSize + northOffset) * resizeRatio);
|
||||
} else { //Cursor entered on the offset tile
|
||||
if (northOffset < 0) { //Offset southwards
|
||||
topOffset = topOffset - ((tooltip.tileSize + northOffset) * resizeRatio);
|
||||
} else { //Offset northwards
|
||||
top--;
|
||||
topOffset = topOffset - (northOffset * resizeRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Handle special cases (for fuck sake)
|
||||
if (tooltip.special !== 'none') {
|
||||
//Put yo special cases here
|
||||
}
|
||||
|
||||
//Clamp values
|
||||
left = (left < 0 ? 0 : (left > tilesShown ? tilesShown : left));
|
||||
top = (top < 0 ? 0 : (top > tilesShown ? tilesShown : top));
|
||||
|
||||
//Calculate where on the screen the popup should appear (below the hovered tile)
|
||||
var posX = Math.round(((left - 1) * realIconSize) + leftOffset + tooltip.padding); //-1 to position at the left of the target tile
|
||||
var posY = Math.round(((tilesShown - top + 1) * realIconSize) + topOffset + tooltip.padding); //+1 to position at the bottom of the target tile
|
||||
|
||||
//alert(mapWidth+' | '+mapHeight+' | '+tilesShown+' | '+realIconSize+' | '+leftOffset+' | '+topOffset+' | '+left+' | '+top+' | '+posX+' | '+posY); //DEBUG
|
||||
|
||||
$('body').attr('class', tooltip.theme);
|
||||
|
||||
var $content = $('#content'),
|
||||
$wrap = $('#wrap');
|
||||
$wrap.attr('style', '');
|
||||
$content.off('mouseover');
|
||||
$content.html(tooltip.text);
|
||||
|
||||
$wrap.width($wrap.width() + 2); //Dumb hack to fix a bizarre sizing bug
|
||||
|
||||
var docWidth = $wrap.outerWidth(),
|
||||
docHeight = $wrap.outerHeight();
|
||||
|
||||
if (posY + docHeight > map.size.y) { //Is the bottom edge below the window? Snap it up if so
|
||||
posY = (posY - docHeight) - realIconSize - tooltip.padding;
|
||||
}
|
||||
|
||||
//Actually size, move and show the tooltip box
|
||||
window.location = 'byond://winset?id='+tooltip.control+';size='+docWidth+'x'+docHeight+';pos='+posX+','+posY+';is-visible=true';
|
||||
|
||||
$content.on('mouseover', function() {
|
||||
tooltip.hide();
|
||||
});
|
||||
},
|
||||
update: function(params, clientView, text, theme, special) {
|
||||
//Assign our global object
|
||||
tooltip.params = $.parseJSON(params);
|
||||
tooltip.clientView = parseInt(clientView);
|
||||
tooltip.text = text;
|
||||
tooltip.theme = theme;
|
||||
tooltip.special = special;
|
||||
|
||||
//Go get the map details
|
||||
window.location = 'byond://winget?callback=tooltip.updateCallback;id=mapwindow.map;property=size,view-size';
|
||||
},
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user