Merge remote-tracking branch 'upstream/master' into embed-changes

This commit is contained in:
Timothy Teakettle
2020-06-15 22:48:26 +01:00
180 changed files with 5227 additions and 1997 deletions

View File

@@ -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,
)

View File

@@ -144,6 +144,13 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
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
@@ -250,9 +257,10 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
. += "[src] is made of cold-resistant materials."
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
@@ -414,6 +422,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
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)
@@ -426,6 +435,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb
// 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

View File

@@ -187,6 +187,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)
. = ..()

View File

@@ -803,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)

View File

@@ -655,9 +655,10 @@ GENETICS 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)

View File

@@ -105,9 +105,28 @@
sharpness = IS_SHARP
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()

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)

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"])

View File

@@ -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.

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

View File

@@ -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), \

View File

@@ -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)

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))

View File

@@ -446,6 +446,7 @@
throw_range = 5
force_unwielded = 0
force_wielded = 0
block_parry_data = null
attack_verb = list("attacked", "struck", "hit")
total_mass_on = TOTAL_MASS_TOY_SWORD
sharpness = IS_BLUNT

View File

@@ -30,6 +30,8 @@
var/wieldsound = null
var/unwieldsound = null
var/slowdown_wielded = 0
/// Do we need to be wielded to actively block/parry?
var/requires_wield_to_block_parry = TRUE
item_flags = SLOWS_WHILE_IN_HAND
/obj/item/twohanded/proc/unwield(mob/living/carbon/user, show_message = TRUE)
@@ -90,6 +92,12 @@
user.put_in_inactive_hand(O)
set_slowdown(slowdown + slowdown_wielded)
/obj/item/twohanded/can_active_block()
return ..() && (!requires_wield_to_block_parry || wielded)
/obj/item/twohanded/can_active_parry()
return ..() && (!requires_wield_to_block_parry || wielded)
/obj/item/twohanded/dropped(mob/user)
. = ..()
//handles unwielding a twohanded weapon when dropped as well as clearing up the offhand
@@ -129,6 +137,7 @@
return ..()
/obj/item/twohanded/offhand/dropped(mob/living/user, show_message = TRUE) //Only utilized by dismemberment since you can't normally switch to the offhand to drop it.
. = ..()
var/obj/I = user.get_active_held_item()
if(I && istype(I, /obj/item/twohanded))
var/obj/item/twohanded/thw = I
@@ -274,6 +283,8 @@
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
var/w_class_on = WEIGHT_CLASS_BULKY
item_flags = ITEM_CAN_PARRY | SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK
block_parry_data = /datum/block_parry_data/dual_esword
force_unwielded = 3
force_wielded = 34
wieldsound = 'sound/weapons/saberon.ogg'
@@ -284,7 +295,6 @@
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
@@ -298,6 +308,42 @@
total_mass = 0.4 //Survival flashlights typically weigh around 5 ounces.
var/total_mass_on = 3.4
/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/twohanded/dualsaber/suicide_act(mob/living/carbon/user)
if(wielded)
user.visible_message("<span class='suicide'>[user] begins spinning way too fast! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -849,6 +895,7 @@
return (BRUTELOSS)
/obj/item/twohanded/pitchfork/demonic/pickup(mob/living/user)
. = ..()
if(isliving(user) && user.mind && user.owns_soul() && !is_devil(user))
var/mob/living/U = user
U.visible_message("<span class='warning'>As [U] picks [src] up, [U]'s arms briefly catch fire.</span>", \
@@ -1030,13 +1077,12 @@
force_wielded = 10
throwforce = 15 //if you are a madman and finish someone off with this, power to you.
throw_speed = 1
item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND
block_chance = 30
item_flags = NO_MAT_REDEMPTION | SLOWS_WHILE_IN_HAND | ITEM_CAN_BLOCK | ITEM_CAN_PARRY
block_parry_data = /datum/block_parry_data/electrostaff
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)
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
var/lethal_cost = 400 //10000/400*20 = 500. decent enough?
var/lethal_damage = 20
var/lethal_stam_cost = 4
@@ -1046,6 +1092,43 @@
var/stun_status_duration = 25
var/stun_stam_cost = 3.5
// 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/twohanded/electrostaff/Initialize(mapload)
. = ..()
if(ispath(cell))
@@ -1061,11 +1144,6 @@
var/mob/living/silicon/robot/R = loc
. = R.get_cell()
/obj/item/twohanded/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/twohanded/electrostaff/proc/min_hitcost()
return min(stun_cost, lethal_cost)
@@ -1183,22 +1261,23 @@
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
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/twohanded/electrostaff/proc/stun_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE)
var/stunforce = stun_stamdmg
/obj/item/twohanded/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>", \
@@ -1228,8 +1307,8 @@
H.forcesay(GLOB.hit_appends)
return TRUE
/obj/item/twohanded/electrostaff/proc/harm_act(mob/living/target, mob/living/user, no_charge_and_force = FALSE)
var/lethal_force = lethal_damage
/obj/item/twohanded/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

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

View File

@@ -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