diff --git a/code/game/gamemodes/clock_cult/clock_items.dm b/code/game/gamemodes/clock_cult/clock_items.dm index 3082e756b88..a69220d5fe5 100644 --- a/code/game/gamemodes/clock_cult/clock_items.dm +++ b/code/game/gamemodes/clock_cult/clock_items.dm @@ -568,7 +568,7 @@ icon = 'icons/obj/clothing/clockwork_garb.dmi' icon_state = "clockwork_helmet" w_class = 3 - armor = list(melee = 80, bullet = 50, laser = -15, energy = 5, bomb = 35, bio = 0, rad = 0) + armor = list(melee = 80, bullet = 50, laser = -15, energy = 0, bomb = 35, bio = 0, rad = 0) /obj/item/clothing/head/helmet/clockwork/equipped(mob/living/user, slot) ..() @@ -599,7 +599,7 @@ icon_state = "clockwork_cuirass" w_class = 4 body_parts_covered = CHEST|GROIN|LEGS - armor = list(melee = 80, bullet = 50, laser = -15, energy = 5, bomb = 35, bio = 0, rad = 0) + armor = list(melee = 80, bullet = 50, laser = -15, energy = 0, bomb = 35, bio = 0, rad = 0) allowed = list(/obj/item/clockwork, /obj/item/clothing/glasses/wraith_spectacles, /obj/item/clothing/glasses/judicial_visor, /obj/item/device/mmi/posibrain/soul_vessel) /obj/item/clothing/suit/armor/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0) @@ -638,7 +638,7 @@ burn_state = FIRE_PROOF siemens_coefficient = 0 permeability_coefficient = 0.05 - armor = list(melee = 80, bullet = 50, laser = -15, energy = 5, bomb = 35, bio = 0, rad = 0) + armor = list(melee = 80, bullet = 50, laser = -15, energy = 0, bomb = 35, bio = 0, rad = 0) /obj/item/clothing/gloves/clockwork/mob_can_equip(mob/M, mob/equipper, slot, disable_warning = 0) if(equipper && !is_servant_of_ratvar(equipper)) diff --git a/code/game/gamemodes/clock_cult/clock_machines.dm b/code/game/gamemodes/clock_cult/clock_machines.dm index c682142aa5d..4509cf916c8 100644 --- a/code/game/gamemodes/clock_cult/clock_machines.dm +++ b/code/game/gamemodes/clock_cult/clock_machines.dm @@ -138,8 +138,8 @@ active_icon = "mending_motor" inactive_icon = "mending_motor_inactive" construction_value = 20 - max_health = 150 - health = 150 + max_health = 125 + health = 125 break_message = "The prism collapses with a heavy thud!" debris = list(/obj/item/clockwork/alloy_shards/small = 5, \ /obj/item/clockwork/alloy_shards/medium = 1, \ @@ -439,46 +439,14 @@ CHECK_TICK for(var/M in atoms_to_test) - if(istype(M, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/A = M - if(A.cell && A.cell.charge) - successfulprocess = TRUE - playsound(A, "sparks", 50, 1) - flick("apc-spark", A) - power_drained += min(A.cell.charge, 100) - A.cell.charge = max(0, A.cell.charge - 100) - if(!A.cell.charge && !A.shorted) - A.shorted = 1 - A.visible_message("The [A.name]'s screen blurs with static.") - A.update() - A.update_icon() - else if(istype(M, /obj/machinery/power/smes)) - var/obj/machinery/power/smes/S = M - if(S.charge) - successfulprocess = TRUE - power_drained += min(S.charge, 500) - S.charge = max(0, S.charge - 50000) //SMES units contain too much power and could run an interdiction lens basically forever, or provide power forever - if(!S.charge && !S.panel_open) - S.panel_open = TRUE - S.icon_state = "[initial(S.icon_state)]-o" - var/datum/effect_system/spark_spread/spks = new(get_turf(S)) - spks.set_up(10, 0, get_turf(S)) - spks.start() - S.visible_message("[S]'s panel flies open with a flurry of sparks.") - S.update_icon() - else if(isrobot(M)) - var/mob/living/silicon/robot/R = M - if(!is_servant_of_ratvar(R) && R.cell && R.cell.charge) - successfulprocess = TRUE - power_drained += min(R.cell.charge, 200) - R.cell.charge = max(0, R.cell.charge - 200) - R << "ERROR: Power loss detected!" - var/datum/effect_system/spark_spread/spks = new(get_turf(R)) - spks.set_up(3, 0, get_turf(R)) - spks.start() + var/atom/movable/A = M + power_drained += A.power_drain(TRUE) CHECK_TICK + if(power_drained) + successfulprocess = TRUE + if(!return_power(power_drained) || power_drained < 50) //failed to return power drained or too little power to return successfulprocess = FALSE if(try_use_power(disrupt_cost) && total_accessable_power() >= disrupt_cost) //if we can disable at least one object @@ -537,8 +505,8 @@ active_icon = "obelisk" inactive_icon = "obelisk_inactive" construction_value = 20 - max_health = 200 - health = 200 + max_health = 150 + health = 150 break_message = "The obelisk falls to the ground, undamaged!" debris = list(/obj/item/clockwork/alloy_shards/small = 3, \ /obj/item/clockwork/component/hierophant_ansible/obelisk = 1) diff --git a/code/game/gamemodes/clock_cult/clock_mobs.dm b/code/game/gamemodes/clock_cult/clock_mobs.dm index d8d3025e088..4793b33766d 100644 --- a/code/game/gamemodes/clock_cult/clock_mobs.dm +++ b/code/game/gamemodes/clock_cult/clock_mobs.dm @@ -38,8 +38,8 @@ health = 90 maxHealth = 90 speed = -1 - melee_damage_lower = 20 - melee_damage_upper = 20 + melee_damage_lower = 18 + melee_damage_upper = 18 attacktext = "crushes" attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg' loot = list(/obj/item/clockwork/component/replicant_alloy/smashed_anima_fragment) diff --git a/code/game/gamemodes/clock_cult/clock_powerdrain.dm b/code/game/gamemodes/clock_cult/clock_powerdrain.dm new file mode 100644 index 00000000000..ef0f6626fb5 --- /dev/null +++ b/code/game/gamemodes/clock_cult/clock_powerdrain.dm @@ -0,0 +1,54 @@ +//horrifying power drain proc made for clockcult's power drain in lieu of six istypes or six for(x in view) loops +/atom/movable/proc/power_drain(clockcult_user) + return 0 + +/obj/machinery/power/apc/power_drain(clockcult_user) + if(cell && cell.charge) + playsound(src, "sparks", 50, 1) + flick("apc-spark", src) + . += min(cell.charge, 500) + cell.charge = max(0, cell.charge - 500) //Better than a power sink! + if(!cell.charge && !shorted) + shorted = 1 + visible_message("The [name]'s screen blurs with static.") + update() + update_icon() + +/obj/machinery/power/smes/power_drain(clockcult_user) + if(charge) + . += min(charge, 500) + charge = max(0, charge - 50000) + if(!charge && !panel_open) + panel_open = TRUE + icon_state = "[initial(icon_state)]-o" + var/datum/effect_system/spark_spread/spks = new(get_turf(src)) + spks.set_up(10, 0, get_turf(src)) + spks.start() + visible_message("[src]'s panel flies open with a flurry of spark") + update_icon() + +/obj/item/weapon/stock_parts/cell/power_drain(clockcult_user) + if(charge) + . += min(charge, 500) + charge = use(max(0, charge - 500)) + updateicon() + +/obj/machinery/light/power_drain(clockcult_user) + if(on) + playsound(src, 'sound/effects/light_flicker.ogg', 50, 1) + flicker(2) + . += 50 + +/mob/living/silicon/robot/power_drain(clockcult_user) + if((!clockcult_user || !is_servant_of_ratvar(src)) && cell && cell.charge) + . += min(cell.charge, 500) + cell.charge = max(0, cell.charge - 500) + src << "ERROR: Power loss detected!" + spark_system.start() + +/obj/mecha/power_drain(clockcult_user) + if((!clockcult_user || !occupant || occupant && !is_servant_of_ratvar(occupant)) && cell && cell.charge) + . += min(cell.charge, 500) + cell.charge = max(0, cell.charge - 500) + occupant << "Power loss detected!" + spark_system.start() \ No newline at end of file diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm index 0156767691a..ad2615e54a1 100644 --- a/code/game/gamemodes/clock_cult/clock_scripture.dm +++ b/code/game/gamemodes/clock_cult/clock_scripture.dm @@ -161,6 +161,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed var/observer_message var/one_per_tile = FALSE var/prevent_path + var/space_allowed = FALSE /datum/clockwork_scripture/create_object/New() ..() @@ -168,7 +169,11 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed prevent_path = object_path /datum/clockwork_scripture/create_object/check_special_requirements() - if(one_per_tile && (locate(prevent_path) in get_turf(invoker))) + var/turf/T = get_turf(invoker) + if(!space_allowed && istype(T, /turf/open/space)) + invoker << "You need solid ground to place this object!" + return 0 + if(one_per_tile && (locate(prevent_path) in T)) invoker << "You can only place one of this object on each tile!" return 0 return 1 @@ -196,19 +201,21 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Useful for crowd control in a populated area and disrupting mass movement." tier = SCRIPTURE_DRIVER sort_priority = 1 + var/noncultist_damage = 2 //damage per chant to noncultists + var/cultist_damage = 8 //damage per chant to non-walking cultists /datum/clockwork_scripture/channeled/belligerent/chant_effects(chant_number) for(var/mob/living/carbon/C in hearers(7, invoker)) if(!is_servant_of_ratvar(C) && !C.null_rod_check() && C.get_num_legs()) //you have legs right - C.apply_damage(1, BURN, "l_leg") - C.apply_damage(1, BURN, "r_leg") + C.apply_damage(noncultist_damage * 0.5, BURN, "l_leg") + C.apply_damage(noncultist_damage * 0.5, BURN, "r_leg") if(C.m_intent != "walk") if(!iscultist(C)) C << "Your legs shiver with pain!" else //Cultists take extra burn damage C << "Your legs burn with pain!" - C.apply_damage(4, BURN, "l_leg") - C.apply_damage(4, BURN, "r_leg") + C.apply_damage(cultist_damage * 0.5, BURN, "l_leg") + C.apply_damage(cultist_damage * 0.5, BURN, "r_leg") C.m_intent = "walk" @@ -227,6 +234,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a judicial visor, which is capable of smiting the unworthy." usage_tip = "The visor has a thirty-second cooldown once used, and the marker it creates has a delay of 3 seconds before exploding." tier = SCRIPTURE_DRIVER + space_allowed = TRUE sort_priority = 2 @@ -380,7 +388,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed name = "Replicant" desc = "Creates a new clockwork slab." invocations = list("Metal, become greater!") - channel_time = 0 + channel_time = 10 required_components = list("replicant_alloy" = 1) whispered = TRUE usage_tip = "This is inefficient as a way to produce components, as the slab produced must be held by someone with no other slabs to produce components." @@ -435,6 +443,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a pair of wraith spectacles, which will grant true sight when worn." usage_tip = "\"True sight\" means that you are able to see through walls and in darkness." tier = SCRIPTURE_DRIVER + space_allowed = TRUE sort_priority = 9 @@ -473,6 +482,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed usage_tip = "Although powerful, the warden is very weak and should optimally be placed behind barricades." tier = SCRIPTURE_SCRIPT one_per_tile = TRUE + space_allowed = TRUE sort_priority = 11 /datum/clockwork_scripture/create_object/ocular_warden/check_special_requirements() @@ -501,47 +511,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed /datum/clockwork_scripture/channeled/volt_void/chant_effects(chant_number) playsound(invoker, 'sound/effects/EMPulse.ogg', 50, 1) var/power_drained = 0 - for(var/obj/machinery/power/apc/A in view(7, invoker)) - if(A.cell && A.cell.charge) - playsound(A, "sparks", 50, 1) - flick("apc-spark", A) - power_drained += min(A.cell.charge, 500) - A.cell.charge = max(0, A.cell.charge - 500) //Better than a power sink! - if(!A.cell.charge && !A.shorted) - A.shorted = 1 - A.visible_message("The [A.name]'s screen blurs with static.") - A.update() - A.update_icon() - for(var/obj/machinery/power/smes/S in view(7, invoker)) - if(S.charge) - power_drained += min(S.charge, 500) - S.charge = max(0, S.charge - 50000) - if(!S.charge && !S.panel_open) - S.panel_open = TRUE - S.icon_state = "[initial(S.icon_state)]-o" - var/datum/effect_system/spark_spread/spks = new(get_turf(S)) - spks.set_up(10, 0, get_turf(S)) - spks.start() - S.visible_message("[S]'s panel flies open with a flurry of sparks.") - S.update_icon() - for(var/obj/item/weapon/stock_parts/cell/C in view(7, invoker)) - if(C.charge) - power_drained += min(C.charge, 500) - C.charge = C.use(max(0, C.charge - 500)) - C.updateicon() - for(var/obj/machinery/light/L in view(7, invoker)) - if(L.on) - playsound(L, 'sound/effects/light_flicker.ogg', 50, 1) - L.flicker(2) - power_drained += 50 - for(var/mob/living/silicon/robot/R in view(7, invoker)) - if(!is_servant_of_ratvar(R) && R.cell && R.cell.charge) - power_drained += min(R.cell.charge, 500) - R.cell.charge = max(0, R.cell.charge - 500) - R << "ERROR: Power loss detected!" - var/datum/effect_system/spark_spread/spks = new(get_turf(R)) - spks.set_up(3, 0, get_turf(R)) - spks.start() + for(var/atom/movable/A in view(7, invoker)) + power_drained += A.power_drain(TRUE) var/obj/effect/clockwork/sigil/transmission/ST = locate(/obj/effect/clockwork/sigil/transmission) in get_turf(invoker) if(ST && power_drained >= 50) var/sigil_drain = 0 @@ -559,7 +530,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed var/mob/living/carbon/human/H = invoker for(var/X in H.bodyparts) var/obj/item/bodypart/BP = X - if(ratvar_awakens || BP.status == BODYPART_ROBOTIC && total_power_drained < augument_damage_threshhold) //if ratvar is alive, it won't damage and will always heal augumented limbs + if(ratvar_awakens || (BP.status == BODYPART_ROBOTIC && total_power_drained < augument_damage_threshhold)) //if ratvar is alive, it won't damage and will always heal augumented limbs if(BP.heal_damage(power_damage, power_damage, 1, 0)) //heals one point of burn and brute for every ~100W drained on augumented limbs H.update_damage_overlays() else @@ -585,6 +556,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a clockwork proselytizer, which is already pre-loaded with a small amount of replicant alloy." usage_tip = "Clockwork walls cause adjacent tinkerer's caches to generate components passively, making them a vital tool. Clockwork floors heal servants standing on them." tier = SCRIPTURE_SCRIPT + space_allowed = TRUE sort_priority = 17 @@ -642,7 +614,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed for(var/datum/action/innate/function_call/F in invoker.actions) invoker << "You have already bound a Ratvarian spear to yourself!" return 0 - return ishuman(invoker) + return invoker.can_hold_items() /datum/clockwork_scripture/function_call/scripture_effects() invoker.visible_message("A shimmer of yellow light infuses [invoker]!", \ @@ -701,7 +673,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed name = "Soul Vessel" desc = "Forms an ancient positronic brain with an overriding directive to serve Ratvar." invocations = list("Herd the souls of...", "...the blasphemous damned!") - channel_time = 20 + channel_time = 30 required_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 2) consumed_components = list("vanguard_cogwheel" = 1, "guvax_capacitor" = 1) whispered = TRUE @@ -709,6 +681,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a soul vessel, which can be used in-hand to attract spirits, or used on an unconscious or dead human to extract their consciousness." usage_tip = "The vessel can be used as a teleport target for Spatial Gateway, though it is generally better-used by placing it in a shell." tier = SCRIPTURE_SCRIPT + space_allowed = TRUE sort_priority = 16 @@ -718,7 +691,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed name = "Cogscarab" desc = "Creates a small shell fitted for soul vessels. Adding an active soul vessel to it results in a small construct with tools and an inbuilt proselytizer." invocations = list("Call forth...", "...the workers of Armorer.") - channel_time = 50 + channel_time = 60 required_components = list("belligerent_eye" = 2, "hierophant_ansible" = 1) consumed_components = list("belligerent_eye" = 1, "hierophant_ansible" = 1) object_path = /obj/structure/destructible/clockwork/shell/cogscarab @@ -757,7 +730,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed desc = "Creates a large shell fitted for soul vessels. Adding an active soul vessel to it results in a powerful construct with decent health, notable melee power, \ and exceptional speed, though taking damage will temporarily slow it down." invocations = list("Call forth...", "...the soldiers of Armorer.") - channel_time = 70 + channel_time = 80 required_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "replicant_alloy" = 3) consumed_components = list("belligerent_eye" = 1, "vanguard_cogwheel" = 1, "replicant_alloy" = 2) object_path = /obj/structure/destructible/clockwork/shell/fragment @@ -985,6 +958,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed creator_message = "You form a daemon shell. Attach it to a tinkerer's cache to increase its rate of production." usage_tip = "Vital to your success!" tier = SCRIPTURE_APPLICATION + space_allowed = TRUE sort_priority = 21 /datum/clockwork_scripture/create_object/tinkerers_daemon/check_special_requirements() @@ -1018,6 +992,8 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed and interdiction lenses, mending motors, mania motors, and clockwork obelisks will all require no power." tier = SCRIPTURE_REVENANT sort_priority = 33 + invokers_required = 3 + multiple_invokers_used = TRUE /datum/clockwork_scripture/invoke_nezbere/check_special_requirements() if(!slab.no_cost && clockwork_generals_invoked["nezbere"] > world.time) diff --git a/code/game/gamemodes/clock_cult/clock_structures.dm b/code/game/gamemodes/clock_cult/clock_structures.dm index 923b83fe8ba..f4c77623c42 100644 --- a/code/game/gamemodes/clock_cult/clock_structures.dm +++ b/code/game/gamemodes/clock_cult/clock_structures.dm @@ -174,7 +174,7 @@ /obj/structure/destructible/clockwork/ocular_warden //Ocular warden: Low-damage, low-range turret. Deals constant damage to whoever it makes eye contact with. name = "ocular warden" desc = "A large brass eye with tendrils trailing below it and a wide red iris." - clockwork_desc = "A stalwart turret that will deal sustained damage to any non-faithful it sees." + clockwork_desc = "A fragile turret that will deal sustained damage to any non-faithful it sees." icon_state = "ocular_warden" health = 25 max_health = 25 @@ -187,7 +187,7 @@ var/sight_range = 3 var/atom/movable/target var/list/idle_messages = list(" sulkily glares around.", " lazily drifts from side to side.", " looks around for something to burn.", " slowly turns in circles.") - var/mech_damage_cycle = 0 //only hits every few cycles so mechs have a chance against it + var/mech_damage_cycle = 0 //so that people in mechs don't get murderspammed with messages /obj/structure/destructible/clockwork/ocular_warden/New() ..() @@ -218,12 +218,14 @@ L.adjust_fire_stacks(damage_per_tick) L.IgniteMob() else if(istype(target,/obj/mecha)) - if(mech_damage_cycle) - var/obj/mecha/M = target - M.take_directional_damage(damage_per_tick, "fire", get_dir(src, M), 0) //does about half of standard damage to mechs * whatever their fire armor is + var/sending_message = FALSE + if(mech_damage_cycle > 1) mech_damage_cycle-- else mech_damage_cycle++ + sending_message = TRUE + var/obj/mecha/M = target + M.take_directional_damage(damage_per_tick, "fire", get_dir(src, M), 0, 1, sending_message) setDir(get_dir(get_turf(src), get_turf(target))) if(!target) if(validtargets.len) diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index 7043e0bf508..438c868d041 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -9,7 +9,7 @@ return 1 //always return non-0 -/obj/mecha/proc/take_damage(amount, type="brute", booster_deflection_modifier = 1, booster_damage_modifier = 1) +/obj/mecha/proc/take_damage(amount, type="brute", booster_deflection_modifier = 1, booster_damage_modifier = 1, send_message = 1) if(prob(deflect_chance * booster_deflection_modifier)) visible_message("[src]'s armour deflects the attack!") log_append_to_last("Armor saved.") @@ -19,18 +19,19 @@ damage = damage * booster_damage_modifier health -= damage update_health() - occupant_message("Taking damage!") + if(send_message) + occupant_message("Taking damage!") log_append_to_last("Took [damage] points of damage. Damage type: \"[type]\".",1) return 1 -/obj/mecha/proc/take_directional_damage(amount, type="brute", adir = 0, booster_deflection_modifier = 1, booster_damage_modifier = 1) +/obj/mecha/proc/take_directional_damage(amount, type="brute", adir = 0, booster_deflection_modifier = 1, booster_damage_modifier = 1, send_message = 1) var/facing_modifier = get_armour_facing(dir2angle(adir) - dir2angle(src)) booster_damage_modifier /= facing_modifier booster_deflection_modifier *= facing_modifier - return take_damage(amount, type, booster_deflection_modifier, booster_damage_modifier) + return take_damage(amount, type, booster_deflection_modifier, booster_damage_modifier, send_message) /obj/mecha/proc/absorbDamage(damage,damage_type) diff --git a/tgstation.dme b/tgstation.dme index ffa047f54fa..45351474e52 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -337,6 +337,7 @@ #include "code\game\gamemodes\clock_cult\clock_items.dm" #include "code\game\gamemodes\clock_cult\clock_machines.dm" #include "code\game\gamemodes\clock_cult\clock_mobs.dm" +#include "code\game\gamemodes\clock_cult\clock_powerdrain.dm" #include "code\game\gamemodes\clock_cult\clock_proselytizer.dm" #include "code\game\gamemodes\clock_cult\clock_ratvar.dm" #include "code\game\gamemodes\clock_cult\clock_scripture.dm"