Merge branch 'master' into spike-loot-differentces

This commit is contained in:
Trilbyspaceclone
2020-08-30 00:41:42 -04:00
committed by GitHub
501 changed files with 14987 additions and 7944 deletions
+1 -1
View File
@@ -46,4 +46,4 @@
var/turf/T = loc
if(!istype(T)) //you know this will happen somehow
CRASH("Turf decal initialized in an object/nullspace")
T.AddElement(/datum/element/decal, icon, icon_state, turn(dir, -dir2angle(T.dir)), CLEAN_GOD, color, null, null, alpha)
T.AddElement(/datum/element/decal, icon, icon_state, dir, CLEAN_GOD, color, null, null, alpha)
-1
View File
@@ -242,7 +242,6 @@ RLD
var/datum/browser/popup = new(user, "rcd_access", "Access Control", 900, 500, src)
popup.set_content(t1)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
/obj/item/construction/rcd/Topic(href, href_list)
+1 -1
View File
@@ -266,7 +266,7 @@ GLOBAL_LIST_EMPTY(PDAs)
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/simple/pda)
assets.send(user)
var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/goonchat)
var/datum/asset/spritesheet/emoji_s = get_asset_datum(/datum/asset/spritesheet/chat)
emoji_s.send(user) //Already sent by chat but no harm doing this
user.set_machine(src)
+1 -1
View File
@@ -590,7 +590,7 @@ Code:
var/static/list/emoji_icon_states
var/static/emoji_table
if(!emoji_table)
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat)
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/chat)
var/list/collate = list("<br><table>")
for(var/emoji in sortList(icon_states(icon('icons/emoji.dmi'))))
var/tag = sheet.icon_tag("emoji-[emoji]")
@@ -0,0 +1,207 @@
/obj/item/storage/portable_chem_mixer
name = "Portable Chemical Mixer"
desc = "A portable device that dispenses and mixes chemicals. All necessary reagents need to be supplied with beakers. A label indicates that a screwdriver is required to open it for refills. This device can be worn on a belt. The letters 'S&T' are imprinted on the side."
icon = 'icons/obj/chemical.dmi'
icon_state = "portablechemicalmixer_open"
w_class = WEIGHT_CLASS_HUGE
slot_flags = ITEM_SLOT_BELT
custom_price = 2000
custom_premium_price = 2000
var/obj/item/reagent_containers/beaker = null ///Creating an empty slot for a beaker that can be added to dispense into
var/amount = 30 ///The amount of reagent that is to be dispensed currently
var/list/dispensable_reagents = list() ///List in which all currently dispensable reagents go
/obj/item/storage/portable_chem_mixer/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 200
STR.max_items = 50
STR.insert_preposition = "in"
STR.can_hold = typecacheof(list(
/obj/item/reagent_containers/glass/beaker,
))
/obj/item/storage/portable_chem_mixer/Destroy()
QDEL_NULL(beaker)
return ..()
/obj/item/storage/portable_chem_mixer/ex_act(severity, target)
if(severity < 3)
..()
/obj/item/storage/portable_chem_mixer/attackby(obj/item/I, mob/user, params)
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if (I.tool_behaviour == TOOL_SCREWDRIVER)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, !locked)
if (!locked)
update_contents()
if (locked)
replace_beaker(user)
update_icon()
I.play_tool_sound(src, 50)
return
else if (istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container() && locked)
var/obj/item/reagent_containers/B = I
. = TRUE //no afterattack
if(!user.transferItemToLoc(B, src))
return
replace_beaker(user, B)
update_icon()
updateUsrDialog()
return
return ..()
/**
* Updates the contents of the portable chemical mixer
*
* A list of dispensable reagents is created by iterating through each source beaker in the portable chemical beaker and reading its contents
*/
/obj/item/storage/portable_chem_mixer/proc/update_contents()
dispensable_reagents.Cut()
for (var/obj/item/reagent_containers/glass/beaker/B in contents)
var/key = B.reagents.get_master_reagent_id()
if (!(key in dispensable_reagents))
dispensable_reagents[key] = list()
dispensable_reagents[key]["reagents"] = list()
dispensable_reagents[key]["reagents"] += B.reagents
return
/obj/item/storage/portable_chem_mixer/update_icon_state()
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if (!locked)
icon_state = "portablechemicalmixer_open"
else if (beaker)
icon_state = "portablechemicalmixer_full"
else
icon_state = "portablechemicalmixer_empty"
/obj/item/storage/portable_chem_mixer/AltClick(mob/living/user)
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if (!locked)
return ..()
if(!can_interact(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
replace_beaker(user)
update_icon()
/**
* Replaces the beaker of the portable chemical mixer with another beaker, or simply adds the new beaker if none is in currently
*
* Checks if a valid user and a valid new beaker exist and attempts to replace the current beaker in the portable chemical mixer with the one in hand. Simply places the new beaker in if no beaker is currently loaded
* Arguments:
* * mob/living/user - The user who is trying to exchange beakers
* * obj/item/reagent_containers/new_beaker - The new beaker that the user wants to put into the device
*/
/obj/item/storage/portable_chem_mixer/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(!user)
return FALSE
if(beaker)
user.put_in_hands(beaker)
beaker = null
if(new_beaker)
beaker = new_beaker
return TRUE
/obj/item/storage/portable_chem_mixer/attack_hand(mob/user)
if (loc != user)
return ..()
if(SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED))
ui_interact(user)
return
/obj/item/storage/portable_chem_mixer/attack_self(mob/user)
if(loc == user)
var/locked = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
if (locked)
ui_interact(user)
return
else
to_chat(user, "<span class='notice'>The portable chemical mixer is currently open and its contents can be accessed.</span>")
return
return
/obj/item/storage/portable_chem_mixer/MouseDrop(obj/over_object)
. = ..()
if(ismob(loc))
var/mob/M = loc
if(!M.incapacitated() && istype(over_object, /obj/screen/inventory/hand))
var/obj/screen/inventory/hand/H = over_object
M.putItemFromInventoryInHandIfPossible(src, H.held_index)
/obj/item/storage/portable_chem_mixer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PortableChemMixer", name)
if(user.hallucinating())
// to not ruin the immersion by constantly changing the fake chemicals
ui.set_autoupdate(FALSE)
ui.open()
/obj/item/storage/portable_chem_mixer/ui_data(mob/user)
var/list/data = list()
data["amount"] = amount
data["isBeakerLoaded"] = beaker ? 1 : 0
data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null
data["beakerMaxVolume"] = beaker ? beaker.volume : null
data["beakerTransferAmounts"] = beaker ? beaker.possible_transfer_amounts : null
var/chemicals[0]
var/is_hallucinating = user.hallucinating()
if(user.hallucinating())
is_hallucinating = TRUE
for(var/re in dispensable_reagents)
var/value = dispensable_reagents[re]
var/datum/reagent/temp = GLOB.chemical_reagents_list[re]
if(temp)
var/chemname = temp.name
var/total_volume = 0
for (var/datum/reagents/rs in value["reagents"])
total_volume += rs.total_volume
if(is_hallucinating && prob(5))
chemname = "[pick_list_replacements("hallucination.json", "chemicals")]"
chemicals.Add(list(list("title" = chemname, "id" = ckey(temp.name), "volume" = total_volume )))
data["chemicals"] = chemicals
var/beakerContents[0]
if(beaker)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "id" = ckey(R.name), "volume" = R.volume))) // list in a list because Byond merges the first list...
data["beakerContents"] = beakerContents
return data
/obj/item/storage/portable_chem_mixer/ui_act(action, params)
if(..())
return
switch(action)
if("amount")
var/target = text2num(params["target"])
amount = target
. = TRUE
if("dispense")
var/reagent_name = params["reagent"]
var/datum/reagent/reagent = GLOB.name2reagent[reagent_name]
var/entry = dispensable_reagents[reagent]
if(beaker)
var/datum/reagents/R = beaker.reagents
var/actual = min(amount, 1000, R.maximum_volume - R.total_volume)
// todo: add check if we have enough reagent left
for (var/datum/reagents/source in entry["reagents"])
var/to_transfer = min(source.total_volume, actual)
source.trans_to(beaker, to_transfer)
actual -= to_transfer
if (actual <= 0)
break
. = TRUE
if("remove")
var/amount = text2num(params["amount"])
beaker.reagents.remove_all(amount)
. = TRUE
if("eject")
replace_beaker(usr)
update_icon()
. = TRUE
@@ -16,9 +16,6 @@
var/on = TRUE
var/shock_cooldown = FALSE
var/ui_x = 260
var/ui_y = 137
/obj/item/electropack/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] hooks [user.p_them()]self to the electropack and spams the trigger! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (FIRELOSS)
@@ -201,17 +198,7 @@
else
return ..()
/obj/item/electropack/shockcollar/ui_interact(mob/user) //note to src: use tgooey
var/dat = {"
<TT>
<B>Frequency/Code</B> for shock collar:<BR>
Frequency:
[format_frequency(src.frequency)]
<A href='byond://?src=[REF(src)];set=freq'>Set</A><BR>
Code:
[src.code]
<A href='byond://?src=[REF(src)];set=code'>Set</A><BR>
</TT>"}
user << browse(dat, "window=radio")
onclose(user, "radio")
return
/obj/item/electropack/ui_act(action, params)
if(action == "power") // DO. NOT.
return FALSE
return ..()
+6 -3
View File
@@ -296,7 +296,8 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
w_class = WEIGHT_CLASS_BULKY
force = 9
force = 7 //how much harm mode damage we do
var/stamina_damage_increment = 4 //how much extra damage do we do when in non-harm mode
throwforce = 10
damtype = STAMINA
attack_verb = list("whacked", "smacked", "struck")
@@ -347,17 +348,19 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/melee/bokken/Initialize()
. = ..()
AddElement(/datum/element/sword_point)
if(!harm) //if initialised in non-harm mode, setup force accordingly
force = force + stamina_damage_increment
/obj/item/melee/bokken/attack_self(mob/user)
harm = !harm
if(harm)
force -= 2
force -= stamina_damage_increment
damtype = BRUTE
attack_verb = list("bashed", "smashed", "attacked")
bare_wound_bonus = 15 // having your leg smacked by a wooden stick is probably not great for it if it's naked
wound_bonus = 0
else
force += 2
force += stamina_damage_increment
damtype = STAMINA
attack_verb = list("whacked", "smacked", "struck")
bare_wound_bonus = 0
+9 -1
View File
@@ -143,10 +143,18 @@
var/amt = max(0, ((force - (move_resist * MOVE_FORCE_CRUSH_RATIO)) / (move_resist * MOVE_FORCE_CRUSH_RATIO)) * 10)
take_damage(amt, BRUTE)
#define BLACKLISTED_OBJECTS list(/obj/machinery/power/apc, /obj/machinery/airalarm, /obj/machinery/power/smes, /obj/structure/cable)
/obj/attack_slime(mob/living/simple_animal/slime/user)
if(!user.is_adult)
return
attack_generic(user, rand(10, 15), "melee", 1)
if(src.type in BLACKLISTED_OBJECTS)
return
if(istype(src, /obj/machinery/atmospherics))
return
attack_generic(user, rand(10, 15), BRUTE, "melee", 1)
#undef BLACKLISTED_OBJECTS
/obj/mech_melee_attack(obj/mecha/M)
M.do_attack_animation(src)
+13 -11
View File
@@ -304,18 +304,20 @@
/obj/proc/reskin_obj(mob/M)
if(!LAZYLEN(unique_reskin))
return
var/dat = "<b>Reskin options for [name]:</b>\n"
for(var/V in unique_reskin)
var/output = icon2html(src, M, unique_reskin[V])
dat += "[V]: <span class='reallybig'>[output]</span>\n"
to_chat(M, dat)
var/choice = input(M, always_reskinnable ? "Choose the a reskin for [src]" : "Warning, you can only reskin [src] once!","Reskin Object") as null|anything in unique_reskin
if(QDELETED(src) || !choice || (current_skin && !always_reskinnable) || M.incapacitated() || !in_range(M,src) || !unique_reskin[choice] || unique_reskin[choice] == current_skin)
return
current_skin = choice
var/list/skins = list()
for(var/S in unique_reskin)
skins[S] = image(icon = icon, icon_state = unique_reskin[S])
var/choice = show_radial_menu(M, src, skins, custom_check = CALLBACK(src, .proc/check_skinnable, M), radius = 40, require_near = TRUE)
if(!choice)
return FALSE
icon_state = unique_reskin[choice]
to_chat(M, "[src] is now skinned as '[choice]'.")
current_skin = choice
return
/obj/proc/check_skinnable(/mob/M)
if(current_skin || !always_reskinnable)
return FALSE
return TRUE
/obj/update_overlays()
. = ..()
@@ -4,25 +4,6 @@
req_access = list(ACCESS_ALL_PERSONAL_LOCKERS)
var/registered_name = null
/obj/structure/closet/secure_closet/personal/examine(mob/user)
. = ..()
if(registered_name)
. += "<span class='notice'>The display reads, \"Owned by [registered_name]\".</span>"
/obj/structure/closet/secure_closet/personal/check_access(obj/item/I)
. = ..()
if(!I || !istype(I))
return
if(istype(I,/obj/item/modular_computer/tablet))
var/obj/item/modular_computer/tablet/ourTablet = I
var/obj/item/computer_hardware/card_slot/card_slot = ourTablet.all_components[MC_CARD]
if(card_slot)
return registered_name == card_slot.stored_card.registered_name || registered_name == card_slot.stored_card2.registered_name
var/obj/item/card/id/ID = I.GetID()
if(ID && registered_name == ID.registered_name)
return TRUE
return FALSE
/obj/structure/closet/secure_closet/personal/PopulateContents()
..()
if(prob(50))
@@ -54,15 +35,24 @@
/obj/structure/closet/secure_closet/personal/attackby(obj/item/W, mob/user, params)
var/obj/item/card/id/I = W.GetID()
if(!I || !istype(I))
return ..()
if(!can_lock(user, FALSE)) //Can't do anything if there isn't a lock!
return
if(I.registered_name && !registered_name)
to_chat(user, "<span class='notice'>You claim [src].</span>")
registered_name = I.registered_name
if(istype(I))
if(broken)
to_chat(user, "<span class='danger'>It appears to be broken.</span>")
return
if(!I || !I.registered_name)
return
if(allowed(user) || !registered_name || (istype(I) && (registered_name == I.registered_name)))
//they can open all lockers, or nobody owns this, or they own this locker
locked = !locked
update_icon()
if(!registered_name)
registered_name = I.registered_name
desc = "Owned by [I.registered_name]."
else
to_chat(user, "<span class='danger'>Access Denied.</span>")
else
..()
return ..()
/obj/structure/closet/secure_closet/personal/handle_lock_addition() //If lock construction is successful we don't care what access the electronics had, so we override it
if(..())