Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into Kungfu

This commit is contained in:
Aurorablade
2016-04-22 21:45:18 -04:00
198 changed files with 7925 additions and 5103 deletions
+4
View File
@@ -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)
+6
View File
@@ -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)
+4
View File
@@ -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"]
-2
View File
@@ -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)
+6 -3
View File
@@ -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)
+2 -1
View File
@@ -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)
..()
+4 -1
View File
@@ -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
+4
View File
@@ -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//
//////////////
+1
View File
@@ -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)
+265 -165
View File
@@ -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"
+52
View File
@@ -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
+4
View File
@@ -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()
+5 -4
View File
@@ -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),
)
+1 -2
View File
@@ -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))
+4 -3
View File
@@ -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
+35 -28
View File
@@ -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
+22 -2
View File
@@ -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
+4 -12
View File
@@ -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)
+127 -2
View File
@@ -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
+33 -26
View File
@@ -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
+5 -8
View File
@@ -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)
-1
View File
@@ -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)
+7 -4
View File
@@ -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))
+42 -229
View File
@@ -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)
+2 -8
View File
@@ -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()
+9 -4
View File
@@ -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
+11 -3
View File
@@ -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)
+9 -1
View File
@@ -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)
+37 -65
View File
@@ -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()
+4 -1
View File
@@ -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
-6
View File
@@ -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
+19 -3
View File
@@ -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))
+1 -1
View File
@@ -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()
-2
View File
@@ -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))
+2 -4
View File
@@ -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")
+7 -2
View File
@@ -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>"
+9 -3
View File
@@ -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
+2
View File
@@ -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>"
+1 -1
View File
@@ -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
+10 -5
View File
@@ -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
+7 -2
View File
@@ -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
+116
View File
@@ -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()
+238
View File
@@ -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>