diff --git a/code/__DEFINES/clockcult.dm b/code/__DEFINES/clockcult.dm index f597eb4ae7..a42ba4996f 100644 --- a/code/__DEFINES/clockcult.dm +++ b/code/__DEFINES/clockcult.dm @@ -23,6 +23,7 @@ GLOBAL_VAR_INIT(script_scripture_unlocked, FALSE) //If script scripture is avail GLOBAL_VAR_INIT(application_scripture_unlocked, FALSE) //If application scripture is available GLOBAL_VAR_INIT(judgement_scripture_unlocked, FALSE) //If judgement scripture is available GLOBAL_LIST_EMPTY(all_scripture) //a list containing scripture instances; not used to track existing scripture +GLOBAL_LIST_INIT(clock_rites, list(typesof(/datum/clockwork_rite) - /datum/clockwork_rite)) //Scripture tiers and requirements; peripherals should never be used #define SCRIPTURE_PERIPHERAL "Peripheral" diff --git a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm index e579023a7a..6cdc781617 100644 --- a/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm +++ b/code/modules/antagonists/clockcult/clock_effects/clock_sigils.dm @@ -405,3 +405,28 @@ animation_number = initial(animation_number) sigil_active = FALSE animate(src, alpha = initial(alpha), time = 10, flags = ANIMATION_END_NOW) + +/obj/effect/clockwork/sigil/rite + name = "radiant sigil" + desc = "A glowing sigil glowing with barely-contained power." + clockwork_desc = "A sigil that will allow you to perform certain rites on it, provided you have access to sufficient power and materials." + icon_state = "sigiltransmission" //TODO + sigil_name = "Sigil of Rites" + alpha = 255 + var/performing_rite = FALSE + color = "#ffe63a" + +/obj/effect/clockwork/sigil/rite/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) + . = ..() + if(.) + return + if(!is_servant_of_ratvar(user)) + return + var/list/possible_rites = list() + for(var/datum/clockwork_rite/R in GLOB.clock_rites) + possible_rites[R] = R + var/input_key = input(user, "Choose a rite to cast", "Casting a rite") as null|anything in possible_rites + if(!input_key) + return + var/datum/clockwork_rite/CR = possible_rites[input_key] + CR.try_cast(src, user) \ No newline at end of file diff --git a/code/modules/antagonists/clockcult/clock_helpers/clock_rites.dm b/code/modules/antagonists/clockcult/clock_helpers/clock_rites.dm new file mode 100644 index 0000000000..09d1aeee47 --- /dev/null +++ b/code/modules/antagonists/clockcult/clock_helpers/clock_rites.dm @@ -0,0 +1,101 @@ +//This file is for clock rites, mainly used by the Sigil of Rites in clock_sigils.dm +//The rites themselves are in this file to prevent bloating the other file too much, aswell as for easier access + +//The base clockwork rite. This should never be visible +/datum/clockwork_rite + var/name = "Some random clockwork rite that you should not be able to see" //The name of the rite + var/list/required_ingredients = list() //What does this rite require? + var/power_cost = 0 //How much power does this rite cost.. or does it even add power? + var/requires_human = FALSE //Does the rite require a ../carbon/human on the rune? + var/must_be_servant = TRUE //If the above is true, does the human need to be a servant? + var/target_can_be_invoker = TRUE //Does this rite work if the invoker is also the target? + var/cast_time = 0 //How long does the rite take to cast? + var/limit = -1 //How often can this rite be used per round? Set this to -1 for unlimited, 0 for disallowed, anything above 0 for a limit + var/times_used = 0 //How often has the rite already been used this shift? + var/rite_cast_sound = 'sound/items/bikehorn.ogg' //The sound played when successfully casting the rite. If it honks, the one adding the rite forgot to set one (or was just lazy). + +/datum/clockwork_rite/proc/try_cast(var/obj/effect/clockwork/sigil/rite/R, var/mob/living/invoker) //Performs a ton of checks to see if the invoker can cast the rite + if(!istype(R)) + return FALSE + if(!R || !R.loc) + return FALSE + var/turf/T = R.loc + if(!T) //Uh oh something is fucky + return FALSE + + if(limit != -1 && times_used >= limit) //Is the limit on casts exceeded? + to_chat(invoker, "There are no more uses left for this rite!") + return FALSE + + var/mob/living/carbon/human/H //This is only used if requires_human is TRUE + if(requires_human) //In case this requires a target + for(var/mob/living/carbon/human/possible_H in T) + if((!must_be_servant || is_servant_of_ratvar(possible_H)) && (target_can_be_invoker || invoker != possible_H)) + H = possible_H + break + if(!H) + to_chat(invoker, "There is no target for the rite on the sigil!") + return FALSE + + if(required_ingredients.len) //In case this requires materials + var/is_missing_materials = FALSE + for(var/obj/item/I in required_ingredients) + var/obj/item/Material = locate(I) in T + if(!Material) + is_missing_materials = TRUE + break + if(!is_missing_materials) + var/still_required_string = "" + for(var/i = 1 to required_ingredients.len) + var/obj/O = required_ingredients[i] + if(i != 1) + still_required_string += ", " + still_required_string += initial(O.name) + to_chat(invoker, "There are still materials missing for this rite. You require [still_required_string].") + return FALSE + + if(power_cost) //If this costs power + if(!get_clockwork_power(power_cost)) + to_chat(invoker, "There is not enough power for this rite!") + return FALSE + R.performing_rite = TRUE + if(!do_after(invoker, cast_time, target = R)) + to_chat(invoker, "span class='warning'>Your rite is disrupted.") + R.performing_rite = FALSE + return FALSE + . = cast(invoker, T, H) + if(!.) + to_chat(invoker, " You fail casting [name]") + post_cast(FALSE) + else + to_chat(invoker, "You successfully cast [name]") + post_cast(TRUE) + R.performing_rite = FALSE + return + +/datum/clockwork_rite/proc/cast(/mob/living/invoker, var/turf/T, var/mob/living/carbon/human/target) //Casts the rite and uses up ingredients. Doublechecks some things to prevent bypassing some restrictions via funky timing or badminnery. + if(requires_human && !target) + return FALSE + if(power_cost && !get_clockwork_power(power_cost)) + return FALSE + adjust_clockwork_power(-power_cost) + if(limit != -1 && times_used >= limit) + return FALSE + if(required_ingredients.len) + var/is_missing_materials = FALSE + for(var/obj/item/I in required_ingredients) + var/obj/item/Material = locate(I) in T + if(!Material) + is_missing_materials = TRUE + break + else + qdel(Material) + if(!is_missing_materials) + return FALSE + playsound(T, rite_cast_sound, 50, 2) + return TRUE + +/datum/clockwork_rite/proc/post_cast(var/cast_succeeded) + if(cast_succeeded) + times_used++ + return TRUE \ No newline at end of file diff --git a/code/modules/antagonists/clockcult/clock_items/clock_augments.dm b/code/modules/antagonists/clockcult/clock_items/clock_augments.dm index 3709e5ee2b..0b9c31f4e0 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_augments.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_augments.dm @@ -4,6 +4,7 @@ /obj/item/organ/cyberimp/arm/clockwork name = "clock-themed arm-mounted implant" var/clockwork_desc = "According to Ratvar, this really shouldn't exist. Tell Him about this immediately." + syndicate_implant = TRUE /obj/item/organ/cyberimp/arm/clockwork/ui_action_click() if(is_servant_of_ratvar(owner) || (obj_flags & EMAGGED)) //If you somehow manage to steal a clockie's implant AND have an emag AND manage to get it implanted for yourself, good on ya! diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/brass_claw.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/brass_claw.dm index cedc04c59e..df84002f69 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/brass_claw.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/brass_claw.dm @@ -1,16 +1,16 @@ -//Brass claw, a armbladelike weapon used by an clock implant. Stealthy if retracted, very obvious if active. Simillar to an armblade strength-wise but has some funky stuff +//Brass claw, an armblade-like weapon used by a clock implant. Stealthy if retracted, very obvious if active. +//Bit weaker than an armblade strength-wise but gains combo on consecutive attacks against the same target, which causes bonus damage /obj/item/clockwork/brass_claw name = "brass claw" desc = "A highly sharp claw made out of brass." - clockwork_desc = "A incredibly sharp claw made out of brass. It is quite effective at crippling enemies, though incredibly obvious aswell." + clockwork_desc = "A incredibly sharp claw made out of brass. It is quite effective at crippling enemies, though incredibly obvious aswell. Gains combo on consecutive attacks against a target, causing bonus damage." icon_state = "brass_claw" //Codersprite moment item_state = "brass_claw" lefthand_file = 'icons/mob/inhands/antag/clockwork_lefthand.dmi' righthand_file = 'icons/mob/inhands/antag/clockwork_righthand.dmi' - //item_flags = NEEDS_PERMIT | ABSTRACT | DROPDEL w_class = WEIGHT_CLASS_HUGE - force = 15 //Doesn't generate vitality like the spear does / has somewhat less damage, but quite good at wounding and gets through armor pretty well. + force = 15 //Doesn't generate vitality like the spear does / has somewhat less damage, but quite good at wounding and gets through armor pretty well. Also gains 2 bonus damage per consecutive attack on the same target throwforce = 0 //haha yes lets be safe about this throw_range = 0 throw_speed = 0 @@ -21,7 +21,23 @@ wound_bonus = 5 bare_wound_bonus = 15 total_mass = TOTAL_MASS_HAND_REPLACEMENT + var/mob/living/last_attacked + var/combo = 0 /obj/item/clockwork/brass_claw/Initialize() . = ..() AddComponent(/datum/component/butchering, 60, 80) + +/obj/item/clockwork/brass_claw/attack(mob/living/target, mob/living/carbon/human/user) + . = ..() + if(QDELETED(target) || target.anti_magic_check(chargecost = 0) || is_servant_of_ratvar(target)) + return + if(target != last_attacked) //Loses all combat on switching targets + last_attacked = target + combo = 0 + else + if(!iscultist(target)) //Hostile cultists being hit stacks up combo far faster than usual + combo++ + else + combo += 3 + target.adjustBruteLoss(combo * 2) diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm index 22b0913b2f..abfba29cc9 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm @@ -45,7 +45,7 @@ else if(iscultist(target) || isconstruct(target)) to_chat(target, "Your body flares with agony at [src]'s presence!") bonus_damage *= 3 //total 30 damage on cultists, 50 with ratvar - GLOB.clockwork_vitality += target.adjustFireLoss(bonus_damage) //adds the damage done to existing vitality + GLOB.clockwork_vitality += max(0, target.adjustFireLoss(bonus_damage)) //adds the damage done to existing vitality /obj/item/clockwork/weapon/ratvarian_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) var/turf/T = get_turf(hit_atom) diff --git a/tgstation.dme b/tgstation.dme index 05154aad92..b6ade162a5 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1519,6 +1519,7 @@ #include "code\modules\antagonists\clockcult\clock_effects\servant_blocker.dm" #include "code\modules\antagonists\clockcult\clock_effects\spatial_gateway.dm" #include "code\modules\antagonists\clockcult\clock_helpers\clock_powerdrain.dm" +#include "code\modules\antagonists\clockcult\clock_helpers\clock_rites.dm" #include "code\modules\antagonists\clockcult\clock_helpers\component_helpers.dm" #include "code\modules\antagonists\clockcult\clock_helpers\fabrication_helpers.dm" #include "code\modules\antagonists\clockcult\clock_helpers\hierophant_network.dm"