This commit is contained in:
Ghommie
2020-06-23 00:13:14 +02:00
727 changed files with 240611 additions and 242127 deletions
+5
View File
@@ -428,6 +428,11 @@
desc = "A poster decipting a snake shaped into an ominous 'S'!"
icon_state = "poster47"
/obj/structure/sign/poster/contraband/bountyhunters
name = "Bounty Hunters"
desc = "A poster advertising bounty hunting services. \"I hear you got a problem.\""
icon_state = "poster48"
/obj/structure/sign/poster/official
poster_item_name = "motivational poster"
poster_item_desc = "An official Nanotrasen-issued poster to foster a compliant and obedient workforce. It comes with state-of-the-art adhesive backing, for easy pinning to any vertical surface."
+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.AddComponent(/datum/component/decal, icon, icon_state, dir, CLEAN_GOD, color, null, null, alpha)
T.AddElement(/datum/element/decal, icon, icon_state, turn(dir, -dir2angle(T.dir)), CLEAN_GOD, color, null, null, alpha)
+28 -10
View File
@@ -5,19 +5,21 @@
anchored = TRUE
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "uglymine"
var/triggered = 0
/// We manually check to see if we've been triggered in case multiple atoms cross us in the time between the mine being triggered and it actually deleting, to avoid a race condition with multiple detonations
var/triggered = FALSE
/obj/effect/mine/proc/mineEffect(mob/victim)
to_chat(victim, "<span class='danger'>*click*</span>")
/obj/effect/mine/Crossed(AM as mob|obj)
if(isturf(loc))
if(ismob(AM))
var/mob/MM = AM
if(!(MM.movement_type & FLYING))
triggermine(AM)
else
triggermine(AM)
/obj/effect/mine/Crossed(atom/movable/AM)
if(triggered || !isturf(loc))
return
. = ..()
if(AM.movement_type & FLYING)
return
triggermine(AM)
/obj/effect/mine/proc/triggermine(mob/victim)
if(triggered)
@@ -27,9 +29,13 @@
s.set_up(3, 1, src)
s.start()
mineEffect(victim)
SEND_SIGNAL(src, COMSIG_MINE_TRIGGERED)
triggered = 1
qdel(src)
/obj/effect/mine/take_damage(damage_amount, damage_type, damage_flag, sound_effect, attack_dir)
. = ..()
triggermine()
/obj/effect/mine/explosive
name = "explosive mine"
@@ -50,6 +56,18 @@
if(isliving(victim))
victim.DefaultCombatKnockdown(stun_time)
/obj/effect/mine/shrapnel
name = "shrapnel mine"
var/shrapnel_type = /obj/item/projectile/bullet/shrapnel
var/shrapnel_magnitude = 3
/obj/effect/mine/shrapnel/mineEffect(mob/victim)
AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_magnitude)
/obj/effect/mine/shrapnel/sting
name = "stinger mine"
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball
/obj/effect/mine/kickmine
name = "kick mine"
@@ -105,7 +123,7 @@
/obj/effect/mine/pickup/triggermine(mob/victim)
if(triggered)
return
triggered = 1
triggered = TRUE
invisibility = INVISIBILITY_ABSTRACT
mineEffect(victim)
qdel(src)
+90 -3
View File
@@ -491,7 +491,7 @@
/obj/item/kitchen/knife = 5,
/obj/item/screwdriver = 5,
/obj/item/crowbar/red = 1, //Dont you need a crowbar to open this?
/obj/item/stack/medical/bruise_pack = 3,
/obj/item/stack/medical/suture = 3,
/obj/item/reagent_containers/food/drinks/bottle/vodka = 2,
/obj/item/radio = 5,
/obj/item/flashlight = 4,
@@ -611,13 +611,13 @@
/obj/item/clothing/mask/breath = 5,
/obj/item/clothing/mask/breath/medical = 1
)
/obj/effect/spawner/lootdrop/welder_tools/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/low_tools/no_turf
spawn_on_turf = FALSE
/obj/effect/spawner/lootdrop/breathing_tanks/no_turf
spawn_on_turf = FALSE
@@ -644,3 +644,90 @@
/obj/effect/spawner/lootdrop/glowstick/no_turf
spawn_on_turf = FALSE
// Random Parts
/obj/effect/spawner/lootdrop/stock_parts
name = "random stock parts spawner"
lootcount = 1
loot = list(
/obj/item/stock_parts/capacitor,
/obj/item/stock_parts/scanning_module,
/obj/item/stock_parts/manipulator,
/obj/item/stock_parts/micro_laser,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/cell
)
// Random Weapon Parts
/obj/effect/spawner/lootdrop/weapon_parts
name = "random weapon parts spawner 50%"
lootcount = 1
spawn_on_turf = FALSE
loot = list("" = 50,
/obj/item/weaponcrafting/improvised_parts/barrel_rifle = 10,
/obj/item/weaponcrafting/improvised_parts/barrel_shotgun = 5,
/obj/item/weaponcrafting/improvised_parts/barrel_pistol = 5,
/obj/item/weaponcrafting/improvised_parts/rifle_receiver = 10,
/obj/item/weaponcrafting/improvised_parts/shotgun_receiver = 3,
/obj/item/weaponcrafting/improvised_parts/pistol_receiver = 3,
/obj/item/weaponcrafting/improvised_parts/laser_receiver = 1,
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 10,
/obj/item/weaponcrafting/improvised_parts/makeshift_lens = 3,
)
/obj/effect/spawner/lootdrop/weapon_parts
name = "random weapon parts spawner 25%"
lootcount = 1
spawn_on_turf = FALSE
loot = list("" = 75,
/obj/item/weaponcrafting/improvised_parts/barrel_rifle = 5,
/obj/item/weaponcrafting/improvised_parts/barrel_pistol = 5,
/obj/item/weaponcrafting/improvised_parts/rifle_receiver = 5,
/obj/item/weaponcrafting/improvised_parts/pistol_receiver = 2,
/obj/item/weaponcrafting/improvised_parts/trigger_assembly = 5,
/obj/item/weaponcrafting/improvised_parts/makeshift_lens = 3,
)
/obj/effect/spawner/lootdrop/ammo
name = "random ammo 75%"
lootcount = 1
spawn_on_turf = FALSE
loot = list("" = 25,
/obj/item/ammo_box/c32mm = 15,
/obj/item/ammo_box/r32mm = 15,
/obj/item/ammo_box/magazine/wt550m9 = 1,
/obj/item/ammo_casing/shotgun/buckshot = 7,
/obj/item/ammo_casing/shotgun/rubbershot = 7,
/obj/item/ammo_casing/a762 = 15,
/obj/item/ammo_box/a762 = 15,
)
/obj/effect/spawner/lootdrop/ammo/fiftypercent
name = "random ammo 50%"
lootcount = 1
spawn_on_turf = FALSE
loot = list("" = 50,
/obj/item/ammo_box/c32mm = 7,
/obj/item/ammo_box/r32mm = 7,
/obj/item/ammo_box/magazine/wt550m9 = 2,
/obj/item/ammo_casing/shotgun/buckshot = 10,
/obj/item/ammo_casing/shotgun/rubbershot = 10,
/obj/item/ammo_casing/a762 = 7,
/obj/item/ammo_box/a762 = 7,
)
/obj/effect/spawner/lootdrop/ammo/shotgun
name = "random ammo 50%"
lootcount = 1
spawn_on_turf = FALSE
loot = list("" = 50,
/obj/item/ammo_box/shotgun/loaded/buckshot = 5,
/obj/item/ammo_box/shotgun/loaded/beanbag = 5,
/obj/item/ammo_box/shotgun/loaded/incendiary = 5,
/obj/item/ammo_casing/shotgun/buckshot = 8,
/obj/item/ammo_casing/shotgun/rubbershot = 9,
/obj/item/ammo_casing/shotgun = 8,
/obj/item/ammo_casing/shotgun/incendiary = 10,
)
@@ -95,6 +95,56 @@
icon_state = "warden_gaze"
duration = 3
/obj/effect/temp_visual/ratvar/volt_hit
name = "volt blast"
layer = ABOVE_MOB_LAYER
duration = 8
icon_state = "volt_hit"
light_range = 1.5
light_power = 2
light_color = LIGHT_COLOR_ORANGE
var/mob/user
var/damage = 20
/obj/effect/temp_visual/ratvar/volt_hit/Initialize(mapload, caster)
. = ..()
user = caster
if(user)
var/matrix/M = new
M.Turn(Get_Angle(src, user))
transform = M
INVOKE_ASYNC(src, .proc/volthit)
/obj/effect/temp_visual/ratvar/volt_hit/proc/volthit()
if(user)
Beam(get_turf(user), "volt_ray", time=duration, maxdistance=8, beam_type=/obj/effect/ebeam/volt_ray)
var/hit_amount = 0
var/turf/T = get_turf(src)
for(var/mob/living/L in T)
if(is_servant_of_ratvar(L))
continue
var/obj/item/I = L.anti_magic_check()
if(I)
L.visible_message("<span class='warning'>Strange energy flows into [L]'s [I.name]!</span>", \
"<span class='userdanger'>Your [I.name] shields you from [src]!</span>")
continue
L.visible_message("<span class='warning'>[L] is struck by a [name]!</span>", "<span class='userdanger'>You're struck by a [name]!</span>")
L.apply_damage(damage, BURN, "chest", L.run_armor_check("chest", "laser", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 0, "Your armor was penetrated by [src]!"))
log_combat(user, L, "struck with a volt blast")
hit_amount++
for(var/obj/mecha/M in T)
if(M.occupant)
if(is_servant_of_ratvar(M.occupant))
continue
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
M.visible_message("<span class='warning'>[M] is struck by a [name]!</span>")
M.take_damage(damage, BURN, 0, 0)
hit_amount++
if(hit_amount)
playsound(src, 'sound/machines/defib_zap.ogg', damage*hit_amount, 1, -1)
else
playsound(src, "sparks", 50, 1)
/obj/effect/temp_visual/ratvar/ocular_warden/Initialize()
. = ..()
pixel_x = rand(-8, 8)
+194 -19
View File
@@ -4,6 +4,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// if true, everyone item when created will have its name changed to be
// more... RPG-like.
GLOBAL_VAR_INIT(stickpocalypse, FALSE) // if true, all non-embeddable items will be able to harmlessly stick to people when thrown
GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to embed in people, takes precedence over stickpocalypse
/obj/item
name = "item"
icon = 'icons/obj/items_and_weapons.dmi'
@@ -55,6 +58,15 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/// How long, in deciseconds, this staggers for, if null it will autocalculate from w_class and force. Unlike total mass this supports 0 and negatives.
var/stagger_force
/**
* Set FALSE and then checked at the end of on mob/living/attackby(), set TRUE on living/pre_attacked_by().
* Should it be FALSE by the end of the item/attack(), that means the item overrode the standard attack behaviour
* and the user still needs the delay applied. We can't be using return values since that'll stop afterattack() from being triggered.
*/
var/attack_delay_done = FALSE
///next_move click/attack delay of this item.
var/click_delay = CLICK_CD_MELEE
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
pass_flags = PASSTABLE
pressure_resistance = 4
@@ -95,7 +107,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged
var/datum/embedding_behavior/embedding
var/list/embedding = NONE
var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES
var/heat = 0
@@ -132,6 +144,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/list/grind_results //A reagent list containing the reagents this item produces when ground up in a grinder - this can be an empty list to allow for reagent transferring only
var/list/juice_results //A reagent list containing blah blah... but when JUICED in a grinder!
/* Our block parry data. Should be set in init, or something if you are using it.
* This won't be accessed without ITEM_CAN_BLOCK or ITEM_CAN_PARRY so do not set it unless you have to to save memory.
* If you decide it's a good idea to leave this unset while turning the flags on, you will runtime. Enjoy.
* If this is set to a path, it'll run get_block_parry_data(path). YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
*/
var/datum/block_parry_data/block_parry_data
///Skills vars
//list of skill PATHS exercised when using this item. An associated bitfield can be set to indicate additional ways the skill is used by this specific item.
var/list/datum/skill/used_skills
@@ -143,7 +162,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
/obj/item/Initialize()
if (attack_verb)
if(attack_verb)
attack_verb = typelist("attack_verb", attack_verb)
. = ..()
@@ -151,9 +170,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
new path(src)
actions_types = null
if(GLOB.rpg_loot_items)
AddComponent(/datum/component/fantasy)
if(force_string)
item_flags |= FORCE_STRING_OVERRIDE
@@ -163,16 +179,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(damtype == "brute")
hitsound = "swing_hit"
if (!embedding)
embedding = getEmbeddingBehavior()
else if (islist(embedding))
embedding = getEmbeddingBehavior(arglist(embedding))
else if (!istype(embedding, /datum/embedding_behavior))
stack_trace("Invalid type [embedding.type] found in .embedding during /obj/item Initialize()")
if(sharpness) //give sharp objects butchering functionality, for consistency
AddComponent(/datum/component/butchering, 80 * toolspeed)
/obj/item/Destroy()
item_flags &= ~DROPDEL //prevent reqdels
if(ismob(loc))
@@ -182,6 +188,26 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
qdel(X)
return ..()
/obj/item/ComponentInitialize()
. = ..()
// this proc says it's for initializing components, but we're initializing elements too because it's you and me against the world >:)
if(!LAZYLEN(embedding))
if(GLOB.embedpocalypse)
embedding = EMBED_POINTY
name = "pointy [name]"
else if(GLOB.stickpocalypse)
embedding = EMBED_HARMLESS
name = "sticky [name]"
updateEmbedding()
if(GLOB.rpg_loot_items)
AddComponent(/datum/component/fantasy)
if(sharpness) //give sharp objects butchering functionality, for consistency
AddComponent(/datum/component/butchering, 80 * toolspeed)
/obj/item/proc/check_allowed_items(atom/target, not_inside, target_self)
if(((src in target) && !target_self) || (!isturf(target.loc) && !isturf(target) && not_inside))
return 0
@@ -232,8 +258,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if(resistance_flags & FIRE_PROOF)
. += "[src] is made of fire-retardant materials."
if(item_flags & (ITEM_CAN_BLOCK | ITEM_CAN_PARRY))
var/datum/block_parry_data/data = return_block_parry_datum(block_parry_data)
. += "[src] has the capacity to be used to block and/or parry. <a href='?src=[REF(data)];name=[name];block=[item_flags & ITEM_CAN_BLOCK];parry=[item_flags & ITEM_CAN_PARRY];render=1'>\[Show Stats\]</a>"
if(!user.research_scanner)
return
@@ -395,6 +422,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
return ITALICS | REDUCE_RANGE
/obj/item/proc/dropped(mob/user)
SHOULD_CALL_PARENT(TRUE)
for(var/X in actions)
var/datum/action/A = X
A.Remove(user)
@@ -407,6 +435,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// called just as an item is picked up (loc is not yet changed)
/obj/item/proc/pickup(mob/user)
SHOULD_CALL_PARENT(TRUE)
SEND_SIGNAL(src, COMSIG_ITEM_PICKUP, user)
item_flags |= IN_INVENTORY
@@ -606,6 +635,18 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/itempush = 1
if(w_class < 4)
itempush = 0 //too light to push anything
if(isliving(hit_atom)) //Living mobs handle hit sounds differently.
var/volume = get_volume_by_throwforce_and_or_w_class()
if (throwforce > 0)
if (throwhitsound)
playsound(hit_atom, throwhitsound, volume, TRUE, -1)
else if(hitsound)
playsound(hit_atom, hitsound, volume, TRUE, -1)
else
playsound(hit_atom, 'sound/weapons/genhit.ogg',volume, TRUE, -1)
else
playsound(hit_atom, 'sound/weapons/throwtap.ogg', 1, volume, -1)
return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum)
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE)
@@ -899,11 +940,13 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
// if w_volume is 0 you fucked up anyways lol
return w_volume || AUTO_SCALE_VOLUME(w_class)
/obj/item/proc/embedded(mob/living/carbon/human/embedded_mob)
/obj/item/proc/embedded(atom/embedded_target)
return
/obj/item/proc/unembedded()
return
if(item_flags & DROPDEL)
QDEL_NULL(src)
return TRUE
/**
* Sets our slowdown and updates equipment slowdown of any mob we're equipped on.
@@ -919,3 +962,135 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
. = ..()
if(var_name == NAMEOF(src, slowdown))
set_slowdown(var_value) //don't care if it's a duplicate edit as slowdown'll be set, do it anyways to force normal behavior.
/**
* Does the current embedding var meet the criteria for being harmless? Namely, does it explicitly define the pain multiplier and jostle pain mult to be 0? If so, return true.
*
*/
/obj/item/proc/isEmbedHarmless()
if(embedding)
return !isnull(embedding["pain_mult"]) && !isnull(embedding["jostle_pain_mult"]) && embedding["pain_mult"] == 0 && embedding["jostle_pain_mult"] == 0
///In case we want to do something special (like self delete) upon failing to embed in something, return true
/obj/item/proc/failedEmbed()
if(item_flags & DROPDEL)
QDEL_NULL(src)
return TRUE
/**
* tryEmbed() is for when you want to try embedding something without dealing with the damage + hit messages of calling hitby() on the item while targetting the target.
*
* Really, this is used mostly with projectiles with shrapnel payloads, from [/datum/element/embed/proc/checkEmbedProjectile], and called on said shrapnel. Mostly acts as an intermediate between different embed elements.
*
* Arguments:
* * target- Either a body part, a carbon, or a closed turf. What are we hitting?
* * forced- Do we want this to go through 100%?
*/
/obj/item/proc/tryEmbed(atom/target, forced=FALSE, silent=FALSE)
if(!isbodypart(target) && !iscarbon(target) && !isclosedturf(target))
return
if(!forced && !LAZYLEN(embedding))
return
if(SEND_SIGNAL(src, COMSIG_EMBED_TRY_FORCE, target, forced, silent))
return TRUE
failedEmbed()
///For when you want to disable an item's embedding capabilities (like transforming weapons and such), this proc will detach any active embed elements from it.
/obj/item/proc/disableEmbedding()
SEND_SIGNAL(src, COMSIG_ITEM_DISABLE_EMBED)
return
///For when you want to add/update the embedding on an item. Uses the vars in [/obj/item/embedding], and defaults to config values for values that aren't set. Will automatically detach previous embed elements on this item.
/obj/item/proc/updateEmbedding()
if(!islist(embedding) || !LAZYLEN(embedding))
return
AddElement(/datum/element/embed,\
embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\
fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\
pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\
pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\
remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\
rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\
ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\
impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\
jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\
jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\
pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\
embed_chance_turf_mod = (!isnull(embedding["embed_chance_turf_mod"]) ? embedding["embed_chance_turf_mod"] : EMBED_CHANCE_TURF_MOD))
return TRUE
+2 -1
View File
@@ -154,7 +154,8 @@ RLD
icon_state = "rcd"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
custom_price = 900
custom_price = PRICE_ABOVE_EXPENSIVE
custom_premium_price = PRICE_ALMOST_ONE_GRAND
max_matter = 160
item_flags = NO_MAT_REDEMPTION | NOBLUDGEON
has_ammobar = TRUE
+1 -1
View File
@@ -157,7 +157,7 @@
to_chat(user, "<span class='notice'>You need to get closer!</span>")
return
if(use_paint(user) && isturf(F))
F.AddComponent(/datum/component/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha)
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, turn(stored_dir, -dir2angle(F.dir)), CLEAN_STRONG, color, null, null, alpha)
/obj/item/airlock_painter/decal/attack_self(mob/user)
if((ink) && (ink.charges >= 1))
+55 -9
View File
@@ -83,7 +83,7 @@
/obj/item/card/emag/bluespace
name = "bluespace cryptographic sequencer"
desc = "It's a blue card with a magnetic strip attached to some circuitry. It appears to have some sort of transmitter attached to it."
color = rgb(40, 130, 255)
icon_state = "emag_bs"
prox_check = FALSE
/obj/item/card/emag/attack()
@@ -166,6 +166,7 @@
slot_flags = ITEM_SLOT_ID
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
resistance_flags = FIRE_PROOF | ACID_PROOF
var/id_type_name = "identification card"
var/mining_points = 0 //For redeeming at mining equipment vendors
var/list/access = list()
var/registered_name = null // The name registered_name on the card
@@ -174,6 +175,8 @@
var/bank_support = ID_FREE_BANK_ACCOUNT
var/datum/bank_account/registered_account
var/obj/machinery/paystand/my_store
var/uses_overlays = TRUE
var/icon/cached_flat_icon
/obj/item/card/id/Initialize(mapload)
. = ..()
@@ -187,6 +190,15 @@
if(ID_LOCKED_BANK_ACCOUNT)
registered_account = new /datum/bank_account/remote/non_transferable(pick(GLOB.redacted_strings))
/obj/item/card/id/Destroy()
if(bank_support == ID_LOCKED_BANK_ACCOUNT)
QDEL_NULL(registered_account)
else
registered_account = null
if(my_store)
my_store.my_card = null
my_store = null
return ..()
/obj/item/card/id/vv_edit_var(var_name, var_value)
. = ..()
@@ -353,20 +365,38 @@
/obj/item/card/id/RemoveID()
return src
/*
Usage:
update_label()
Sets the id name to whatever registered_name and assignment is
/obj/item/card/id/update_overlays()
. = ..()
if(!uses_overlays)
return
cached_flat_icon = null
var/job = assignment ? ckey(GetJobName()) : null
if(registered_name == "Captain")
job = "captain"
if(registered_name && registered_name != "Captain")
. += mutable_appearance(icon, "assigned")
if(job)
. += mutable_appearance(icon, "id[job]")
/obj/item/card/id/proc/get_cached_flat_icon()
if(!cached_flat_icon)
cached_flat_icon = getFlatIcon(src)
return cached_flat_icon
/obj/item/card/id/get_examine_string(mob/user, thats = FALSE)
if(uses_overlays)
return "[icon2html(get_cached_flat_icon(), user)] [thats? "That's ":""][get_examine_name(user)]" //displays all overlays in chat
return ..()
update_label("John Doe", "Clowny")
Properly formats the name and occupation and sets the id name to the arguments
*/
/obj/item/card/id/proc/update_label(newname, newjob)
if(newname || newjob)
name = "[(!newname) ? "identification card" : "[newname]'s ID Card"][(!newjob) ? "" : " ([newjob])"]"
update_icon()
return
name = "[(!registered_name) ? "identification card" : "[registered_name]'s ID Card"][(!assignment) ? "" : " ([assignment])"]"
update_icon()
/obj/item/card/id/silver
name = "silver identification card"
@@ -379,6 +409,7 @@ update_label("John Doe", "Clowny")
/obj/item/card/id/silver/reaper
name = "Thirteen's ID Card (Reaper)"
access = list(ACCESS_MAINT_TUNNELS)
icon_state = "reaper"
assignment = "Reaper"
registered_name = "Thirteen"
@@ -530,7 +561,7 @@ update_label("John Doe", "Clowny")
/obj/item/card/id/ert
name = "\improper CentCom ID"
desc = "An ERT ID card."
icon_state = "centcom"
icon_state = "ert_commander"
registered_name = "Emergency Response Team Commander"
assignment = "Emergency Response Team Commander"
@@ -539,6 +570,7 @@ update_label("John Doe", "Clowny")
. = ..()
/obj/item/card/id/ert/Security
icon_state = "ert_security"
registered_name = "Security Response Officer"
assignment = "Security Response Officer"
@@ -547,6 +579,7 @@ update_label("John Doe", "Clowny")
. = ..()
/obj/item/card/id/ert/Engineer
icon_state = "ert_engineer"
registered_name = "Engineer Response Officer"
assignment = "Engineer Response Officer"
@@ -555,6 +588,7 @@ update_label("John Doe", "Clowny")
. = ..()
/obj/item/card/id/ert/Medical
icon_state = "ert_medical"
registered_name = "Medical Response Officer"
assignment = "Medical Response Officer"
@@ -563,6 +597,7 @@ update_label("John Doe", "Clowny")
. = ..()
/obj/item/card/id/ert/chaplain
icon_state = "ert_chaplain"
registered_name = "Religious Response Officer"
assignment = "Religious Response Officer"
@@ -615,40 +650,49 @@ update_label("John Doe", "Clowny")
. += "<span class='notice'>Your sentence is up! You're free!</span>"
/obj/item/card/id/prisoner/one
icon_state = "prisoner_001"
name = "Prisoner #13-001"
registered_name = "Prisoner #13-001"
/obj/item/card/id/prisoner/two
icon_state = "prisoner_002"
name = "Prisoner #13-002"
registered_name = "Prisoner #13-002"
/obj/item/card/id/prisoner/three
icon_state = "prisoner_003"
name = "Prisoner #13-003"
registered_name = "Prisoner #13-003"
/obj/item/card/id/prisoner/four
icon_state = "prisoner_004"
name = "Prisoner #13-004"
registered_name = "Prisoner #13-004"
/obj/item/card/id/prisoner/five
icon_state = "prisoner_005"
name = "Prisoner #13-005"
registered_name = "Prisoner #13-005"
/obj/item/card/id/prisoner/six
icon_state = "prisoner_006"
name = "Prisoner #13-006"
registered_name = "Prisoner #13-006"
/obj/item/card/id/prisoner/seven
icon_state = "prisoner_007"
name = "Prisoner #13-007"
registered_name = "Prisoner #13-007"
/obj/item/card/id/mining
name = "mining ID"
icon_state = "retro"
access = list(ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MAILSORTING, ACCESS_MINERAL_STOREROOM)
/obj/item/card/id/away
name = "a perfectly generic identification card"
desc = "A perfectly generic identification card. Looks like it could use some flavor."
icon_state = "retro"
access = list(ACCESS_AWAY_GENERAL)
/obj/item/card/id/away/hotel
@@ -691,6 +735,7 @@ update_label("John Doe", "Clowny")
/obj/item/card/id/departmental_budget
name = "departmental card (FUCK)"
desc = "Provides access to the departmental budget."
icon_state = "budgetcard"
var/department_ID = ACCOUNT_CIV
var/department_name = ACCOUNT_CIV_NAME
@@ -703,6 +748,7 @@ update_label("John Doe", "Clowny")
B.bank_cards += src
name = "departmental card ([department_name])"
desc = "Provides access to the [department_name]."
icon_state = "[lowertext(department_ID)]_budget"
SSeconomy.dep_cards += src
/obj/item/card/id/departmental_budget/Destroy()
+1 -1
View File
@@ -65,7 +65,7 @@
. = ..()
AddElement(/datum/element/update_icon_blocker)
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0)
/obj/item/gun/energy/chrono_gun/process_fire(atom/target, mob/living/user, message = TRUE, params = null, zone_override = "", bonus_spread = 0, stam_cost = 0)
if(field)
field_disconnect(field)
..()
+6 -1
View File
@@ -8,6 +8,9 @@ CIGARS
SMOKING PIPES
CHEAP LIGHTERS
ZIPPO
ROLLING PAPER
VAPES
BONGS
CIGARETTE PACKETS ARE IN FANCY.DM
*/
@@ -506,7 +509,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
resistance_flags = FIRE_PROOF
light_color = LIGHT_COLOR_FIRE
grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/oil = 5)
custom_price = 55
custom_price = PRICE_ALMOST_CHEAP
/obj/item/lighter/Initialize()
. = ..()
@@ -616,6 +619,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
desc = "A cheap-as-free lighter."
icon_state = "lighter"
fancy = FALSE
custom_price = PRICE_CHEAP_AS_FREE
overlay_list = list(
"transp",
"tall",
@@ -799,6 +803,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
to_chat(user, "<span class='warning'>You need to close the cap first!</span>")
/obj/item/clothing/mask/vape/dropped(mob/user)
. = ..()
var/mob/living/carbon/C = user
if(C.get_item_by_slot(SLOT_WEAR_MASK) == src)
ENABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
@@ -14,6 +14,10 @@
name = "Security Cameras (Computer Board)"
build_path = /obj/machinery/computer/security
/obj/item/circuitboard/computer/security/shuttle
name = "Shuttlelinking Security Cameras (Computer Board)"
build_path = /obj/machinery/computer/security/shuttle
/obj/item/circuitboard/computer/xenobiology
name = "circuit board (Xenobiology Console)"
build_path = /obj/machinery/computer/camera_advanced/xenobio
@@ -293,6 +297,10 @@
name = "Mining Shuttle (Computer Board)"
build_path = /obj/machinery/computer/shuttle/mining
/obj/item/circuitboard/computer/snow_taxi
name = "Snow Taxi (Computer Board)"
build_path = /obj/machinery/computer/shuttle/snow_taxi
/obj/item/circuitboard/computer/white_ship
name = "White Ship (Computer Board)"
build_path = /obj/machinery/computer/shuttle/white_ship
@@ -375,3 +383,11 @@
/obj/item/circuitboard/computer/nanite_cloud_controller
name = "Nanite Cloud Control (Computer Board)"
build_path = /obj/machinery/computer/nanite_cloud_controller
/obj/item/circuitboard/computer/shuttle/flight_control
name = "Shuttle Flight Control (Computer Board)"
build_path = /obj/machinery/computer/custom_shuttle
/obj/item/circuitboard/computer/shuttle/docker
name = "Shuttle Navigation Computer (Computer Board)"
build_path = /obj/machinery/computer/camera_advanced/shuttle_docker/custom
@@ -1102,3 +1102,28 @@
/obj/item/stock_parts/micro_laser = 2,
/obj/item/stock_parts/scanning_module = 2
)
/obj/item/circuitboard/machine/shuttle/engine
name = "Thruster (Machine Board)"
build_path = /obj/machinery/shuttle/engine
req_components = list()
/obj/item/circuitboard/machine/shuttle/engine/plasma
name = "Plasma Thruster (Machine Board)"
build_path = /obj/machinery/shuttle/engine/plasma
req_components = list(/obj/item/stock_parts/capacitor = 2,
/obj/item/stack/cable_coil = 5,
/obj/item/stock_parts/micro_laser = 1)
/obj/item/circuitboard/machine/shuttle/engine/void
name = "Void Thruster (Machine Board)"
build_path = /obj/machinery/shuttle/engine/void
req_components = list(/obj/item/stock_parts/capacitor/quadratic = 2,
/obj/item/stack/cable_coil = 5,
/obj/item/stock_parts/micro_laser/quadultra = 1)
/obj/item/circuitboard/machine/shuttle/heater
name = "Electronic Engine Heater (Machine Board)"
build_path = /obj/machinery/atmospherics/components/unary/shuttle/heater
req_components = list(/obj/item/stock_parts/micro_laser = 2,
/obj/item/stock_parts/matter_bin = 1)
@@ -1,7 +1,7 @@
/obj/item/flashlight
name = "flashlight"
desc = "A hand-held emergency light."
custom_price = 100
custom_price = PRICE_REALLY_CHEAP
icon = 'icons/obj/lighting.dmi'
icon_state = "flashlight"
item_state = "flashlight"
@@ -211,6 +211,7 @@
light_color = "#CDDDFF"
flashlight_power = 0.9
hitsound = 'sound/weapons/genhit1.ogg'
custom_price = PRICE_ALMOST_CHEAP
// the desk lamps are a bit special
/obj/item/flashlight/lamp
@@ -351,12 +352,13 @@
brightness_on = 6 // luminosity when on
light_color = "#FFAA44"
flashlight_power = 0.8
custom_price = PRICE_CHEAP
/obj/item/flashlight/lantern/jade
name = "jade lantern"
desc = "An ornate, green lantern."
color = LIGHT_COLOR_GREEN
light_color = LIGHT_COLOR_GREEN
light_color = LIGHT_COLOR_GREEN
/obj/item/flashlight/slime
gender = PLURAL
@@ -429,7 +431,7 @@
/obj/item/flashlight/glowstick
name = "glowstick"
desc = "A military-grade glowstick."
custom_price = 50
custom_price = PRICE_CHEAP_AS_FREE
w_class = WEIGHT_CLASS_SMALL
brightness_on = 4
color = LIGHT_COLOR_GREEN
+6 -3
View File
@@ -6,12 +6,14 @@ T-RAY
HEALTH ANALYZER
GAS ANALYZER
SLIME SCANNER
NANITE SCANNER
GENETICS SCANNER
*/
/obj/item/t_scanner
name = "\improper T-ray scanner"
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
custom_price = 150
custom_price = PRICE_REALLY_CHEAP
icon = 'icons/obj/device.dmi'
icon_state = "t-ray0"
var/on = FALSE
@@ -653,9 +655,10 @@ SLIME SCANNER
amount += inaccurate
return DisplayTimeText(max(1,amount))
/proc/atmosanalyzer_scan(mixture, mob/living/user, atom/target = src)
/proc/atmosanalyzer_scan(mixture, mob/living/user, atom/target = src, visible = TRUE)
var/icon = target
user.visible_message("[user] has used the analyzer on [icon2html(icon, viewers(user))] [target].", "<span class='notice'>You use the analyzer on [icon2html(icon, user)] [target].</span>")
if(visible)
user.visible_message("[user] has used the analyzer on [icon2html(icon, viewers(user))] [target].", "<span class='notice'>You use the analyzer on [icon2html(icon, user)] [target].</span>")
to_chat(user, "<span class='boldnotice'>Results of analysis of [icon2html(icon, user)] [target].</span>")
var/list/airs = islist(mixture) ? mixture : list(mixture)
@@ -5,7 +5,7 @@
icon_state = "scanner"
w_class = WEIGHT_CLASS_SMALL
slot_flags = ITEM_SLOT_BELT
custom_price = 900
custom_price = PRICE_ABOVE_EXPENSIVE
/obj/item/sensor_device/attack_self(mob/user)
GLOB.crewmonitor.show(user,src) //Proc already exists, just had to call it
+39 -1
View File
@@ -20,10 +20,10 @@
var/saber_color = "green"
light_color = "#00ff00"//green
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
block_chance = 75
max_integrity = 200
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
resistance_flags = FIRE_PROOF
block_parry_data = /datum/block_parry_data/dual_esword
var/hacked = FALSE
/// Can this reflect all energy projectiles?
var/can_reflect = TRUE
@@ -36,6 +36,42 @@
var/wielded = FALSE // track wielded status on item
var/slowdown_wielded = 0
/datum/block_parry_data/dual_esword
block_damage_absorption = 2
block_damage_multiplier = 0.15
block_damage_multiplier_override = list(
ATTACK_TYPE_MELEE = 0.25
)
block_start_delay = 0 // instantaneous block
block_stamina_cost_per_second = 2.5
block_stamina_efficiency = 3
block_lock_sprinting = TRUE
// no attacking while blocking
block_lock_attacking = TRUE
block_projectile_mitigation = 75
parry_time_windup = 0
parry_time_active = 8
parry_time_spindown = 0
// we want to signal to players the most dangerous phase, the time when automatic counterattack is a thing.
parry_time_windup_visual_override = 1
parry_time_active_visual_override = 3
parry_time_spindown_visual_override = 4
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK // esword users can attack while parrying.
parry_time_perfect = 2 // first ds isn't perfect
parry_time_perfect_leeway = 1
parry_imperfect_falloff_percent = 10
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 25 // VERY generous
parry_efficiency_perfect = 90
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = CLICK_CD_MELEE
// more efficient vs projectiles
block_stamina_efficiency_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 4
)
/obj/item/dualsaber/ComponentInitialize()
. = ..()
AddComponent(/datum/component/two_handed, force_unwielded=3, force_wielded=34, \
@@ -70,6 +106,7 @@
START_PROCESSING(SSobj, src)
set_light(brightness_on)
AddElement(/datum/element/sword_point)
item_flags |= (ITEM_CAN_BLOCK|ITEM_CAN_PARRY)
/// Triggered on unwield of two handed item
/// switch hitsounds
@@ -83,6 +120,7 @@
STOP_PROCESSING(SSobj, src)
set_light(0)
RemoveElement(/datum/element/sword_point)
item_flags &= ~(ITEM_CAN_BLOCK|ITEM_CAN_PARRY)
/obj/item/dualsaber/Destroy()
STOP_PROCESSING(SSobj, src)
+50 -16
View File
@@ -12,9 +12,9 @@
throwforce = 15 //if you are a madman and finish someone off with this, power to you.
throw_speed = 1
item_flags = NO_MAT_REDEMPTION
block_chance = 30
attack_verb = list("struck", "beaten", "thwacked", "pulped")
total_mass = 5 //yeah this is a heavy thing, beating people with it while it's off is not going to do you any favors. (to curb stun-kill rampaging without it being on)
block_parry_data = /datum/block_parry_data/electrostaff
var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell/high
var/on = FALSE
var/can_block_projectiles = FALSE //can't block guns
@@ -28,6 +28,43 @@
var/stun_stam_cost = 3.5
var/wielded = FALSE // track wielded status on item
// haha security desword time /s
/datum/block_parry_data/electrostaff
block_damage_absorption = 0
block_damage_multiplier = 1
can_block_attack_types = ~ATTACK_TYPE_PROJECTILE // only able to parry non projectiles
block_damage_multiplier_override = list(
TEXT_ATTACK_TYPE_MELEE = 0.5, // only useful on melee and unarmed
TEXT_ATTACK_TYPE_UNARMED = 0.3
)
block_start_delay = 0.5 // near instantaneous block
block_stamina_cost_per_second = 3
block_stamina_efficiency = 2 // haha this is a horrible idea
// more slowdown that deswords because security
block_slowdown = 2
// no attacking while blocking
block_lock_attacking = TRUE
parry_time_windup = 1
parry_time_active = 5
parry_time_spindown = 0
parry_time_spindown_visual_override = 1
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING // no attacking while parrying
parry_time_perfect = 0
parry_time_perfect_leeway = 0.5
parry_efficiency_perfect = 100
parry_imperfect_falloff_percent = 1
parry_imperfect_falloff_percent_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 45 // really crappy vs projectiles
)
parry_time_perfect_leeway_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 1 // extremely harsh window for projectiles
)
// not extremely punishing to fail, but no spamming the parry.
parry_cooldown = 2.5 SECONDS
parry_failed_stagger_duration = 1.5 SECONDS
parry_failed_clickcd_duration = 1 SECONDS
/obj/item/electrostaff/Initialize(mapload)
. = ..()
if(ispath(cell))
@@ -50,16 +87,12 @@
var/mob/living/silicon/robot/R = loc
. = R.get_cell()
/obj/item/electrostaff/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(!on || (!can_block_projectiles && (attack_type & ATTACK_TYPE_PROJECTILE)))
return BLOCK_NONE
return ..()
/obj/item/electrostaff/proc/min_hitcost()
return min(stun_cost, lethal_cost)
/obj/item/electrostaff/proc/turn_on(obj/item/source, mob/user)
wielded = TRUE
item_flags |= (ITEM_CAN_BLOCK|ITEM_CAN_PARRY)
if(!cell)
if(user)
to_chat(user, "<span class='warning'>[src] has no cell.</span>")
@@ -75,6 +108,7 @@
/obj/item/electrostaff/proc/turn_off(obj/item/source, mob/user)
wielded = FALSE
item_flags &= ~(ITEM_CAN_BLOCK|ITEM_CAN_PARRY)
if(user)
to_chat(user, "<span class='warning'>You turn [src] off.</span>")
on = FALSE
@@ -137,30 +171,30 @@
/obj/item/electrostaff/attack(mob/living/target, mob/living/user)
if(IS_STAMCRIT(user))//CIT CHANGE - makes it impossible to baton in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")//CIT CHANGE - ditto
to_chat(user, "<span class='danger'>You're too exhausted to use [src] properly.</span>")//CIT CHANGE - ditto
return //CIT CHANGE - ditto
if(on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
clowning_around(user) //ouch!
return
if(iscyborg(target))
..()
return
if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS) //No message; run_block() handles that
return ..()
var/list/return_list = list()
if(target.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, return_list) & BLOCK_SUCCESS) //No message; run_block() handles that
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(user.a_intent != INTENT_HARM)
if(stun_act(target, user))
if(stun_act(target, user, null, return_list))
user.do_attack_animation(target)
user.adjustStaminaLossBuffered(stun_stam_cost)
return
else if(!harm_act(target, user))
else if(!harm_act(target, user, null, return_list))
return ..() //if you can't fry them just beat them with it
else //we did harm act them
user.do_attack_animation(target)
user.adjustStaminaLossBuffered(lethal_stam_cost)
/obj/item/electrostaff/proc/stun_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE)
var/stunforce = stun_stamdmg
/obj/item/electrostaff/proc/stun_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE, list/block_return = list())
var/stunforce = block_calculate_resultant_damage(stun_stamdmg, block_return)
if(!no_charge_and_force)
if(!on)
target.visible_message("<span class='warning'>[user] has bapped [target] with [src]. Luckily it was off.</span>", \
@@ -190,8 +224,8 @@
H.forcesay(GLOB.hit_appends)
return TRUE
/obj/item/electrostaff/proc/harm_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE)
var/lethal_force = lethal_damage
/obj/item/electrostaff/proc/harm_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE, list/block_return = list())
var/lethal_force = block_calculate_resultant_damage(lethal_damage, block_return)
if(!no_charge_and_force)
if(!on)
return FALSE //standard item attack
@@ -7,7 +7,8 @@
var/forced_value = 0
var/duration = 300
/obj/item/grenade/antigravity/prime()
/obj/item/grenade/antigravity/prime(mob/living/lanced_by)
. = ..()
update_mob()
for(var/turf/T in view(range,src))
@@ -174,10 +174,11 @@
message_admins(message)
user.log_message("primed [src] ([reagent_string])",LOG_GAME)
/obj/item/grenade/chem_grenade/prime()
/obj/item/grenade/chem_grenade/prime(mob/living/lanced_by)
if(stage != READY)
return FALSE
. = ..()
var/list/datum/reagents/reactants = list()
for(var/obj/item/reagent_containers/glass/G in beakers)
reactants += G.reagents
@@ -217,7 +218,7 @@
ignition_temp = 25 // Large grenades are slightly more effective at setting off heat-sensitive mixtures than smaller grenades.
threatscale = 1.1 // 10% more effective.
/obj/item/grenade/chem_grenade/large/prime()
/obj/item/grenade/chem_grenade/large/prime(mob/living/lanced_by)
if(stage != READY)
return FALSE
@@ -286,7 +287,7 @@
return
..()
/obj/item/grenade/chem_grenade/adv_release/prime()
/obj/item/grenade/chem_grenade/adv_release/prime(mob/living/lanced_by)
if(stage != READY)
return FALSE
@@ -14,7 +14,8 @@
var/max_spawned = 8
var/segment_chance = 35
/obj/item/grenade/clusterbuster/prime()
/obj/item/grenade/clusterbuster/prime(mob/living/lanced_by)
. = ..()
update_mob()
var/numspawned = rand(min_spawned,max_spawned)
var/again = 0
@@ -59,7 +60,7 @@
step_away(src,loc)
addtimer(CALLBACK(src, .proc/prime), rand(15,60))
/obj/item/grenade/clusterbuster/segment/prime()
/obj/item/grenade/clusterbuster/segment/prime(mob/living/lanced_by)
new payload_spawner(drop_location(), payload, rand(min_spawned,max_spawned))
playsound(src, prime_sound, 75, 1, -3)
qdel(src)
@@ -4,7 +4,8 @@
icon_state = "emp"
item_state = "emp"
/obj/item/grenade/empgrenade/prime()
/obj/item/grenade/empgrenade/prime(mob/living/lanced_by)
. = ..()
update_mob()
empulse(src, 4, 10)
qdel(src)
+91 -1
View File
@@ -6,7 +6,8 @@
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
var/flashbang_range = 7 //how many tiles away the mob will be stunned.
/obj/item/grenade/flashbang/prime()
/obj/item/grenade/flashbang/prime(mob/living/lanced_by)
. = ..()
update_mob()
var/flashbang_turf = get_turf(src)
if(!flashbang_turf)
@@ -42,3 +43,92 @@
var/distance = get_dist(get_turf(M), source)
if(M.flash_act(affect_silicon = 1))
M.DefaultCombatKnockdown(max(200/max(1,distance), 60))
/obj/item/grenade/stingbang
name = "stingbang"
icon_state = "timeg"
item_state = "flashbang"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
var/flashbang_range = 1 //how many tiles away the mob will be stunned.
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball
shrapnel_radius = 5
custom_premium_price = 700 // mostly gotten through cargo, but throw in one for the sec vendor ;)
/obj/item/grenade/stingbang/mega
name = "mega stingbang"
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/mega
shrapnel_radius = 12
/obj/item/grenade/stingbang/prime(mob/living/lanced_by)
if(iscarbon(loc))
var/mob/living/carbon/C = loc
var/obj/item/bodypart/B = C.get_holding_bodypart_of_item(src)
if(B)
C.visible_message("<b><span class='danger'>[src] goes off in [C]'s hand, blowing [C.p_their()] [B.name] to bloody shreds!</span></b>", "<span class='userdanger'>[src] goes off in your hand, blowing your [B.name] to bloody shreds!</span>")
B.dismember()
. = ..()
update_mob()
var/flashbang_turf = get_turf(src)
if(!flashbang_turf)
return
do_sparks(rand(5, 9), FALSE, src)
playsound(flashbang_turf, 'sound/weapons/flashbang.ogg', 50, TRUE, 8, 0.9)
new /obj/effect/dummy/lighting_obj (flashbang_turf, LIGHT_COLOR_WHITE, (flashbang_range + 2), 2, 1)
for(var/mob/living/M in get_hearers_in_view(flashbang_range, flashbang_turf))
pop(get_turf(M), M)
qdel(src)
/obj/item/grenade/stingbang/proc/pop(turf/T , mob/living/M)
if(M.stat == DEAD) //They're dead!
return
M.show_message("<span class='warning'>POP</span>", MSG_AUDIBLE)
var/distance = max(0,get_dist(get_turf(src),T))
//Flash
if(M.flash_act(affect_silicon = 1))
M.Paralyze(max(10/max(1,distance), 5))
M.Knockdown(max(100/max(1,distance), 60))
//Bang
if(!distance || loc == M || loc == M.loc)
M.Paralyze(20)
M.Knockdown(200)
M.soundbang_act(1, 200, 10, 15)
if(M.apply_damages(10, 10))
to_chat(M, "<span class='userdanger'>The blast from \the [src] bruises and burns you!</span>")
// only checking if they're on top of the tile, cause being one tile over will be its own punishment
// Grenade that releases more shrapnel the more times you use it in hand between priming and detonation (sorta like the 9bang from MW3), for admin goofs
/obj/item/grenade/primer
name = "rotfrag grenade"
desc = "A grenade that generates more shrapnel the more you rotate it in your hand after pulling the pin. This one releases shrapnel shards."
icon_state = "timeg"
item_state = "flashbang"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
var/rots_per_mag = 3 /// how many times we need to "rotate" the charge in hand per extra tile of magnitude
shrapnel_type = /obj/item/projectile/bullet/shrapnel
var/rots = 1 /// how many times we've "rotated" the charge
/obj/item/grenade/primer/attack_self(mob/user)
. = ..()
if(active)
user.playsound_local(user, 'sound/misc/box_deploy.ogg', 50, TRUE)
rots++
user.changeNext_move(CLICK_CD_RAPID)
/obj/item/grenade/primer/prime(mob/living/lanced_by)
shrapnel_radius = round(rots / rots_per_mag)
. = ..()
qdel(src)
/obj/item/grenade/primer/stingbang
name = "rotsting"
desc = "A grenade that generates more shrapnel the more you rotate it in your hand after pulling the pin. This one releases stingballs."
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
rots_per_mag = 2
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball
@@ -45,12 +45,13 @@
/obj/item/grenade/iedcasing/attack_self(mob/user) //
if(!active)
if(clown_check(user))
if(!botch_check(user))
to_chat(user, "<span class='warning'>You light the [name]!</span>")
cut_overlay("improvised_grenade_filled")
preprime(user, null, FALSE)
/obj/item/grenade/iedcasing/prime() //Blowing that can up
/obj/item/grenade/iedcasing/prime(mob/living/lanced_by) //Blowing that can up
. = ..()
update_mob()
explosion(src.loc,-1,-1,2, flame_range = 4) // small explosion, plus a very large fireball.
qdel(src)
+45 -6
View File
@@ -17,10 +17,31 @@
var/det_time = 50
var/display_timer = 1
var/clumsy_check = GRENADE_CLUMSY_FUMBLE
var/sticky = FALSE
// I moved the explosion vars and behavior to base grenades because we want all grenades to call [/obj/item/grenade/proc/prime] so we can send COMSIG_GRENADE_PRIME
///how big of a devastation explosion radius on prime
var/ex_dev = 0
///how big of a heavy explosion radius on prime
var/ex_heavy = 0
///how big of a light explosion radius on prime
var/ex_light = 0
///how big of a flame explosion radius on prime
var/ex_flame = 0
// dealing with creating a [/datum/component/pellet_cloud] on prime
/// if set, will spew out projectiles of this type
var/shrapnel_type
/// the higher this number, the more projectiles are created as shrapnel
var/shrapnel_radius
var/shrapnel_initialized
/obj/item/grenade/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] primes [src], then eats it! It looks like [user.p_theyre()] trying to commit suicide!</span>")
if(shrapnel_type && shrapnel_radius)
shrapnel_initialized = TRUE
AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_radius)
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
SEND_SIGNAL(src, COMSIG_GRENADE_ARMED, det_time)
preprime(user, det_time)
user.transferItemToLoc(src, user, TRUE)//>eat a grenade set to 5 seconds >rush captain
sleep(det_time)//so you dont die instantly
@@ -32,19 +53,21 @@
if(!QDELETED(src))
qdel(src)
/obj/item/grenade/proc/clown_check(mob/living/carbon/human/user)
/obj/item/grenade/proc/botch_check(mob/living/carbon/human/user)
var/clumsy = HAS_TRAIT(user, TRAIT_CLUMSY)
if(clumsy)
if(clumsy_check == GRENADE_CLUMSY_FUMBLE && prob(50))
to_chat(user, "<span class='warning'>Huh? How does this thing work?</span>")
preprime(user, 5, FALSE)
return FALSE
return TRUE
else if(clumsy_check == GRENADE_NONCLUMSY_FUMBLE && !(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY)))
to_chat(user, "<span class='warning'>You pull the pin on [src]. Attached to it is a pink ribbon that says, \"<span class='clown'>HONK</span>\"</span>")
preprime(user, 5, FALSE)
return FALSE
return TRUE
return TRUE
else if(sticky && prob(50)) // to add risk to sticky tape grenade cheese, no return cause we still prime as normal after
to_chat(user, "<span class='warning'>What the... [src] is stuck to your hand!</span>")
ADD_TRAIT(src, TRAIT_NODROP, STICKY_NODROP)
/obj/item/grenade/examine(mob/user)
. = ..()
@@ -56,8 +79,16 @@
/obj/item/grenade/attack_self(mob/user)
if(HAS_TRAIT(src, TRAIT_NODROP))
to_chat(user, "<span class='notice'>You try prying [src] off your hand...</span>")
if(do_after(user, 70, target=src))
to_chat(user, "<span class='notice'>You manage to remove [src] from your hand.</span>")
REMOVE_TRAIT(src, TRAIT_NODROP, STICKY_NODROP)
return
if(!active)
if(clown_check(user))
if(!botch_check(user)) // if they botch the prime, it'll be handled in botch_check
preprime(user)
/obj/item/grenade/proc/log_grenade(mob/user, turf/T)
@@ -81,10 +112,18 @@
icon_state = initial(icon_state) + "_active"
addtimer(CALLBACK(src, .proc/prime), isnull(delayoverride)? det_time : delayoverride)
/obj/item/grenade/proc/prime()
/obj/item/grenade/proc/prime(mob/living/lanced_by)
var/turf/T = get_turf(src)
log_game("Grenade detonation at [AREACOORD(T)], location [loc]")
if(shrapnel_type && shrapnel_radius && !shrapnel_initialized) // add a second check for adding the component in case whatever triggered the grenade went straight to prime (badminnery for example)
shrapnel_initialized = TRUE
AddComponent(/datum/component/pellet_cloud, projectile_type=shrapnel_type, magnitude=shrapnel_radius)
SEND_SIGNAL(src, COMSIG_GRENADE_PRIME, lanced_by)
if(ex_dev || ex_heavy || ex_light || ex_flame)
explosion(loc, ex_dev, ex_heavy, ex_light, flame_range = ex_flame)
/obj/item/grenade/proc/update_mob()
if(ismob(loc))
var/mob/M = loc
+5 -2
View File
@@ -122,7 +122,9 @@
var/obj/item/I = AM
I.throw_speed = max(1, (I.throw_speed - 3))
I.throw_range = max(1, (I.throw_range - 3))
I.embedding = I.embedding.setRating(embed_chance = 0)
if(I.embedding)
I.embedding["embed_chance"] = 0
I.updateEmbedding()
target.add_overlay(plastic_overlay, TRUE)
if(!nadeassembly)
@@ -205,9 +207,10 @@
else
return ..()
/obj/item/grenade/plastic/c4/prime()
/obj/item/grenade/plastic/c4/prime(mob/living/lanced_by)
if(QDELETED(src))
return
. = ..()
var/turf/location
if(target)
if(!QDELETED(target))
@@ -17,7 +17,8 @@
qdel(smoke)
return ..()
/obj/item/grenade/smokebomb/prime()
/obj/item/grenade/smokebomb/prime(mob/living/lanced_by)
. = ..()
update_mob()
playsound(src.loc, 'sound/effects/smoke.ogg', 50, 1, -3)
smoke.set_up(4, src)
@@ -7,7 +7,8 @@
var/spawner_type = null // must be an object path
var/deliveryamt = 1 // amount of type to deliver
/obj/item/grenade/spawnergrenade/prime() // Prime now just handles the two loops that query for people in lockers and people who can see it.
/obj/item/grenade/spawnergrenade/prime(mob/living/lanced_by) // Prime now just handles the two loops that query for people in lockers and people who can see it.
. = ..()
update_mob()
if(spawner_type && deliveryamt)
// Make a quick flash
@@ -4,27 +4,45 @@
icon = 'icons/obj/grenade.dmi'
icon_state = "syndicate"
item_state = "flashbang"
ex_dev = 1
ex_heavy = 2
ex_light = 4
ex_flame = 2
/obj/item/grenade/syndieminibomb/prime()
/obj/item/grenade/syndieminibomb/prime(mob/living/lanced_by)
. = ..()
update_mob()
explosion(src.loc,1,2,4,flame_range = 2)
qdel(src)
/obj/item/grenade/syndieminibomb/concussion
name = "HE Grenade"
desc = "A compact shrapnel grenade meant to devastate nearby organisms and cause some damage in the process. Pull pin and throw opposite direction."
icon_state = "concussion"
ex_heavy = 2
ex_light = 3
ex_flame = 3
/obj/item/grenade/syndieminibomb/concussion/prime()
update_mob()
explosion(src.loc,0,2,3,flame_range = 3)
qdel(src)
/obj/item/grenade/syndieminibomb/concussion/frag
/obj/item/grenade/frag
name = "frag grenade"
desc = "Fire in the hole."
desc = "An anti-personnel fragmentation grenade, this weapon excels at killing soft targets by shredding them with metal shrapnel."
icon_state = "frag"
shrapnel_type = /obj/item/projectile/bullet/shrapnel
shrapnel_radius = 4
ex_heavy = 1
ex_light = 3
ex_flame = 4
/obj/item/grenade/frag/mega
name = "FRAG grenade"
desc = "An anti-everything fragmentation grenade, this weapon excels at killing anything any everything by shredding them with metal shrapnel."
shrapnel_type = /obj/item/projectile/bullet/shrapnel/mega
shrapnel_radius = 12
/obj/item/grenade/frag/prime(mob/living/lanced_by)
. = ..()
update_mob()
qdel(src)
/obj/item/grenade/gluon
desc = "An advanced grenade that releases a harmful stream of gluons inducing radiation in those nearby. These gluon streams will also make victims feel exhausted, and induce shivering. This extreme coldness will also likely wet any nearby floors."
@@ -36,7 +54,8 @@
var/rad_damage = 350
var/stamina_damage = 30
/obj/item/grenade/gluon/prime()
/obj/item/grenade/gluon/prime(mob/living/lanced_by)
. = ..()
update_mob()
playsound(loc, 'sound/effects/empulse.ogg', 50, 1)
radiation_pulse(src, rad_damage)
+6 -3
View File
@@ -71,7 +71,7 @@
sharpness = IS_SHARP_ACCURATE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
var/bayonet = FALSE //Can this be attached to a gun?
custom_price = 250
custom_price = PRICE_NORMAL
/obj/item/kitchen/knife/Initialize()
. = ..()
@@ -131,13 +131,14 @@
custom_materials = list(/datum/material/iron=18000)
attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
w_class = WEIGHT_CLASS_NORMAL
custom_price = 600
custom_price = PRICE_EXPENSIVE
/obj/item/kitchen/knife/combat
name = "combat knife"
icon_state = "buckknife"
item_state = "knife"
desc = "A military combat utility survival knife."
embedding = list("pain_mult" = 4, "embed_chance" = 65, "fall_chance" = 10, "ignore_throwspeed_threshold" = TRUE)
force = 20
throwforce = 20
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
@@ -148,6 +149,7 @@
icon_state = "survivalknife"
item_state = "knife"
desc = "A hunting grade survival knife."
embedding = list("pain_mult" = 4, "embed_chance" = 35, "fall_chance" = 10)
force = 15
throwforce = 15
bayonet = TRUE
@@ -159,6 +161,7 @@
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
desc = "A sharpened bone. The bare minimum in survival."
embedding = list("pain_mult" = 4, "embed_chance" = 35, "fall_chance" = 10)
force = 15
throwforce = 15
custom_materials = null
@@ -200,7 +203,7 @@
w_class = WEIGHT_CLASS_NORMAL
custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.5)
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked")
custom_price = 200
custom_price = PRICE_ALMOST_CHEAP
/obj/item/kitchen/rollingpin/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins flattening [user.p_their()] head with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
+26 -2
View File
@@ -103,11 +103,30 @@
throw_speed = 3
throw_range = 5
sharpness = IS_SHARP
embedding = list("embed_chance" = 75, "embedded_impact_pain_multiplier" = 10)
embedding = list("embed_chance" = 75, "impact_pain_mult" = 10)
armour_penetration = 35
block_chance = 50
item_flags = NEEDS_PERMIT | ITEM_CAN_PARRY
block_parry_data = /datum/block_parry_data/energy_sword
var/list/possible_colors = list("red" = LIGHT_COLOR_RED, "blue" = LIGHT_COLOR_LIGHT_CYAN, "green" = LIGHT_COLOR_GREEN, "purple" = LIGHT_COLOR_LAVENDER)
/datum/block_parry_data/energy_sword
parry_time_windup = 0
parry_time_active = 25
parry_time_spindown = 0
// we want to signal to players the most dangerous phase, the time when automatic counterattack is a thing.
parry_time_windup_visual_override = 1
parry_time_active_visual_override = 3
parry_time_spindown_visual_override = 12
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK // esword users can attack while
parry_time_perfect = 2.5 // first ds isn't perfect
parry_time_perfect_leeway = 1.5
parry_imperfect_falloff_percent = 5
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 65 // VERY generous
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 4 SECONDS
parry_cooldown = 0.5 SECONDS
/obj/item/melee/transforming/energy/sword/Initialize(mapload)
. = ..()
set_sword_color()
@@ -273,6 +292,10 @@
light_color = "#37FFF7"
actions_types = list()
/obj/item/melee/transforming/energy/sword/cx/Initialize()
icon_state_on = icon_state
return ..()
/obj/item/melee/transforming/energy/sword/cx/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
@@ -290,6 +313,7 @@
if(!supress_message_text)
to_chat(user, "<span class='notice'>[src] [active ? "is now active":"can now be concealed"].</span>")
/obj/item/melee/transforming/energy/sword/cx/update_overlays()
. = ..()
var/mutable_appearance/blade_overlay = mutable_appearance(icon, "cxsword_blade")
+51 -10
View File
@@ -61,13 +61,25 @@
force = 18
throwforce = 15
w_class = WEIGHT_CLASS_BULKY
block_chance = 50
armour_penetration = 75
sharpness = IS_SHARP
attack_verb = list("slashed", "cut")
hitsound = 'sound/weapons/rapierhit.ogg'
custom_materials = list(/datum/material/iron = 1000)
total_mass = 3.4
item_flags = NEEDS_PERMIT | ITEM_CAN_PARRY
block_parry_data = /datum/block_parry_data/captain_saber
/datum/block_parry_data/captain_saber
parry_time_windup = 0.5
parry_time_active = 4
parry_time_spindown = 1
parry_time_perfect = 0.75
parry_time_perfect_leeway = 0.75
parry_imperfect_falloff_percent = 30
parry_efficiency_perfect = 100
parry_failed_stagger_duration = 3 SECONDS
parry_failed_clickcd_duration = 2 SECONDS
/obj/item/melee/sabre/Initialize()
. = ..()
@@ -150,7 +162,6 @@
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
force = 15
throwforce = 25
block_chance = 50
armour_penetration = 200 //Apparently this gives it the ability to pierce block
flags_1 = CONDUCT_1
obj_flags = UNIQUE_RENAME
@@ -159,16 +170,47 @@
attack_verb = list("stabs", "punctures", "pierces", "pokes")
hitsound = 'sound/weapons/rapierhit.ogg'
total_mass = 0.4
item_flags = ITEM_CAN_PARRY | NEEDS_PERMIT
block_parry_data = /datum/block_parry_data/traitor_rapier
// Fast, efficient parry.
/datum/block_parry_data/traitor_rapier
parry_time_windup = 0.5
parry_time_active = 5
parry_time_spindown = 0
parry_time_active_visual_override = 3
parry_time_spindown_visual_override = 2
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
parry_time_perfect = 0
parry_time_perfect_leeway = 3
parry_time_perfect_leeway_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 1
)
parry_imperfect_falloff_percent_override = list(
TEXT_ATTACK_TYPE_PROJECTILE = 50 // useless after 3rd decisecond
)
parry_imperfect_falloff_percent = 30
parry_efficiency_to_counterattack = 100
parry_efficiency_considered_successful = 1
parry_efficiency_perfect = 100
parry_data = list(
PARRY_DISARM_ATTACKER = TRUE,
PARRY_KNOCKDOWN_ATTACKER = 10
)
parry_failed_stagger_duration = 2 SECONDS
parry_failed_clickcd_duration = CLICK_CD_RANGE
parry_cooldown = 0
/obj/item/melee/rapier/active_parry_reflex_counter(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list, parry_efficiency, list/effect_text)
. = ..()
if((attack_type & ATTACK_TYPE_PROJECTILE) && (parry_efficiency >= 100))
. |= BLOCK_SHOULD_REDIRECT
return_list[BLOCK_RETURN_REDIRECT_METHOD] = REDIRECT_METHOD_DEFLECT
/obj/item/melee/rapier/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 20, 65, 0)
/obj/item/melee/rapier/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(attack_type == ATTACK_TYPE_PROJECTILE)
final_block_chance = 0
return ..()
/obj/item/melee/rapier/on_exit_storage(datum/component/storage/S)
var/obj/item/storage/belt/sabre/rapier/B = S.parent
if(istype(B))
@@ -191,10 +233,9 @@
. = ..()
if(iscarbon(target))
var/mob/living/carbon/H = target
var/loss = H.getStaminaLoss()
H.Dizzy(10)
H.adjustStaminaLoss(30)
if((loss > 40) && prob(loss)) // if above 40, roll for sleep using 1% every 1 stamina damage
if(CHECK_STAMCRIT(H) != NOT_STAMCRIT)
H.Sleeping(180)
/obj/item/melee/classic_baton
@@ -664,4 +705,4 @@
. = ..()
overlay = mutable_appearance(icon, overlay_state)
overlay.appearance_flags = RESET_COLOR
add_overlay(overlay)
add_overlay(overlay)
@@ -53,6 +53,8 @@
throw_speed = 4
if(attack_verb_on.len)
attack_verb = attack_verb_on
if(embedding)
updateEmbedding()
icon_state = icon_state_on
w_class = w_class_on
else
@@ -62,6 +64,8 @@
throw_speed = initial(throw_speed)
if(attack_verb_off.len)
attack_verb = attack_verb_off
if(embedding)
updateEmbedding()
icon_state = initial(icon_state)
w_class = initial(w_class)
total_mass = initial(total_mass)
+24
View File
@@ -129,6 +129,30 @@
hos_gun_list[initial(A.name)] = A
return hos_gun_list
/obj/item/choice_beacon/augments
name = "augment beacon"
desc = "Summons augmentations."
/obj/item/choice_beacon/augments/generate_display_names()
var/static/list/augment_list
if(!augment_list)
augment_list = list()
var/list/templist = list(
/obj/item/organ/cyberimp/brain/anti_drop,
/obj/item/organ/cyberimp/arm/toolset,
/obj/item/organ/cyberimp/arm/surgery,
/obj/item/organ/cyberimp/chest/thrusters,
/obj/item/organ/lungs/cybernetic,
/obj/item/organ/liver/cybernetic) //cyberimplants range from a nice bonus to fucking broken bullshit so no subtypesof
for(var/V in templist)
var/atom/A = V
augment_list[initial(A.name)] = A
return augment_list
/obj/item/choice_beacon/augments/spawn_option(obj/choice,mob/living/M)
new choice(get_turf(M))
to_chat(M, "<span class='hear'>You hear something crackle from the beacon for a moment before a voice speaks. \"Please stand by for a message from S.E.L.F. Message as follows: <b>Item request received. Your package has been transported, use the autosurgeon supplied to apply the upgrade.</b> Message ends.\"</span>")
/obj/item/skub
desc = "It's skub."
name = "skub"
+18 -1
View File
@@ -78,7 +78,7 @@
name = "crew pinpointer"
desc = "A handheld tracking device that points to crew suit sensors."
icon_state = "pinpointer_crew"
custom_price = 600
custom_price = PRICE_ABOVE_EXPENSIVE
var/has_owner = FALSE
var/pinpointer_owner = null
@@ -183,3 +183,20 @@
A.other_pair = B
B.other_pair = A
/obj/item/pinpointer/shuttle
name = "fugitive pinpointer"
desc = "A handheld tracking device that locates the bounty hunter shuttle for quick escapes."
icon_state = "pinpointer_hunter"
var/obj/shuttleport
/obj/item/pinpointer/shuttle/Initialize(mapload)
. = ..()
shuttleport = SSshuttle.getShuttle("huntership")
/obj/item/pinpointer/shuttle/scan_for_target()
target = shuttleport
/obj/item/pinpointer/shuttle/Destroy()
shuttleport = null
. = ..()
+5 -4
View File
@@ -140,7 +140,8 @@
if(jsonlist["icon_state"])
icon_state = jsonlist["icon_state"]
item_state = jsonlist["item_state"]
icon = 'config/plushies/sprites.dmi'
var/static/config_sprites = file("config/plushies/sprites.dmi")
icon = config_sprites
if(jsonlist["attack_verb"])
attack_verb = jsonlist["attack_verb"]
if(jsonlist["squeak_override"])
@@ -436,13 +437,13 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
/obj/item/toy/plush/random/Initialize()
var/newtype
var/list/snowflake_list = CONFIG_GET(keyed_list/snowflake_plushies)
/// If there are no snowflake plushies we'll default to base plush, so we grab from the valid list
if (snowflake_list.len)
newtype = prob(CONFIG_GET(number/snowflake_plushie_prob)) ? /obj/item/toy/plush/random_snowflake : pick(GLOB.valid_plushie_paths)
else
else
newtype = pick(GLOB.valid_plushie_paths)
new newtype(loc)
return INITIALIZE_HINT_QDEL
+42 -37
View File
@@ -6,6 +6,7 @@
lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi'
flags_1 = CONDUCT_1
item_flags = NEEDS_PERMIT | NO_COMBAT_MODE_FORCE_MODIFIER //To avoid ambushing and oneshotting healthy crewmembers on force setting 3.
attack_verb = list("whacked", "fisted", "power-punched")
force = 20
throwforce = 10
@@ -13,7 +14,7 @@
w_class = WEIGHT_CLASS_NORMAL
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 40)
resistance_flags = FIRE_PROOF
var/click_delay = 1.5
click_delay = CLICK_CD_MELEE * 1.5
var/fisto_setting = 1
var/gasperfist = 3
var/obj/item/tank/internals/tank = null //Tank used for the gauntlet's piston-ram.
@@ -70,42 +71,46 @@
/obj/item/melee/powerfist/attack(mob/living/target, mob/living/user)
if(!tank)
to_chat(user, "<span class='warning'>\The [src] can't operate without a source of gas!</span>")
return
var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting)
var/turf/T = get_turf(src)
if(!T)
return
T.assume_air(gasused)
T.air_update_turf()
if(!gasused)
to_chat(user, "<span class='warning'>\The [src]'s tank is empty!</span>")
target.apply_damage((force / 5), BRUTE)
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punches you!</span>")
return
if(gasused.total_moles() < gasperfist * fisto_setting)
to_chat(user, "<span class='warning'>\The [src]'s piston-ram lets out a weak hiss, it needs more gas!</span>")
playsound(loc, 'sound/weapons/punch4.ogg', 50, 1)
target.apply_damage((force / 2), BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
return
target.apply_damage(force * fisto_setting, BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
new /obj/effect/temp_visual/kinetic_blast(target.loc)
playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1)
playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='warning'>You don't want to harm other living beings!</span>")
return FALSE
if(!tank)
to_chat(user, "<span class='warning'>\The [src] can't operate without a source of gas!</span>")
return FALSE
var/datum/gas_mixture/gasused = tank.air_contents.remove(gasperfist * fisto_setting)
var/turf/T = get_turf(src)
if(!T)
return FALSE
var/totalitemdamage = target.pre_attacked_by(src, user)
T.assume_air(gasused)
T.air_update_turf()
if(!gasused)
to_chat(user, "<span class='warning'>\The [src]'s tank is empty!</span>")
target.apply_damage((totalitemdamage / 5), BRUTE)
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a dull thunk as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punches you!</span>")
return
if(gasused.total_moles() < gasperfist * fisto_setting)
to_chat(user, "<span class='warning'>\The [src]'s piston-ram lets out a weak hiss, it needs more gas!</span>")
playsound(loc, 'sound/weapons/punch4.ogg', 50, 1)
target.apply_damage((totalitemdamage / 2), BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
return
target.apply_damage(totalitemdamage * fisto_setting, BRUTE)
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
new /obj/effect/temp_visual/kinetic_blast(target.loc)
playsound(loc, 'sound/weapons/resonator_blast.ogg', 50, 1)
playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1)
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2))
target.throw_at(throw_target, 5 * fisto_setting, 0.5 + (fisto_setting / 2))
log_combat(user, target, "power fisted", src)
log_combat(user, target, "power fisted", src)
user.changeNext_move(CLICK_CD_MELEE * click_delay)
return
var/weight = getweight(user, STAM_COST_ATTACK_MOB_MULT)
if(weight)
user.adjustStaminaLossBuffered(weight)
return TRUE
+2 -1
View File
@@ -215,8 +215,9 @@
/obj/item/clothing/head/helmet/plate/crusader/prophet
name = "Prophet's Hat"
desc = "A religious-looking hat."
icon_state = "prophet"
mob_overlay_icon = 'icons/mob/large-worn-icons/64x64/head.dmi'
flags_1 = 0
flags_1 = NONE
armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 50, "bomb" = 70, "bio" = 50, "rad" = 50, "fire" = 60, "acid" = 60) //religion protects you from disease and radiation, honk.
worn_x_dimension = 64
worn_y_dimension = 64
@@ -358,6 +358,7 @@
check_amount()
/obj/item/borg/lollipop/dropped(mob/user)
. = ..()
check_amount()
/obj/item/borg/lollipop/proc/check_amount() //Doesn't even use processing ticks.
@@ -545,7 +545,7 @@
to_chat(usr, "<span class='notice'>This unit already has an expand module installed!</span>")
return FALSE
R.notransform = TRUE
R.mob_transforming = TRUE
var/prev_locked_down = R.locked_down
R.SetLockdown(1)
R.anchored = TRUE
@@ -559,7 +559,7 @@
if(!prev_locked_down)
R.SetLockdown(0)
R.anchored = FALSE
R.notransform = FALSE
R.mob_transforming = FALSE
R.resize = 2
R.hasExpanded = TRUE
R.update_transform()
+44 -29
View File
@@ -1,7 +1,8 @@
/obj/item/shield
name = "shield"
icon = 'icons/obj/shields.dmi'
block_chance = 50
item_flags = ITEM_CAN_BLOCK
block_parry_data = /datum/block_parry_data/shield
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70)
/// Shield flags
var/shield_flags = SHIELD_FLAGS_DEFAULT
@@ -22,6 +23,18 @@
/// Shield bashing push distance
var/shieldbash_push_distance = 1
/datum/block_parry_data/shield
block_damage_multiplier = 0.25
block_stamina_efficiency = 2.5
block_stamina_cost_per_second = 3.5
block_slowdown = 0
block_lock_attacking = FALSE
block_lock_sprinting = TRUE
block_start_delay = 1.5
block_damage_absorption = 5
block_resting_stamina_penalty_multiplier = 2
block_projectile_mitigation = 75
/obj/item/shield/examine(mob/user)
. = ..()
if(shield_flags & SHIELD_CAN_BASH)
@@ -154,6 +167,22 @@
icon_state = "shield_bash"
duration = 3
/obj/item/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(ismovable(object))
var/atom/movable/AM = object
if(CHECK_BITFIELD(shield_flags, SHIELD_TRANSPARENT) && (AM.pass_flags & PASSGLASS))
return BLOCK_NONE
if(attack_type & ATTACK_TYPE_THROWN)
final_block_chance += 30
if(attack_type & ATTACK_TYPE_TACKLE)
final_block_chance = 100
. = ..()
if(. & BLOCK_SUCCESS)
on_shield_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
/obj/item/shield/on_active_block(mob/living/owner, atom/object, damage, damage_blocked, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return, override_direction)
on_shield_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance)
/obj/item/shield/riot
name = "riot shield"
desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder."
@@ -172,20 +201,7 @@
var/repair_material = /obj/item/stack/sheet/mineral/titanium
var/can_shatter = TRUE
shield_flags = SHIELD_FLAGS_DEFAULT | SHIELD_TRANSPARENT
max_integrity = 75
/obj/item/shield/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(ismovable(object))
var/atom/movable/AM = object
if(CHECK_BITFIELD(shield_flags, SHIELD_TRANSPARENT) && (AM.pass_flags & PASSGLASS))
return BLOCK_NONE
if(attack_type & ATTACK_TYPE_THROWN)
final_block_chance += 30
if(attack_type & ATTACK_TYPE_TACKLE)
final_block_chance = 100
. = ..()
if(. & BLOCK_SUCCESS)
on_shield_block(owner, object, damage, attack_text, attack_type, armour_penetration, attacker, def_zone, final_block_chance, block_return)
max_integrity = 450
/obj/item/shield/riot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/melee/baton))
@@ -238,13 +254,13 @@
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 55 //Weak
max_integrity = 300
obj/item/shield/riot/bullet_proof
name = "bullet resistant shield"
desc = "A far more frail shield made of resistant plastics and kevlar meant to block ballistics."
armor = list("melee" = 30, "bullet" = 80, "laser" = 0, "energy" = 0, "bomb" = -40, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
max_integrity = 55 //Weaker
max_integrity = 300
/obj/item/shield/riot/roman
name = "\improper Roman shield"
@@ -255,13 +271,13 @@ obj/item/shield/riot/bullet_proof
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
repair_material = /obj/item/stack/sheet/mineral/wood
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 65
max_integrity = 250
/obj/item/shield/riot/roman/fake
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>. It appears to be a bit flimsy."
block_chance = 0
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
max_integrity = 30
max_integrity = 40
/obj/item/shield/riot/roman/shatter(mob/living/carbon/human/owner)
playsound(owner, 'sound/effects/grillehit.ogg', 100)
@@ -279,7 +295,7 @@ obj/item/shield/riot/bullet_proof
repair_material = /obj/item/stack/sheet/mineral/wood
block_chance = 30
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 55
max_integrity = 150
/obj/item/shield/riot/buckler/shatter(mob/living/carbon/human/owner)
playsound(owner, 'sound/effects/bang.ogg', 50)
@@ -297,13 +313,16 @@ obj/item/shield/riot/bullet_proof
throw_speed = 3
throw_range = 4
w_class = WEIGHT_CLASS_NORMAL
var/active = 0
var/active = FALSE
/obj/item/shield/riot/tele/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return)
if(!active)
return BLOCK_NONE
return ..()
/obj/item/shield/riot/tele/can_active_block()
return ..() && active
/obj/item/shield/riot/tele/attack_self(mob/living/user)
active = !active
icon_state = "teleriot[active]"
@@ -335,8 +354,7 @@ obj/item/shield/riot/bullet_proof
icon_state = "makeshift_shield"
custom_materials = list(/datum/material/iron = 18000)
slot_flags = null
block_chance = 35
max_integrity = 100 //Made of metal welded together its strong but not unkillable
max_integrity = 300 //Made of metal welded together its strong but not unkillable
force = 10
throwforce = 7
@@ -346,7 +364,6 @@ obj/item/shield/riot/bullet_proof
armor = list("melee" = 95, "bullet" = 95, "laser" = 75, "energy" = 60, "bomb" = 90, "bio" = 90, "rad" = 0, "fire" = 90, "acid" = 10) //Armor for the item, dosnt transfer to user
item_state = "metal"
icon_state = "metal"
block_chance = 75 //1/4 shots will hit*
force = 16
slowdown = 2
throwforce = 15 //Massive pice of metal
@@ -357,19 +374,17 @@ obj/item/shield/riot/bullet_proof
/obj/item/shield/riot/tower/swat
name = "swat shield"
desc = "A massive, heavy shield that can block a lot of attacks, can take a lot of abuse before breaking."
max_integrity = 175
block_chance = 50
max_integrity = 250
/obj/item/shield/riot/implant
name = "telescoping shield implant"
desc = "A compact, arm-mounted telescopic shield. While nigh-indestructible when powered by a host user, it will eventually overload from damage. Recharges while inside its implant."
item_state = "metal"
icon_state = "metal"
block_chance = 50
slowdown = 1
shield_flags = SHIELD_FLAGS_DEFAULT
max_integrity = 60
obj_integrity = 60
max_integrity = 100
obj_integrity = 100
can_shatter = FALSE
item_flags = SLOWS_WHILE_IN_HAND
var/recharge_timerid
+64
View File
@@ -0,0 +1,64 @@
/obj/item/shrapnel // frag grenades
name = "shrapnel shard"
embedding = list(embed_chance=70, ignore_throwspeed_threshold=TRUE, fall_chance=4, embed_chance_turf_mod=-100)
custom_materials = list(/datum/material/iron=50)
armour_penetration = -20
icon = 'icons/obj/shards.dmi'
icon_state = "large"
w_class = WEIGHT_CLASS_TINY
item_flags = DROPDEL
/obj/item/shrapnel/stingball // stingbang grenades
name = "stingball"
embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15, embed_chance_turf_mod=-100)
icon_state = "tiny"
/obj/item/shrapnel/bullet // bullets
name = "bullet"
icon = 'icons/obj/ammo.dmi'
icon_state = "s-casing"
item_flags = NONE
/obj/item/shrapnel/bullet/c38 // .38 round
name = "\improper .38 bullet"
/obj/item/shrapnel/bullet/c38/dumdum // .38 DumDum round
name = "\improper .38 DumDum bullet"
embedding = list(embed_chance=70, fall_chance=7, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10, embed_chance_turf_mod=-100)
/obj/item/projectile/bullet/shrapnel
name = "flying shrapnel shard"
damage = 9
range = 10
armour_penetration = -30
dismemberment = 5
ricochets_max = 2
ricochet_chance = 40
shrapnel_type = /obj/item/shrapnel
ricochet_incidence_leeway = 60
/obj/item/projectile/bullet/shrapnel/mega
name = "flying shrapnel hunk"
range = 25
dismemberment = 10
ricochets_max = 4
ricochet_chance = 90
ricochet_decay_chance = 0.9
/obj/item/projectile/bullet/pellet/stingball
name = "stingball pellet"
damage = 3
stamina = 8
ricochets_max = 4
ricochet_chance = 66
ricochet_decay_chance = 1
ricochet_decay_damage = 0.9
ricochet_auto_aim_angle = 10
ricochet_auto_aim_range = 2
ricochet_incidence_leeway = 0
shrapnel_type = /obj/item/shrapnel/stingball
/obj/item/projectile/bullet/pellet/stingball/mega
name = "megastingball pellet"
ricochets_max = 6
ricochet_chance = 110
+5 -1
View File
@@ -10,7 +10,7 @@
slot_flags = ITEM_SLOT_BACK
throwforce = 20
throw_speed = 4
embedding = list("embedded_impact_pain_multiplier" = 3, "embed_chance" = 90)
embedding = list("impact_pain_mult" = 3)
armour_penetration = 10
custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075)
hitsound = 'sound/weapons/bladeslice.ogg'
@@ -102,6 +102,8 @@
var/obj/item/shard/tip = locate() in parts_list
if (istype(tip, /obj/item/shard/plasma))
throwforce = 21
embedding = list(embed_chance = 75, pain_mult = 1.5) //plasmaglass spears are sharper
updateEmbedding()
icon_prefix = "spearplasma"
AddComponent(/datum/component/two_handed, force_unwielded=11, force_wielded=19, icon_wielded="[icon_prefix]1")
qdel(tip)
@@ -117,6 +119,8 @@
if(G)
explosive = G
name = "explosive lance"
embedding = list(embed_chance = 0, pain_mult = 1)//elances should not be embeddable
updateEmbedding()
desc = "A makeshift spear with \a [G] attached to it."
update_icon()
+122 -2
View File
@@ -13,18 +13,33 @@
novariants = FALSE
item_flags = NOBLUDGEON
var/self_delay = 50
var/other_delay = 0
var/repeating = FALSE
/obj/item/stack/medical/attack(mob/living/M, mob/user)
. = ..()
try_heal(M, user)
/obj/item/stack/medical/proc/try_heal(mob/living/M, mob/user, silent = FALSE)
if(!M.can_inject(user, TRUE))
return
if(M == user)
user.visible_message("<span class='notice'>[user] starts to apply \the [src] on [user.p_them()]self...</span>", "<span class='notice'>You begin applying \the [src] on yourself...</span>")
if(!silent)
user.visible_message("<span class='notice'>[user] starts to apply \the [src] on [user.p_them()]self...</span>", "<span class='notice'>You begin applying \the [src] on yourself...</span>")
if(!do_mob(user, M, self_delay, extra_checks=CALLBACK(M, /mob/living/proc/can_inject, user, TRUE)))
return
else if(other_delay)
if(!silent)
user.visible_message("<span class='notice'>[user] starts to apply \the [src] on [M].</span>", "<span class='notice'>You begin applying \the [src] on [M]...</span>")
if(!do_mob(user, M, other_delay, extra_checks=CALLBACK(M, /mob/living/proc/can_inject, user, TRUE)))
return
if(heal(M, user))
log_combat(user, M, "healed", src.name)
use(1)
if(repeating && amount > 0)
try_heal(M, user, TRUE)
/obj/item/stack/medical/proc/heal(mob/living/M, mob/user)
@@ -96,7 +111,7 @@
var/stop_bleeding = 1800
var/heal_brute = 5
self_delay = 10
custom_price = 100
custom_price = PRICE_REALLY_CHEAP
/obj/item/stack/medical/gauze/heal(mob/living/M, mob/user)
if(ishuman(M))
@@ -174,3 +189,108 @@
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
return TOXLOSS
/obj/item/stack/medical/suture
name = "suture"
desc = "Sterile sutures used to seal up cuts and lacerations."
gender = PLURAL
singular_name = "suture"
icon_state = "suture"
self_delay = 30
other_delay = 10
amount = 15
max_amount = 15
repeating = TRUE
var/heal_brute = 10
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
/obj/item/stack/medical/suture/one
amount = 1
/obj/item/stack/medical/suture/heal(mob/living/M, mob/user)
. = ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
return
if(iscarbon(M))
return heal_carbon(M, user, heal_brute, 0)
if(isanimal(M))
var/mob/living/simple_animal/critter = M
if (!(critter.healable))
to_chat(user, "<span class='warning'>You cannot use \the [src] on [M]!</span>")
return FALSE
else if (critter.health == critter.maxHealth)
to_chat(user, "<span class='notice'>[M] is at full health.</span>")
return FALSE
user.visible_message("<span class='green'>[user] applies \the [src] on [M].</span>", "<span class='green'>You apply \the [src] on [M].</span>")
M.heal_bodypart_damage(heal_brute)
return TRUE
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
/obj/item/stack/medical/mesh
name = "regenerative mesh"
desc = "A bacteriostatic mesh used to dress burns."
gender = PLURAL
singular_name = "regenerative mesh"
icon_state = "regen_mesh"
self_delay = 30
other_delay = 10
amount = 15
max_amount = 15
repeating = TRUE
var/heal_burn = 10
var/is_open = TRUE ///This var determines if the sterile packaging of the mesh has been opened.
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
/obj/item/stack/medical/mesh/one
amount = 1
/obj/item/stack/medical/mesh/Initialize()
. = ..()
if(amount == max_amount) //only seal full mesh packs
is_open = FALSE
update_icon()
/obj/item/stack/medical/mesh/update_icon_state()
if(!is_open)
icon_state = "regen_mesh_closed"
else
return ..()
/obj/item/stack/medical/mesh/heal(mob/living/M, mob/user)
. = ..()
if(M.stat == DEAD)
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
return
if(iscarbon(M))
return heal_carbon(M, user, 0, heal_burn)
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
/obj/item/stack/medical/mesh/try_heal(mob/living/M, mob/user, silent = FALSE)
if(!is_open)
to_chat(user, "<span class='warning'>You need to open [src] first.</span>")
return
. = ..()
/obj/item/stack/medical/mesh/AltClick(mob/living/user)
if(!is_open)
to_chat(user, "<span class='warning'>You need to open [src] first.</span>")
return
. = ..()
/obj/item/stack/medical/mesh/attack_hand(mob/user)
if(!is_open & user.get_inactive_held_item() == src)
to_chat(user, "<span class='warning'>You need to open [src] first.</span>")
return
. = ..()
/obj/item/stack/medical/mesh/attack_self(mob/user)
if(!is_open)
is_open = TRUE
to_chat(user, "<span class='notice'>You open the sterile mesh package.</span>")
update_icon()
playsound(src, 'sound/items/poster_ripped.ogg', 20, TRUE)
return
. = ..()
+1
View File
@@ -21,6 +21,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \
max_amount = 50
attack_verb = list("hit", "bludgeoned", "whacked")
hitsound = 'sound/weapons/grenadelaunch.ogg'
embedding = list()
novariants = TRUE
/obj/item/stack/rods/suicide_act(mob/living/carbon/user)
@@ -291,6 +291,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
max_integrity = 40
sharpness = IS_SHARP
var/icon_prefix
embedding = list("embed_chance" = 65)
/obj/item/shard/suicide_act(mob/user)
@@ -242,6 +242,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
null, \
new/datum/stack_recipe("wooden firearm body", /obj/item/weaponcrafting/improvised_parts/wooden_body, 10, time = 40), \
new/datum/stack_recipe("rifle stock", /obj/item/weaponcrafting/stock, 10, time = 40), \
new/datum/stack_recipe("pistol grip", /obj/item/weaponcrafting/improvised_parts/wooden_grip, 5, time = 40), \
new/datum/stack_recipe("rolling pin", /obj/item/kitchen/rollingpin, 2, time = 30), \
new/datum/stack_recipe("wooden bucket", /obj/item/reagent_containers/glass/bucket/wood, 2, time = 30), \
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
@@ -778,6 +779,9 @@ GLOBAL_LIST_INIT(plastic_recipes, list(
/obj/item/stack/sheet/plastic/fifty
amount = 50
/obj/item/stack/sheet/plastic/twenty
amount = 20
/obj/item/stack/sheet/plastic/five
amount = 5
+61
View File
@@ -0,0 +1,61 @@
/obj/item/stack/sticky_tape
name = "sticky tape"
singular_name = "sticky tape"
desc = "Used for sticking to things for sticking said things to people."
icon = 'icons/obj/tapes.dmi'
icon_state = "tape_w"
var/prefix = "sticky"
item_flags = NOBLUDGEON
amount = 5
max_amount = 5
resistance_flags = FLAMMABLE
var/list/conferred_embed = EMBED_HARMLESS
var/overwrite_existing = FALSE
/obj/item/stack/sticky_tape/afterattack(obj/item/I, mob/living/user)
if(!istype(I))
return
if(I.embedding && I.embedding == conferred_embed)
to_chat(user, "<span class='warning'>[I] is already coated in [src]!</span>")
return
user.visible_message("<span class='notice'>[user] begins wrapping [I] with [src].</span>", "<span class='notice'>You begin wrapping [I] with [src].</span>")
if(do_after(user, 30, target=I))
I.embedding = conferred_embed
I.updateEmbedding()
to_chat(user, "<span class='notice'>You finish wrapping [I] with [src].</span>")
use(1)
I.name = "[prefix] [I.name]"
if(istype(I, /obj/item/grenade))
var/obj/item/grenade/sticky_bomb = I
sticky_bomb.sticky = TRUE
/obj/item/stack/sticky_tape/super
name = "super sticky tape"
singular_name = "super sticky tape"
desc = "Quite possibly the most mischevious substance in the galaxy. Use with extreme lack of caution."
icon_state = "tape_y"
prefix = "super sticky"
conferred_embed = EMBED_HARMLESS_SUPERIOR
/obj/item/stack/sticky_tape/pointy
name = "pointy tape"
singular_name = "pointy tape"
desc = "Used for sticking to things for sticking said things inside people."
icon_state = "tape_evil"
prefix = "pointy"
conferred_embed = EMBED_POINTY
/obj/item/stack/sticky_tape/pointy/super
name = "super pointy tape"
singular_name = "super pointy tape"
desc = "You didn't know tape could look so sinister. Welcome to Space Station 13."
icon_state = "tape_spikes"
prefix = "super pointy"
conferred_embed = EMBED_POINTY_SUPERIOR
@@ -266,6 +266,9 @@
/obj/item/stack/tile/carpet/blackred/twenty
amount = 20
/obj/item/stack/tile/carpet/blackred/thirty
amount = 30
/obj/item/stack/tile/carpet/blackred/fifty
amount = 50
@@ -275,6 +278,9 @@
/obj/item/stack/tile/carpet/monochrome/twenty
amount = 20
/obj/item/stack/tile/carpet/monochrome/thirty
amount = 30
/obj/item/stack/tile/carpet/monochrome/fifty
amount = 50
@@ -284,6 +290,9 @@
/obj/item/stack/tile/carpet/blue/twenty
amount = 20
/obj/item/stack/tile/carpet/blue/thirty
amount = 30
/obj/item/stack/tile/carpet/blue/fifty
amount = 50
@@ -293,6 +302,9 @@
/obj/item/stack/tile/carpet/cyan/twenty
amount = 20
/obj/item/stack/tile/carpet/cyan/thirty
amount = 30
/obj/item/stack/tile/carpet/cyan/fifty
amount = 50
@@ -302,6 +314,9 @@
/obj/item/stack/tile/carpet/green/twenty
amount = 20
/obj/item/stack/tile/carpet/green/thirty
amount = 30
/obj/item/stack/tile/carpet/green/fifty
amount = 50
@@ -311,6 +326,9 @@
/obj/item/stack/tile/carpet/orange/twenty
amount = 20
/obj/item/stack/tile/carpet/orange/thirty
amount = 30
/obj/item/stack/tile/carpet/orange/fifty
amount = 50
@@ -320,6 +338,9 @@
/obj/item/stack/tile/carpet/purple/twenty
amount = 20
/obj/item/stack/tile/carpet/purple/thirty
amount = 30
/obj/item/stack/tile/carpet/purple/fifty
amount = 50
@@ -329,6 +350,9 @@
/obj/item/stack/tile/carpet/red/twenty
amount = 20
/obj/item/stack/tile/carpet/red/thirty
amount = 30
/obj/item/stack/tile/carpet/red/fifty
amount = 50
@@ -338,6 +362,9 @@
/obj/item/stack/tile/carpet/royalblack/twenty
amount = 20
/obj/item/stack/tile/carpet/royalblack/thirty
amount = 30
/obj/item/stack/tile/carpet/royalblack/fifty
amount = 50
@@ -347,6 +374,9 @@
/obj/item/stack/tile/carpet/royalblue/twenty
amount = 20
/obj/item/stack/tile/carpet/royalblue/thirty
amount = 30
/obj/item/stack/tile/carpet/royalblue/fifty
amount = 50
+23 -5
View File
@@ -382,16 +382,16 @@
icon = 'icons/obj/chemical.dmi'
icon_state = "bag"
desc = "A bag for storing pills, patches, and bottles."
w_class = WEIGHT_CLASS_TINY
slot_flags = ITEM_SLOT_BELT|ITEM_SLOT_POCKET
resistance_flags = FLAMMABLE
/obj/item/storage/bag/chemistry/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = 200
STR.max_items = 50
STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT
STR.max_volume = STORAGE_VOLUME_CHEMISTRY_BAG
STR.insert_preposition = "in"
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/syringe/dart))
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/syringe/dart, /obj/item/reagent_containers/chem_pack))
/*
* Biowaste bag (mostly for xenobiologists)
@@ -402,7 +402,7 @@
icon = 'icons/obj/chemical.dmi'
icon_state = "biobag"
desc = "A bag for the safe transportation and disposal of biowaste and other biological materials."
w_class = WEIGHT_CLASS_TINY
slot_flags = ITEM_SLOT_BELT|ITEM_SLOT_POCKET
resistance_flags = FLAMMABLE
/obj/item/storage/bag/bio/ComponentInitialize()
@@ -427,3 +427,21 @@
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_combined_w_class = INFINITY
STR.max_items = 100
/obj/item/storage/bag/ammo
name = "ammo pouch"
desc = "A pouch for your ammo that goes in your pocket."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "ammopouch"
slot_flags = ITEM_SLOT_POCKET
w_class = WEIGHT_CLASS_BULKY
resistance_flags = FLAMMABLE
/obj/item/storage/bag/ammo/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.max_combined_w_class = 30
STR.max_items = 3
STR.display_numerical_stacking = FALSE
STR.can_hold = typecacheof(list(/obj/item/ammo_box/magazine, /obj/item/ammo_casing))
+13 -12
View File
@@ -180,7 +180,8 @@
/obj/item/implantcase,
/obj/item/implant,
/obj/item/implanter,
/obj/item/pinpointer/crew
/obj/item/pinpointer/crew,
/obj/item/reagent_containers/chem_pack
))
/obj/item/storage/belt/medical/surgery_belt_adv
@@ -512,16 +513,16 @@
new /obj/item/grenade/smokebomb(src)
new /obj/item/grenade/empgrenade(src)
new /obj/item/grenade/empgrenade(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/syndieminibomb/concussion/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/frag(src)
new /obj/item/grenade/gluon(src)
new /obj/item/grenade/gluon(src)
new /obj/item/grenade/gluon(src)
@@ -713,7 +714,7 @@
icon_state = "fannypack_leather"
item_state = "fannypack_leather"
dying_key = DYE_REGISTRY_FANNYPACK
custom_price = 100
custom_price = PRICE_ALMOST_CHEAP
/obj/item/storage/belt/fannypack/ComponentInitialize()
. = ..()
+15 -3
View File
@@ -275,6 +275,16 @@
for(var/i in 1 to 7)
new /obj/item/grenade/flashbang(src)
obj/item/storage/box/stingbangs
name = "box of stingbangs (WARNING)"
desc = "<B>WARNING: These devices are extremely dangerous and can cause severe injuries or death in repeated use.</B>"
icon_state = "secbox"
illustration = "flashbang"
/obj/item/storage/box/stingbangs/PopulateContents()
for(var/i in 1 to 5)
new /obj/item/grenade/stingbang(src)
/obj/item/storage/box/flashes
name = "box of flashbulbs"
desc = "<B>WARNING: Flashes can cause serious eye damage, protective eyewear is required.</B>"
@@ -434,6 +444,7 @@
desc = "<B>Instructions:</B> <I>Heat in microwave. Product will cool if not eaten within seven minutes.</I>"
icon_state = "donkpocketbox"
illustration=null
custom_premium_price = PRICE_ABOVE_NORMAL // git gud
/obj/item/storage/box/donkpockets/ComponentInitialize()
. = ..()
@@ -622,7 +633,7 @@
item_state = "zippo"
w_class = WEIGHT_CLASS_TINY
slot_flags = ITEM_SLOT_BELT
custom_price = 20
custom_price = PRICE_REALLY_CHEAP
/obj/item/storage/box/matches/ComponentInitialize()
. = ..()
@@ -744,8 +755,8 @@
//////
/obj/item/storage/box/hug/medical/PopulateContents()
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/ointment(src)
new /obj/item/stack/medical/suture(src)
new /obj/item/stack/medical/mesh(src)
new /obj/item/reagent_containers/hypospray/medipen(src)
// Clown survival box
@@ -1343,6 +1354,7 @@
name = "box of marshmallows"
desc = "A box of marshmallows."
illustration = "marshmallow"
custom_premium_price = PRICE_BELOW_NORMAL
/obj/item/storage/box/marshmallow/PopulateContents()
for (var/i in 1 to 5)
+22 -2
View File
@@ -70,6 +70,7 @@
name = "donut box"
spawn_type = /obj/item/reagent_containers/food/snacks/donut
fancy_open = TRUE
custom_price = PRICE_NORMAL
/obj/item/storage/fancy/donut_box/ComponentInitialize()
. = ..()
@@ -136,7 +137,23 @@
slot_flags = ITEM_SLOT_BELT
icon_type = "cigarette"
spawn_type = /obj/item/clothing/mask/cigarette/space_cigarette
custom_price = 75
custom_price = PRICE_ALMOST_CHEAP
var/spawn_coupon = TRUE
/obj/item/storage/fancy/cigarettes/attack_self(mob/user)
if(contents.len == 0 && spawn_coupon)
to_chat(user, "<span class='notice'>You rip the back off \the [src] and get a coupon!</span>")
var/obj/item/coupon/attached_coupon = new
user.put_in_hands(attached_coupon)
attached_coupon.generate()
attached_coupon = null
spawn_coupon = FALSE
name = "discarded cigarette packet"
desc = "An old cigarette packet with the back torn off, worth less than nothing now."
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 0
return
return ..()
/obj/item/storage/fancy/cigarettes/ComponentInitialize()
. = ..()
@@ -147,6 +164,8 @@
/obj/item/storage/fancy/cigarettes/examine(mob/user)
. = ..()
. += "<span class='notice'>Alt-click to extract contents.</span>"
if(spawn_coupon)
. += "<span class='notice'>There's a coupon on the back of the pack! You can tear it off once it's empty.</span>"
/obj/item/storage/fancy/cigarettes/AltClick(mob/living/carbon/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
@@ -278,7 +297,7 @@
///The value in here has NOTHING to do with icons. It needs to be this for the proper examine.
icon_type = "rolling paper"
spawn_type = /obj/item/rollingpaper
custom_price = 25
custom_price = PRICE_REALLY_CHEAP
/obj/item/storage/fancy/rollingpapers/ComponentInitialize()
. = ..()
@@ -307,6 +326,7 @@
w_class = WEIGHT_CLASS_NORMAL
icon_type = "premium cigar"
spawn_type = /obj/item/clothing/mask/cigarette/cigar
spawn_coupon = FALSE
/obj/item/storage/fancy/cigarettes/cigars/ComponentInitialize()
. = ..()
+15 -14
View File
@@ -37,10 +37,10 @@
if(empty)
return
new /obj/item/stack/medical/gauze(src)
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/ointment(src)
new /obj/item/stack/medical/ointment(src)
new /obj/item/stack/medical/suture(src)
new /obj/item/stack/medical/suture(src)
new /obj/item/stack/medical/mesh(src)
new /obj/item/stack/medical/mesh(src)
new /obj/item/reagent_containers/hypospray/medipen(src)
new /obj/item/healthanalyzer(src)
@@ -52,12 +52,12 @@
if(empty)
return
new /obj/item/stack/medical/gauze(src)
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/bruise_pack(src)
new /obj/item/stack/medical/ointment(src)
new /obj/item/stack/medical/ointment(src)
new /obj/item/stack/medical/ointment(src)
new /obj/item/stack/medical/suture(src)
new /obj/item/stack/medical/suture(src)
new /obj/item/stack/medical/suture(src)
new /obj/item/stack/medical/mesh(src)
new /obj/item/stack/medical/mesh(src)
new /obj/item/stack/medical/mesh(src)
/obj/item/storage/firstaid/fire
name = "burn treatment kit"
@@ -224,7 +224,7 @@
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.storage_flags = STORAGE_FLAGS_VOLUME_DEFAULT
STR.max_volume = 14
STR.max_volume = STORAGE_VOLUME_PILL_BOTTLE
STR.allow_quick_gather = TRUE
STR.click_gather = TRUE
STR.can_hold = typecacheof(list(/obj/item/reagent_containers/pill, /obj/item/dice))
@@ -418,7 +418,8 @@
/obj/item/circuitboard/computer/crew,
/obj/item/stack/sheet/glass,
/obj/item/stack/sheet/mineral/silver,
/obj/item/organ_storage
/obj/item/organ_storage,
/obj/item/reagent_containers/chem_pack
))
//hijacking the minature first aids for hypospray boxes. <3
@@ -432,8 +433,8 @@
throw_range = 7
var/empty = FALSE
item_state = "firstaid"
custom_price = 300
custom_premium_price = 500
custom_price = PRICE_ABOVE_NORMAL
custom_premium_price = PRICE_EXPENSIVE
/obj/item/storage/hypospraykit/ComponentInitialize()
. = ..()
+43 -10
View File
@@ -188,19 +188,52 @@
new /obj/item/clothing/accessory/medal/plasma/nobel_science(src)
/obj/item/storage/lockbox/medal/engineering
name = "engineering medal box"
desc = "A locked box used to store medals to be given to the members of the engineering department."
req_access = list(ACCESS_CE)
name = "engineering medal box"
desc = "A locked box used to store medals to be given to the members of the engineering department."
req_access = list(ACCESS_CE)
/obj/item/storage/lockbox/medal/engineering/PopulateContents()
for(var/i in 1 to 3)
new /obj/item/clothing/accessory/medal/engineer(src)
for(var/i in 1 to 3)
new /obj/item/clothing/accessory/medal/engineer(src)
/obj/item/storage/lockbox/medal/medical
name = "medical medal box"
desc = "A locked box used to store medals to be given to the members of the medical department."
req_access = list(ACCESS_CMO)
name = "medical medal box"
desc = "A locked box used to store medals to be given to the members of the medical department."
req_access = list(ACCESS_CMO)
/obj/item/storage/lockbox/medal/medical/PopulateContents()
for(var/i in 1 to 3)
new /obj/item/clothing/accessory/medal/ribbon/medical_doctor(src)
for(var/i in 1 to 3)
new /obj/item/clothing/accessory/medal/ribbon/medical_doctor(src)
/obj/item/storage/lockbox/order
name = "order lockbox"
desc = "A box used to secure small cargo orders from being looted by those who didn't order it. Yeah, cargo tech, that means you."
icon = 'icons/obj/storage.dmi'
icon_state = "secure"
item_state = "sec-case"
lefthand_file = 'icons/mob/inhands/equipment/briefcase_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi'
w_class = WEIGHT_CLASS_HUGE
var/datum/bank_account/buyer_account
var/privacy_lock = TRUE
/obj/item/storage/lockbox/order/Initialize(datum/bank_account/_buyer_account)
. = ..()
buyer_account = _buyer_account
/obj/item/storage/lockbox/order/attackby(obj/item/W, mob/user, params)
if(!istype(W, /obj/item/card/id))
return ..()
var/obj/item/card/id/id_card = W
if(iscarbon(user))
add_fingerprint(user)
if(id_card.registered_account != buyer_account)
to_chat(user, "<span class='notice'>Bank account does not match with buyer!</span")
return
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_SET_LOCKSTATE, !privacy_lock)
privacy_lock = SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED)
user.visible_message("<span class='notice'>[user] [privacy_lock ? "" : "un"]locks [src]'s privacy lock.</span>",
"<span class='notice'>You [privacy_lock ? "" : "un"]lock [src]'s privacy lock.</span>")
+2 -2
View File
@@ -174,7 +174,7 @@
name = "\improper X-01 Multiphase energy gun box"
desc = "A storage case for a high-tech energy firearm."
/obj/item/storage/secure/briefcase/mws_pack_hos/PopulateContents()
/obj/item/storage/secure/briefcase/hos/multiphase_box/PopulateContents()
new /obj/item/gun/energy/e_gun/hos(src)
// -----------------------------
@@ -212,4 +212,4 @@
return attack_self(user)
/obj/item/storage/secure/safe/HoS
name = "head of security's safe"
name = "head of security's safe"
+5 -3
View File
@@ -141,7 +141,7 @@
/obj/item/melee/baton/attack(mob/M, mob/living/carbon/human/user)
var/interrupt = common_baton_melee(M, user, FALSE)
if(!interrupt)
..()
return ..()
/obj/item/melee/baton/alt_pre_attack(atom/A, mob/living/user, params)
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-disarming.
@@ -154,7 +154,7 @@
if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
clowning_around(user)
if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")
to_chat(user, "<span class='danger'>You're too exhausted to use [src] properly.</span>")
return TRUE
if(ishuman(M))
var/mob/living/carbon/human/L = M
@@ -170,10 +170,12 @@
return disarming || (user.a_intent != INTENT_HARM)
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user, disarming = FALSE)
if(L.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, null) & BLOCK_SUCCESS) //No message; check_shields() handles that
var/list/return_list = list()
if(L.mob_run_block(src, 0, "[user]'s [name]", ATTACK_TYPE_MELEE, 0, user, null, return_list) & BLOCK_SUCCESS) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
var/stunpwr = stamforce
stunpwr = block_calculate_resultant_damage(stunpwr, return_list)
var/obj/item/stock_parts/cell/our_cell = get_cell()
if(!our_cell)
switch_status(FALSE)
+4 -1
View File
@@ -93,11 +93,13 @@
F.update_icon()
else
return ..()
//Makes empty oxygen tanks spawn without gas
/obj/item/tank/internals/plasma/empty/populate_gas()
return
/obj/item/tank/internals/plasma/full/populate_gas()
air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
/*
* Plasmaman Plasma Tank
*/
@@ -130,6 +132,7 @@
air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C)
return
//makes empty plasma tanks spawn without gas.
/obj/item/tank/internals/plasmaman/belt/empty/populate_gas()
return
+4
View File
@@ -153,6 +153,10 @@
return (BRUTELOSS)
/obj/item/tank/attack_ghost(mob/dead/observer/O)
. = ..()
atmosanalyzer_scan(air_contents, O, src, FALSE)
/obj/item/tank/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
if(istype(W, /obj/item/assembly_holder))
+1 -1
View File
@@ -145,7 +145,7 @@
desc = "A janitorial watertank backpack with nozzle to clean dirt and graffiti."
icon_state = "waterbackpackjani"
item_state = "waterbackpackjani"
custom_price = 1000
custom_price = PRICE_ALMOST_ONE_GRAND
/obj/item/watertank/janitor/Initialize()
. = ..()
+4 -3
View File
@@ -444,6 +444,7 @@
throwforce = 0
throw_speed = 3
throw_range = 5
block_parry_data = null
attack_verb = list("attacked", "struck", "hit")
total_mass_on = TOTAL_MASS_TOY_SWORD
sharpness = IS_BLUNT
@@ -840,11 +841,11 @@
/obj/item/toy/cards/deck/update_icon_state()
switch(cards.len)
if(INFINITY to original_size/2)
if(original_size*0.5 to INFINITY)
icon_state = "deck_[deckstyle]_full"
if(original_size/2 to original_size/4)
if(original_size*0.25 to original_size*0.5)
icon_state = "deck_[deckstyle]_half"
if(original_size/4 to 1)
if(1 to original_size*0.25)
icon_state = "deck_[deckstyle]_low"
else
icon_state = "deck_[deckstyle]_empty"
+20 -2
View File
@@ -122,11 +122,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
/obj/item/claymore/highlander/pickup(mob/living/user)
. = ..()
to_chat(user, "<span class='notice'>The power of Scotland protects you! You are shielded from all stuns and knockdowns.</span>")
user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!")
user.ignore_slowdown(HIGHLANDER)
/obj/item/claymore/highlander/dropped(mob/living/user)
. = ..()
user.unignore_slowdown(HIGHLANDER)
if(!QDELETED(src))
qdel(src) //If this ever happens, it's because you lost an arm
@@ -297,12 +299,28 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
force = 2
throwforce = 20 //This is never used on mobs since this has a 100% embed chance.
throw_speed = 4
embedding = list("embedded_pain_multiplier" = 4, "embed_chance" = 100, "embedded_fall_chance" = 0)
embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15)
armour_penetration = 40
w_class = WEIGHT_CLASS_SMALL
sharpness = IS_SHARP
custom_materials = list(/datum/material/iron=500, /datum/material/glass=500)
resistance_flags = FIRE_PROOF
/obj/item/throwing_star/stamina
name = "shock throwing star"
desc = "An aerodynamic disc designed to cause excruciating pain when stuck inside fleeing targets, hopefully without causing fatal harm."
throwforce = 5
embedding = list("pain_chance" = 5, "embed_chance" = 100, "fall_chance" = 0, "jostle_chance" = 10, "pain_stam_pct" = 0.8, "jostle_pain_mult" = 3)
/obj/item/throwing_star/toy
name = "toy throwing star"
desc = "An aerodynamic disc strapped with adhesive for sticking to people, good for playing pranks and getting yourself killed by security."
sharpness = IS_BLUNT
force = 0
throwforce = 0
embedding = list("pain_mult" = 0, "jostle_pain_mult" = 0, "embed_chance" = 100, "fall_chance" = 0)
/obj/item/switchblade
name = "switchblade"
icon_state = "switchblade"
@@ -675,7 +693,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
to_chat(user, "<span class='warning'>You easily land a critical blow on the [target].</span>")
if(istype(target, /mob/living/))
var/mob/living/bug = target
bug.adjustBruteLoss(-35) //What kinda mad man would go into melee with a spider?!
bug.adjustBruteLoss(35) //What kinda mad man would go into melee with a spider?!
else
qdel(target)
+2 -1
View File
@@ -74,7 +74,8 @@
/obj/bullet_act(obj/item/projectile/P)
. = ..()
playsound(src, P.hitsound, 50, 1)
visible_message("<span class='danger'>[src] is hit by \a [P]!</span>", null, null, COMBAT_MESSAGE_RANGE)
if(P.suppressed != SUPPRESSED_VERY)
visible_message("<span class='danger'>[src] is hit by \a [P]!</span>", null, null, COMBAT_MESSAGE_RANGE)
if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object
take_damage(P.damage, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration)
+5
View File
@@ -323,3 +323,8 @@
/obj/proc/rnd_crafted(obj/machinery/rnd/production/P)
return
/obj/handle_ricochet(obj/item/projectile/P)
. = ..()
if(. && ricochet_damage_mod)
take_damage(P.damage * ricochet_damage_mod, P.damage_type, P.flag, 0, turn(P.dir, 180), P.armour_penetration) // pass along ricochet_damage_mod damage to the structure for the ricochet
+2
View File
@@ -9,6 +9,8 @@
var/mob/living/structureclimber
var/broken = 0 //similar to machinery's stat BROKEN
layer = BELOW_OBJ_LAYER
flags_ricochet = RICOCHET_HARD
ricochet_chance_mod = 0.5
/obj/structure/Initialize()
if (!armor)
+2 -2
View File
@@ -41,7 +41,7 @@ LINEN BINS
return
/obj/item/bedsheet/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wirecutters) || I.get_sharpness())
if(!(flags_1 & HOLOGRAM_1) && (istype(I, /obj/item/wirecutters) || I.get_sharpness()))
var/obj/item/stack/sheet/cloth/C = new (get_turf(src), 3)
transfer_fingerprints_to(C)
C.add_fingerprint(user)
@@ -369,4 +369,4 @@ LINEN BINS
/obj/structure/bedsheetbin/color
sheet_types = list(/obj/item/bedsheet, /obj/item/bedsheet/blue, /obj/item/bedsheet/green, /obj/item/bedsheet/orange, \
/obj/item/bedsheet/purple, /obj/item/bedsheet/red, /obj/item/bedsheet/yellow, /obj/item/bedsheet/brown, \
/obj/item/bedsheet/black)
/obj/item/bedsheet/black)
@@ -51,7 +51,6 @@
new /obj/item/storage/backpack/satchel/leather/withwallet( src )
new /obj/item/instrument/piano_synth(src)
new /obj/item/radio/headset( src )
new /obj/item/clothing/head/colour(src)
/obj/structure/closet/secure_closet/personal/attackby(obj/item/W, mob/user, params)
var/obj/item/card/id/I = W.GetID()
@@ -6,8 +6,16 @@
max_integrity = 250
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
secure = TRUE
var/melee_min_damage = 20
/obj/structure/closet/secure_closet/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir)
if(damage_flag == "melee" && damage_amount < 20)
if(damage_flag == "melee" && damage_amount < melee_min_damage)
return 0
. = ..()
. = ..()
// Exists to work around the minimum 700 cr price for goodies / small items
/obj/structure/closet/secure_closet/goodies
icon_state = "goodies"
desc = "A sturdier card-locked storage unit used for bulky shipments."
max_integrity = 500 // Same as crates.
melee_min_damage = 25 // Idem.
@@ -0,0 +1,66 @@
/obj/effect/mob_spawn/human/fugitive
assignedrole = "Fugitive Hunter"
flavour_text = "" //the flavor text will be the backstory argument called on the antagonist's greet, see hunter.dm for details
roundstart = FALSE
death = FALSE
random = TRUE
show_flavour = FALSE
density = TRUE
var/back_story = "error"
/obj/effect/mob_spawn/human/fugitive/Initialize(mapload)
. = ..()
notify_ghosts("Hunters are waking up looking for refugees!", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_FUGITIVE)
/obj/effect/mob_spawn/human/fugitive/special(mob/living/new_spawn)
var/datum/antagonist/fugitive_hunter/fughunter = new
fughunter.backstory = back_story
new_spawn.mind.add_antag_datum(fughunter)
fughunter.greet()
message_admins("[ADMIN_LOOKUPFLW(new_spawn)] has been made into a Fugitive Hunter by an event.")
log_game("[key_name(new_spawn)] was spawned as a Fugitive Hunter by an event.")
/obj/effect/mob_spawn/human/fugitive/spacepol
name = "police pod"
desc = "A small sleeper typically used to put people to sleep for briefing on the mission."
mob_name = "a spacepol officer"
flavour_text = "Justice has arrived. I am a member of the Spacepol!"
back_story = "space cop"
outfit = /datum/outfit/spacepol
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
/obj/effect/mob_spawn/human/fugitive/russian
name = "russian pod"
flavour_text = "Ay blyat. I am a space-russian smuggler! We were mid-flight when our cargo was beamed off our ship!"
back_story = "russian"
desc = "A small sleeper typically used to make long distance travel a bit more bearable."
mob_name = "russian"
outfit = /datum/outfit/russiancorpse/hunter
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
/obj/effect/mob_spawn/human/fugitive/bounty
name = "bounty hunter pod"
flavour_text = "We got a new bounty on some fugitives, dead or alive."
back_story = "bounty hunters"
desc = "A small sleeper typically used to make long distance travel a bit more bearable."
mob_name = "bounty hunter"
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
/obj/effect/mob_spawn/human/fugitive/bounty/Destroy()
var/obj/structure/fluff/empty_sleeper/S = new(drop_location())
S.setDir(dir)
return ..()
/obj/effect/mob_spawn/human/fugitive/bounty/armor
outfit = /datum/outfit/bountyarmor
/obj/effect/mob_spawn/human/fugitive/bounty/hook
outfit = /datum/outfit/bountyhook
/obj/effect/mob_spawn/human/fugitive/bounty/synth
outfit = /datum/outfit/bountysynth
@@ -581,7 +581,7 @@
uniform = /obj/item/clothing/under/rank/rnd/scientist
shoes = /obj/item/clothing/shoes/laceup
id = /obj/item/card/id/away/old/sci
l_pocket = /obj/item/stack/medical/bruise_pack
l_pocket = /obj/item/stack/medical/suture
assignedrole = "Ancient Crew"
job_description = "Oldstation Crew"
@@ -694,15 +694,12 @@
..()
var/suited = !preference_source || preference_source.prefs.jumpsuit_style == PREF_SUIT
if (CONFIG_GET(flag/grey_assistants))
if(suited)
uniform = /obj/item/clothing/under/color/grey
else
uniform = /obj/item/clothing/under/color/jumpskirt/grey
uniform = suited ? /obj/item/clothing/under/color/grey : /obj/item/clothing/under/color/jumpskirt/grey
else
if(suited)
uniform = /obj/item/clothing/under/color/random
if(SSevents.holidays && SSevents.holidays[PRIDE_MONTH])
uniform = suited ? /obj/item/clothing/under/color/rainbow : /obj/item/clothing/under/color/jumpskirt/rainbow
else
uniform = /obj/item/clothing/under/color/jumpskirt/random
uniform = suited ? /obj/item/clothing/under/color/random : /obj/item/clothing/under/color/jumpskirt/random
/obj/item/storage/box/syndie_kit/chameleon/ghostcafe
name = "ghost cafe costuming kit"
@@ -4,11 +4,13 @@
icon_state = "human_male"
density = TRUE
anchored = TRUE
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
max_integrity = 200
var/timer = 240 //eventually the person will be freed
var/timer = 8 MINUTES //eventually the person will be freed
var/mob/living/petrified_mob
/obj/structure/statue/petrified/New(loc, mob/living/L, statue_timer)
/obj/structure/statue/petrified/Initialize(mapload, mob/living/L, statue_timer)
. = ..()
if(statue_timer)
timer = statue_timer
if(L)
@@ -17,25 +19,18 @@
L.buckled.unbuckle_mob(L,force=1)
L.visible_message("<span class='warning'>[L]'s skin rapidly turns to marble!</span>", "<span class='userdanger'>Your body freezes up! Can't... move... can't... think...</span>")
L.forceMove(src)
ADD_TRAIT(L, TRAIT_MUTE, STATUE_MUTE)
ADD_TRAIT(L, TRAIT_MUTE, STATUE_TRAIT)
ADD_TRAIT(L, TRAIT_EMOTEMUTE, STATUE_TRAIT)
ADD_TRAIT(L, TRAIT_LOOC_MUTE, STATUE_TRAIT)
ADD_TRAIT(L, TRAIT_AOOC_MUTE, STATUE_TRAIT)
ADD_TRAIT(L, TRAIT_MOBILITY_NOMOVE, STATUE_TRAIT)
ADD_TRAIT(L, TRAIT_MOBILITY_NOPICKUP, STATUE_TRAIT)
ADD_TRAIT(L, TRAIT_MOBILITY_NOUSE, STATUE_TRAIT)
L.faction += "mimic" //Stops mimics from instaqdeling people in statues
L.status_flags |= GODMODE
obj_integrity = L.health + 100 //stoning damaged mobs will result in easier to shatter statues
max_integrity = obj_integrity
START_PROCESSING(SSobj, src)
..()
/obj/structure/statue/petrified/process()
if(!petrified_mob)
STOP_PROCESSING(SSobj, src)
timer--
petrified_mob.Stun(40) //So they can't do anything while petrified
if(timer <= 0)
STOP_PROCESSING(SSobj, src)
qdel(src)
/obj/structure/statue/petrified/contents_explosion(severity, target)
return
QDEL_IN(src, timer)
/obj/structure/statue/petrified/handle_atom_del(atom/A)
if(A == petrified_mob)
@@ -59,7 +54,13 @@
if(petrified_mob)
petrified_mob.status_flags &= ~GODMODE
petrified_mob.forceMove(loc)
REMOVE_TRAIT(petrified_mob, TRAIT_MUTE, STATUE_MUTE)
REMOVE_TRAIT(petrified_mob, TRAIT_MUTE, STATUE_TRAIT)
REMOVE_TRAIT(petrified_mob, TRAIT_EMOTEMUTE, STATUE_TRAIT)
REMOVE_TRAIT(petrified_mob, TRAIT_LOOC_MUTE, STATUE_TRAIT)
REMOVE_TRAIT(petrified_mob, TRAIT_AOOC_MUTE, STATUE_TRAIT)
REMOVE_TRAIT(petrified_mob, TRAIT_MOBILITY_NOMOVE, STATUE_TRAIT)
REMOVE_TRAIT(petrified_mob, TRAIT_MOBILITY_NOPICKUP, STATUE_TRAIT)
REMOVE_TRAIT(petrified_mob, TRAIT_MOBILITY_NOUSE, STATUE_TRAIT)
petrified_mob.take_overall_damage((petrified_mob.health - obj_integrity + 100)) //any new damage the statue incurred is transfered to the mob
petrified_mob.faction -= "mimic"
petrified_mob = null
+74 -1
View File
@@ -80,10 +80,11 @@
name = "shock trap"
desc = "A trap that will shock and render you immobile. You'd better avoid it."
icon_state = "trap-shock"
var/stun_time = 100
/obj/structure/trap/stun/trap_effect(mob/living/L)
L.electrocute_act(30, src, flags = SHOCK_NOGLOVES) // electrocute act does a message.
L.DefaultCombatKnockdown(100)
L.Paralyze(stun_time)
/obj/structure/trap/fire
name = "flame trap"
@@ -151,3 +152,75 @@
new /mob/living/simple_animal/hostile/construct/proteon/hostile(loc)
new /mob/living/simple_animal/hostile/construct/proteon/hostile(loc)
QDEL_IN(src, 30)
//fugitive traps
/obj/structure/trap/stun/hunter
name = "bounty trap"
desc = "A trap that only goes off when a fugitive steps on it, announcing the location and stunning the target. You'd better avoid it."
icon = 'icons/obj/objects.dmi'
icon_state = "bounty_trap_on"
stun_time = 200
var/obj/item/bountytrap/stored_item
var/caught = FALSE
/obj/structure/trap/stun/hunter/Initialize(mapload)
. = ..()
time_between_triggers = 10
/obj/structure/trap/stun/hunter/Crossed(atom/movable/AM)
if(isliving(AM))
var/mob/living/L = AM
if(!L.mind?.has_antag_datum(/datum/antagonist/fugitive))
return
caught = TRUE
. = ..()
/obj/structure/trap/stun/hunter/flare()
..()
stored_item.forceMove(get_turf(src))
forceMove(stored_item)
if(caught)
stored_item.announce_fugitive()
caught = FALSE
/obj/item/bountytrap
name = "bounty trap"
desc = "A trap that only goes off when a fugitive steps on it, announcing the location and stunning the target. It's currently inactive."
icon = 'icons/obj/objects.dmi'
icon_state = "bounty_trap_off"
var/obj/structure/trap/stun/hunter/stored_trap
var/obj/item/radio/radio
var/datum/effect_system/spark_spread/spark_system
/obj/item/bountytrap/Initialize(mapload)
. = ..()
radio = new(src)
radio.subspace_transmission = TRUE
radio.canhear_range = 0
radio.recalculateChannels()
spark_system = new
spark_system.set_up(4,1,src)
spark_system.attach(src)
name = "[name] #[rand(1, 999)]"
stored_trap = new(src)
stored_trap.name = name
stored_trap.stored_item = src
/obj/item/bountytrap/proc/announce_fugitive()
spark_system.start()
playsound(src, 'sound/machines/ding.ogg', 50, TRUE)
radio.talk_into(src, "Fugitive has triggered this trap in the [get_area_name(src)]!", RADIO_CHANNEL_COMMON)
/obj/item/bountytrap/attack_self(mob/living/user)
var/turf/T = get_turf(src)
if(!user || !user.transferItemToLoc(src, T))//visibly unequips
return
to_chat(user, "<span class=notice>You set up [src]. Examine while close to disarm it.</span>")
stored_trap.forceMove(T)//moves trap to ground
forceMove(stored_trap)//moves item into trap
/obj/item/bountytrap/Destroy()
qdel(stored_trap)
QDEL_NULL(radio)
QDEL_NULL(spark_system)
. = ..()
@@ -19,6 +19,13 @@
open = round(rand(0, 1))
update_icon()
/obj/structure/toilet/Destroy()
if(loc)
for(var/A in contents)
var/atom/movable/AM = A
AM.forceMove(loc)
return ..()
/obj/structure/toilet/attack_hand(mob/living/user)
. = ..()
if(.)
+4
View File
@@ -38,6 +38,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
var/hitsound = 'sound/effects/Glasshit.ogg'
rad_insulation = RAD_VERY_LIGHT_INSULATION
rad_flags = RAD_PROTECT_CONTENTS
flags_ricochet = RICOCHET_HARD
ricochet_chance_mod = 0.4
/// Electrochromatic status
var/electrochromatic_status = NOT_ELECTROCHROMATIC
@@ -525,6 +527,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
explosion_block = 1
glass_type = /obj/item/stack/sheet/rglass
rad_insulation = RAD_HEAVY_INSULATION
ricochet_chance_mod = 0.8
/obj/structure/window/reinforced/spawner/east
dir = EAST
@@ -690,6 +693,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
level = 3
glass_type = /obj/item/stack/sheet/titaniumglass
glass_amount = 2
ricochet_chance_mod = 0.9
/obj/structure/window/shuttle/narsie_act()
add_atom_colour("#3C3434", FIXED_COLOUR_PRIORITY)