diff --git a/code/game/gamemodes/technomancer/spells/audible_deception.dm b/code/game/gamemodes/technomancer/spells/audible_deception.dm index 0170ebd790d..4090aa7f44d 100644 --- a/code/game/gamemodes/technomancer/spells/audible_deception.dm +++ b/code/game/gamemodes/technomancer/spells/audible_deception.dm @@ -76,7 +76,7 @@ . = ..() var/turf/T = get_turf(hit_atom) if(selected_sound && pay_energy(200)) - playsound(src, selected_sound, 80, 1, -1) + playsound(T, selected_sound, 80, 1, -1) adjust_instability(1) // Air Horn time. if(selected_sound == 'sound/items/AirHorn.ogg' && pay_energy(3800)) diff --git a/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm b/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm index 3d515319b99..247ce483c7a 100644 --- a/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/biomed_aura.dm @@ -20,6 +20,7 @@ /obj/item/spell/aura/biomed/process() if(!pay_energy(75)) qdel(src) + return regen_tick++ if(regen_tick % 5 == 0) var/list/nearby_mobs = range(calculate_spell_power(4),owner) diff --git a/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm b/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm index bd21a3e7bcb..2a444aaf1eb 100644 --- a/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/fire_aura.dm @@ -20,6 +20,7 @@ /obj/item/spell/aura/fire/process() if(!pay_energy(100)) qdel(src) + return var/list/nearby_things = range(round(calculate_spell_power(4)),owner) var/temp_change = calculate_spell_power(25) diff --git a/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm b/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm index 1761205e0a8..8b336a495b6 100644 --- a/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/frost_aura.dm @@ -20,6 +20,7 @@ /obj/item/spell/aura/frost/process() if(!pay_energy(100)) qdel(src) + return var/list/nearby_mobs = range(round(calculate_spell_power(4)),owner) var/temp_change = calculate_spell_power(40) diff --git a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm index 4925027311f..aad9989c77c 100644 --- a/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/shock_aura.dm @@ -19,6 +19,7 @@ /obj/item/spell/aura/shock/process() if(!pay_energy(500)) qdel(src) + return var/list/nearby_mobs = range(calculate_spell_power(4), owner) var/power = calculate_spell_power(7) if(check_for_scepter()) diff --git a/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm b/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm index dca2e43f530..f58d2090cd3 100644 --- a/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm +++ b/code/game/gamemodes/technomancer/spells/aura/unstable_aura.dm @@ -20,6 +20,7 @@ /obj/item/spell/aura/unstable/process() if(!pay_energy(200)) qdel(src) + return var/list/nearby_mobs = range(calculate_spell_power(14),owner) for(var/mob/living/L in nearby_mobs) if(is_ally(L)) diff --git a/code/game/gamemodes/technomancer/spells/dispel.dm b/code/game/gamemodes/technomancer/spells/dispel.dm index d34d3890a21..6e6c32e1d93 100644 --- a/code/game/gamemodes/technomancer/spells/dispel.dm +++ b/code/game/gamemodes/technomancer/spells/dispel.dm @@ -17,5 +17,36 @@ /obj/item/spell/dispel/on_ranged_cast(atom/hit_atom, mob/living/user) . = ..() - user.adjust_instability(10) + if(!isliving(hit_atom)) + return FALSE + + var/mob/living/L = hit_atom + var/dispelled_effects = 0 + + if(L.modifiers) + var/list/modifiers_to_dispel = L.modifiers.Copy() + for(var/datum/modifier/technomancer/M in modifiers_to_dispel) + M.stop() + dispelled_effects++ + + var/list/inserted_spells_to_dispel = list() + for(var/obj/item/inserted_spell/IS in L.contents) + inserted_spells_to_dispel += IS + for(var/obj/item/inserted_spell/IS in inserted_spells_to_dispel) + IS.on_expire(TRUE) + dispelled_effects++ + + if(L.instability) + var/instability_to_remove = min(L.instability, calculate_spell_power(25)) + L.adjust_instability(-instability_to_remove) + dispelled_effects++ + + if(!dispelled_effects) + to_chat(user, SPAN_WARNING("\The [L] has no Technomancer effects to dispel.")) + return FALSE + + to_chat(user, SPAN_NOTICE("You dispel the Technomancer energies affecting \the [L].")) + log_and_message_admins("has dispelled Technomancer effects from [L].") + adjust_instability(10) qdel(src) + return TRUE diff --git a/code/game/gamemodes/technomancer/spells/energy_siphon.dm b/code/game/gamemodes/technomancer/spells/energy_siphon.dm index 7d21991b3f7..818f00aa633 100644 --- a/code/game/gamemodes/technomancer/spells/energy_siphon.dm +++ b/code/game/gamemodes/technomancer/spells/energy_siphon.dm @@ -136,15 +136,15 @@ // Now we can actually fill up the core. if(core.energy < core.max_energy) + var/overflow_energy = max(charge_to_give - (core.max_energy - core.energy), 0) give_energy(charge_to_give) to_chat(user, SPAN_NOTICE("Stolen [charge_to_give * CELLRATE] kJ and converted to [charge_to_give] Core energy.")) - if((core.max_energy - core.energy) < charge_to_give ) // We have some overflow, if this is true. + if(overflow_energy) // We have some overflow, if this is true. if(user.isSynthetic() && ishuman(user)) // Let's do something with it, if we're a robot. var/mob/living/carbon/human/H = user - charge_to_give = charge_to_give - (core.max_energy - core.energy) var/obj/item/organ/internal/machine/power_core/C = H.internal_organs_by_name[BP_CELL] var/obj/item/cell/potato = C.get_cell() - potato.give(charge_to_give) + potato.give(overflow_energy) to_chat(user, SPAN_NOTICE("Redirected energy to internal microcell.")) else to_chat(user, SPAN_NOTICE("Stolen [charge_to_give * CELLRATE] kJ.")) diff --git a/code/game/gamemodes/technomancer/spells/mend_organs.dm b/code/game/gamemodes/technomancer/spells/mend_organs.dm index b57b967d935..6f89afe3f6e 100644 --- a/code/game/gamemodes/technomancer/spells/mend_organs.dm +++ b/code/game/gamemodes/technomancer/spells/mend_organs.dm @@ -40,7 +40,7 @@ H.sdisabilities &= ~BLIND for(var/obj/item/organ/external/O in H.organs) // Fix limbs - if(!O.robotic < ORGAN_ROBOT) // No robot parts for this. + if(BP_IS_ROBOTIC(O)) // No robot parts for this. continue O.heal_damage(0, heal_power / 4, internal = 1, robo_repair = 0) diff --git a/code/game/gamemodes/technomancer/spells/modifier/corona.dm b/code/game/gamemodes/technomancer/spells/modifier/corona.dm index 59c77c14bd9..96a2d9a7f3a 100644 --- a/code/game/gamemodes/technomancer/spells/modifier/corona.dm +++ b/code/game/gamemodes/technomancer/spells/modifier/corona.dm @@ -22,3 +22,33 @@ /datum/modifier/technomancer/corona on_created_text = SPAN_WARNING("You start to glow very brightly!") on_expired_text = SPAN_NOTICE("Your glow has ended.") + miss_chance_modifier = -25 + var/obj/effect/technomancer_corona/corona_light + +/datum/modifier/technomancer/corona/activate() + . = ..() + if(!.) + return + corona_light = new(target) + RegisterSignal(target, COMSIG_UNARMED_HARM_DEFENDER, PROC_REF(handle_harm_defend), override = TRUE) + +/datum/modifier/technomancer/corona/deactivate() + QDEL_NULL(corona_light) + if(target) + UnregisterSignal(target, COMSIG_UNARMED_HARM_DEFENDER) + return ..() + +/datum/modifier/technomancer/corona/proc/handle_harm_defend(mob/defender, mob/attacker, defender_skill_level, miss_chance, rand_damage, block_chance) + SIGNAL_HANDLER + *miss_chance = max(*miss_chance - 10, 0) + +/obj/effect/technomancer_corona + name = "corona" + invisibility = INVISIBILITY_ABSTRACT + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + light_system = MOVABLE_LIGHT + +/obj/effect/technomancer_corona/Initialize() + . = ..() + set_light_range_power_color(6, 4, "#D9D900") + set_light_on(TRUE) diff --git a/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm b/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm index 0cae0e61909..7b46d393994 100644 --- a/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm +++ b/code/game/gamemodes/technomancer/spells/modifier/mend_synthetic.dm @@ -19,30 +19,63 @@ modifier_type = /datum/modifier/technomancer/mend_synthetic modifier_duration = 10 SECONDS +/obj/item/spell/modifier/mend_synthetic/on_add_modifier(var/mob/living/L) + if(!has_synthetic_damage_to_repair(L)) + to_chat(owner, SPAN_WARNING("\The [L] has no synthetic damage to repair.")) + return FALSE + return ..() + +//dont fucking look at it +/obj/item/spell/modifier/mend_synthetic/proc/has_synthetic_damage_to_repair(var/mob/living/L) + if(ishuman(L)) + var/mob/living/carbon/human/H = L + for(var/obj/item/organ/external/O in H.organs) + if(BP_IS_ROBOTIC(O) && (O.brute_dam || O.burn_dam)) + return TRUE + return FALSE + if(L.isSynthetic() && (L.getBruteLoss() || L.getFireLoss())) + return TRUE + return FALSE + /datum/modifier/technomancer/mend_synthetic on_created_text = SPAN_WARNING("Sparkles begin to appear around you, and your systems report integrity rising.") on_expired_text = SPAN_NOTICE("The sparkles have faded, although your systems seem to be better than before.") +//dont fucking look at it i said! /datum/modifier/technomancer/mend_synthetic/process() . = ..() + if(!. || QDELETED(src)) + return if(isliving(target)) var/mob/living/M = target - if(!M.getBruteLoss() && !M.getFireLoss()) // No point existing if the spell can't heal. - stop() - return + var/repaired_damage = FALSE if(ishuman(M)) var/mob/living/carbon/human/H = target for(var/obj/item/organ/external/E in H.organs) var/obj/item/organ/external/O = E - if(O.robotic >= ORGAN_ROBOT) - O.heal_damage(4 * strength, 4 * strength, 0, TRUE) + if(!BP_IS_ROBOTIC(O) || (!O.brute_dam && !O.burn_dam)) + continue + var/previous_brute = O.brute_dam + var/previous_burn = O.burn_dam + O.heal_damage(4 * strength, 4 * strength, 0, TRUE) + if(O.brute_dam < previous_brute || O.burn_dam < previous_burn) + repaired_damage = TRUE else if(M.isSynthetic()) + var/previous_brute = M.getBruteLoss() + var/previous_burn = M.getFireLoss() M.adjustBruteLoss(-4 * strength) // Should heal roughly 20 burn/brute over 10 seconds, as tick() is run every 2 seconds. M.adjustFireLoss(-4 * strength) // Ditto. + repaired_damage = M.getBruteLoss() < previous_brute || M.getFireLoss() < previous_burn + if(repaired_damage) + M.updatehealth() + + if(!repaired_damage) // No point existing if the spell can't heal. + stop() + return M.adjust_instability(1) if(source) var/mob/living/L = source - if(istype(L)) + if(istype(L) && L != M) L.adjust_instability(1) diff --git a/code/game/gamemodes/technomancer/spells/resurrect.dm b/code/game/gamemodes/technomancer/spells/resurrect.dm index 2dcf79b73bb..be23392731e 100644 --- a/code/game/gamemodes/technomancer/spells/resurrect.dm +++ b/code/game/gamemodes/technomancer/spells/resurrect.dm @@ -25,10 +25,10 @@ if(L.stat != DEAD) to_chat(user, SPAN_WARNING("\The [L] isn't dead!")) return 0 + if(L.timeofdeath && (world.time - L.timeofdeath) > 30 MINUTES) + to_chat(user, SPAN_DANGER("\The [L]'s been dead for too long, even this function cannot replace cloning at this point.")) + return 0 if(pay_energy(5000)) - if(L.tod > world.time + 30 MINUTES) - to_chat(user, SPAN_DANGER("\The [L]'s been dead for too long, even this function cannot replace cloning at this point.")) - return 0 to_chat(user, SPAN_NOTICE("You stab \the [L] with a hidden integrated hypo, attempting to bring them back...")) if(istype(L, /mob/living/simple_animal)) var/mob/living/simple_animal/SM = L diff --git a/code/game/gamemodes/technomancer/spells/shield.dm b/code/game/gamemodes/technomancer/spells/shield.dm index 2135877ddea..5d9c58f092b 100644 --- a/code/game/gamemodes/technomancer/spells/shield.dm +++ b/code/game/gamemodes/technomancer/spells/shield.dm @@ -42,7 +42,7 @@ if(istype(H.get_other_hand(src), src.type)) // Two shields in both hands. damage_to_energy_cost *= 0.75 - else if(check_for_scepter()) + if(check_for_scepter()) damage_to_energy_cost *= 0.50 if(!pay_energy(damage_to_energy_cost)) diff --git a/code/game/modifiers/modifiers.dm b/code/game/modifiers/modifiers.dm index a361d20f52d..7afdc15add0 100644 --- a/code/game/modifiers/modifiers.dm +++ b/code/game/modifiers/modifiers.dm @@ -165,6 +165,8 @@ it should be avoided in favour of manual removal where possible var/source_data = 0 var/strength = 0 var/duration = null + /// Additive mod applied to targeted miss chances while active + var/miss_chance_modifier = 0 //A list of equip slots which are considered 'worn'. //For equipment modifier type to be valid, the source object must be in a mob's contents @@ -182,8 +184,8 @@ it should be avoided in favour of manual removal where possible var/last_tick = 0 -//If creation of a modifier is successful, it will return a reference to itself -//If creation fails for any reason, it will return null as well as giving some debug output +/// If creation of a modifier is successful, it will return a reference to itself +/// If creation fails for any reason, it will return null as well as giving some debug output /datum/modifier/New(var/atom/_target, var/_modifier_type, var/_source = null, var/_source_data = 0, var/_strength = 0, var/_duration = 0, var/_check_interval = 0) ..() target = _target @@ -304,7 +306,7 @@ it should be avoided in favour of manual removal where possible return 1 -//Override this without a call to parent, for custom validity conditions +/// Override this without a call to parent, for custom validity conditions /datum/modifier/proc/custom_validity() return 1 @@ -317,7 +319,7 @@ it should be avoided in favour of manual removal where possible qdel(src) return 0 -//called by any object to either pause or remove the proc. +/// Called by any object to either pause or remove the proc. /datum/modifier/proc/stop(var/instant = 0, var/suspend = 0) //Instant var removes us from the lists immediately, instead of waiting til next frame when qdel goes through @@ -331,7 +333,7 @@ it should be avoided in favour of manual removal where possible else qdel(src) -//Suspends and immediately restarts the proc, thus reapplying its effects +/// Suspends and immediately restarts the proc, thus reapplying its effects /datum/modifier/proc/refresh() deactivate() activate() @@ -346,8 +348,8 @@ it should be avoided in favour of manual removal where possible return ..() -//Handles overriding an existing modifier of the same type. -//This function should return either src or the existing, depending on whether or not src will be kept +/// Handles overriding an existing modifier of the same type. +/// This function should return either src or the existing, depending on whether or not src will be kept /datum/modifier/proc/handle_override(var/override, var/datum/modifier/existing) switch(override) if (MODIFIER_OVERRIDE_DENY) @@ -399,7 +401,7 @@ it should be avoided in favour of manual removal where possible qdel(src) return existing -//This function should be completely overwritten, without a call to parent, to specify custom override +/// This function should be completely overwritten, without a call to parent, to specify custom override /datum/modifier/proc/custom_override(var/datum/modifier/existing) qdel(src) return existing diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 9cbd1edb8b0..0c1c4796692 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -349,11 +349,20 @@ GLOBAL_LIST_INIT(organ_rel_size, list( return target.calculate_zone_with_miss_chance(zone, miss_chance_mod) +/mob/proc/get_modifier_miss_chance_modifier() + if(!modifiers) + return 0 + var/total_modifier = 0 + for(var/datum/modifier/M in modifiers) + if(M.active) + total_modifier += M.miss_chance_modifier + return total_modifier + /mob/proc/calculate_zone_with_miss_chance(var/zone, var/miss_chance_mod) var/miss_chance = 10 if (zone in GLOB.base_miss_chance) miss_chance = GLOB.base_miss_chance[zone] - miss_chance = max(miss_chance + miss_chance_mod, 0) + miss_chance = max(miss_chance + miss_chance_mod + get_modifier_miss_chance_modifier(), 0) if(prob(miss_chance)) if(prob(70)) return null @@ -367,7 +376,7 @@ GLOBAL_LIST_INIT(organ_rel_size, list( var/miss_chance = 10 if(zone in GLOB.base_miss_chance) miss_chance = GLOB.base_miss_chance[zone] - miss_chance = max(miss_chance + miss_chance_mod, 0) + miss_chance = max(miss_chance + miss_chance_mod + get_modifier_miss_chance_modifier(), 0) if(prob(miss_chance)) return pick(GLOB.base_miss_chance) return zone diff --git a/html/changelogs/Bat-JesusChristTechnomancers.yml b/html/changelogs/Bat-JesusChristTechnomancers.yml new file mode 100644 index 00000000000..3677cd5c5a4 --- /dev/null +++ b/html/changelogs/Bat-JesusChristTechnomancers.yml @@ -0,0 +1,13 @@ +author: Batrachophrenoboocosmomachia +delete-after: True + +changes: + - bugfix: "Fixes Mend Synthetic not repairing synthetic/robotic limbs correctly." + - bugfix: "Fixes Dispel not removing Technomancer effects from its target." + - bugfix: "Fixes Corona not making targets glow or easier to hit." + - bugfix: "Fixes Resurrect not enforcing its maximum time-since-death limit." + - bugfix: "Fixes Mend Internals skipping organic body parts because it used old bitflags." + - bugfix: "Fixes Shield's scepter enhancement being straight up ignored." + - bugfix: "Fixes Energy Siphon overfilling synthetic internal cells." + - bugfix: "Fixes Audible Deception playing on the user instead of the targeted turf, defeating the entire point of it." + - bugfix: "Fixes a bunch of spells not actually ending immediately when energy runs out (and potential harddels.)"