diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index e7083cacea..4acd2ac6c0 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -86,7 +86,7 @@ GLOBAL_LIST_EMPTY(objectives) if(M) . += M -/datum/objective/proc/find_target() +/datum/objective/proc/find_target(blacklist) var/list/datum/mind/owners = get_owners() var/list/possible_targets = list() var/try_target_late_joiners = FALSE @@ -96,7 +96,8 @@ GLOBAL_LIST_EMPTY(objectives) try_target_late_joiners = TRUE for(var/datum/mind/possible_target in get_crewmember_minds()) if(!(possible_target in owners) && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && is_unique_objective(possible_target)) - possible_targets += possible_target + if(!(possible_target in blacklist)) + possible_targets += possible_target if(try_target_late_joiners) var/list/all_possible_targets = possible_targets.Copy() for(var/I in all_possible_targets) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 9c544a34ef..2f8b562cca 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -180,13 +180,60 @@ slot_flags = ITEM_SLOT_BELT force = 12 //9 hit crit w_class = WEIGHT_CLASS_NORMAL - var/cooldown = 13 - var/on = TRUE - var/last_hit = 0 var/stun_stam_cost_coeff = 1.25 - var/hardstun_ds = 1 + var/hardstun_ds = TRUE var/softstun_ds = 0 var/stam_dmg = 30 + var/cooldown_check = 0 // Used internally, you don't want to modify + var/cooldown = 13 // Default wait time until can stun again. + var/stun_time_silicon = 60 // How long it stuns silicons for - 6 seconds. + var/affect_silicon = FALSE // Does it stun silicons. + var/on_sound // "On" sound, played when switching between able to stun or not. + var/on_stun_sound = "sound/effects/woodhit.ogg" // Default path to sound for when we stun. + var/stun_animation = FALSE // Do we animate the "hit" when stunning. + var/on = TRUE // Are we on or off + var/on_icon_state // What is our sprite when turned on + var/off_icon_state // What is our sprite when turned off + var/on_item_state // What is our in-hand sprite when turned on + var/force_on // Damage when on - not stunning + var/force_off // Damage when off - not stunning + var/weight_class_on // What is the new size class when turned on + +/obj/item/melee/classic_baton/Initialize() + . = ..() + +// Description for trying to stun when still on cooldown. +/obj/item/melee/classic_baton/proc/get_wait_description() + return + +// Description for when turning their baton "on" +/obj/item/melee/classic_baton/proc/get_on_description() + . = list() + .["local_on"] = "You extend the baton." + .["local_off"] = "You collapse the baton." + return . + +// Default message for stunning mob. +/obj/item/melee/classic_baton/proc/get_stun_description(mob/living/target, mob/living/user) + . = list() + .["visible"] = "[user] has knocked down [target] with [src]!" + .["local"] = "[user] has knocked down [target] with [src]!" + return . + +// Default message for stunning a silicon. +/obj/item/melee/classic_baton/proc/get_silicon_stun_description(mob/living/target, mob/living/user) + . = list() + .["visible"] = "[user] pulses [target]'s sensors with the baton!" + .["local"] = "You pulse [target]'s sensors with the baton!" + return . + +// Are we applying any special effects when we stun to carbon +/obj/item/melee/classic_baton/proc/additional_effects_carbon(mob/living/target, mob/living/user) + return + +// Are we applying any special effects when we stun to silicon +/obj/item/melee/classic_baton/proc/additional_effects_silicon(mob/living/target, mob/living/user) + return /obj/item/melee/classic_baton/attack(mob/living/target, mob/living/user) if(!on) @@ -207,15 +254,28 @@ user.take_bodypart_damage(2*force) return if(iscyborg(target)) - ..() + if(user.a_intent != INTENT_HARM) // We don't stun if we're on harm. + if(affect_silicon) + var/list/desc = get_silicon_stun_description(target, user) + target.flash_act(affect_silicon = TRUE) + target.Stun(stun_time_silicon) + additional_effects_silicon(target, user) + user.visible_message(desc["visible"], desc["local"]) + playsound(get_turf(src), on_stun_sound, 100, TRUE, -1) + if(stun_animation) + user.do_attack_animation(target) + else + ..() + else + ..() return if(!isliving(target)) return - if (user.a_intent == INTENT_HARM) + if(user.a_intent == INTENT_HARM) if(!..() || !iscyborg(target)) return else - if(last_hit < world.time) + if(cooldown_check < world.time) if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) playsound(target, 'sound/weapons/genhit.ogg', 50, 1) return @@ -223,18 +283,25 @@ var/mob/living/carbon/human/H = target if(check_martial_counter(H, user)) return - playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1) + var/list/desc = get_stun_description(target, user) + if(stun_animation) + user.do_attack_animation(target) + playsound(get_turf(src), on_stun_sound, 75, 1, -1) target.Knockdown(softstun_ds, TRUE, FALSE, hardstun_ds, stam_dmg) + additional_effects_carbon(target, user) log_combat(user, target, "stunned", src) - src.add_fingerprint(user) - target.visible_message("[user] has knocked down [target] with [src]!", \ - "[user] has knocked down [target] with [src]!") + add_fingerprint(user) + target.visible_message(desc["visible"], desc["local"]) if(!iscarbon(user)) target.LAssailant = null else target.LAssailant = user - last_hit = world.time + cooldown + cooldown_check = world.time + cooldown user.adjustStaminaLossBuffered(getweight())//CIT CHANGE - makes swinging batons cost stamina + else + var/wait_desc = get_wait_description() + if(wait_desc) + to_chat(user, wait_desc) /obj/item/melee/classic_baton/telescopic name = "telescopic baton" @@ -249,6 +316,13 @@ item_flags = NONE force = 0 on = FALSE + on_sound = 'sound/weapons/batonextend.ogg' + on_icon_state = "telebaton_1" + off_icon_state = "telebaton_0" + on_item_state = "nullrod" + force_on = 10 + force_off = 0 + weight_class_on = WEIGHT_CLASS_BULKY total_mass = TOTAL_MASS_NORMAL_ITEM /obj/item/melee/classic_baton/telescopic/suicide_act(mob/user) @@ -259,7 +333,7 @@ if(!on) src.attack_self(user) else - playsound(loc, 'sound/weapons/batonextend.ogg', 50, 1) + playsound(loc, on_sound, 50, 1) add_fingerprint(user) sleep(3) if (H && !QDELETED(H)) @@ -272,24 +346,57 @@ /obj/item/melee/classic_baton/telescopic/attack_self(mob/user) on = !on if(on) - to_chat(user, "You extend the baton.") - icon_state = "telebaton_1" - item_state = "nullrod" - w_class = WEIGHT_CLASS_BULKY //doesnt fit in backpack when its on for balance - force = 10 //stunbaton damage + to_chat(user, desc["local_on"]) + icon_state = on_icon_state + item_state = on_item_state + w_class = weight_class_on + force = force_on attack_verb = list("smacked", "struck", "cracked", "beaten") else - to_chat(user, "You collapse the baton.") - icon_state = "telebaton_0" + to_chat(user, desc["local_off"]) + icon_state = off_icon_state item_state = null //no sprite for concealment even when in hand slot_flags = ITEM_SLOT_BELT w_class = WEIGHT_CLASS_SMALL - force = 0 //not so robust now + force = force_off attack_verb = list("hit", "poked") - playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1) + playsound(src.loc, on_sound, 50, 1) add_fingerprint(user) +/obj/item/melee/classic_baton/telescopic/contractor_baton + name = "contractor baton" + desc = "A compact, specialised baton assigned to Syndicate contractors. Applies light electrical shocks to targets." + icon = 'icons/obj/items_and_weapons.dmi' + icon_state = "contractor_baton_0" + lefthand_file = 'icons/mob/inhands/weapons/melee_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/melee_righthand.dmi' + item_state = null + slot_flags = ITEM_SLOT_BELT + w_class = WEIGHT_CLASS_SMALL + item_flags = NONE + force = 5 + cooldown = 30 + stam_dmg = 45 //3 hit stamcrit + affect_silicon = TRUE + on_sound = 'sound/weapons/contractorbatonextend.ogg' + on_stun_sound = 'sound/effects/contractorbatonhit.ogg' + stun_animation = TRUE + on_icon_state = "contractor_baton_1" + off_icon_state = "contractor_baton_0" + on_item_state = "contractor_baton" + force_on = 16 + force_off = 5 + weight_class_on = WEIGHT_CLASS_NORMAL + +/obj/item/melee/classic_baton/telescopic/contractor_baton/get_wait_description() + return "The baton is still charging!" + +/obj/item/melee/classic_baton/telescopic/contractor_baton/additional_effects_carbon(mob/living/target, mob/living/user) + target.Jitter(20) + target.apply_effect(EFFECT_STUTTER, 20) + target.apply_status_effect(/datum/status_effect/electrostaff, 30) //knockdown, disarm, and slowdown, the unholy triumvirate of stam combat + /obj/item/melee/supermatter_sword name = "supermatter sword" desc = "In a station full of bad ideas, this might just be the worst." diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 9abf5c6337..43b69676eb 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -426,21 +426,24 @@
  • Here, you can accept a contract, and redeem your TC payments from completed contracts.
  • The payment number shown in brackets is the bonus you'll recieve when bringing your target alive. You recieve the other number regardless of if they were alive or dead.
  • +
  • Contracts are completed by bringing the target to designated dropoff, calling for extraction, and putting them + inside the pod.
  • Be careful when accepting a contract. While you'll be able to see the location of the dropoff point, cancelling will make it unavailable to take on again.

    -

    The tablet can be recharged at any cell charger.

    +

    The tablet can also be recharged at any cell charger.

    Extracting

    1. Make sure both yourself and your target are at the dropoff.
    2. -
    3. Call the extraction. Stand back from the drop point - it'll be coming down hard.
    4. +
    5. Call the extraction, and stand back from the drop point
    6. If it fails, make sure your target is inside, and there's a free space for the pod to land.
    7. -
    8. Drag your target into the pod.
    9. +
    10. Grab your target, and drag them into the pod.

    Ransoms

    We need your target for our own reasons, but we ransom them back to your mission area once their use is served. They will return back - from where you sent them off from in several minutes time. Don't worry agent, we give you a cut of what we get paid. We pay this into whatever - ID card you have equipped, on top of the TC payment we give.

    "} + from where you sent them off from in several minutes time. You will be paid in TC for your services.

    + +

    Good luck agent.

    "} return ..() @@ -456,6 +459,7 @@ /obj/item/storage/box/syndie_kit/contract_kit/PopulateContents() new /obj/item/modular_computer/tablet/syndicate_contract_uplink/preset/uplink(src) new /obj/item/storage/box/syndicate/contractor_loadout(src) + new /obj/item/melee/classic_baton/telescopic/contractor_baton(src) var/list/item_list = list( // All 4 TC or less - some nukeops only items, but fit nicely to the theme. /obj/item/storage/backpack/duffelbag/syndie/x4, /obj/item/storage/box/syndie_kit/throwing_weapons, diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 791724d162..d05d1e383d 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -31,14 +31,26 @@ ..() /datum/antagonist/traitor/proc/create_contracts() - var/contract_generation_quantity = 6 - var/lowest_TC_threshold = 28 // We don't want the sum of all the payouts to be under this amount + // 6 contracts + var/list/to_generate = list( + CONTRACT_PAYOUT_LARGE, + CONTRACT_PAYOUT_MEDIUM, + CONTRACT_PAYOUT_SMALL, + CONTRACT_PAYOUT_SMALL, + CONTRACT_PAYOUT_SMALL, + CONTRACT_PAYOUT_SMALL + ) + var/lowest_TC_threshold = 30 // We don't want the sum of all the payouts to be under this amount var/total = 0 var/lowest_paying_sum = 0 var/datum/syndicate_contract/lowest_paying_contract - for(var/i = 1; i <= contract_generation_quantity; i++) - var/datum/syndicate_contract/contract_to_add = new(owner) + + to_generate = shuffle(to_generate) // Randomise order, so we don't have contracts always in payout order. + var/list/assigned_targets = list() + for (var/i = 1; i <= to_generate.len; i++) // Generate contracts, and find the lowest paying. + var/datum/syndicate_contract/contract_to_add = new(owner, to_generate[i], assigned_targets) var/contract_payout_total = contract_to_add.contract.payout + contract_to_add.contract.payout_bonus + assigned_targets.Add(contract_to_add.contract.target) if(!lowest_paying_contract || (contract_payout_total < lowest_paying_sum)) lowest_paying_sum = contract_payout_total lowest_paying_contract = contract_to_add diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index d31b18e1d7..e82a2141eb 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -233,6 +233,10 @@ handleReturningClose(holder, TRUE) /obj/structure/closet/supplypod/extractionpod/close(atom/movable/holder) //handles closing, and returns pod - deletes itself when returned + . = ..() + return + +/obj/structure/closet/supplypod/extractionpod/proc/send_up(atom/movable/holder) if(!holder) holder = src if(leavingSound) diff --git a/code/modules/uplink/uplink_items/uplink_bundles.dm b/code/modules/uplink/uplink_items/uplink_bundles.dm index 2a0a7f947a..039a29a69d 100644 --- a/code/modules/uplink/uplink_items/uplink_bundles.dm +++ b/code/modules/uplink/uplink_items/uplink_bundles.dm @@ -35,7 +35,7 @@ desc = "The Syndicate have offered you the chance to become a contractor, take on kidnapping contracts for TC and cash payouts. Upon purchase, \ you'll be granted your own contract uplink embedded within the supplied tablet computer. Additionally, you'll be granted \ standard contractor gear to help with your mission - comes supplied with the tablet, specialised space suit, chameleon jumpsuit and mask, \ - agent card, and three randomly selected low cost items. Includes potentially otherwise unobtainable items." + specialised contractor baton, and three randomly selected low cost items. Can include otherwise unobtainable items." item = /obj/item/storage/box/syndie_kit/contract_kit cost = 20 player_minimum = 20 diff --git a/icons/mob/inhands/weapons/melee_lefthand.dmi b/icons/mob/inhands/weapons/melee_lefthand.dmi index bb4289a860..bd038883a0 100644 Binary files a/icons/mob/inhands/weapons/melee_lefthand.dmi and b/icons/mob/inhands/weapons/melee_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/melee_righthand.dmi b/icons/mob/inhands/weapons/melee_righthand.dmi index 4e9f5266b2..7284f43e60 100644 Binary files a/icons/mob/inhands/weapons/melee_righthand.dmi and b/icons/mob/inhands/weapons/melee_righthand.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index bdad12b0b6..8967879362 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ