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

# Conflicts:
#	code/modules/mob/mob_helpers.dm
#	icons/obj/ammo.dmi
#	icons/obj/guns/projectile.dmi
#	icons/obj/storage.dmi
This commit is contained in:
Markolie
2017-01-31 17:44:38 +01:00
48 changed files with 717 additions and 227 deletions
+4 -1
View File
@@ -393,8 +393,11 @@
logout_status = " <i>(snpc)</i>"
else
logout_status = M.client ? "" : " <i>(logged out)</i>"
var/dname = M.real_name
if(!dname)
dname = M
return {"<tr><td><a href='?src=[UID()];adminplayeropts=\ref[M]'>[M.real_name]</a><b>[caption]</b>[logout_status][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>
return {"<tr><td><a href='?src=[UID()];adminplayeropts=\ref[M]'>[dname]</a><b>[caption]</b>[logout_status][M.stat == 2 ? " <b><font color=red>(DEAD)</font></b>" : ""]</td>
<td><A href='?src=[usr.UID()];priv_msg=\ref[M]'>PM</A></td>[close ? "</tr>" : ""]"}
/datum/admins/proc/check_antagonists()
+1
View File
@@ -119,6 +119,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
for(var/client/X in modholders + adminholders)
if(X.prefs.sound & SOUND_ADMINHELP)
X << 'sound/effects/adminhelp.ogg'
window_flash(X)
to_chat(X, msg)
//show it to the person adminhelping too
+1
View File
@@ -133,6 +133,7 @@
if(holder && !C.holder)
recieve_message = "<span class='[recieve_span]' size='3'>-- Click the [recieve_pm_type]'s name to reply --</span>\n"
if(C.adminhelped)
window_flash(C)
to_chat(C, recieve_message)
C.adminhelped = 0
@@ -93,6 +93,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
var/show_ghostitem_attack = TRUE
var/UI_style_color = "#ffffff"
var/UI_style_alpha = 255
var/windowflashing = TRUE
//character preferences
@@ -418,6 +419,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
dat += "<h2>General Settings</h2>"
dat += "<b>Fancy NanoUI:</b> <a href='?_src_=prefs;preference=nanoui'>[(nanoui_fancy) ? "Yes" : "No"]</a><br>"
dat += "<b>Ghost-Item Attack Animation:</b> <a href='?_src_=prefs;preference=ghost_att_anim'>[(show_ghostitem_attack) ? "Yes" : "No"]</a><br>"
dat += "<b>Window Flashing:</b> <a href='?_src_=prefs;preference=winflash'>[(windowflashing) ? "Yes" : "No"]</a><br>"
dat += "<b>Custom UI settings:</b><br>"
dat += " - <b>UI Style:</b> <a href='?_src_=prefs;preference=ui'><b>[UI_style]</b></a><br>"
dat += " - <b>Color:</b> <a href='?_src_=prefs;preference=UIcolor'><b>[UI_style_color]</b></a> <table style='display:inline;' bgcolor='[UI_style_color]'<tr><td>__</td></tr></table><br>"
@@ -1935,6 +1937,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if("ghost_att_anim")
show_ghostitem_attack = !show_ghostitem_attack
if("winflash")
windowflashing = !windowflashing
if("UIcolor")
var/UI_style_color_new = input(user, "Choose your UI color, dark colors are not recommended!", UI_style_color) as color|null
if(!UI_style_color_new) return
@@ -14,7 +14,8 @@
nanoui_fancy,
show_ghostitem_attack,
lastchangelog,
exp
exp,
windowflashing
FROM [format_table_name("player")]
WHERE ckey='[C.ckey]'"}
)
@@ -42,6 +43,7 @@
show_ghostitem_attack = text2num(query.item[12])
lastchangelog = query.item[13]
exp = query.item[14]
windowflashing = text2num(query.item[15])
//Sanitize
ooccolor = sanitize_hexcolor(ooccolor, initial(ooccolor))
@@ -57,6 +59,7 @@
show_ghostitem_attack = sanitize_integer(show_ghostitem_attack, 0, 1, initial(show_ghostitem_attack))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
exp = sanitize_text(exp, initial(exp))
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
return 1
/datum/preferences/proc/save_preferences(client/C)
+3 -2
View File
@@ -193,8 +193,9 @@ BLIND // can't see anything
"Drask" = 'icons/mob/species/drask/gloves.dmi'
)
/obj/item/clothing/gloves/proc/Touch()
return
// Called just before an attack_hand(), in mob/UnarmedAttack()
/obj/item/clothing/gloves/proc/Touch(atom/A, proximity)
return 0 // return 1 to cancel attack_hand()
/obj/item/clothing/gloves/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/wirecutters))
@@ -56,3 +56,74 @@
icon_state = "latex"
item_state = "lgloves"
flags = NODROP
/obj/item/clothing/gloves/color/yellow/stun
name = "stun gloves"
desc = "Horrendous and awful. It smells like cancer. The fact it has wires attached to it is incidental."
var/obj/item/weapon/stock_parts/cell/cell = null
var/stun_strength = 5
var/stun_cost = 3750
/obj/item/clothing/gloves/color/yellow/stun/New()
..()
update_icon()
/obj/item/clothing/gloves/color/yellow/stun/Destroy()
if(cell)
qdel(cell)
cell = null
return ..()
/obj/item/clothing/gloves/color/yellow/stun/Touch(atom/A, proximity)
if(!ishuman(loc))
return FALSE //Only works while worn
if(!iscarbon(A))
return FALSE
if(!proximity)
return FALSE
if(cell)
var/mob/living/carbon/human/H = loc
if(H.a_intent == I_HARM)
var/mob/living/carbon/C = A
if(cell.use(stun_cost))
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(5, 0, loc)
s.start()
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
H.do_attack_animation(C)
visible_message("<span class='danger'>[C] has been touched with [src] by [H]!</span>")
C.Stun(stun_strength)
C.Weaken(stun_strength)
C.apply_effect(STUTTER, stun_strength)
else
to_chat(H, "<span class='notice'>Not enough charge!</span>")
return TRUE
return FALSE
/obj/item/clothing/gloves/color/yellow/stun/update_icon()
..()
overlays.Cut()
overlays += "gloves_wire"
if(cell)
overlays += "gloves_cell"
/obj/item/clothing/gloves/color/yellow/stun/attackby(obj/item/weapon/W, mob/living/user, params)
if(istype(W, /obj/item/weapon/stock_parts/cell))
if(!cell)
if(!user.drop_item())
to_chat(user, "<span class='warning'>[W] is stuck to you!</span>")
return
W.forceMove(src)
cell = W
to_chat(user, "<span class='notice'>You attach [W] to [src].</span>")
update_icon()
else
to_chat(user, "<span class='notice'>[src] already has a cell.</span>")
else if(iswirecutter(W))
if(cell)
to_chat(user, "<span class='notice'>You cut [cell] away from [src].</span>")
cell.forceMove(get_turf(loc))
cell = null
update_icon()
+1 -1
View File
@@ -340,7 +340,7 @@
icon_override = 'icons/goonstation/mob/clothing/mask.dmi'
lefthand_file = 'icons/goonstation/mob/inhands/clothing_lefthand.dmi'
righthand_file = 'icons/goonstation/mob/inhands/clothing_righthand.dmi'
flags = NODROP
flags = NODROP | AIRTIGHT | MASKCOVERSMOUTH
/obj/item/clothing/mask/cursedclown/equipped(mob/user, slot)
..()
+2
View File
@@ -29,6 +29,8 @@
respawnable_list -= C.client
var/mob/living/carbon/alien/larva/new_xeno = new(vent.loc)
new_xeno.key = C.key
if(ticker && ticker.mode)
ticker.mode.xenos += new_xeno.mind
spawncount--
successSpawn = 1
+4 -7
View File
@@ -1,7 +1,7 @@
/*
===============================================================================
How Garbage Collection Works
How Garbage Collection Works
===============================================================================
In BYOND, there are exactly two ways anything gets deleted:
@@ -31,8 +31,8 @@ that can't be. There are two main procs involved in this process:
/proc/qdel(datumToDelete)
This is, effectively, a replacement for del that tells an object to prepare itself to be soft deleted by calling its
Destroy() proc. Depending on the qdel hint returned by Destroy(), qdel will queue the object in the garbage collector
(to be hard deleted if it isn't soft deleted), directly delete the object, pool the object, or ignore the object and
assume it will handle deleting itself. An object passed into qdel will have its gcDestroyed var set, so
(to be hard deleted if it isn't soft deleted), directly delete the object, or ignore the object and
assume it will handle deleting itself. An object passed into qdel will have its gcDestroyed var set, so
isnull(gcDestroyed) will be true if an object is not being destroyed, and false if it is (which means you should get
rid of the reference you have to it).
@@ -50,7 +50,7 @@ that can't be. There are two main procs involved in this process:
should use a Del proc for any necessary cleanup, as a Destroy proc on them will not automatically get called.
When called by qdel, Destroy is expected to return a qdel hint, which determines whether the object should be directly
deleted, queued for deletion, pooled, or ignored entirely; which of these are appropriate will vary, though objects
deleted, queued for deletion, or ignored entirely; which of these are appropriate will vary, though objects
should be pooled or queued whenever possible. The full list of qdel hints are in the code for the qdel proc.
As mentioned above, gcDestroyed can be used to tell whether an object is being destroyed. This is important, because if
@@ -62,7 +62,4 @@ reference immediately.
The inner workings of the GC itself and the stuff related to testing it probably don't need a detailed description - if
you intend to work with them, it would be best to read the code to understand what they do.
Pooling is related to GC, in that it's meant to reduce deletion overhead, but it does so by re-using objects instead of
deleting them at all. Explaining pooling is outside the scope of this file.
*/
@@ -10,6 +10,7 @@
/mob/living/carbon/brain/New()
create_reagents(330)
add_language("Galactic Common")
..()
/mob/living/carbon/brain/Destroy()
@@ -788,6 +788,7 @@ Pass a positive integer as an argument to override a bot's default speed.
frustration = 0
/mob/living/simple_animal/bot/show_inv()
return
/mob/living/simple_animal/bot/proc/show_controls(mob/M)
users |= M
@@ -58,7 +58,7 @@
dat += "<tr><td><B>Back:</B></td><td><A href='?src=[UID()];[inventory_back?"remove_inv":"add_inv"]=back'>[(inventory_back && !(inventory_back.flags&ABSTRACT)) ? inventory_back : "<font color=grey>Empty</font>"]</A></td></tr>"
if(can_collar)
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Collar:</B></td><td><A href='?src=[UID()];[collar?"remove_inv":"add_inv"]=collar'>[(collar && !(collar.flags&ABSTRACT)) ? collar : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Collar:</B></td><td><A href='?src=[UID()];item=[slot_collar]'>[(collar && !(collar.flags&ABSTRACT)) ? collar : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += {"</table>
<A href='?src=[user.UID()];mach_close=mob\ref[src]'>Close</A>
@@ -582,21 +582,7 @@
density = initial(density)
update_canmove()
/mob/living/simple_animal/show_inv(mob/user as mob)
user.set_machine(src)
var/dat = {"<table>
<tr><td><B>Left Hand:</B></td><td><A href='?src=[UID()];item=[slot_l_hand]'>[(l_hand && !(l_hand.flags&ABSTRACT)) ? l_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td><B>Right Hand:</B></td><td><A href='?src=[UID()];item=[slot_r_hand]'>[(r_hand && !(r_hand.flags&ABSTRACT)) ? r_hand : "<font color=grey>Empty</font>"]</A></td></tr>
<tr><td>&nbsp;</td></tr>"}
if(can_collar)
dat += "<tr><td><B>Collar:</B></td><td><A href='?src=[UID()];[collar?"remove_inv":"add_inv"]=collar'>[(collar && !(collar.flags&ABSTRACT)) ? collar : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += {"</table>
<A href='?src=[user.UID()];mach_close=mob\ref[src]'>Close</A>
"}
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 250)
popup.set_content(dat)
popup.open()
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || !scan_ready || !childtype || !simplespecies)
@@ -655,57 +641,74 @@
if(changed)
animate(src, transform = ntransform, time = 2, easing = EASE_IN|EASE_OUT)
/mob/living/simple_animal/Topic(href, href_list)
if(!usr.stat && usr.canmove && !usr.restrained() && in_range(src, usr))
if(href_list["remove_inv"])
if(!Adjacent(usr) || !(ishuman(usr) || isrobot(usr) || isalienadult(usr)))
return
var/remove_from = href_list["remove_inv"]
switch(remove_from)
if("collar")
if(!can_collar)
return
if(collar)
if(collar.flags & NODROP)
to_chat(usr, "<span class='warning'>\The [collar] is stuck too hard to [src] for you to remove!</span>")
return
collar.dropped(src)
collar.forceMove(src.loc)
collar = null
regenerate_icons()
else
to_chat(usr, "<span class='danger'>There is nothing to remove from its [remove_from].</span>")
return
show_inv(usr)
else if(href_list["add_inv"])
if(!Adjacent(usr) || !(ishuman(usr) || isrobot(usr) || isalienadult(usr)))
return
/* Inventory */
var/add_to = href_list["add_inv"]
switch(add_to)
if("collar")
if(!can_collar || collar)
return
var/obj/item/clothing/accessory/petcollar/C = usr.get_active_hand()
if(!istype(C))
usr.visible_message("[usr] rubs [src]'s neck.","<span class='notice'>You rub [src]'s neck for a moment.</span>")
return
usr.drop_item()
C.forceMove(src)
collar = C
collar.equipped(src)
regenerate_icons()
to_chat(usr, "<span class='notice'>You put \the [C] around \the [src]'s neck.</span>")
if(C.tagname)
name = C.tagname
real_name = C.tagname
show_inv(usr)
/mob/living/simple_animal/show_inv(mob/user as mob)
if(!can_collar)
return
user.set_machine(src)
var/dat = "<table><tr><td><B>Collar:</B></td><td><A href='?src=[UID()];item=[slot_collar]'>[(collar && !(collar.flags&ABSTRACT)) ? collar : "<font color=grey>Empty</font>"]</A></td></tr></table>"
dat += "<A href='?src=[user.UID()];mach_close=mob\ref[src]'>Close</A>"
var/datum/browser/popup = new(user, "mob\ref[src]", "[src]", 440, 250)
popup.set_content(dat)
popup.open()
/mob/living/simple_animal/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_collar)
return collar
. = ..()
/mob/living/simple_animal/can_equip(obj/item/I, slot, disable_warning = 0)
// . = ..() // Do not call parent. We do not want animals using their hand slots.
switch(slot)
if(slot_collar)
if(collar)
return 0
if(!can_collar)
return 0
if(!istype(I, /obj/item/clothing/accessory/petcollar))
return 0
return 1
/mob/living/simple_animal/equip_to_slot(obj/item/W, slot)
if(!istype(W))
return 0
if(!slot)
return 0
W.forceMove(src)
W.equipped(src, slot)
W.layer = 20
W.plane = HUD_PLANE
switch(slot)
if(slot_collar)
collar = W
if(collar.tagname)
name = collar.tagname
real_name = collar.tagname
regenerate_icons()
/mob/living/simple_animal/unEquip(obj/item/I, force)
. = ..()
if(!. || !I)
return
if(I == collar)
collar = null
regenerate_icons()
/mob/living/simple_animal/get_access()
. = ..()
if(collar)
. |= collar.GetAccess()
/* End Inventory */
/mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion
return
+3 -1
View File
@@ -1222,9 +1222,11 @@ mob/proc/yank_out_object()
if(mind)
return mind.grab_ghost(force = force)
/mob/proc/notify_ghost_cloning(var/message = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!", var/sound = 'sound/effects/genetics.ogg', var/atom/source = null)
/mob/proc/notify_ghost_cloning(message = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!", sound = 'sound/effects/genetics.ogg', atom/source = null, flashwindow = TRUE)
var/mob/dead/observer/ghost = get_ghost()
if(ghost)
if(flashwindow)
window_flash(ghost.client)
ghost.notify_cloning(message, sound, source)
return ghost
+5 -3
View File
@@ -434,12 +434,14 @@ 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, var/enter_link = null, var/atom/source = null, var/image/alert_overlay = null, var/action = NOTIFY_JUMP) //Easy notification of ghosts.
/proc/notify_ghosts(message, ghost_sound = null, enter_link = null, atom/source = null, image/alert_overlay = null, attack_not_jump = 0, flashwindow = TRUE, var/action = NOTIFY_JUMP) //Easy notification of ghosts.
for(var/mob/dead/observer/O in player_list)
if(O.client)
to_chat(O, "<span class='ghostalert'>[message][(enter_link) ? " [enter_link]" : ""]<span>")
if(ghost_sound)
O << sound(ghost_sound)
if(flashwindow)
window_flash(O.client)
if(source)
var/obj/screen/alert/notify_action/A = O.throw_alert("\ref[source]_notify_action", /obj/screen/alert/notify_action)
if(A)
@@ -586,8 +588,8 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HARM)
if(5)
newletter="glor"
newphrase+="[newletter]";counter-=1
return newphrase
return newphrase
/mob/proc/get_preference(toggleflag)
if(!client)
return FALSE
@@ -375,3 +375,9 @@
desc = "A cap for children toys."
caliber = "caps"
projectile_type = /obj/item/projectile/bullet/cap
/obj/item/ammo_casing/laser
desc = "An experimental laser casing."
caliber = "laser"
projectile_type = /obj/item/projectile/beam/laser
icon_state = "lasercasing"
@@ -437,3 +437,12 @@
/obj/item/ammo_box/magazine/toy/m762/update_icon()
..()
icon_state = "a762-[round(ammo_count(),10)]"
/obj/item/ammo_box/magazine/laser
name = "encased laser projector magazine"
desc = "Fits experimental laser ammo casings."
icon_state = "laser"
ammo_type = /obj/item/ammo_casing/laser
origin_tech = "combat=3"
caliber = "laser"
max_ammo = 20
@@ -249,3 +249,15 @@
/obj/item/weapon/gun/projectile/automatic/shotgun/bulldog/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag)
..()
empty_alarm()
/obj/item/weapon/gun/projectile/automatic/lasercarbine
name = "\improper IK-60 Laser Carbine"
desc = "An experimental carbine. Uses encased laser projectors as ammunition."//we need to uncouple the toroidal resistance dejammers
icon_state = "lasercarbine"
item_state = "laser"
w_class = 3
origin_tech = "combat=5;materials=5"
mag_type = /obj/item/ammo_box/magazine/laser
fire_sound = 'sound/weapons/emitter2.ogg'
can_suppress = 0
burst_size = 2
@@ -91,8 +91,7 @@
var/mob/living/carbon/human/H = M
//Mitocholide is hard enough to get, it's probably fair to make this all internal organs
for(var/name in H.internal_organs)
var/obj/item/organ/internal/I = H.get_int_organ(name)
for(var/obj/item/organ/internal/I in H.internal_organs)
if(I.damage > 0)
I.damage = max(I.damage-0.4, 0)
..()
@@ -635,7 +634,8 @@
return
var/mob/dead/observer/ghost = M.get_ghost()
if(ghost)
to_chat(ghost, "<span class='ghostalert'>Your are attempting to be revived with Strange Reagent. Return to your body if you want to be revived!</span> (Verbs -> Ghost -> Re-enter corpse)")
to_chat(ghost, "<span class='ghostalert'>You are attempting to be revived with Strange Reagent. Return to your body if you want to be revived!</span> (Verbs -> Ghost -> Re-enter corpse)")
window_flash(ghost.client)
ghost << sound('sound/effects/genetics.ogg')
M.visible_message("<span class='notice'>[M] doesn't appear to respond, perhaps try again later?</span>")
if(!M.suiciding && !ghost && !(NOCLONE in M.mutations))
@@ -974,4 +974,4 @@
/datum/reagent/medicine/liquid_solder/on_mob_life(mob/living/M)
M.adjustBrainLoss(-3)
..()
..()
@@ -67,12 +67,24 @@
/datum/chemical_reaction/slimemetal/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal
M.amount = 15
M.forceMove(get_turf(holder.my_atom))
var/obj/item/stack/sheet/plasteel/P = new /obj/item/stack/sheet/plasteel
P.amount = 5
P.forceMove(get_turf(holder.my_atom))
var/turf/location = get_turf(holder.my_atom)
new /obj/item/stack/sheet/plasteel (location, 5)
new /obj/item/stack/sheet/metal (location, 15)
/datum/chemical_reaction/slimeglass
name = "Slime Glass"
id = "m_glass"
result = null
required_reagents = list("water" = 1)
result_amount = 1
required_container = /obj/item/slime_extract/metal
required_other = 1
/datum/chemical_reaction/slimeglass/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
var/turf/location = get_turf(holder.my_atom)
new /obj/item/stack/sheet/rglass (location, 5)
new /obj/item/stack/sheet/glass (location, 15)
//Gold
/datum/chemical_reaction/slimecrit
@@ -209,8 +221,7 @@
required_other = 1
/datum/chemical_reaction/slimefrost/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
feedback_add_details("slime_cores_used","[type]")
/datum/chemical_reaction/slimestabilizer
name = "Slime Stabilizer"
@@ -226,8 +237,6 @@
var/obj/item/slimepotion/stabilizer/P = new /obj/item/slimepotion/stabilizer
P.forceMove(get_turf(holder.my_atom))
//Dark Blue
/datum/chemical_reaction/slimefreeze
name = "Slime Freeze"
@@ -383,12 +392,10 @@
/datum/chemical_reaction/slimeplasma/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
var/obj/item/stack/sheet/mineral/plasma/P = new /obj/item/stack/sheet/mineral/plasma
P.amount = 3
P.forceMove(get_turf(holder.my_atom))
var/turf/location = get_turf(holder.my_atom)
new /obj/item/stack/sheet/mineral/plasma (location, 3)
//Red
/datum/chemical_reaction/slimemutator
name = "Slime Mutator"
id = "m_slimemutator"
@@ -661,4 +668,18 @@
var/mob/living/carbon/slime/S = new /mob/living/carbon/slime
S.colour = pick("grey","orange", "metal", "blue", "purple", "dark purple", "dark blue", "green", "silver", "yellow", "gold", "yellow", "red", "silver", "pink", "cerulean", "sepia", "bluespace", "pyrite", "light pink", "oil", "adamantine", "black")
S.forceMove(get_turf(holder.my_atom))
S.visible_message("<span class='danger'>Infused with plasma, the core begins to quiver and grow, and soon a new baby slime emerges from it!</span>")
S.visible_message("<span class='danger'>Infused with plasma, the core begins to quiver and grow, and soon a new baby slime emerges from it!</span>")
/datum/chemical_reaction/slime_transfer
name = "Transfer Potion"
id = "slimetransfer"
result = null
required_reagents = list("blood" = 1)
result_amount = 1
required_other = 1
required_container = /obj/item/slime_extract/rainbow
/datum/chemical_reaction/slime_transfer/on_reaction(datum/reagents/holder)
feedback_add_details("slime_cores_used","[type]")
var/obj/item/slimepotion/transference/P = new /obj/item/slimepotion/transference
P.forceMove(get_turf(holder.my_atom))
+10 -5
View File
@@ -138,7 +138,8 @@
msg_admin_attack("[key_name_admin(user)] placed [key_name_admin(GM)] in a disposals unit. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</a>)")
return
if(!I) return
if(!I)
return
if(!user.drop_item())
return
@@ -530,14 +531,18 @@
has_fat_guy = 1 // set flag on holder
if(istype(AM, /obj/structure/bigDelivery) && !hasmob)
var/obj/structure/bigDelivery/T = AM
src.destinationTag = T.sortTag
destinationTag = T.sortTag
if(istype(AM, /obj/item/smallDelivery) && !hasmob)
var/obj/item/smallDelivery/T = AM
src.destinationTag = T.sortTag
destinationTag = T.sortTag
//Drones can mail themselves through maint.
if(istype(AM, /mob/living/silicon/robot/drone))
var/mob/living/silicon/robot/drone/drone = AM
src.destinationTag = drone.mail_destination
destinationTag = drone.mail_destination
if(istype(AM, /obj/item/shippingPackage) && !hasmob)
var/obj/item/shippingPackage/sp = AM
if(sp.sealed) //only sealed packages get delivered to their intended destination
destinationTag = sp.sortTag
// start the movement process
@@ -987,7 +992,7 @@
/obj/structure/disposalpipe/sortjunction
icon_state = "pipe-j1s"
var/sortType = 0 //Look at the list called TAGGERLOCATIONS in setup.dm
var/sortType = 0 //Look at the list called TAGGERLOCATIONS in /code/_globalvars/lists/flavor_misc.dm
var/posdir = 0
var/negdir = 0
var/sortdir = 0
+186 -86
View File
@@ -35,6 +35,16 @@
sortTag = O.currTag
playsound(loc, 'sound/machines/twobeep.ogg', 100, 1)
else if(istype(W, /obj/item/shippingPackage))
var/obj/item/shippingPackage/sp = W
if(sp.sealed)
return
else
sortTag = sp.sortTag
to_chat(user, "<span class='notice'>You rip the label off the shipping package and affix it to [src].</span>")
qdel(sp)
playsound(loc, 'sound/items/poster_ripped.ogg', 50, 1)
else if(istype(W, /obj/item/weapon/pen))
var/str = copytext(sanitize(input(user,"Label text?","Set label","")),1,MAX_NAME_LEN)
if(!str || !length(str))
@@ -89,6 +99,16 @@
sortTag = O.currTag
playsound(loc, 'sound/machines/twobeep.ogg', 100, 1)
else if(istype(W, /obj/item/shippingPackage))
var/obj/item/shippingPackage/sp = W
if(sp.sealed)
return
else
sortTag = sp.sortTag
to_chat(user, "<span class='notice'>You rip the label off the shipping package and affix it to [src].</span>")
qdel(sp)
playsound(loc, 'sound/items/poster_ripped.ogg', 50, 1)
else if(istype(W, /obj/item/weapon/pen))
var/str = copytext(sanitize(input(user,"Label text?","Set label","")),1,MAX_NAME_LEN)
if(!str || !length(str))
@@ -134,7 +154,7 @@
if(istype(target, /obj/item) && !(istype(target, /obj/item/weapon/storage) && !istype(target,/obj/item/weapon/storage/box)))
if(istype(target, /obj/item) && !(istype(target, /obj/item/weapon/storage) && !istype(target,/obj/item/weapon/storage/box) && !istype(target, /obj/item/shippingPackage)))
var/obj/item/O = target
if(use(1))
var/obj/item/smallDelivery/P = new /obj/item/smallDelivery(get_turf(O.loc)) //Aaannd wrap it up!
@@ -235,101 +255,181 @@
var/c_mode = 0
New()
..()
spawn(5)
trunk = locate() in src.loc
if(trunk)
trunk.linked = src // link the pipe trunk to self
/obj/machinery/disposal/deliveryChute/New()
..()
spawn(5)
trunk = locate() in src.loc
if(trunk)
trunk.linked = src // link the pipe trunk to self
interact()
return
/obj/machinery/disposal/deliveryChute/interact()
return
update()
return
/obj/machinery/disposal/deliveryChute/update()
return
Bumped(var/atom/movable/AM) //Go straight into the chute
if(istype(AM, /obj/item/projectile)) return
switch(dir)
if(NORTH)
if(AM.loc.y != src.loc.y+1) return
if(EAST)
if(AM.loc.x != src.loc.x+1) return
if(SOUTH)
if(AM.loc.y != src.loc.y-1) return
if(WEST)
if(AM.loc.x != src.loc.x-1) return
/obj/machinery/disposal/deliveryChute/Bumped(atom/movable/AM) //Go straight into the chute
if(istype(AM, /obj/item/projectile)) return
switch(dir)
if(NORTH)
if(AM.loc.y != src.loc.y+1) return
if(EAST)
if(AM.loc.x != src.loc.x+1) return
if(SOUTH)
if(AM.loc.y != src.loc.y-1) return
if(WEST)
if(AM.loc.x != src.loc.x-1) return
if(istype(AM, /obj))
var/obj/O = AM
O.loc = src
else if(istype(AM, /mob))
var/mob/M = AM
M.loc = src
src.flush()
if(istype(AM, /obj))
var/obj/O = AM
O.loc = src
else if(istype(AM, /mob))
var/mob/M = AM
M.loc = src
src.flush()
flush()
flushing = 1
flick("intake-closing", src)
var/deliveryCheck = 0
var/obj/structure/disposalholder/H = new() // virtual holder object which actually
/obj/machinery/disposal/deliveryChute/flush()
flushing = 1
flick("intake-closing", src)
var/deliveryCheck = 0
var/obj/structure/disposalholder/H = new() // virtual holder object which actually
// travels through the pipes.
for(var/obj/structure/bigDelivery/O in src)
deliveryCheck = 1
if(O.sortTag == 0)
O.sortTag = 1
for(var/obj/item/smallDelivery/O in src)
deliveryCheck = 1
if(O.sortTag == 0)
O.sortTag = 1
if(deliveryCheck == 0)
H.destinationTag = 1
for(var/obj/structure/bigDelivery/O in src)
deliveryCheck = 1
if(O.sortTag == 0)
O.sortTag = 1
for(var/obj/item/smallDelivery/O in src)
deliveryCheck = 1
if(O.sortTag == 0)
O.sortTag = 1
for(var/obj/item/shippingPackage/O in src)
deliveryCheck = 1
if(!O.sealed || O.sortTag == 0) //unsealed or untagged shipping packages will default to disposals
O.sortTag = 1
if(deliveryCheck == 0)
H.destinationTag = 1
sleep(10)
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
sleep(5) // wait for animation to finish
sleep(10)
playsound(src, 'sound/machines/disposalflush.ogg', 50, 0, 0)
sleep(5) // wait for animation to finish
H.init(src) // copy the contents of disposer to holder
air_contents = new() // The holder just took our gas; replace it
H.start(src) // start the holder processing movement
flushing = 0
// now reset disposal state
flush = 0
if(mode == 2) // if was ready,
mode = 1 // switch to charging
update()
H.init(src) // copy the contents of disposer to holder
air_contents = new() // The holder just took our gas; replace it
H.start(src) // start the holder processing movement
flushing = 0
// now reset disposal state
flush = 0
if(mode == 2) // if was ready,
mode = 1 // switch to charging
update()
return
/obj/machinery/disposal/deliveryChute/attackby(obj/item/I, mob/user, params)
if(!I || !user)
return
attackby(var/obj/item/I, var/mob/user, params)
if(!I || !user)
if(istype(I, /obj/item/weapon/screwdriver))
if(c_mode==0)
c_mode=1
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
to_chat(user, "You remove the screws around the power connection.")
return
else if(c_mode==1)
c_mode=0
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
to_chat(user, "You attach the screws around the power connection.")
return
else if(istype(I,/obj/item/weapon/weldingtool) && c_mode==1)
var/obj/item/weapon/weldingtool/W = I
if(W.remove_fuel(0,user))
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
to_chat(user, "You start slicing the floorweld off the delivery chute.")
if(do_after(user,20, target = src))
if(!src || !W.isOn()) return
to_chat(user, "You sliced the floorweld off the delivery chute.")
var/obj/structure/disposalconstruct/C = new (src.loc)
C.ptype = 8 // 8 = Delivery chute
C.update()
C.anchored = 1
C.density = 1
qdel(src)
return
else
to_chat(user, "You need more welding fuel to complete this task.")
return
if(istype(I, /obj/item/weapon/screwdriver))
if(c_mode==0)
c_mode=1
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
to_chat(user, "You remove the screws around the power connection.")
return
else if(c_mode==1)
c_mode=0
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
to_chat(user, "You attach the screws around the power connection.")
return
else if(istype(I,/obj/item/weapon/weldingtool) && c_mode==1)
var/obj/item/weapon/weldingtool/W = I
if(W.remove_fuel(0,user))
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
to_chat(user, "You start slicing the floorweld off the delivery chute.")
if(do_after(user,20, target = src))
if(!src || !W.isOn()) return
to_chat(user, "You sliced the floorweld off the delivery chute.")
var/obj/structure/disposalconstruct/C = new (src.loc)
C.ptype = 8 // 8 = Delivery chute
C.update()
C.anchored = 1
C.density = 1
qdel(src)
return
else
to_chat(user, "You need more welding fuel to complete this task.")
/obj/item/shippingPackage
name = "Shipping package"
desc = "A pre-labeled package for shipping an item to coworkers."
icon = 'icons/obj/storage.dmi'
icon_state = "shippack"
var/obj/item/wrapped = null
var/sortTag = 0
var/sealed = 0
/obj/item/shippingPackage/attackby(obj/item/O, mob/user, params)
if(sealed)
if(istype(O, /obj/item/weapon/pen))
var/str = copytext(sanitize(input(user,"Intended recipient?","Address","")),1,MAX_NAME_LEN)
if(!str || !length(str))
to_chat(user, "<span class='notice'>Invalid text.</span>")
return
user.visible_message("<span class='notice'>[user] addresses [src] to [str].</span>")
name = "Shipping package (RE: [str])"
return
if(wrapped)
to_chat(user, "<span class='notice'>[src] already contains \a [wrapped].</span>")
return
if(istype(O, /obj/item) && !istype(O, /obj/item/weapon/storage) && !istype(O, /obj/item/shippingPackage))
if(!user.canUnEquip(O))
to_chat(user, "<span class='warning'>[O] is stuck to your hand, you cannot put it in [src]!</span>")
return
if(O.w_class > 3)
to_chat(user, "<span class='notice'>[O] is too large to fit in [src].</span>")
else
wrapped = O
user.unEquip(O)
O.forceMove(src)
O.add_fingerprint(usr)
add_fingerprint(usr)
to_chat(user, "<span class='notice'>You put [O] in [src].</span>")
/obj/item/shippingPackage/attack_self(mob/user)
if(sealed)
to_chat(user, "<span class='notice'>You tear open [src], dropping the contents onto the floor.</span>")
playsound(loc, 'sound/items/poster_ripped.ogg', 50, 1)
user.unEquip(src)
wrapped.forceMove(get_turf(user))
wrapped = null
qdel(src)
else if(wrapped)
switch(alert("Select an action:",, "Remove Object", "Seal Package", "Cancel"))
if("Remove Object")
to_chat(user, "<span class='notice'>You shake out [src]'s contents onto the floor.</span>")
wrapped.forceMove(get_turf(user))
wrapped = null
if("Seal Package")
to_chat(user, "<span class='notice'>You seal [src], preparing it for delivery.</span>")
icon_state = "shippack_sealed"
sealed = 1
update_desc()
else
if(alert("Do you want to tear up the package?",, "Yes", "No") == "Yes")
to_chat(user, "<span class='notice'>You shred [src].</span>")
playsound(loc, 'sound/items/poster_ripped.ogg', 50, 1)
user.unEquip(src)
qdel(src)
/obj/item/shippingPackage/proc/update_desc()
desc = "A pre-labeled package for shipping an item to coworkers."
if(sortTag)
desc += " The label says \"Deliver to [TAGGERLOCATIONS[sortTag]]\"."
if(!sealed)
desc += " The package is not sealed."
/obj/item/shippingPackage/Destroy()
if(wrapped)
qdel(wrapped)
wrapped = null
return ..()
@@ -25,8 +25,8 @@
..()
/obj/item/slime_extract/New()
..()
create_reagents(100)
..()
create_reagents(100)
/obj/item/slime_extract/grey
name = "grey slime extract"
@@ -124,7 +124,9 @@
w_class = 1
origin_tech = "biotech=4"
/obj/item/slimepotion/afterattack(obj/item/weapon/reagent_containers/target, mob/user , proximity)
/obj/item/slimepotion/afterattack(obj/item/weapon/reagent_containers/target, mob/user, proximity_flag)
if(!proximity_flag)
return
if(istype(target))
to_chat(user, "<span class='notice'>You cannot transfer [src] to [target]! It appears the potion must be given directly to a slime to absorb.</span>") // le fluff faec
return
@@ -174,7 +176,7 @@
/obj/item/slimepotion/sentience
name = "sentience potion"
desc = "A miraculous chemical mix that can raise the intelligence of creatures to human levels. Unlike normal slime potions, it can be absorbed by any nonsentient being."
desc = "A miraculous chemical mix that can raise the intelligence of creatures to human levels."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle19"
origin_tech = "biotech=5"
@@ -182,7 +184,9 @@
var/being_used = 0
var/sentience_type = SENTIENCE_ORGANIC
/obj/item/slimepotion/sentience/afterattack(mob/living/M, mob/user)
/obj/item/slimepotion/sentience/afterattack(mob/living/M, mob/user, proximity_flag)
if(!proximity_flag)
return
if(being_used || !ismob(M))
return
if(!isanimal(M) || M.ckey) //only works on animals that aren't player controlled
@@ -221,6 +225,50 @@
being_used = 0
..()
/obj/item/slimepotion/transference
name = "consciousness transference potion"
desc = "A strange slime-based chemical that, when used, allows the user to transfer their consciousness to a lesser being."
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle19"
origin_tech = "biotech=6"
var/prompted = FALSE
var/animal_type = SENTIENCE_ORGANIC
/obj/item/slimepotion/transference/afterattack(mob/living/M, mob/user, proximity_flag)
if(!proximity_flag)
return
if(prompted || !ismob(M))
return
if(!isanimal(M) || M.ckey) //much like sentience, these will not work on something that is already player controlled
to_chat(user, "<span class='warning'>[M] already has a higher consciousness!</span>")
return ..()
if(M.stat)
to_chat(user, "<span class='warning'>[M] is dead!</span>")
return ..()
var/mob/living/simple_animal/SM = M
if(SM.sentience_type != animal_type)
to_chat(user, "<span class='warning'>You cannot transfer your consciousness to [SM].</span>") //no controlling machines
return ..()
if(jobban_isbanned(user, ROLE_SENTIENT))
to_chat(user, "<span class='warning'>Your mind goes blank as you attempt to use the potion.</span>")
return
prompted = TRUE
if(alert("This will permanently transfer your consciousness to [SM]. Are you sure you want to do this?",,"Yes","No")=="No")
prompted = FALSE
return
to_chat(user, "<span class='notice'>You drink the potion then place your hands on [SM]...</span>")
user.mind.transfer_to(SM)
SM.universal_speak = 1
SM.faction = user.faction
SM.sentience_act() //Same deal here as with sentience
user.death()
to_chat(SM, "<span class='notice'>In a quick flash, you feel your consciousness flow into [SM]!</span>")
to_chat(SM, "<span class='warning'>You are now [SM]. Your allegiances, alliances, and roles are still the same as they were prior to consciousness transfer!</span>")
SM.name = "[SM.name] as [user.real_name]"
qdel(src)
/obj/item/slimepotion/steroid
name = "slime steroid"
desc = "A potent chemical mix that will cause a baby slime to generate more extract."
@@ -303,15 +351,17 @@
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle3"
/obj/item/slimepotion/speed/afterattack(obj/item/C, mob/user)
/obj/item/slimepotion/speed/afterattack(obj/item/C, mob/user, proximity_flag)
if(!proximity_flag)
return
..()
if(!istype(C))
to_chat(user, "<span class='warning'>The potion can only be used on items!</span>")
return
if(C.slowdown <= 0)
to_chat(user, "<span class='warning'>The [C] can't be made any faster!</span>")
to_chat(user, "<span class='warning'>[C] can't be made any faster!</span>")
return..()
to_chat(user, "<span class='notice'>You slather the red gunk over the [C], making it faster.</span>")
to_chat(user, "<span class='notice'>You slather the red gunk over [C], making it faster.</span>")
C.color = "#FF0000"
C.slowdown = 0
qdel(src)
@@ -323,8 +373,10 @@
icon_state = "bottle17"
var/uses = 3
/obj/item/slimepotion/fireproof/afterattack(obj/item/clothing/C, mob/user)
/obj/item/slimepotion/fireproof/afterattack(obj/item/clothing/C, mob/user, proximity_flag)
..()
if(!proximity_flag)
return
if(!uses)
qdel(src)
return
@@ -332,9 +384,9 @@
to_chat(user, "<span class='warning'>The potion can only be used on clothing!</span>")
return
if(C.max_heat_protection_temperature == FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
to_chat(user, "<span class='warning'>The [C] is already fireproof!</span>")
to_chat(user, "<span class='warning'>[C] is already fireproof!</span>")
return ..()
to_chat(user, "<span class='notice'>You slather the blue gunk over the [C], fireproofing it.</span>")
to_chat(user, "<span class='notice'>You slather the blue gunk over [C], fireproofing it.</span>")
C.name = "fireproofed [C.name]"
C.color = "#000080"
C.max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
@@ -366,9 +418,9 @@
else
icon_state = "golem"
/obj/effect/golemrune/attack_hand(mob/living/user as mob)
/obj/effect/golemrune/attack_hand(mob/living/user)
var/mob/dead/observer/ghost
for(var/mob/dead/observer/O in src.loc)
for(var/mob/dead/observer/O in loc)
if(!check_observer(O))
to_chat(O, "\red You are not eligible to become a golem.")
continue
@@ -391,21 +443,22 @@
volunteer(O)
/obj/effect/golemrune/attack_ghost(var/mob/dead/observer/O)
if(!O) return
if(!O)
return
volunteer(O)
/obj/effect/golemrune/proc/check_observer(var/mob/dead/observer/O)
if(!O)
return 0
return FALSE
if(!O.client)
return 0
return FALSE
if(O.mind && O.mind.current && O.mind.current.stat != DEAD)
return 0
return FALSE
if(!O.can_reenter_corpse)
return 0
return FALSE
if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
return 0
return 1
return FALSE
return TRUE
/obj/effect/golemrune/proc/volunteer(var/mob/dead/observer/O)
if(O in ghosts)
@@ -448,8 +501,8 @@
/obj/effect/timestop/proc/timestop()
playsound(get_turf(src), 'sound/magic/TIMEPARADOX2.ogg', 100, 1, -1)
for(var/i in 1 to duration-1)
for(var/A in orange (freezerange, src.loc))
if(istype(A, /mob/living))
for(var/A in orange (freezerange, loc))
if(isliving(A))
var/mob/living/M = A
if(M in immune)
continue
+1 -2
View File
@@ -24,14 +24,13 @@
return 0
var/dental_implants = 0
for(var/obj/item/weapon/reagent_containers/food/pill in target.internal_organs) // Can't give them more than 4 dental implants.
for(var/obj/item/weapon/reagent_containers/food/pill in target.contents) // Can't give them more than 4 dental implants.
dental_implants++
if(dental_implants >= 4)
user.visible_message("[user] pulls \the [tool] back out of [target]'s [parse_zone(target_zone)]!", "<span class='notice'>You pull \the [tool] back out of [target]'s [parse_zone(target_zone)], there wans't enough room...</span>")
return 0
user.drop_item()
target.internal_organs += tool
tool.forceMove(target)
var/datum/action/item_action/hands_free/activate_pill/P = new