[READY] Syndicate Contractors (#14605)

* Syndicate Contractors initial PR

* Finalize initial version

DNP

Finalize initial version

* Baton now costs 6 Rep, show dead extraction penalty, fix scroll

* Reduce total TC, add zippo, balloon, icon tweaks

* Address moxian, AA and Farie

* Fix mode.txt

* oops

* Address Farie 2

* Tweak baton to work around stam crits, address SteelSlayer

* Address TM issues, TP menu

* Fix wrongly merged DME

* Tick contractor DM files again

* Remove step_y

* TC rewards always higher than preceding difficulty's reward

* Address Farie

* Remove extraction_turf from handle_target_return

* fix doc

* Merge part2

* Address AA again
This commit is contained in:
dearmochi
2020-12-09 12:03:23 -05:00
committed by GitHub
parent 2897b82345
commit 5edee29a50
73 changed files with 3588 additions and 250 deletions
+111 -31
View File
@@ -1,8 +1,3 @@
/// Delay in deci-seconds between two non-lethal attacks
#define BATON_STUN_COOLDOWN 4 SECONDS
/// Force of the telescopic baton when deployed
#define BATON_TELESCOPIC_FORCE_DEPLOYED 10
/**
* # Police Baton
*
@@ -18,6 +13,18 @@
slot_flags = SLOT_BELT
force = 12 //9 hit crit
w_class = WEIGHT_CLASS_NORMAL
// Settings
/// Whether the baton can stun silicon mobs
var/affect_silicon = FALSE
/// The stun time (in life cycles) for non-silicons
var/stun_time = 6 SECONDS_TO_LIFE_CYCLES
/// The stun time (in life cycles) for silicons
var/stun_time_silicon = 10 SECONDS_TO_LIFE_CYCLES
/// Cooldown in deciseconds between two knockdowns
var/cooldown = 4 SECONDS
/// Sound to play when knocking someone down
var/stun_sound = 'sound/effects/woodhit.ogg'
// Variables
/// Whether the baton is on cooldown
var/on_cooldown = FALSE
/// Whether the baton is toggled on (to allow attacking)
@@ -39,27 +46,68 @@
user.take_organ_damage(force * 2)
return
if(user.a_intent == INTENT_HARM || isrobot(target)) // Lethal attack or it's a borg (can't knock them down!)
if(user.a_intent == INTENT_HARM)
return ..()
else if(!on_cooldown) // Non-lethal attack - knock them down
if(on_cooldown)
return
if(issilicon(target) && !affect_silicon)
return ..()
else
stun(target, user)
/**
* Called when a target is about to be hit non-lethally.
*
* Arguments:
* * target - The mob about to be hit
* * user - The attacking user
*/
/obj/item/melee/classic_baton/proc/stun(mob/living/target, mob/living/user)
if(issilicon(target))
user.visible_message("<span class='danger'>[user] pulses [target]'s sensors with [src]!</span>",\
"<span class='danger'>You pulse [target]'s sensors with [src]!</span>")
on_silicon_stun(target, user)
else
// Check for shield/countering
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
return
return FALSE
if(check_martial_counter(H, user))
return
// Visuals and sound
user.do_attack_animation(target)
playsound(target, 'sound/effects/woodhit.ogg', 75, TRUE, -1)
add_attack_logs(user, target, "Stunned with [src]")
target.visible_message("<span class='danger'>[user] has knocked down [target] with \the [src]!</span>", \
"<span class='userdanger'>[user] has knocked down [target] with \the [src]!</span>")
// Hit 'em
target.LAssailant = iscarbon(user) ? user : null
target.Weaken(3)
on_cooldown = TRUE
addtimer(CALLBACK(src, .proc/cooldown_finished), BATON_STUN_COOLDOWN)
return FALSE
user.visible_message("<span class='danger'>[user] knocks down [target] with [src]!</span>",\
"<span class='danger'>You knock down [target] with [src]!</span>")
on_non_silicon_stun(target, user)
// Visuals and sound
user.do_attack_animation(target)
playsound(target, stun_sound, 75, TRUE, -1)
add_attack_logs(user, target, "Stunned with [src]")
// Hit 'em
target.LAssailant = iscarbon(user) ? user : null
target.Weaken(stun_time)
on_cooldown = TRUE
addtimer(CALLBACK(src, .proc/cooldown_finished), cooldown)
return TRUE
/**
* Called when a silicon has been stunned.
*
* Arguments:
* * target - The hit mob
* * user - The attacking user
*/
/obj/item/melee/classic_baton/proc/on_silicon_stun(mob/living/silicon/target, mob/living/user)
target.flash_eyes(affect_silicon = TRUE)
/**
* Called when a non-silicon has been stunned.
*
* Arguments:
* * target - The hit mob
* * user - The attacking user
*/
/obj/item/melee/classic_baton/proc/on_non_silicon_stun(mob/living/target, mob/living/user)
return
/**
* Called some time after a non-lethal attack
@@ -86,13 +134,23 @@
/obj/item/melee/classic_baton/telescopic
name = "telescopic baton"
desc = "A compact yet robust personal defense weapon. Can be concealed when folded."
icon_state = "telebaton_0"
item_state = null
slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
needs_permit = FALSE
force = 0
on = FALSE
/// Force when concealed
var/force_off = 0
/// Force when extended
var/force_on = 10
/// Item state when extended
var/item_state_on = "nullrod"
/// Icon state when concealed
var/icon_state_off = "telebaton_0"
/// Icon state when extended
var/icon_state_on = "telebaton_1"
/// Sound to play when concealing or extending
var/extend_sound = 'sound/weapons/batonextend.ogg'
/// Attack verbs when concealed (created on Initialize)
var/static/list/attack_verb_off
/// Attack verbs when extended (created on Initialize)
@@ -103,31 +161,53 @@
if(!attack_verb_off)
attack_verb_off = list("hit", "poked")
attack_verb_on = list("smacked", "struck", "cracked", "beaten")
icon_state = icon_state_off
force = force_off
attack_verb = on ? attack_verb_on : attack_verb_off
/obj/item/melee/classic_baton/telescopic/attack_self(mob/user)
on = !on
icon_state = "telebaton_[on]"
icon_state = on ? icon_state_on : icon_state_off
if(on)
to_chat(user, "<span class='warning'>You extend the baton.</span>")
item_state = "nullrod"
to_chat(user, "<span class='warning'>You extend [src].</span>")
item_state = item_state_on
w_class = WEIGHT_CLASS_BULKY //doesnt fit in backpack when its on for balance
force = BATON_TELESCOPIC_FORCE_DEPLOYED //stunbaton damage
force = force_on //stunbaton damage
attack_verb = attack_verb_on
else
to_chat(user, "<span class='notice'>You collapse the baton.</span>")
to_chat(user, "<span class='notice'>You collapse [src].</span>")
item_state = null //no sprite for concealment even when in hand
slot_flags = SLOT_BELT
w_class = WEIGHT_CLASS_SMALL
force = 0 //not so robust now
force = force_off //not so robust now
attack_verb = attack_verb_off
// Update mob hand visuals
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.update_inv_l_hand()
H.update_inv_r_hand()
playsound(loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
// Update blood splatter
if(blood_overlay)
cut_overlay(blood_overlay)
qdel(blood_overlay)
add_blood_overlay(blood_overlay_color)
playsound(loc, extend_sound, 50, TRUE)
add_fingerprint(user)
#undef BATON_STUN_COOLDOWN
#undef BATON_TELESCOPIC_FORCE_DEPLOYED
/obj/item/melee/classic_baton/telescopic/blood_splatter_index()
return "\ref[icon]-[icon_state]"
/obj/item/melee/classic_baton/telescopic/add_blood_overlay(color)
var/index = blood_splatter_index()
var/icon/blood_splatter_icon = GLOB.blood_splatter_icons[index]
if(!blood_splatter_icon)
blood_splatter_icon = icon(icon, icon_state)
blood_splatter_icon.Blend("#ffffff", ICON_ADD)
blood_splatter_icon.Blend(icon('icons/effects/blood.dmi', "itemblood"), ICON_MULTIPLY)
blood_splatter_icon = fcopy_rsc(blood_splatter_icon)
GLOB.blood_splatter_icons[index] = blood_splatter_icon
blood_overlay = image(blood_splatter_icon)
blood_overlay.color = color
blood_overlay_color = color
add_overlay(blood_overlay)