Merge branch 'master' into WanderingFox95-TheUnrollingPin

This commit is contained in:
WanderingFox95
2021-04-29 10:54:00 +02:00
committed by GitHub
155 changed files with 4299 additions and 1203 deletions
+8 -6
View File
@@ -375,12 +375,14 @@ GLOBAL_LIST_INIT(fluid_duct_recipes, list(
. = TRUE
if((mode & DESTROY_MODE) && istype(A, /obj/item/pipe) || istype(A, /obj/structure/disposalconstruct) || istype(A, /obj/structure/c_transit_tube) || istype(A, /obj/structure/c_transit_tube_pod) || istype(A, /obj/item/pipe_meter))
to_chat(user, "<span class='notice'>You start destroying a pipe...</span>")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, destroy_speed, target = A))
activate()
qdel(A)
return
var/obj/item/pipe/P = A
if(!istype(P) || P.disposable)
to_chat(user, "<span class='notice'>You start destroying a pipe...</span>")
playsound(get_turf(src), 'sound/machines/click.ogg', 50, 1)
if(do_after(user, destroy_speed, target = A))
activate()
qdel(A)
return
if((mode & PAINT_MODE))
if(istype(A, /obj/machinery/atmospherics/pipe) && !istype(A, /obj/machinery/atmospherics/pipe/layer_manifold))
+7 -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.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, turn(stored_dir, -dir2angle(F.dir)), CLEAN_STRONG, color, null, null, alpha)
F.AddElement(/datum/element/decal, 'icons/turf/decals.dmi', stored_decal_total, stored_dir, CLEAN_STRONG, color, null, null, alpha)
/obj/item/airlock_painter/decal/attack_self(mob/user)
if((ink) && (ink.charges >= 1))
@@ -180,6 +180,11 @@
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
return
/obj/item/airlock_painter/decal/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/decals)
)
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -189,6 +194,7 @@
/obj/item/airlock_painter/decal/ui_data(mob/user)
var/list/data = list()
data["decal_direction"] = stored_dir
data["decal_dir_text"] = dir2text(stored_dir)
data["decal_color"] = stored_color
data["decal_style"] = stored_decal
data["decal_list"] = list()
-15
View File
@@ -75,18 +75,3 @@
desc = "A chromosome that reduces action based mutation cooldowns by by 50%."
icon_state = "energy"
energy_coeff = 0.5
/obj/item/chromosome/reinforcer
name = "reinforcement chromosome"
desc = "A chromosome that renders mutations immune to mutadone."
icon_state = "reinforcer"
weight = 3
/obj/item/chromosome/reinforcer/can_apply(datum/mutation/human/HM)
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
return FALSE
return !HM.mutadone_proof
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
HM.mutadone_proof = TRUE
..()
+2 -4
View File
@@ -210,8 +210,7 @@
target.apply_effect(EFFECT_STUTTER, stunforce)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
if(user)
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
target.set_last_attacker(user)
target.visible_message("<span class='danger'>[user] has shocked [target] with [src]!</span>", \
"<span class='userdanger'>[user] has shocked you with [src]!</span>")
log_combat(user, target, "stunned with an electrostaff")
@@ -237,8 +236,7 @@
target.adjustFireLoss(lethal_force) //good against ointment spam
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK)
if(user)
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
target.set_last_attacker(user)
target.visible_message("<span class='danger'>[user] has seared [target] with [src]!</span>", \
"<span class='userdanger'>[user] has seared you with [src]!</span>")
log_combat(user, target, "burned with an electrostaff")
+1 -1
View File
@@ -312,7 +312,7 @@
trap_damage = 0
item_flags = DROPDEL
flags_1 = NONE
breakouttime = 50
breakouttime = 25
/obj/item/restraints/legcuffs/beartrap/energy/New()
..()
@@ -0,0 +1,74 @@
/datum/deathrattle_group
var/name
var/list/datum/weakref/implant_refs = list()
/datum/deathrattle_group/New()
// Give the group a unique name for debugging, and possible future
// use for making custom linked groups.
name = "[rand(100,999)] [pick(GLOB.phonetic_alphabet)]"
/datum/deathrattle_group/proc/rattle(obj/item/implant/deathrattle/origin, mob/living/owner)
var/name = owner.mind ? owner.mind.name : owner.real_name
var/area = get_area_name(get_turf(owner))
for(var/r in implant_refs)
var/datum/weakref/R = r
var/obj/item/implant/deathrattle/implant = R.resolve()
if(!implant || implant == origin)
continue
// Not all the implants may be actually implanted in people.
if(!implant.imp_in)
continue
// Deliberately the same message framing as nanite message + ghost deathrattle
var/mob/living/recipient = implant.imp_in
to_chat(recipient, "<i>You hear a strange, robotic voice in your head...</i> \"<span class='robot'><b>[name]</b> has died at <b>[area]</b>.</span>\"")
SEND_SOUND(recipient, pick(
'sound/items/knell1.ogg',
'sound/items/knell2.ogg',
'sound/items/knell3.ogg',
'sound/items/knell4.ogg',
))
/datum/deathrattle_group/proc/register(obj/item/implant/deathrattle/implant)
implant.group = src
implant_refs += WEAKREF(implant)
/obj/item/implant/deathrattle
name = "deathrattle implant"
desc = "Hope no one else dies, prepare for when they do."
activated = FALSE
var/datum/deathrattle_group/group = null
/obj/item/implant/deathrattle/Destroy()
group = null
return ..()
/obj/item/implant/deathrattle/can_be_implanted_in(mob/living/target)
// Can be implanted in anything that's a mob. Syndicate cyborgs, talking fish, humans...
return TRUE
/obj/item/implant/deathrattle/proc/on_predeath(datum/source, gibbed)
SIGNAL_HANDLER
if(group)
group.rattle(origin = src, owner = source)
/obj/item/implant/deathrattle/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE)
. = ..()
if(.)
RegisterSignal(target, COMSIG_LIVING_PREDEATH, .proc/on_predeath)
if(!group)
to_chat(target, "<i>You hear a strange, robotic voice in your head...</i> \"<span class='robot'>Warning: No other linked implants detected.</span>\"")
/obj/item/implantcase/deathrattle
name = "implant case - 'Deathrattle'"
desc = "A glass case containing a deathrattle implant."
imp_type = /obj/item/implant/deathrattle
+2 -2
View File
@@ -135,8 +135,8 @@
/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
/obj/item/organ/lungs/cybernetic/tier3,
/obj/item/organ/liver/cybernetic/tier3) //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
@@ -272,7 +272,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list(
. = ..()
. += GLOB.plastitaniumglass_recipes
/obj/item/stack/sheet/titaniumglass/on_solar_construction(obj/machinery/power/solar/S)
/obj/item/stack/sheet/plastitaniumglass/on_solar_construction(obj/machinery/power/solar/S)
S.max_integrity *= 2
S.efficiency *= 2
+69
View File
@@ -351,6 +351,75 @@
if(!contents.len)
. += "[icon_state]_empty"
//Derringer "Cigarettes"//
/obj/item/storage/fancy/cigarettes/derringer
name = "\improper Robust packet"
desc = "Smoked by the robust."
icon_state = "robust"
spawn_type = /obj/item/gun/ballistic/derringer/traitor
/obj/item/storage/fancy/cigarettes/derringer/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(/obj/item/clothing/mask/cigarette, /obj/item/lighter, /obj/item/gun/ballistic/derringer, /obj/item/ammo_casing/c38, /obj/item/ammo_casing/a357, /obj/item/ammo_casing/g4570))
/obj/item/storage/fancy/cigarettes/derringer/AltClick(mob/living/carbon/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
var/obj/item/W = (locate(/obj/item/ammo_casing/a357) in contents) || (locate(/obj/item/clothing/mask/cigarette) in contents) || locate(/obj/item/ammo_casing/g4570) //Easy access smokes and bullets
if(W && contents.len > 0)
SEND_SIGNAL(src, COMSIG_TRY_STORAGE_TAKE, W, user)
user.put_in_hands(W)
contents -= W
to_chat(user, "<span class='notice'>You take \a [W] out of the pack.</span>")
else
to_chat(user, "<span class='notice'>There are no items left in the pack.</span>")
/obj/item/storage/fancy/cigarettes/derringer/PopulateContents()
new spawn_type(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/ammo_casing/a357(src)
new /obj/item/clothing/mask/cigarette/syndicate(src)
//For traitors with luck/class
/obj/item/storage/fancy/cigarettes/derringer/gold
name = "\improper Robust Gold packet"
desc = "Smoked by the truly robust."
icon_state = "robustg"
spawn_type = /obj/item/gun/ballistic/derringer/gold
//For operatives, bound in a ka-tet.
/obj/item/storage/fancy/cigarettes/derringer/midworld
name = "\improper Midworld's Lime Bend"
desc = "The wheel of Ka turns, Gunslinger."
icon_state = "slime"
spawn_type = /obj/item/gun/ballistic/derringer/nukeop
/obj/item/storage/fancy/cigarettes/derringer/midworld/PopulateContents()
new spawn_type(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/ammo_casing/g4570(src)
new /obj/item/clothing/mask/cigarette/xeno(src)
//For Cargomen, looking for a good deal on arms, with no quarrels as to where they're from.
/obj/item/storage/fancy/cigarettes/derringer/smuggled
name = "\improper Shady Jim's Super Slims packet"
desc = "If you get caught with this, we don't know you, capiche?"
icon_state = "shadyjim"
spawn_type = /obj/item/gun/ballistic/derringer
/obj/item/storage/fancy/cigarettes/derringer/smuggled/PopulateContents()
new spawn_type(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/ammo_casing/c38/lethal(src)
new /obj/item/clothing/mask/cigarette/shadyjims (src)
/////////////
//CIGAR BOX//
/////////////
@@ -546,3 +546,21 @@
. = ..()
new /obj/item/cardpack/syndicate(src)
new /obj/item/cardpack/syndicate(src)
/obj/item/storage/box/syndie_kit/imp_deathrattle
name = "deathrattle implant box"
desc = "Contains eight linked deathrattle implants."
/obj/item/storage/box/syndie_kit/imp_deathrattle/PopulateContents()
new /obj/item/implanter(src)
var/datum/deathrattle_group/group = new
var/implants = list()
for(var/j in 1 to 8)
var/obj/item/implantcase/deathrattle/case = new (src)
implants += case.imp
for(var/i in implants)
group.register(i)
desc += " The implants are registered to the \"[group.name]\" group."
+2 -1
View File
@@ -46,7 +46,8 @@
/obj/item/instrument/harmonica,
/obj/item/mining_voucher,
/obj/item/suit_voucher,
/obj/item/reagent_containers/pill))
/obj/item/reagent_containers/pill,
/obj/item/gun/ballistic/derringer))
/obj/item/storage/wallet/Exited(atom/movable/AM)
. = ..()
+57 -30
View File
@@ -16,17 +16,21 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
attack_speed = CLICK_CD_MELEE
var/stamforce = 35
var/stamina_loss_amount = 35
var/turned_on = FALSE
var/knockdown = TRUE
var/obj/item/stock_parts/cell/cell
var/hitcost = 750
var/throw_hit_chance = 35
var/preload_cell_type //if not empty the baton starts with this type of cell
var/cooldown_duration = 5 SECONDS //How long our baton rightclick goes on cooldown for after applying a knockdown
var/status_duration = 5 SECONDS //how long our status effects last for otherwise
COOLDOWN_DECLARE(shove_cooldown)
/obj/item/melee/baton/examine(mob/user)
. = ..()
. += "<span class='notice'>Right click attack while in combat mode to disarm instead of stun.</span>"
. += "<span class='notice'>Right click attack while in combat mode to knockdown, but only once per [cooldown_duration / 10] seconds.</span>"
. += "<span class='notice'>This knockdown will also put them off balance for [status_duration / 20] seconds, allowing you to shove a weapon out of their hand with a right click in Disarm intent.</span>"
/obj/item/melee/baton/get_cell()
. = cell
@@ -53,8 +57,8 @@
/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
..()
//Only mob/living types have stun handling
if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom))
baton_stun(hit_atom)
if(turned_on && prob(throw_hit_chance) && iscarbon(hit_atom) && thrownby)
baton_stun(hit_atom, thrownby, shoving = TRUE)
/obj/item/melee/baton/loaded //this one starts with a cell pre-installed.
preload_cell_type = /obj/item/stock_parts/cell/high/plus
@@ -74,6 +78,16 @@
//we're below minimum, turn off
switch_status(FALSE)
///Check for our cell to determine how much penetration our weapon does.
/obj/item/melee/baton/proc/get_cell_zap_pen()
var/obj/item/stock_parts/cell/copper_top = get_cell()
if(copper_top)
var/chargepower = copper_top.maxcharge
var/zap_penetration = (chargepower/1000) //This is our effective penetration. Every 1000 max charge, we get 1 pen power. A high capacity cell is equal to 10 armor pen, as an example.
return zap_penetration
else
return 0
/obj/item/melee/baton/proc/switch_status(new_status = FALSE, silent = FALSE)
if(turned_on != new_status)
turned_on = new_status
@@ -101,6 +115,7 @@
var/obj/item/stock_parts/cell/copper_top = get_cell()
if(copper_top)
. += "<span class='notice'>\The [src] is [round(copper_top.percent())]% charged.</span>"
. += "<span class='notice'>\The [src] currently can penetrate [round(copper_top.maxcharge/1000)]% of enemy armor thanks to it's loaded cell.</span>"
else
. += "<span class='warning'>\The [src] does not have a power source installed.</span>"
@@ -150,10 +165,10 @@
/obj/item/melee/baton/alt_pre_attack(atom/A, mob/living/user, params)
if(!user.CheckActionCooldown(CLICK_CD_MELEE))
return
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-disarming.
. = common_baton_melee(A, user, TRUE) //return true (attackchain interrupt) if this also returns true. no harm-shoving.
//return TRUE to interrupt attack chain.
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE)
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, shoving = FALSE)
if(iscyborg(M) || !isliving(M)) //can't baton cyborgs
return FALSE
if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
@@ -167,21 +182,26 @@
if(check_martial_counter(L, user))
return TRUE
if(turned_on)
if(baton_stun(M, user, disarming))
if(baton_stun(M, user, shoving))
user.do_attack_animation(M)
else if(user.a_intent != INTENT_HARM) //they'll try to bash in the last proc.
M.visible_message("<span class='warning'>[user] has prodded [M] with [src]. Luckily it was off.</span>", \
"<span class='warning'>[user] has prodded you with [src]. Luckily it was off</span>")
return disarming || (user.a_intent != INTENT_HARM)
return shoving || (user.a_intent != INTENT_HARM)
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/living/user, disarming = FALSE)
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/living/user, shoving = FALSE)
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/final_stamina_loss_amount = stamina_loss_amount //Our stunning power for the baton
var/shoved = FALSE //Did we succeed on knocking our target over?
var/zap_penetration = get_cell_zap_pen() //Find out what kind of cell we have, and calculating the resultant armor pen we get from it
var/zap_block = L.run_armor_check(BODY_ZONE_CHEST, "melee", null, null, zap_penetration) //armor check, including calculation for armor penetration, for our attack
final_stamina_loss_amount = block_calculate_resultant_damage(final_stamina_loss_amount, return_list)
var/obj/item/stock_parts/cell/our_cell = get_cell()
if(!our_cell)
switch_status(FALSE)
return FALSE
@@ -194,26 +214,31 @@
L.visible_message("<span class='warning'>[user] has prodded [L] with [src]. Luckily it was out of charge.</span>", \
"<span class='warning'>[user] has prodded you with [src]. Luckily it was out of charge.</span>")
return FALSE
stunpwr *= round(stuncharge/hitcost, 0.1)
final_stamina_loss_amount *= round(stuncharge/hitcost, 0.1)
if(user && !user.UseStaminaBuffer(getweight(user, STAM_COST_BATON_MOB_MULT), warn = TRUE))
return FALSE
if(!disarming)
if(knockdown)
L.DefaultCombatKnockdown(50, override_stamdmg = 0) //knockdown
L.adjustStaminaLoss(stunpwr)
else
L.drop_all_held_items() //no knockdown/stamina damage, instead disarm.
if(shoving && COOLDOWN_FINISHED(src, shove_cooldown) && !HAS_TRAIT(L, TRAIT_IWASBATONED)) //Rightclicking applies a knockdown, but only once every couple of seconds, based on the cooldown_duration var. If they were recently knocked down, they can't be knocked down again by a baton.
L.DefaultCombatKnockdown(50, override_stamdmg = 0)
L.apply_status_effect(STATUS_EFFECT_TASED_WEAK, status_duration) //Even if they shove themselves up, they're still slowed.
L.apply_status_effect(STATUS_EFFECT_OFF_BALANCE, status_duration) //They're very likely to drop items if shoved briefly after a knockdown.
shoved = TRUE
COOLDOWN_START(src, shove_cooldown, cooldown_duration)
ADD_TRAIT(L, TRAIT_IWASBATONED, STATUS_EFFECT_TRAIT) //Prevents swapping to a new baton to avoid the cooldown by just acquiring more batons
addtimer(TRAIT_CALLBACK_REMOVE(L, TRAIT_IWASBATONED, STATUS_EFFECT_TRAIT), cooldown_duration)
playsound(loc, 'sound/weapons/zapbang.ogg', 50, 1, -1)
else //If we cannot/don't knock down the target, we apply a stagger, which keeps them from just running off
L.apply_status_effect(STATUS_EFFECT_STAGGERED, status_duration)
L.apply_effect(EFFECT_STUTTER, stamforce)
L.apply_damage (final_stamina_loss_amount, STAMINA, BODY_ZONE_CHEST, zap_block)
L.apply_effect(EFFECT_STUTTER, stamina_loss_amount)
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
if(user)
L.lastattacker = user.real_name
L.lastattackerckey = user.ckey
L.visible_message("<span class='danger'>[user] has [disarming? "disarmed" : "stunned"] [L] with [src]!</span>", \
"<span class='userdanger'>[user] has [disarming? "disarmed" : "stunned"] you with [src]!</span>")
log_combat(user, L, disarming? "disarmed" : "stunned")
L.set_last_attacker(user)
L.visible_message("<span class='danger'>[user] has [shoved ? "brutally stunned" : "stunned"] [L] with [src]!</span>", \
"<span class='userdanger'>[user] has [shoved ? "brutally stunnned" : "stunned"] you with [src]!</span>")
log_combat(user, L, shoved ? "stunned and attempted knockdown" : "stunned")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
@@ -228,7 +253,7 @@
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
user.DefaultCombatKnockdown(stamforce*6)
user.DefaultCombatKnockdown(stamina_loss_amount*6)
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
deductcharge(hitcost)
@@ -306,18 +331,20 @@
w_class = WEIGHT_CLASS_BULKY
force = 3
throwforce = 5
stamforce = 25
stamina_loss_amount = 25
hitcost = 1000
throw_hit_chance = 10
slot_flags = ITEM_SLOT_BACK
cooldown_duration = 7 SECONDS //It's a little on the weak side
status_duration = 3 //Slows someone for a tiny bit
var/obj/item/assembly/igniter/sparkler
/obj/item/melee/baton/cattleprod/Initialize()
. = ..()
sparkler = new (src)
sparkler.activate_cooldown = 5
sparkler.activate_cooldown = 7 //Helps visualize the knockdown
/obj/item/melee/baton/cattleprod/baton_stun()
/obj/item/melee/baton/cattleprod/baton_stun(mob/living/L, mob/living/carbon/user, shoving = FALSE)
sparkler?.activate()
. = ..()
@@ -344,8 +371,8 @@
/obj/item/melee/baton/boomerang/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(turned_on)
var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum)
if(ishuman(hit_atom) && !caught && prob(throw_hit_chance))//if they are a carbon and they didn't catch it
baton_stun(hit_atom)
if(ishuman(hit_atom) && !caught && prob(throw_hit_chance) && thrownby)//if they are a carbon and they didn't catch it
baton_stun(hit_atom, thrownby, shoving = TRUE)
if(thrownby && !caught)
sleep(1)
if(!QDELETED(src))
+2 -2
View File
@@ -6,7 +6,7 @@
item_state = "teleprod"
slot_flags = null
/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/L, mob/living/carbon/user)//handles making things teleport when hit
/obj/item/melee/baton/cattleprod/teleprod/baton_stun(mob/living/L, mob/living/carbon/user, shoving = FALSE)//handles making things teleport when hit
. = ..()
if(!. || L.anchored)
return
@@ -16,7 +16,7 @@
user.visible_message("<span class='danger'>[user] accidentally hits [user.p_them()]self with [src]!</span>", \
"<span class='userdanger'>You accidentally hit yourself with [src]!</span>")
SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK)
user.DefaultCombatKnockdown(stamforce * 6)
user.DefaultCombatKnockdown(stamina_loss_amount * 6)
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
if(do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE))
deductcharge(hitcost)
@@ -19,3 +19,50 @@
desc = "A sturdier card-locked storage unit used for bulky shipments."
max_integrity = 500 // Same as crates.
melee_min_damage = 25 // Idem.
/obj/structure/closet/secure_closet/goodies/owned
name = "private locker"
desc = "A locker designed to only open for who purchased its contents."
///Account of the person buying the crate if private purchasing.
var/datum/bank_account/buyer_account
///Department of the person buying the crate if buying via the NIRN app.
var/datum/bank_account/department/department_account
///Is the secure crate opened or closed?
var/privacy_lock = TRUE
///Is the crate being bought by a person, or a budget card?
var/department_purchase = FALSE
/obj/structure/closet/secure_closet/goodies/owned/examine(mob/user)
. = ..()
. += "<span class='notice'>It's locked with a privacy lock, and can only be unlocked by the buyer's ID.</span>"
/obj/structure/closet/secure_closet/goodies/owned/Initialize(mapload, datum/bank_account/_buyer_account)
. = ..()
buyer_account = _buyer_account
if(istype(buyer_account, /datum/bank_account/department))
department_purchase = TRUE
department_account = buyer_account
/obj/structure/closet/secure_closet/goodies/owned/togglelock(mob/living/user, silent)
if(privacy_lock)
if(!broken)
var/obj/item/card/id/id_card = user.get_idcard(TRUE)
if(id_card)
if(id_card.registered_account)
if(id_card.registered_account == buyer_account || (department_purchase && (id_card.registered_account?.account_job?.paycheck_department) == (department_account.department_id)))
if(iscarbon(user))
add_fingerprint(user)
locked = !locked
user.visible_message("<span class='notice'>[user] unlocks [src]'s privacy lock.</span>",
"<span class='notice'>You unlock [src]'s privacy lock.</span>")
privacy_lock = FALSE
update_icon()
else if(!silent)
to_chat(user, "<span class='notice'>Bank account does not match with buyer!</span>")
else if(!silent)
to_chat(user, "<span class='notice'>No linked bank account detected!</span>")
else if(!silent)
to_chat(user, "<span class='notice'>No ID detected!</span>")
else if(!silent)
to_chat(user, "<span class='warning'>[src] is broken!</span>")
else ..()
@@ -590,7 +590,7 @@
/obj/effect/mob_spawn/human/pirate
name = "space pirate sleeper"
desc = "A cryo sleeper smelling faintly of rum."
desc = "A cryo sleeper smelling faintly of rum. The sleeper looks unstable. <i>Perhaps the pirate within can be killed with the right tools...</i>"
job_description = "Space Pirate"
random = TRUE
icon = 'icons/obj/machines/sleeper.dmi'
@@ -608,6 +608,54 @@
assignedrole = "Space Pirate"
var/rank = "Mate"
/obj/effect/mob_spawn/human/pirate/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
. = ..()
if(.)
return
if(user.mind.has_antag_datum(/datum/antagonist/pirate))
to_chat(user, "<span class='notice'>Your shipmate sails within their dreams for now. Perhaps they may wake up eventually.</span>")
else
to_chat(user, "<span class='notice'>If you want to kill the pirate off, something to pry open the sleeper might be the best way to do it.</span>")
/obj/effect/mob_spawn/human/pirate/attackby(obj/item/W, mob/user, params)
if(W.tool_behaviour == TOOL_CROWBAR && user.a_intent != INTENT_HARM)
if(user.mind.has_antag_datum(/datum/antagonist/pirate))
to_chat(user,"<span class='warning'>Why would you want to do that to your shipmate? That'd kill them.</span>")
return
user.visible_message("<span class='warning'>[user] start to pry open [src]...</span>",
"<span class='notice'>You start to pry open [src]...</span>",
"<span class='italics'>You hear prying...</span>")
W.play_tool_sound(src)
if(do_after(user, 100*W.toolspeed, target = src))
user.visible_message("<span class='warning'>[user] pries open [src], disrupting the sleep of the pirate within and killing them.</span>",
"<span class='notice'>You pry open [src], disrupting the sleep of the pirate within and killing them.</span>",
"<span class='italics'>You hear prying, followed by the death rattling of bones.</span>")
log_game("[key_name(user)] has successfully pried open [src] and disabled a space pirate spawner.")
W.play_tool_sound(src)
playsound(src.loc, 'modular_citadel/sound/voice/scream_skeleton.ogg', 50, 1, 4, 1.2)
if(rank == "Captain")
new /obj/effect/mob_spawn/human/pirate/corpse/captain(get_turf(src))
else
new /obj/effect/mob_spawn/human/pirate/corpse(get_turf(src))
qdel(src)
else
..()
/obj/effect/mob_spawn/human/pirate/corpse //occurs when someone pries a pirate out of their sleeper.
mob_name = "Dead Space Pirate"
death = TRUE
instant = TRUE
random = FALSE
/obj/effect/mob_spawn/human/pirate/corpse/Destroy()
return ..()
/obj/effect/mob_spawn/human/pirate/corpse/captain
rank = "Captain"
mob_name = "Dead Space Pirate Captain"
outfit = /datum/outfit/pirate/space/captain
/obj/effect/mob_spawn/human/pirate/special(mob/living/new_spawn)
new_spawn.fully_replace_character_name(new_spawn.real_name,generate_pirate_name())
new_spawn.mind.add_antag_datum(/datum/antagonist/pirate)
@@ -199,8 +199,7 @@
return TRUE
/obj/item/gun_control/attack(mob/living/M, mob/living/user)
M.lastattacker = user.real_name
M.lastattackerckey = user.ckey
M.set_last_attacker(user)
M.attacked_by(src, user)
add_fingerprint(user)
+1 -1
View File
@@ -554,7 +554,7 @@
if(B.cell)
if(B.cell.charge > 0 && B.turned_on)
flick("baton_active", src)
var/stunforce = B.stamforce
var/stunforce = B.stamina_loss_amount
user.DefaultCombatKnockdown(stunforce * 2)
user.stuttering = stunforce/20
B.deductcharge(B.hitcost)