From e77ea39458866e91e6ac89115cf1cdad340371a7 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Fri, 9 Sep 2022 22:20:56 -0400 Subject: [PATCH 01/17] Adds shield generators. Kinda WIP but it functions ATM. --- .../devices/personal_shield_generator_vr.dm | 364 ++++++++++++++++++ code/modules/mob/_modifiers/modifiers.dm | 4 + code/modules/mob/_modifiers/modifiers_vr.dm | 68 +++- .../mob/living/carbon/human/human_damage.dm | 24 ++ .../mob/living/carbon/human/human_defense.dm | 12 + code/modules/mob/living/living.dm | 23 ++ icons/obj/items_vr.dmi | Bin 5259 -> 6797 bytes vorestation.dme | 1 + 8 files changed, 495 insertions(+), 1 deletion(-) create mode 100644 code/game/objects/items/devices/personal_shield_generator_vr.dm diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm new file mode 100644 index 00000000000..cff54a33d53 --- /dev/null +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -0,0 +1,364 @@ +//backpack item +/obj/item/device/personal_shield_generator + name = "personal shield generator" + desc = "A personal shield generator." + icon = 'icons/obj/items_vr.dmi' //Placeholder + icon_state = "shield_pack" //Placeholder + item_state = "defibunit" //Placeholder + slot_flags = SLOT_BACK + force = 5 + throwforce = 6 + preserve_item = 1 + w_class = ITEMSIZE_HUGE //It's a giant shield generator!!! + unacidable = TRUE + origin_tech = list(TECH_BIO = 4, TECH_POWER = 2) //Set this to better stuff later. + action_button_name = "Toggle Shield" + + var/obj/item/weapon/gun/energy/gun/generator/active_weapon + var/obj/item/weapon/cell/device/bcell = null + var/generator_hit_cost = 100 // Power used when a special effect (such as a bullet being blocked) is performed! + var/generator_active_cost = 10 // Power used when turned on. + var/has_weapon = 1 + var/shield_active = 0 // If the shield gen is active. + var/energy_modifier = 25 // 40 damage absorbed per 1000 charge. If the charge used is > the cell's remaining charge, the excess is dealt to the user! + +/obj/item/device/personal_shield_generator/get_cell() + return bcell + +/obj/item/device/personal_shield_generator/New() //starts without a cell for rnd + ..() + if(ispath(bcell)) + bcell = new bcell(src) + + if(has_weapon) + if(ispath(active_weapon)) + active_weapon = new active_weapon(src, src) + active_weapon.power_supply = bcell + else + active_weapon = new(src, src) + active_weapon.power_supply = bcell + else + verbs -= /obj/item/device/personal_shield_generator/verb/weapon_toggle + update_icon() + +/obj/item/device/personal_shield_generator/Destroy() + . = ..() + QDEL_NULL(active_weapon) + QDEL_NULL(bcell) + +/obj/item/device/personal_shield_generator/loaded //starts with a cell + bcell = /obj/item/weapon/cell/device/weapon/recharge + + +/obj/item/device/personal_shield_generator/update_icon() + if(shield_active) + icon_state = "shield_back_active" + else + icon_state = "shield_pack" + +/obj/item/device/personal_shield_generator/examine(mob/user) + . = ..() + if(Adjacent(user)) + . += "The installed cell has has a power rating of [bcell.maxcharge] and is [round(bcell.percent() )]% charged ." + . += "It reads that it can take [bcell.charge/energy_modifier] more damage before the shield goes down." + if(bcell.self_recharge && bcell.charge_amount) + . += "This model is self charging and will take [bcell.maxcharge/bcell.charge_amount] seconds to fully charge from empty." + + +/* //This would be cool, but we need sprites. + cut_overlays() + + if(has_weapon && active_weapon && active_weapon.loc == src) //in case gun gets destroyed somehow. + add_overlay("[initial(icon_state)]-paddles") + if(bcell) + if(bcell.check_charge(generator_hit_cost)) //Can we take a blow? + add_overlay("[initial(icon_state)]-powered") + else if(has_weapon && active_weapon) + if(bcell.check_charge(active_weapon.charge_cost)) //We got enough to go pew pew? + add_overlay("[initial(icon_state)]-powered") + + var/ratio = CEILING(bcell.percent()/25, 1) * 25 + add_overlay("[initial(icon_state)]-charge[ratio]") + else + add_overlay("[initial(icon_state)]-nocell") +*/ + +/obj/item/device/personal_shield_generator/ui_action_click() + toggle_shield() + +/obj/item/device/personal_shield_generator/attack_hand(mob/user) + if(loc == user) + toggle_shield() + else + ..() + +/obj/item/device/personal_shield_generator/AltClick(mob/living/user) + weapon_toggle() + +/obj/item/device/personal_shield_generator/MouseDrop() + if(ismob(src.loc)) + if(!CanMouseDrop(src)) + return + var/mob/M = src.loc + if(!M.unEquip(src)) + return + src.add_fingerprint(usr) + M.put_in_any_hand_if_possible(src) + + +/obj/item/device/personal_shield_generator/attackby(obj/item/weapon/W, mob/user, params) //This should never happen unless admin spawns in an empty one. + if(W == active_weapon) + reattach_gun(user) + else if(istype(W, /obj/item/weapon/cell)) + if(bcell) + to_chat(user, "\The [src] already has a cell.") + else if(!istype(W, /obj/item/weapon/cell/device/weapon)) //Weapon cells only! + to_chat(user, "This cell will not fit in the device.") + else + if(!user.unEquip(W)) + return + W.forceMove(src) + bcell = W + to_chat(user, "You install a cell in \the [src].") + update_icon() + + else if(W.is_screwdriver()) + if(bcell) + if(istype(bcell, /obj/item/weapon/cell/device/weapon/recharge)) //No stealing self charging batteries! + to_chat(user, "You can not remove the cell from \the [src] without destroying the unit.") + return + else + bcell.update_icon() + bcell.forceMove(get_turf(src.loc)) + bcell = null + to_chat(user, "You remove the cell from \the [src].") + update_icon() + else + return ..() + +/* //TODO +/obj/item/device/personal_shield_generator/emag_act(var/remaining_charges, var/mob/user) + if(active_weapon) + . = active_weapon.emag_act(user) + update_icon() + return +*/ + +//Gun stuff + + +/obj/item/device/personal_shield_generator/verb/toggle_shield() + set name = "Toggle Shield" + set category = "Object" + + var/mob/living/carbon/human/user = usr + + if(user.last_special > world.time) + return + user.last_special = world.time + 10 //No spamming! + + if(!bcell || !bcell.check_charge(generator_hit_cost)) + to_chat(user, "You require a charged cell to do this!") + return + + if(!slot_check()) + to_chat(user, "You need to equip [src] before starting the shield up!") + return + else + if(shield_active) + shield_active = !shield_active //Deactivate the shield! + to_chat(user, "You deactive the shield!") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + STOP_PROCESSING(SSobj, src) + else + shield_active = !shield_active + to_chat(user, "You activate the shield!") + user.add_modifier(/datum/modifier/shield_projection) + START_PROCESSING(SSobj, src) //Let's only bother draining power when we're being used! + update_icon() + +/obj/item/device/personal_shield_generator/verb/weapon_toggle() //Make this work on Alt-Click + set name = "Toggle Gun" + set category = "Object" + + var/mob/living/carbon/human/user = usr + + if(user.last_special > world.time) + return + user.last_special = world.time + 10 //No spamming! + if(!active_weapon) + to_chat(user, "The gun is missing!") + return + + if(active_weapon.loc != src) + reattach_gun(user) //Remove from their hands and back onto the defib unit + return + + if(!slot_check()) + to_chat(user, "You need to equip [src] before taking out [active_weapon].") + else + if(!usr.put_in_hands(active_weapon)) //Detach the gun into the user's hands + to_chat(user, "You need a free hand to hold the gun!") + update_icon() //success + +/obj/item/device/personal_shield_generator/process() + if(shield_active) + bcell.use(generator_active_cost) + if(bcell.charge < generator_hit_cost) //Out of charge... + shield_active = 0 + if(istype(loc, /mob/living/carbon/human)) //We on someone? Tell them it turned off. + var/mob/living/carbon/human/user = loc + to_chat(user, "The shield deactivates.!") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + STOP_PROCESSING(SSobj, src) + + + +//checks that the base unit is in the correct slot to be used +/obj/item/device/personal_shield_generator/proc/slot_check() + var/mob/M = loc + if(!istype(M)) + return 0 //not equipped + + if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_back) == src) + return 1 + if((slot_flags & SLOT_BELT) && M.get_equipped_item(slot_belt) == src) + return 1 + //RIGSuit compatability. This shouldn't be possible, however, except for select RIGs. + if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_s_store) == src) + return 1 + if((slot_flags & SLOT_BELT) && M.get_equipped_item(slot_s_store) == src) + return 1 + + return 0 + +/obj/item/device/personal_shield_generator/dropped(mob/user) + ..() + reattach_gun(user) //A gun attached to a base unit should never exist outside of their base unit or the mob equipping the base unit + +/obj/item/device/personal_shield_generator/proc/reattach_gun(mob/user) + if(!active_weapon) return + + if(ismob(active_weapon.loc)) + var/mob/M = active_weapon.loc + if(M.drop_from_inventory(active_weapon, src)) + to_chat(user, "\The [active_weapon] snaps back into the main unit.") + else + active_weapon.forceMove(src) + + update_icon() + +/* + Base Unit Subtypes +*/ + +/obj/item/device/personal_shield_generator/belt + name = "personal shield generator" + desc = "A personal shield generator." + icon_state = "shield_back_active" + item_state = "shield_pack" + w_class = ITEMSIZE_LARGE //No putting these in backpacks! + slot_flags = SLOT_BELT + origin_tech = list(TECH_BIO = 5, TECH_POWER = 3) + has_weapon = 0 //No gun with the belt! + +/obj/item/device/personal_shield_generator/belt/loaded + bcell = /obj/item/weapon/cell/device/weapon/recharge + +/obj/item/device/personal_shield_generator/belt/update_icon() + if(shield_active) + icon_state = "shield_back_active" + else + icon_state = "shield_pack" + + +//The gun + +/obj/item/weapon/gun/energy/gun/generator //The gun attached to the personal shield generator. + name = "energy gun" + desc = "Another bestseller of Lawson Arms, the LAEP80 Thor is a versatile energy based pistol, capable of switching between low and high \ + capacity projectile settings. In other words: Stun or Kill." + description_fluff = "Lawson Arms is Hephaestus Industries’ main personal-energy-weapon branding, often sold alongside MarsTech projectile \ + weapons to security and law enforcement agencies." + icon_state = "egunstun" + item_state = null //so the human update icon uses the icon_state instead. + fire_delay = 8 + use_external_power = TRUE + cell_type = null //No cell! It runs off the cell in the shield_gen! + + projectile_type = /obj/item/projectile/beam/stun/med + modifystate = "egunstun" + + firemodes = list( + list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun/med, modifystate="egunstun", fire_sound='sound/weapons/Taser.ogg', charge_cost = 240), + list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="egunkill", fire_sound='sound/weapons/Laser.ogg', charge_cost = 480), + ) //Zero charge_cost since it's handled per shot. + + var/obj/item/device/personal_shield_generator/shield_generator //The generator we are linked to! + var/wielded = 0 + var/cooldown = 0 + var/busy = 0 + +/obj/item/weapon/gun/energy/gun/generator/New(newloc, obj/item/device/personal_shield_generator/shield_gen) + ..(newloc) + shield_generator = shield_gen + power_supply = shield_generator.bcell + +/* //Unused. Use for large guns. +/obj/item/weapon/gun/energy/gun/generator/update_held_icon() + var/mob/living/M = loc + if(istype(M) && M.item_is_in_hands(src) && !M.hands_are_full()) + wielded = 1 + name = "[initial(name)] (wielded)" + else + wielded = 0 + name = initial(name) + update_icon() + ..() +*/ + +/obj/item/weapon/gun/energy/gun/generator/proc/can_use(mob/user, mob/M) + if(busy) + return 0 + if(!check_charge(charge_cost)) + to_chat(user, "\The [src] doesn't have enough charge left to do that.") + return 0 + if(!wielded && !isrobot(user)) + to_chat(user, "You need to wield the gun with both hands before you can use it on someone!") + return 0 + if(cooldown) + to_chat(user, "\The [src] are re-energizing!") + return 0 + return 1 + +/* //TODO: Emp act. +/obj/item/weapon/shockpaddles/emp_act(severity) + var/new_safety = rand(0, 1) + if(safety != new_safety) + safety = new_safety + if(safety) + make_announcement("beeps, \"Safety protocols enabled!\"", "notice") + playsound(src, 'sound/machines/defib_safetyon.ogg', 50, 0) + else + make_announcement("beeps, \"Safety protocols disabled!\"", "warning") + playsound(src, 'sound/machines/defib_safetyoff.ogg', 50, 0) + update_icon() + ..() +*/ + +/obj/item/weapon/gun/energy/gun/generator/dropped(mob/user) + ..() //update twohanding + if(shield_generator) + shield_generator.reattach_gun(user) + +/obj/item/weapon/gun/energy/proc/check_charge(var/charge_amt) //In case using any other guns. + return 0 + +/obj/item/weapon/gun/energy/proc/checked_use(var/charge_amt) //In case using any other guns. + return 0 + +/obj/item/weapon/gun/energy/gun/generator/check_charge(var/charge_amt) + return (shield_generator.bcell && shield_generator.bcell.check_charge(charge_amt)) + +/obj/item/weapon/gun/energy/gun/generator/checked_use(var/charge_amt) + return (shield_generator.bcell && shield_generator.bcell.checked_use(charge_amt)) \ No newline at end of file diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index 56422efdf66..2fc4ef03e3f 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -64,6 +64,10 @@ var/siemens_coefficient = null // Similar to above two vars but 0 = full protection, to be consistant with siemens numbers everywhere else. var/vision_flags // Vision flags to add to the mob. SEE_MOB, SEE_OBJ, etc. + var/energy_based // Sees if the modifier is based on something electronic based. + var/energy_cost // How much the modifier uses per action/special effect blocked. For base values. + var/energy_modifier // How much energy is used when numbers are involed. For values, such as taking damage. Ex: (Damage*energy_modifier) + var/obj/item/weapon/cell/energy_source = null // The source of the above. /datum/modifier/New(var/new_holder, var/new_origin) holder = new_holder diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index a56bc5d2e0a..ab486c3b705 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -30,4 +30,70 @@ if(water_floor.depth < 1) //You're not in deep enough water anymore. expire(silent = FALSE) else - expire(silent = FALSE) \ No newline at end of file + expire(silent = FALSE) + + + + + + + + + +/datum/modifier/shield_projection + name = "Shield Projection" + desc = "You are currently protected by a shield, rendering nigh impossible to hit you through conventional means." + + on_created_text = "Your shield generator buzzes on." + on_expired_text = "Your shield generator buzzes off." + mob_overlay_state = "repel_missiles" //Looks alright, I guess. Placeholder. + stacks = MODIFIER_STACK_FORBID //No stacking shields. If you put one one your belt and backpack it won't work. + + siemens_coefficient = 2 //Stun weapons drain 100% charge per damage. They're good at blocking lasers and bullets but not good at blocking stun beams! + incoming_brute_damage_percent = 0 + incoming_fire_damage_percent = 0 + incoming_hal_damage_percent = 0 + energy_based = 1 + energy_cost = 99999 //This is changed to the shield_genertor's energy_cost. + energy_modifier = 50 //This is how much battery is used per damage unit absorbed. Higher damage means higher charge use per damage absorbed. Changed below! + var/obj/item/device/personal_shield_generator/shield_generator //This is the shield generator you're wearing! + + +/datum/modifier/shield_projection/on_applied() + return + +/datum/modifier/shield_projection/on_expire() + return + +/datum/modifier/shield_projection/check_if_valid() //Let's check to make sure you got the stuff and set the vars. + if(ishuman(holder)) //Only humans can use this! + var/mob/living/carbon/human/H = holder + if(istype(H.get_equipped_item(slot_back), /obj/item/device/personal_shield_generator)) + shield_generator = H.get_equipped_item(slot_back) //Sets the var on the modifier that the shield gen is their back shield gen. + energy_source = shield_generator.bcell + energy_cost = shield_generator.generator_hit_cost + energy_modifier = shield_generator.energy_modifier + else if(istype(H.get_equipped_item(slot_belt), /obj/item/device/personal_shield_generator)) + shield_generator = H.get_equipped_item(slot_belt) //No need for other checks. If they got hit by this, they just turned it on. + energy_source = shield_generator.bcell + energy_cost = shield_generator.generator_hit_cost + energy_modifier = shield_generator.energy_modifier + else if(istype(H.get_equipped_item(slot_s_store), /obj/item/device/personal_shield_generator) ) //Rigsuits. + shield_generator = H.get_equipped_item(slot_s_store) + energy_source = shield_generator.bcell + energy_cost = shield_generator.generator_hit_cost + energy_modifier = shield_generator.energy_modifier + else + expire(silent = TRUE) + else + expire(silent = TRUE) + +/datum/modifier/shield_projection/tick() //When the shield generator runs out of charge, it'll remove this naturally. + if(holder.stat == DEAD) + expire(silent = TRUE) //If you're dead the generator stops protecting you but keeps running. + if(!shield_generator || !shield_generator.slot_check()) //No shield to begin with/shield is not on them any longer. + expire(silent = FALSE) + var/shield_efficiency = 1-(energy_source.charge/energy_source.maxcharge) //0 = complete resistance. 1 = no resistance. + incoming_brute_damage_percent = shield_efficiency //Less charge means less resistance! + incoming_fire_damage_percent = shield_efficiency + incoming_hal_damage_percent = shield_efficiency \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index a3554a262f7..e3aa906bf83 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -115,8 +115,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_brute_damage_percent if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(amount, 0) @@ -133,8 +137,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_fire_damage_percent if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(0, amount) @@ -153,8 +161,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_brute_damage_percent if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) @@ -175,8 +187,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_fire_damage_percent if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) @@ -497,8 +513,12 @@ This function restores all organs. for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*damage) damage *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*damage) damage *= M.incoming_brute_damage_percent if(organ.take_damage(damage, 0, sharp, edge, used_weapon)) @@ -510,8 +530,12 @@ This function restores all organs. for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*damage) damage *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*damage) damage *= M.incoming_fire_damage_percent if(organ.take_damage(0, damage, sharp, edge, used_weapon)) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 1988405272f..ce93ed26472 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -37,6 +37,18 @@ emp_act var/armor = getarmor_organ(organ, "bullet") if(!prob(armor/2)) //Even if the armor doesn't stop the bullet from hurting you, it might stop it from embedding. var/hit_embed_chance = P.embed_chance + (P.damage - armor) //More damage equals more chance to embed + + //Modifiers can make bullets less likely to embed! + for(var/datum/modifier/M in modifiers) + if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_cost) //We use energy_cost here for special effects, such as embedding. + hit_embed_chance = hit_embed_chance*M.incoming_damage_percent + if(P.damage_type == BRUTE && (!isnull(M.incoming_brute_damage_percent))) + if(M.energy_based) + M.energy_source.use(M.energy_cost) + hit_embed_chance = hit_embed_chance*M.incoming_brute_damage_percent + if(prob(max(hit_embed_chance, 0))) var/obj/item/weapon/material/shard/shrapnel/SP = new() SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index cc0d773af26..2fe479ccafc 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -192,8 +192,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_brute_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -219,8 +223,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_oxy_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_oxy_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -243,8 +251,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_tox_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_tox_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -273,8 +285,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_fire_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -298,8 +314,12 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_clone_damage_percent)) + if(M.energy_based) + M.energy_source.use(M.energy_modifier*amount) amount *= M.incoming_clone_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -331,6 +351,9 @@ if(status_flags & GODMODE) return 0 //godmode if(amount > 0) for(var/datum/modifier/M in modifiers) + if(M.energy_based && (!isnull(M.incoming_hal_damage_percent) || !isnull(M.disable_duration_percent))) + M.energy_source.use(M.energy_modifier*amount) // Cost of the Damage absorbed. + M.energy_source.use(M.energy_cost) // Cost of the Effect absorbed. if(!isnull(M.incoming_damage_percent)) amount *= M.incoming_damage_percent if(!isnull(M.incoming_hal_damage_percent)) diff --git a/icons/obj/items_vr.dmi b/icons/obj/items_vr.dmi index ca82649d88380c434e50a0941c6be35a551134d5..2c2758763cc471bd73d670d234a6698b05fafb12 100644 GIT binary patch literal 6797 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 D@Y(AF literal 5259 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 diff --git a/vorestation.dme b/vorestation.dme index fb34f310a1c..91f03dda54f 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1199,6 +1199,7 @@ #include "code\game\objects\items\devices\multitool.dm" #include "code\game\objects\items\devices\paicard.dm" #include "code\game\objects\items\devices\paicard_vr.dm" +#include "code\game\objects\items\devices\personal_shield_generator_vr.dm" #include "code\game\objects\items\devices\pipe_painter.dm" #include "code\game\objects\items\devices\powersink.dm" #include "code\game\objects\items\devices\spy_bug.dm" From e4bb0438d0fa28e3a4786fdcaa27c563c281392b Mon Sep 17 00:00:00 2001 From: "C.L" Date: Sat, 10 Sep 2022 01:16:06 -0400 Subject: [PATCH 02/17] Variation! Fixes some exploits - Makes it so you can't remove the cell and keep firing the gun. - Makes the modifier addition be a var so you can have it do variants! - Adds a check so you can't take your gun out if the generator doesn't have a cell. --- .../items/devices/personal_shield_generator_vr.dm | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index cff54a33d53..5089bc68f56 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -21,6 +21,7 @@ var/has_weapon = 1 var/shield_active = 0 // If the shield gen is active. var/energy_modifier = 25 // 40 damage absorbed per 1000 charge. If the charge used is > the cell's remaining charge, the excess is dealt to the user! + var/modifier_type = /datum/modifier/shield_projection //What type of modifier will it add? Used for variant modifiers! /obj/item/device/personal_shield_generator/get_cell() return bcell @@ -119,6 +120,8 @@ return W.forceMove(src) bcell = W + if(active_weapon) + active_weapon.power_supply = bcell to_chat(user, "You install a cell in \the [src].") update_icon() @@ -131,6 +134,9 @@ bcell.update_icon() bcell.forceMove(get_turf(src.loc)) bcell = null + if(active_weapon) + reattach_gun() //Put the gun back if it's out. No shooting if we don't have a cell! + active_weapon.power_supply = null //No power cell anymore! to_chat(user, "You remove the cell from \the [src].") update_icon() else @@ -173,7 +179,8 @@ else shield_active = !shield_active to_chat(user, "You activate the shield!") - user.add_modifier(/datum/modifier/shield_projection) + user.remove_modifiers_of_type(/datum/modifier/shield_projection) //Just to make sure they aren't using two at once! + user.add_modifier(modifier_type) //TESTING. START_PROCESSING(SSobj, src) //Let's only bother draining power when we're being used! update_icon() @@ -186,10 +193,15 @@ if(user.last_special > world.time) return user.last_special = world.time + 10 //No spamming! + if(!active_weapon) to_chat(user, "The gun is missing!") return + if(!bcell) + to_chat(user, "The gun requires a power supply!") + return + if(active_weapon.loc != src) reattach_gun(user) //Remove from their hands and back onto the defib unit return From 937026bd90e4b8630ae58932d62bf3801fb11ee2 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Sun, 11 Sep 2022 04:24:26 -0400 Subject: [PATCH 03/17] Massive changes. - Changes how it mitigates damage. - It now only affects external attacks (punches, mobs, items, guns, etc.) - Now is PRE armor mitigation! https://i.imgur.com/CXx82J5.png - Adds variants. Allows mobs to use the new variants, but not the pack itself. - Adds an extended description and fluff text. - Adds ability to have both min&max for each variable. I still need to make them have specialized recharging batteries (especially for the belt unit), but currently the normal recharging batteries are fine. --- .../devices/personal_shield_generator_vr.dm | 119 ++++++++----- code/modules/examine/descriptions/devices.dm | 16 +- code/modules/mob/_modifiers/modifiers.dm | 39 +++++ code/modules/mob/_modifiers/modifiers_vr.dm | 162 ++++++++++++++++-- .../mob/living/carbon/human/human_damage.dm | 48 +++++- .../mob/living/carbon/human/human_defense.dm | 2 +- code/modules/mob/living/damage_procs.dm | 48 ++++++ 7 files changed, 372 insertions(+), 62 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 5089bc68f56..4cd30f98fe6 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -16,9 +16,9 @@ var/obj/item/weapon/gun/energy/gun/generator/active_weapon var/obj/item/weapon/cell/device/bcell = null - var/generator_hit_cost = 100 // Power used when a special effect (such as a bullet being blocked) is performed! + var/generator_hit_cost = 100 // Power used when a special effect (such as a bullet being blocked) is performed! Could also be expanded to other things. var/generator_active_cost = 10 // Power used when turned on. - var/has_weapon = 1 + var/has_weapon = 1 // Backpack units generally have weapons. var/shield_active = 0 // If the shield gen is active. var/energy_modifier = 25 // 40 damage absorbed per 1000 charge. If the charge used is > the cell's remaining charge, the excess is dealt to the user! var/modifier_type = /datum/modifier/shield_projection //What type of modifier will it add? Used for variant modifiers! @@ -107,7 +107,7 @@ M.put_in_any_hand_if_possible(src) -/obj/item/device/personal_shield_generator/attackby(obj/item/weapon/W, mob/user, params) //This should never happen unless admin spawns in an empty one. +/obj/item/device/personal_shield_generator/attackby(obj/item/weapon/W, mob/user, params) if(W == active_weapon) reattach_gun(user) else if(istype(W, /obj/item/weapon/cell)) @@ -260,38 +260,11 @@ update_icon() -/* - Base Unit Subtypes -*/ - -/obj/item/device/personal_shield_generator/belt - name = "personal shield generator" - desc = "A personal shield generator." - icon_state = "shield_back_active" - item_state = "shield_pack" - w_class = ITEMSIZE_LARGE //No putting these in backpacks! - slot_flags = SLOT_BELT - origin_tech = list(TECH_BIO = 5, TECH_POWER = 3) - has_weapon = 0 //No gun with the belt! - -/obj/item/device/personal_shield_generator/belt/loaded - bcell = /obj/item/weapon/cell/device/weapon/recharge - -/obj/item/device/personal_shield_generator/belt/update_icon() - if(shield_active) - icon_state = "shield_back_active" - else - icon_state = "shield_pack" - - //The gun /obj/item/weapon/gun/energy/gun/generator //The gun attached to the personal shield generator. - name = "energy gun" - desc = "Another bestseller of Lawson Arms, the LAEP80 Thor is a versatile energy based pistol, capable of switching between low and high \ - capacity projectile settings. In other words: Stun or Kill." - description_fluff = "Lawson Arms is Hephaestus Industries’ main personal-energy-weapon branding, often sold alongside MarsTech projectile \ - weapons to security and law enforcement agencies." + name = "generator gun" + desc = "A gun that is attached to the battery of the personal shield generator." icon_state = "egunstun" item_state = null //so the human update icon uses the icon_state instead. fire_delay = 8 @@ -304,7 +277,7 @@ firemodes = list( list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun/med, modifystate="egunstun", fire_sound='sound/weapons/Taser.ogg', charge_cost = 240), list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="egunkill", fire_sound='sound/weapons/Laser.ogg', charge_cost = 480), - ) //Zero charge_cost since it's handled per shot. + ) var/obj/item/device/personal_shield_generator/shield_generator //The generator we are linked to! var/wielded = 0 @@ -344,17 +317,7 @@ return 1 /* //TODO: Emp act. -/obj/item/weapon/shockpaddles/emp_act(severity) - var/new_safety = rand(0, 1) - if(safety != new_safety) - safety = new_safety - if(safety) - make_announcement("beeps, \"Safety protocols enabled!\"", "notice") - playsound(src, 'sound/machines/defib_safetyon.ogg', 50, 0) - else - make_announcement("beeps, \"Safety protocols disabled!\"", "warning") - playsound(src, 'sound/machines/defib_safetyoff.ogg', 50, 0) - update_icon() +/obj/item/weapon/gun/energy/gun/generator/emp_act(severity) ..() */ @@ -373,4 +336,70 @@ return (shield_generator.bcell && shield_generator.bcell.check_charge(charge_amt)) /obj/item/weapon/gun/energy/gun/generator/checked_use(var/charge_amt) - return (shield_generator.bcell && shield_generator.bcell.checked_use(charge_amt)) \ No newline at end of file + return (shield_generator.bcell && shield_generator.bcell.checked_use(charge_amt)) + + + +//VARIANTS. + +/obj/item/device/personal_shield_generator/belt + name = "personal shield generator" + desc = "A personal shield generator." + icon_state = "shield_back_active" + item_state = "shield_pack" + w_class = ITEMSIZE_LARGE //No putting these in backpacks! + slot_flags = SLOT_BELT + origin_tech = list(TECH_BIO = 5, TECH_POWER = 3) + has_weapon = 0 //No gun with the belt! + +/obj/item/device/personal_shield_generator/belt/loaded + bcell = /obj/item/weapon/cell/device/weapon/recharge + +/obj/item/device/personal_shield_generator/belt/update_icon() + if(shield_active) + icon_state = "shield_back_active" + else + icon_state = "shield_pack" + +/obj/item/device/personal_shield_generator/belt/bruteburn //Example of a modified generator. + modifier_type = /datum/modifier/shield_projection/bruteburn +/obj/item/device/personal_shield_generator/belt/bruteburn/loaded //If mapped in, ONLY put loaded ones down. + bcell = /obj/item/weapon/cell/device/weapon/recharge + +/obj/item/device/personal_shield_generator/belt/mining + name = "mining personal shield generator" + desc = "A personal shield generator designed for mining. It has a warning on the back: 'Do NOT expose the shield to stun-based weaponry.'" + modifier_type = /datum/modifier/shield_projection/mining + +/obj/item/device/personal_shield_generator/belt/mining/loaded + bcell = /obj/item/weapon/cell/device/weapon/recharge + +/obj/item/device/personal_shield_generator/belt/security + name = "security personal shield generator" + desc = "A personal shield generator designed for security." + modifier_type = /datum/modifier/shield_projection/security/weak + +/obj/item/device/personal_shield_generator/belt/security/loaded + bcell = /obj/item/weapon/cell/device/weapon/recharge + +/* +/obj/item/device/personal_shield_generator/belt/mining/attackby(obj/item/weapon/W, mob/user, params) + if(modifier_type == /datum/modifier/shield_projection/mining/strong)) + to_chat(user, "This shield generator is already upgraded!") + return + if(istype(W, /obj/item/borg/upgrade/modkit/shield_upgrade)) + modifier_type = /datum/modifier/shield_projection/mining/strong + drop_from_inventory(W) + qdel(W) + else + ..() +*/ + +/obj/item/device/personal_shield_generator/belt/adminbus + desc = "You should not see this. You REALLY should not see this. If you do, you have either been blessed or are about to be the target of some sick prank." + modifier_type = /datum/modifier/shield_projection/admin + generator_hit_cost = 0 + generator_active_cost = 0 + shield_active = 0 + energy_modifier = 0 + bcell = /obj/item/weapon/cell/device/weapon/recharge \ No newline at end of file diff --git a/code/modules/examine/descriptions/devices.dm b/code/modules/examine/descriptions/devices.dm index 7b5c0019a43..35933facf69 100644 --- a/code/modules/examine/descriptions/devices.dm +++ b/code/modules/examine/descriptions/devices.dm @@ -29,4 +29,18 @@ /obj/item/device/assembly/electronic_assembly description_info = "This is the casing for the 'device' type of electronic assembly. It behaves like any other 'assembly' type device such as an igniter or signaler \ - and can be attached to others in the same way. Use the 'toggle-open' verb (right click) or a crowbar to pop the electronic device open to add components and close when finished." \ No newline at end of file + and can be attached to others in the same way. Use the 'toggle-open' verb (right click) or a crowbar to pop the electronic device open to add components and close when finished." + +/obj/item/device/personal_shield_generator + description_info = "This is a personal shield generator. Depending on the type, it can either be worn on your backpack slot, your belt slot, or in a rigsuit \ + storage slot. It runs on an internal battery, which is usually self-charging. Some versions come with a gun. To active the shield, click the button in the upper \ + right of the screen, use the 'Toggle Shield' command under your objects tab, or click the device itself while it is on you. Some units come with an active weapon \ + which can be taken out at any time by Alt-clicking the device. If the device requires a cell, a screwdriver can be used. The shield slowly drains charge while \ + active and becomes weaker with each individual strike taken." + + description_fluff = "A relatively new invention, made in a collaboration between Hephaestus Industries and a startup known as Kuznetsova Enterprise in the year \ + 2322. Numerous variants of the device have been made for specific tasks, ranging from riot control, mining, biohazard containment, and search and rescue, among \ + others. Most of the devices share the flaw that electrical attacks can easily overload the device and cause a shield failure, encouraging combatants to swap to \ + the use of stun-based electric weaponry when shield generators are in use. Most shield devices are self-charging, running off a micro-nuclear reactor built into \ + the chassis itself, although some variants exist without this capability and can have normal cells inserted into them. Larger units boast the capability of \ + storing a weapon, although without upgraded batteries the usage of said weapon is ill-advised." \ No newline at end of file diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index 2fc4ef03e3f..7b68c41691e 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -64,11 +64,50 @@ var/siemens_coefficient = null // Similar to above two vars but 0 = full protection, to be consistant with siemens numbers everywhere else. var/vision_flags // Vision flags to add to the mob. SEE_MOB, SEE_OBJ, etc. + + + // ENERGY CODE. Variables to allow for energy based modifiers. var/energy_based // Sees if the modifier is based on something electronic based. var/energy_cost // How much the modifier uses per action/special effect blocked. For base values. var/energy_modifier // How much energy is used when numbers are involed. For values, such as taking damage. Ex: (Damage*energy_modifier) var/obj/item/weapon/cell/energy_source = null // The source of the above. + // RESISTANCES CODE. Variable to enable external damage resistance modifiers. This is not unlike armor. + // 0 = immune || < 0 = heals || 1 = full damage || >1 = increased damage. + // It should never be below zero as it is not intended to do such, but you are free to experiment! + // Ex: Max_brute_resistance = 0. Min_brute resistance = 1. When started, provides 100% resistance to brute. When cell is dying, goes down to 0% resistance. + // Max is the MAXIMUM % multiplier that will be taken at a low charge. Min is the MINIMUM % multiplier that will be taken at a full charge. + // Think of it like this: Minimum = what happens at minimum charge. Max = what happens at maximum charge. + // Why do I mention this so much? Because even /I/ got confused, and I wrote this thing! + var/min_damage_resistance + var/max_damage_resistance + var/effective_damage_resistance + + var/min_brute_resistance + var/max_brute_resistance + var/effective_brute_resistance + + var/min_fire_resistance + var/max_fire_resistance + var/effective_fire_resistance + + var/min_tox_resistance + var/max_tox_resistance + var/effective_tox_resistance + + var/min_oxy_resistance + var/max_oxy_resistance + var/effective_oxy_resistance + + var/min_clone_resistance + var/max_clone_resistance + var/effective_clone_resistance + + var/min_hal_resistance + var/max_hal_resistance + var/effective_hal_resistance + // Resistances end + /datum/modifier/New(var/new_holder, var/new_origin) holder = new_holder if(new_origin) diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index ab486c3b705..10bb048a839 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -46,27 +46,51 @@ on_created_text = "Your shield generator buzzes on." on_expired_text = "Your shield generator buzzes off." - mob_overlay_state = "repel_missiles" //Looks alright, I guess. Placeholder. + mob_overlay_state = "repel_missiles" //Looks actually pretty good. Could use a better sprite, but that'll work! stacks = MODIFIER_STACK_FORBID //No stacking shields. If you put one one your belt and backpack it won't work. - siemens_coefficient = 2 //Stun weapons drain 100% charge per damage. They're good at blocking lasers and bullets but not good at blocking stun beams! - incoming_brute_damage_percent = 0 - incoming_fire_damage_percent = 0 - incoming_hal_damage_percent = 0 + siemens_coefficient = 2 //Stun weapons drain 100% charge per point of damage. They're good at blocking lasers and bullets but not good at blocking stun beams! energy_based = 1 - energy_cost = 99999 //This is changed to the shield_genertor's energy_cost. + energy_cost = 99999 //This is changed to the shield_generator's energy_cost. energy_modifier = 50 //This is how much battery is used per damage unit absorbed. Higher damage means higher charge use per damage absorbed. Changed below! + + //Not actually in use until effective resistances are set. Just here so it doesn't have to be placed down for all the variants. Less lines. + max_damage_resistance = 1 + max_brute_resistance = 1 + max_fire_resistance = 1 + max_tox_resistance = 1 + max_oxy_resistance = 1 + max_clone_resistance = 1 + max_hal_resistance = 1 + min_damage_resistance = 1 + min_brute_resistance = 1 + min_fire_resistance = 1 + min_tox_resistance = 1 + min_oxy_resistance = 1 + min_clone_resistance = 1 + min_hal_resistance = 1 + +/* // These are not set, but left here as an example. All three (min,max,effective) must be set or BAD THINGS will happen. + min_brute_resistance = 1 // Min = WHAT HAPPENS AT MINIMUM CHARGE + max_brute_resistance = 0 // MAX = WHAT HAPPENS AT MAXIMUM CHARGE + effective_brute_resistance = 1 //Just tells the game that it has vars. Done to use less checks. + + min_fire_resistance = 1 + max_fire_resistance = 0 + effective_fire_resistance = 1 + disable_duration_percent = 1 //THIS CAN ALSO BE USED! Don't be too afraid to use this one, but use it sparingly! +*/ var/obj/item/device/personal_shield_generator/shield_generator //This is the shield generator you're wearing! -/datum/modifier/shield_projection/on_applied() +/datum/modifier/shield_projection/on_applied() //Don't need to modify this! return -/datum/modifier/shield_projection/on_expire() +/datum/modifier/shield_projection/on_expire() //Don't need to modify this! return -/datum/modifier/shield_projection/check_if_valid() //Let's check to make sure you got the stuff and set the vars. - if(ishuman(holder)) //Only humans can use this! +/datum/modifier/shield_projection/check_if_valid() //Let's check to make sure you got the stuff and set the vars. Don't need to modify this for any subtypes! + if(ishuman(holder)) //Only humans can use this! Other things later down the line might use the same stuff this does, but the shield generator is human only! var/mob/living/carbon/human/H = holder if(istype(H.get_equipped_item(slot_back), /obj/item/device/personal_shield_generator)) shield_generator = H.get_equipped_item(slot_back) //Sets the var on the modifier that the shield gen is their back shield gen. @@ -93,7 +117,117 @@ expire(silent = TRUE) //If you're dead the generator stops protecting you but keeps running. if(!shield_generator || !shield_generator.slot_check()) //No shield to begin with/shield is not on them any longer. expire(silent = FALSE) - var/shield_efficiency = 1-(energy_source.charge/energy_source.maxcharge) //0 = complete resistance. 1 = no resistance. - incoming_brute_damage_percent = shield_efficiency //Less charge means less resistance! - incoming_fire_damage_percent = shield_efficiency - incoming_hal_damage_percent = shield_efficiency \ No newline at end of file + + var/shield_efficiency = (energy_source.charge/energy_source.maxcharge) //1 = complete resistance. 0 = no resistance. Must be adjusted for subtypes! + if(!isnull(effective_damage_resistance)) + effective_damage_resistance = min_damage_resistance + (max_damage_resistance - min_damage_resistance) * shield_efficiency + + if(!isnull(effective_brute_resistance)) + effective_brute_resistance = min_brute_resistance + (max_brute_resistance - min_brute_resistance) * shield_efficiency + + if(!isnull(effective_fire_resistance)) + effective_fire_resistance = min_fire_resistance + (max_fire_resistance - min_fire_resistance) * shield_efficiency + + if(!isnull(effective_tox_resistance)) + effective_tox_resistance = min_tox_resistance + (max_tox_resistance - min_tox_resistance) * shield_efficiency + + if(!isnull(effective_oxy_resistance)) + effective_oxy_resistance = min_oxy_resistance + (max_oxy_resistance - min_oxy_resistance) * shield_efficiency + + if(!isnull(effective_clone_resistance)) + effective_clone_resistance = min_clone_resistance + (max_clone_resistance - min_clone_resistance) * shield_efficiency + + if(!isnull(effective_hal_resistance)) + effective_hal_resistance = min_hal_resistance + (max_hal_resistance - min_hal_resistance) * shield_efficiency + +//Shield variants. + +//Simple. Goes from 100% resistance to 0% resistance depending on charge. +/datum/modifier/shield_projection/bruteburn + max_brute_resistance = 0 + effective_brute_resistance = 1 + + max_fire_resistance = 0 + effective_fire_resistance = 1 + +/datum/modifier/shield_projection/bruteburn/weak + max_brute_resistance = 0.5 + max_fire_resistance = 0.5 + +/datum/modifier/shield_projection/security // Security backpack. + max_brute_resistance = 0.5 + effective_brute_resistance = 1 + + max_fire_resistance = 0.5 + effective_fire_resistance = 1 + + max_hal_resistance = 0.5 + effective_hal_resistance = 1 + +/datum/modifier/shield_projection/security/weak // Security belt. + max_brute_resistance = 0.75 + max_fire_resistance = 0.75 + max_hal_resistance = 0.75 + +/datum/modifier/shield_projection/security/strong // Dunno. Upgraded variant of security backpack? + max_brute_resistance = 0.25 + max_fire_resistance = 0.25 + max_hal_resistance = 0.25 + siemens_coefficient = 1.5 //Not as weak as normal, but still weak. + +/datum/modifier/shield_projection/mining //Base mining belt. 25% resistance. + max_brute_resistance = 0.75 + effective_brute_resistance = 1 + + max_fire_resistance = 0.75 + effective_fire_resistance = 1 + + max_hal_resistance = 1.5 // No mobs should be shooting you with halloss. If this happens, it means you're using it wrong!!! + min_hal_resistance = 1.5 + effective_hal_resistance = 1 + + disable_duration_percent = 0.75 //Miners often come into contact with things that can stun them. + +/datum/modifier/shield_projection/mining/strong // Mining belt, but upgraded. Even weaker to halloss! Tasers WILL destroy you. Don't try to be superman. + max_brute_resistance = 0.5 + max_fire_resistance = 0.5 + disable_duration_percent = 0.5 + + max_hal_resistance = 2 + min_hal_resistance = 2 + +/datum/modifier/shield_projection/admin // Adminbus. + on_created_text = "Your shield generator activates and you feel the power of the tesla buzzing around you." + on_expired_text = "Your shield generator deactivates, leaving you feeling weak and vulnerable." + siemens_coefficient = 0 + disable_duration_percent = 0 + min_damage_resistance = 0 + max_damage_resistance = 0 + effective_damage_resistance = 0 + min_brute_resistance = 0 + max_brute_resistance = 0 + effective_brute_resistance = 0 + min_fire_resistance = 0 + max_fire_resistance = 0 + effective_fire_resistance = 0 + min_tox_resistance = 0 + max_tox_resistance = 0 + effective_tox_resistance = 0 + min_oxy_resistance = 0 + max_oxy_resistance = 0 + effective_oxy_resistance = 0 + min_clone_resistance = 0 + max_clone_resistance = 0 + effective_clone_resistance = 0 + min_hal_resistance = 0 + max_hal_resistance = 0 + effective_hal_resistance = 0 + +/datum/modifier/shield_projection/broken //For broken variants. Good if possible randomization is included for packs spawned on PoIs. + max_brute_resistance = 2 + min_brute_resistance = 2 + effective_brute_resistance = 1 + + max_fire_resistance = 2 + min_fire_resistance = 2 + effective_fire_resistance = 1 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index e3aa906bf83..be8577fb2fc 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -475,6 +475,53 @@ This function restores all organs. if(!def_zone) def_zone = ran_zone(def_zone) organ = get_organ(check_zone(def_zone)) + for(var/datum/modifier/M in modifiers) //MODIFIER STUFF. It's best to do this RIGHT before armor is calculated, so it's done here! This is the 'forcefield' defence. + if(damagetype == BRUTE && (!isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_brute_resistance + continue + if((damagetype == BURN || damagetype == ELECTROCUTE)&& (!isnull(M.effective_fire_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_fire_resistance + continue + if(damagetype == TOX && (!isnull(M.effective_tox_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_tox_resistance + continue + if(damagetype == OXY && (!isnull(M.effective_oxy_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_oxy_resistance + continue + if(damagetype == CLONE && (!isnull(M.effective_clone_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_clone_resistance + continue + if(damagetype == HALLOSS && (!isnull(M.effective_hal_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_hal_resistance + continue + if(damagetype == SEARING && (!isnull(M.effective_fire_resistance) || !isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + var/damage_mitigation = 0//Used for dual calculations. + if(!isnull(M.effective_fire_resistance)) + damage_mitigation += round((1/3)*damage * M.effective_fire_resistance) + if(!isnull(M.effective_brute_resistance)) + damage_mitigation += round((2/3)*damage * M.effective_brute_resistance) + damage -= damage_mitigation + continue + if(damagetype == BIOACID && (isSynthetic() && (!isnull(M.effective_fire_resistance))) || (!isSynthetic() && M.effective_tox_resistance)) + if(isSynthetic()) + damage = damage * M.effective_fire_resistance + else + damage = damage * M.effective_tox_resistance + continue //Handle other types of damage if((damagetype != BRUTE) && (damagetype != BURN)) if(damagetype == HALLOSS) @@ -504,7 +551,6 @@ This function restores all organs. if(Debug2) to_world_log("## DEBUG: [src] was hit for [damage].") - switch(damagetype) if(BRUTE) damageoverlaytemp = 20 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index ce93ed26472..1834c683e01 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -38,7 +38,7 @@ emp_act if(!prob(armor/2)) //Even if the armor doesn't stop the bullet from hurting you, it might stop it from embedding. var/hit_embed_chance = P.embed_chance + (P.damage - armor) //More damage equals more chance to embed - //Modifiers can make bullets less likely to embed! + //Modifiers can make bullets less likely to embed! These are the normal modifiers and shouldn't be related to energy stuff, but they can be anyways! for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 4eaab779266..a73b9818c20 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -13,6 +13,53 @@ to_world_log("## DEBUG: apply_damage() was called on [src], with [damage] damage, and an armor value of [blocked].") if(!damage || (blocked >= 100)) return 0 + for(var/datum/modifier/M in modifiers) //MODIFIER STUFF. It's best to do this RIGHT before armor is calculated, so it's done here! This is the 'forcefield' defence. + if(damagetype == BRUTE && (!isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_brute_resistance + continue + if((damagetype == BURN || damagetype == ELECTROCUTE)&& (!isnull(M.effective_fire_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_fire_resistance + continue + if(damagetype == TOX && (!isnull(M.effective_tox_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_tox_resistance + continue + if(damagetype == OXY && (!isnull(M.effective_oxy_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_oxy_resistance + continue + if(damagetype == CLONE && (!isnull(M.effective_clone_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_clone_resistance + continue + if(damagetype == HALLOSS && (!isnull(M.effective_hal_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + damage = damage * M.effective_hal_resistance + continue + if(damagetype == SEARING && (!isnull(M.effective_fire_resistance) || !isnull(M.effective_brute_resistance))) + if(M.energy_based) + M.energy_source.use(M.energy_modifier * damage) + var/damage_mitigation = 0//Used for dual calculations. + if(!isnull(M.effective_fire_resistance)) + damage_mitigation += round((1/3)*damage * M.effective_fire_resistance) + if(!isnull(M.effective_brute_resistance)) + damage_mitigation += round((2/3)*damage * M.effective_brute_resistance) + damage -= damage_mitigation + continue + if(damagetype == BIOACID && (isSynthetic() && (!isnull(M.effective_fire_resistance))) || (!isSynthetic() && M.effective_tox_resistance)) + if(isSynthetic()) + damage = damage * M.effective_fire_resistance + else + damage = damage * M.effective_tox_resistance + continue if(soaked) if(soaked >= round(damage*0.8)) damage -= round(damage*0.8) @@ -55,6 +102,7 @@ /mob/living/proc/apply_damages(var/brute = 0, var/burn = 0, var/tox = 0, var/oxy = 0, var/clone = 0, var/halloss = 0, var/def_zone = null, var/blocked = 0) if(blocked >= 100) return 0 + // INSERT MODIFIER CODE HERE... But no, really, only two things in the game use it, quad and viruses. The former is admin-only and the latter wouldn't be affected logically, but would if shield code was inerted here. If you really want, you can copy&paste the above and modify it to adjust brute/burn/etc. I do not advise this however. if(brute) apply_damage(brute, BRUTE, def_zone, blocked) if(burn) apply_damage(burn, BURN, def_zone, blocked) if(tox) apply_damage(tox, TOX, def_zone, blocked) From 7fbbee9782f99911598fe22bd0aa1adc50b36237 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Mon, 12 Sep 2022 03:39:40 -0400 Subject: [PATCH 04/17] More changes - Adds more variants - Adds personalized power cells for the shield generator. - Adds more variants. - Fixes a mixup of words. - Rebalances some of the modifiers to make it so they ramp up slower & have at least some effect when nearing the end of the charge. - Fixes a dividing by 0 bug on specialty shield generators, such as the 'parry' one. - Adds a huge text wall to explain this stuff to future people. - Power cells now take longer before starting to charge and now charge slower by default. --- .../devices/personal_shield_generator_vr.dm | 133 ++++++++++++++---- code/modules/mob/_modifiers/modifiers.dm | 2 +- code/modules/mob/_modifiers/modifiers_vr.dm | 63 ++++++++- 3 files changed, 160 insertions(+), 38 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 4cd30f98fe6..f542218b053 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -1,4 +1,18 @@ -//backpack item +// TO ANYBODY LOOKING AT THIS FILE: +// Everything is mostly commented on to give as much detailed information as possible. +// Some things may be difficult to understand, but every variable in here has a comment explaining what it is/does. +// The base unit, the 'personal_shield_generator' is a backpack, comes with a gun, and has normal numbers for everything. +// The belt units do NOT come with a gun and have a cell that is half the capacity of backpack units. +// These can be VERY, VERY, VERY strong if too many are handed out, the cell is too strong, or the modifier is too strong. +// Additionally, if you are mapping any of these in, ensure you map in the /loaded versions or else they won't have a battery. +// I have also made it so you can modify everything about them, including the modifier they give and the cell, which can be changed via mapping. + +// In essence, these can be viewed as an extra layer of armor that has upsides and downsides with more extensive features. +// Shield generators apply PRE armor. Ultimately this shouldn't matter too much, but it makes more sense this way. +// There are a good amount of variants in here, ranging from mining to security to misc ones. +// If you want to make a variant, you need to only change modifier_type and make the modifier desired. + + /obj/item/device/personal_shield_generator name = "personal shield generator" desc = "A personal shield generator." @@ -11,17 +25,19 @@ preserve_item = 1 w_class = ITEMSIZE_HUGE //It's a giant shield generator!!! unacidable = TRUE - origin_tech = list(TECH_BIO = 4, TECH_POWER = 2) //Set this to better stuff later. + origin_tech = list(TECH_MATERIAL = 6, TECH_COMBAT = 8, TECH_POWER = 6, TECH_DATA = 4) //These are limited AND high tech. Breaking one of them down is massive. action_button_name = "Toggle Shield" - var/obj/item/weapon/gun/energy/gun/generator/active_weapon var/obj/item/weapon/cell/device/bcell = null - var/generator_hit_cost = 100 // Power used when a special effect (such as a bullet being blocked) is performed! Could also be expanded to other things. - var/generator_active_cost = 10 // Power used when turned on. - var/has_weapon = 1 // Backpack units generally have weapons. - var/shield_active = 0 // If the shield gen is active. - var/energy_modifier = 25 // 40 damage absorbed per 1000 charge. If the charge used is > the cell's remaining charge, the excess is dealt to the user! - var/modifier_type = /datum/modifier/shield_projection //What type of modifier will it add? Used for variant modifiers! + + + var/generator_hit_cost = 100 // Power used when a special effect (such as a bullet being blocked) is performed! Could also be expanded to other things. + var/generator_active_cost = 10 // Power used when turned on. + var/energy_modifier = 25 // 40 damage absorbed per 1000 charge. + var/modifier_type = /datum/modifier/shield_projection // What type of modifier will it add? Used for variant modifiers! + + var/has_weapon = 1 // Backpack units generally have weapons. + var/shield_active = 0 // If the shield gen is active. /obj/item/device/personal_shield_generator/get_cell() return bcell @@ -48,7 +64,7 @@ QDEL_NULL(bcell) /obj/item/device/personal_shield_generator/loaded //starts with a cell - bcell = /obj/item/weapon/cell/device/weapon/recharge + bcell = /obj/item/weapon/cell/device/shield_generator/backpack /obj/item/device/personal_shield_generator/update_icon() @@ -60,8 +76,9 @@ /obj/item/device/personal_shield_generator/examine(mob/user) . = ..() if(Adjacent(user)) - . += "The installed cell has has a power rating of [bcell.maxcharge] and is [round(bcell.percent() )]% charged ." - . += "It reads that it can take [bcell.charge/energy_modifier] more damage before the shield goes down." + . += "The internal cell is [round(bcell.percent() )]% charged." + if(energy_modifier) //Prevention of dividing by 0 errors. + . += "It reads that it can take [bcell.charge/energy_modifier] more damage before the shield goes down." if(bcell.self_recharge && bcell.charge_amount) . += "This model is self charging and will take [bcell.maxcharge/bcell.charge_amount] seconds to fully charge from empty." @@ -127,7 +144,7 @@ else if(W.is_screwdriver()) if(bcell) - if(istype(bcell, /obj/item/weapon/cell/device/weapon/recharge)) //No stealing self charging batteries! + if(istype(bcell, /obj/item/weapon/cell/device/shield_generator)) //No stealing self charging batteries! to_chat(user, "You can not remove the cell from \the [src] without destroying the unit.") return else @@ -163,7 +180,7 @@ return user.last_special = world.time + 10 //No spamming! - if(!bcell || !bcell.check_charge(generator_hit_cost)) + if(!bcell || !bcell.check_charge(generator_hit_cost) || !bcell.check_charge(generator_active_cost)) to_chat(user, "You require a charged cell to do this!") return @@ -216,13 +233,13 @@ /obj/item/device/personal_shield_generator/process() if(shield_active) bcell.use(generator_active_cost) - if(bcell.charge < generator_hit_cost) //Out of charge... + if(bcell.charge < generator_hit_cost || bcell.charge < generator_active_cost) //Out of charge... shield_active = 0 if(istype(loc, /mob/living/carbon/human)) //We on someone? Tell them it turned off. var/mob/living/carbon/human/user = loc to_chat(user, "The shield deactivates.!") user.remove_modifiers_of_type(/datum/modifier/shield_projection) - STOP_PROCESSING(SSobj, src) + STOP_PROCESSING(SSobj, src) @@ -349,11 +366,10 @@ item_state = "shield_pack" w_class = ITEMSIZE_LARGE //No putting these in backpacks! slot_flags = SLOT_BELT - origin_tech = list(TECH_BIO = 5, TECH_POWER = 3) has_weapon = 0 //No gun with the belt! /obj/item/device/personal_shield_generator/belt/loaded - bcell = /obj/item/weapon/cell/device/weapon/recharge + bcell = /obj/item/weapon/cell/device/shield_generator /obj/item/device/personal_shield_generator/belt/update_icon() if(shield_active) @@ -364,23 +380,16 @@ /obj/item/device/personal_shield_generator/belt/bruteburn //Example of a modified generator. modifier_type = /datum/modifier/shield_projection/bruteburn /obj/item/device/personal_shield_generator/belt/bruteburn/loaded //If mapped in, ONLY put loaded ones down. - bcell = /obj/item/weapon/cell/device/weapon/recharge + bcell = /obj/item/weapon/cell/device/shield_generator +// Mining belts /obj/item/device/personal_shield_generator/belt/mining name = "mining personal shield generator" desc = "A personal shield generator designed for mining. It has a warning on the back: 'Do NOT expose the shield to stun-based weaponry.'" modifier_type = /datum/modifier/shield_projection/mining /obj/item/device/personal_shield_generator/belt/mining/loaded - bcell = /obj/item/weapon/cell/device/weapon/recharge - -/obj/item/device/personal_shield_generator/belt/security - name = "security personal shield generator" - desc = "A personal shield generator designed for security." - modifier_type = /datum/modifier/shield_projection/security/weak - -/obj/item/device/personal_shield_generator/belt/security/loaded - bcell = /obj/item/weapon/cell/device/weapon/recharge + bcell = /obj/item/weapon/cell/device/shield_generator /* /obj/item/device/personal_shield_generator/belt/mining/attackby(obj/item/weapon/W, mob/user, params) @@ -389,12 +398,24 @@ return if(istype(W, /obj/item/borg/upgrade/modkit/shield_upgrade)) modifier_type = /datum/modifier/shield_projection/mining/strong - drop_from_inventory(W) + user.drop_from_inventory(W) qdel(W) else ..() */ +//Security belts + +/obj/item/device/personal_shield_generator/belt/security + name = "security personal shield generator" + desc = "A personal shield generator designed for security." + modifier_type = /datum/modifier/shield_projection/security/weak + +/obj/item/device/personal_shield_generator/belt/security/loaded + bcell = /obj/item/weapon/cell/device/shield_generator + +//Misc belts. Admin-spawn only atm. + /obj/item/device/personal_shield_generator/belt/adminbus desc = "You should not see this. You REALLY should not see this. If you do, you have either been blessed or are about to be the target of some sick prank." modifier_type = /datum/modifier/shield_projection/admin @@ -402,4 +423,56 @@ generator_active_cost = 0 shield_active = 0 energy_modifier = 0 - bcell = /obj/item/weapon/cell/device/weapon/recharge \ No newline at end of file + bcell = /obj/item/weapon/cell/device/shield_generator + +/obj/item/device/personal_shield_generator/belt/parry //The 'provides one second of pure immunity to brute/burn/halloss' belt. + name = "personal shield generator variant-P" //Not meant to be used in any serious capacity. + desc = "A personal shield generator that sacrifices long-term usability in exchange for a strong, short-lived shield projection, enabling the user to be nigh \ + impervious for a second." + modifier_type = /datum/modifier/shield_projection/parry + generator_hit_cost = 0 //No cost for being hit. + energy_modifier = 0//No cost for blocking effects. + generator_active_cost = 100 //However, it disables the tick immediately after being turned on. + shield_active = 0 + bcell = /obj/item/weapon/cell/device/shield_generator/parry + +// Backpacks. These are meant to be MUCH stronger in exchange for the fact that you are giving up a backpack slot. +// HOWEVER, be careful with these. They come loaded with a gun in them, so they shouldn't be handed out willy-nilly. + +/obj/item/device/personal_shield_generator/security + name = "security personal shield generator" + desc = "A personal shield generator designed for security." + modifier_type = /datum/modifier/shield_projection/security + +/obj/item/device/personal_shield_generator/security/loaded + bcell = /obj/item/weapon/cell/device/shield_generator/backpack + +/obj/item/device/personal_shield_generator/security/strong + modifier_type = /datum/modifier/shield_projection/security/strong + +/obj/item/device/personal_shield_generator/security/strong/loaded + bcell = /obj/item/weapon/cell/device/shield_generator/backpack + + +//Power cells. +/obj/item/weapon/cell/device/shield_generator //The base power cell the shield gen comes with. + name = "shield generator battery" + desc = "A self charging battery which houses a micro-nuclear reactor. Takes a while to start charging." + maxcharge = 2400 + self_recharge = TRUE + charge_amount = 80 //After the charge_delay is over, charges the cell over 30 seconds. + charge_delay = 600 //Takes a minute before it starts to recharge. + +/obj/item/weapon/cell/device/shield_generator/backpack //The base power cell the backpack units come with. Double the charge vs the belt. + maxcharge = 4800 + +/obj/item/weapon/cell/device/shield_generator/upgraded //A stronger version of the normal cell. Double the maxcharge, halved charge time. + maxcharge = 4800 + charge_amount = 320 + charge_delay = 300 + +/obj/item/weapon/cell/device/shield_generator/parry //The cell for the 'parry' shield gen. + maxcharge = 100 + self_recharge = TRUE + charge_amount = 100 + charge_delay = 20 //Starts charging two seconds after it's discharged. \ No newline at end of file diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index 7b68c41691e..61380cbb646 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -76,7 +76,7 @@ // 0 = immune || < 0 = heals || 1 = full damage || >1 = increased damage. // It should never be below zero as it is not intended to do such, but you are free to experiment! // Ex: Max_brute_resistance = 0. Min_brute resistance = 1. When started, provides 100% resistance to brute. When cell is dying, goes down to 0% resistance. - // Max is the MAXIMUM % multiplier that will be taken at a low charge. Min is the MINIMUM % multiplier that will be taken at a full charge. + // Max is the MAXIMUM % multiplier that will be taken at a MAX charge. Min is the MINIMUM % multiplier that will be taken at a MINIMUM charge. // Think of it like this: Minimum = what happens at minimum charge. Max = what happens at maximum charge. // Why do I mention this so much? Because even /I/ got confused, and I wrote this thing! var/min_damage_resistance diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index 10bb048a839..24100efec1a 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -142,7 +142,7 @@ //Shield variants. -//Simple. Goes from 100% resistance to 0% resistance depending on charge. +//Simple. Goes from 100% resistance to 0% resistance depending on charge. This is mostly an example of a shield variant. /datum/modifier/shield_projection/bruteburn max_brute_resistance = 0 effective_brute_resistance = 1 @@ -154,19 +154,25 @@ max_brute_resistance = 0.5 max_fire_resistance = 0.5 -/datum/modifier/shield_projection/security // Security backpack. +//SECURITY VARIANTS +/datum/modifier/shield_projection/security // Security backpack. 50% resistance at full charge. 90% resistance for the last shot taken. max_brute_resistance = 0.5 + min_brute_resistance = 0.9 effective_brute_resistance = 1 max_fire_resistance = 0.5 + min_fire_resistance = 0.9 effective_fire_resistance = 1 max_hal_resistance = 0.5 + min_hal_resistance = 0.9 effective_hal_resistance = 1 /datum/modifier/shield_projection/security/weak // Security belt. max_brute_resistance = 0.75 + min_brute_resistance = 0.95 max_fire_resistance = 0.75 + min_fire_resistance = 0.95 max_hal_resistance = 0.75 /datum/modifier/shield_projection/security/strong // Dunno. Upgraded variant of security backpack? @@ -175,11 +181,15 @@ max_hal_resistance = 0.25 siemens_coefficient = 1.5 //Not as weak as normal, but still weak. -/datum/modifier/shield_projection/mining //Base mining belt. 25% resistance. - max_brute_resistance = 0.75 + +//MINING VARIANTS +/datum/modifier/shield_projection/mining //Base mining belt. 45% resistance that fades to 15% resistance + max_brute_resistance = 0.55 + min_brute_resistance = 0.85 effective_brute_resistance = 1 - max_fire_resistance = 0.75 + max_fire_resistance = 0.55 + min_brute_resistance = 0.85 effective_fire_resistance = 1 max_hal_resistance = 1.5 // No mobs should be shooting you with halloss. If this happens, it means you're using it wrong!!! @@ -188,14 +198,31 @@ disable_duration_percent = 0.75 //Miners often come into contact with things that can stun them. -/datum/modifier/shield_projection/mining/strong // Mining belt, but upgraded. Even weaker to halloss! Tasers WILL destroy you. Don't try to be superman. +/datum/modifier/shield_projection/mining/strong // Mining belt, but upgraded. Even weaker to halloss! It also scales from .5 to .75 instead of back to 1.0! max_brute_resistance = 0.5 + min_brute_resistance = 0.75 max_fire_resistance = 0.5 + min_fire_resistance = 0.75 disable_duration_percent = 0.5 max_hal_resistance = 2 min_hal_resistance = 2 +//MISC VARIANTS + +/datum/modifier/shield_projection/biohazard //The odd-ball damage types. Provides near-complete immunity while it's up. + min_tox_resistance = 0.25 + max_tox_resistance = 0 + effective_tox_resistance = 1 + + min_oxy_resistance = 0.25 + max_oxy_resistance = 0 + effective_oxy_resistance = 1 + + min_clone_resistance = 0.25 + max_clone_resistance = 0 + effective_clone_resistance = 1 + /datum/modifier/shield_projection/admin // Adminbus. on_created_text = "Your shield generator activates and you feel the power of the tesla buzzing around you." on_expired_text = "Your shield generator deactivates, leaving you feeling weak and vulnerable." @@ -230,4 +257,26 @@ max_fire_resistance = 2 min_fire_resistance = 2 - effective_fire_resistance = 1 \ No newline at end of file + effective_fire_resistance = 1 + +/datum/modifier/shield_projection/inverted //Becomes stronger the weaker the cell is. Means the last shot taken will be the weakest. Example just to show it can be done. + max_brute_resistance = 1 + min_brute_resistance = 0 + effective_brute_resistance = 1 + + max_fire_resistance = 1 + min_fire_resistance = 0 + effective_fire_resistance = 1 + +/datum/modifier/shield_projection/parry //Intended for 'parry' shields, which only last for a single second before running out of charge + max_brute_resistance = 0 + min_brute_resistance = 0 + effective_brute_resistance = 1 + + max_fire_resistance = 0 + min_fire_resistance = 0 + effective_fire_resistance = 1 + + max_hal_resistance = 0 + min_hal_resistance = 0 + effective_hal_resistance = 1 \ No newline at end of file From 7e63c498d4f3ce26eb205740e4bcf30c807b6f96 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Mon, 12 Sep 2022 23:53:12 -0400 Subject: [PATCH 05/17] Let's move you to prevent conflicts. --- code/modules/mob/_modifiers/modifiers.dm | 43 -------------------- code/modules/mob/_modifiers/modifiers_vr.dm | 45 +++++++++++++++++++++ 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/code/modules/mob/_modifiers/modifiers.dm b/code/modules/mob/_modifiers/modifiers.dm index 61380cbb646..56422efdf66 100644 --- a/code/modules/mob/_modifiers/modifiers.dm +++ b/code/modules/mob/_modifiers/modifiers.dm @@ -65,49 +65,6 @@ var/vision_flags // Vision flags to add to the mob. SEE_MOB, SEE_OBJ, etc. - - // ENERGY CODE. Variables to allow for energy based modifiers. - var/energy_based // Sees if the modifier is based on something electronic based. - var/energy_cost // How much the modifier uses per action/special effect blocked. For base values. - var/energy_modifier // How much energy is used when numbers are involed. For values, such as taking damage. Ex: (Damage*energy_modifier) - var/obj/item/weapon/cell/energy_source = null // The source of the above. - - // RESISTANCES CODE. Variable to enable external damage resistance modifiers. This is not unlike armor. - // 0 = immune || < 0 = heals || 1 = full damage || >1 = increased damage. - // It should never be below zero as it is not intended to do such, but you are free to experiment! - // Ex: Max_brute_resistance = 0. Min_brute resistance = 1. When started, provides 100% resistance to brute. When cell is dying, goes down to 0% resistance. - // Max is the MAXIMUM % multiplier that will be taken at a MAX charge. Min is the MINIMUM % multiplier that will be taken at a MINIMUM charge. - // Think of it like this: Minimum = what happens at minimum charge. Max = what happens at maximum charge. - // Why do I mention this so much? Because even /I/ got confused, and I wrote this thing! - var/min_damage_resistance - var/max_damage_resistance - var/effective_damage_resistance - - var/min_brute_resistance - var/max_brute_resistance - var/effective_brute_resistance - - var/min_fire_resistance - var/max_fire_resistance - var/effective_fire_resistance - - var/min_tox_resistance - var/max_tox_resistance - var/effective_tox_resistance - - var/min_oxy_resistance - var/max_oxy_resistance - var/effective_oxy_resistance - - var/min_clone_resistance - var/max_clone_resistance - var/effective_clone_resistance - - var/min_hal_resistance - var/max_hal_resistance - var/effective_hal_resistance - // Resistances end - /datum/modifier/New(var/new_holder, var/new_origin) holder = new_holder if(new_origin) diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index 24100efec1a..1f925a76b56 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -1,3 +1,48 @@ +/datum/modifier + // ENERGY CODE. Variables to allow for energy based modifiers. + var/energy_based // Sees if the modifier is based on something electronic based. + var/energy_cost // How much the modifier uses per action/special effect blocked. For base values. + var/energy_modifier // How much energy is used when numbers are involed. For values, such as taking damage. Ex: (Damage*energy_modifier) + var/obj/item/weapon/cell/energy_source = null // The source of the above. + + // RESISTANCES CODE. Variable to enable external damage resistance modifiers. This is not unlike armor. + // 0 = immune || < 0 = heals || 1 = full damage || >1 = increased damage. + // It should never be below zero as it is not intended to do such, but you are free to experiment! + // Ex: Max_brute_resistance = 0. Min_brute resistance = 1. When started, provides 100% resistance to brute. When cell is dying, goes down to 0% resistance. + // Max is the MAXIMUM % multiplier that will be taken at a MAX charge. Min is the MINIMUM % multiplier that will be taken at a MINIMUM charge. + // Think of it like this: Minimum = what happens at minimum charge. Max = what happens at maximum charge. + // Why do I mention this so much? Because even /I/ got confused, and I wrote this thing! + var/min_damage_resistance + var/max_damage_resistance + var/effective_damage_resistance + + var/min_brute_resistance + var/max_brute_resistance + var/effective_brute_resistance + + var/min_fire_resistance + var/max_fire_resistance + var/effective_fire_resistance + + var/min_tox_resistance + var/max_tox_resistance + var/effective_tox_resistance + + var/min_oxy_resistance + var/max_oxy_resistance + var/effective_oxy_resistance + + var/min_clone_resistance + var/max_clone_resistance + var/effective_clone_resistance + + var/min_hal_resistance + var/max_hal_resistance + var/effective_hal_resistance + // Resistances end + + + /datum/modifier/underwater_stealth name = "underwater stealth" desc = "You are currently underwater, rendering it more difficult to see you and enabling you to move quicker, thanks to your aquatic nature." From 82f916e3039c5acaef89286438a9eb4e524f65cc Mon Sep 17 00:00:00 2001 From: "C.L" Date: Mon, 12 Sep 2022 23:56:19 -0400 Subject: [PATCH 06/17] space --- code/modules/mob/living/carbon/human/human_damage.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index be8577fb2fc..42ced726ba8 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -481,7 +481,7 @@ This function restores all organs. M.energy_source.use(M.energy_modifier * damage) damage = damage * M.effective_brute_resistance continue - if((damagetype == BURN || damagetype == ELECTROCUTE)&& (!isnull(M.effective_fire_resistance))) + if((damagetype == BURN || damagetype == ELECTROCUTE) && (!isnull(M.effective_fire_resistance))) if(M.energy_based) M.energy_source.use(M.energy_modifier * damage) damage = damage * M.effective_fire_resistance @@ -551,6 +551,7 @@ This function restores all organs. if(Debug2) to_world_log("## DEBUG: [src] was hit for [damage].") + switch(damagetype) if(BRUTE) damageoverlaytemp = 20 From 9a8b6d5f27a6595d7fc5182b1b35803cbfc179a7 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Tue, 13 Sep 2022 00:14:03 -0400 Subject: [PATCH 07/17] Gave the belt a special sprite. --- .../devices/personal_shield_generator_vr.dm | 4 ++-- icons/obj/items_vr.dmi | Bin 6797 -> 6379 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index f542218b053..541eaa38cdb 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -373,9 +373,9 @@ /obj/item/device/personal_shield_generator/belt/update_icon() if(shield_active) - icon_state = "shield_back_active" + icon_state = "shield_belt_active" else - icon_state = "shield_pack" + icon_state = "shield_belt" /obj/item/device/personal_shield_generator/belt/bruteburn //Example of a modified generator. modifier_type = /datum/modifier/shield_projection/bruteburn diff --git a/icons/obj/items_vr.dmi b/icons/obj/items_vr.dmi index 2c2758763cc471bd73d670d234a6698b05fafb12..52da93a6b8a9c19f7336887d5412ec09634bfa9b 100644 GIT binary patch literal 6379 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 D@Y(AF From 254334e0339ff4605773d3818eafb1d00217be78 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Tue, 13 Sep 2022 03:42:44 -0400 Subject: [PATCH 08/17] More changes! - Adds ability for modifiers to use a custom _vr sprite file. - Changes the appearance of the sprite used for the shield overlay. - Adds ability to color the shield sprite via a multitool. - More fiddling with numbers... - Allows rechargers to recharge them to allow for non-recharging variants to recharge. - Gives shields a default 'cyan' color. - Adds a mining disk to the equipment vendor to upgrade it. --- code/game/machinery/recharger.dm | 2 +- .../devices/personal_shield_generator_vr.dm | 51 ++++++++++++++---- .../equipment_vendor.dm | 1 + code/modules/mob/_modifiers/modifiers_vr.dm | 43 ++++++++------- .../mob/living/carbon/human/update_icons.dm | 10 +++- icons/mob/modifier_effects_vr.dmi | Bin 0 -> 1128 bytes icons/obj/items_vr.dmi | Bin 6379 -> 7509 bytes 7 files changed, 77 insertions(+), 30 deletions(-) create mode 100644 icons/mob/modifier_effects_vr.dmi diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index ea2854480a8..f028cef8a2f 100644 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -10,7 +10,7 @@ active_power_usage = 40000 //40 kW var/efficiency = 40000 //will provide the modified power rate when upgraded var/obj/item/charging = null - var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/modular_computer, /obj/item/weapon/computer_hardware/battery_module, /obj/item/weapon/cell, /obj/item/device/suit_cooling_unit/emergency, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric, /obj/item/ammo_magazine/smart, /obj/item/device/flash, /obj/item/device/defib_kit, /obj/item/ammo_casing/microbattery, /obj/item/device/paicard) //VOREStation Add - NSFW Batteries + var/list/allowed_devices = list(/obj/item/weapon/gun/energy, /obj/item/weapon/melee/baton, /obj/item/modular_computer, /obj/item/weapon/computer_hardware/battery_module, /obj/item/weapon/cell, /obj/item/device/suit_cooling_unit/emergency, /obj/item/device/flashlight, /obj/item/device/electronic_assembly, /obj/item/weapon/weldingtool/electric, /obj/item/ammo_magazine/smart, /obj/item/device/flash, /obj/item/device/defib_kit, /obj/item/ammo_casing/microbattery, /obj/item/device/paicard, /obj/item/device/personal_shield_generator) //VOREStation Add - NSFW Batteries var/icon_state_charged = "recharger2" var/icon_state_charging = "recharger1" var/icon_state_idle = "recharger0" //also when unpowered diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 541eaa38cdb..06e306c3e92 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -38,6 +38,7 @@ var/has_weapon = 1 // Backpack units generally have weapons. var/shield_active = 0 // If the shield gen is active. + var/effect_color = "#99FFFF" // Allows for changing shield colors. Default cyan. /obj/item/device/personal_shield_generator/get_cell() return bcell @@ -101,6 +102,18 @@ add_overlay("[initial(icon_state)]-nocell") */ +/obj/item/device/personal_shield_generator/emp_act(severity) + if(bcell) + switch(severity) + if(1) //Point blank EMP shots have a good chance of burning the cell charge." + if(prob(50)) + bcell.emp_act(severity) + bcell.corrupt() + else + if(prob(25)) + bcell.emp_act(severity) + ..() + /obj/item/device/personal_shield_generator/ui_action_click() toggle_shield() @@ -156,6 +169,10 @@ active_weapon.power_supply = null //No power cell anymore! to_chat(user, "You remove the cell from \the [src].") update_icon() + else if(istype(W,/obj/item/device/multitool)) + var/new_color = input(usr, "Choose a color to set the shield to!", "", effect_color) as color|null + if(new_color) + effect_color = new_color else return ..() @@ -198,6 +215,7 @@ to_chat(user, "You activate the shield!") user.remove_modifiers_of_type(/datum/modifier/shield_projection) //Just to make sure they aren't using two at once! user.add_modifier(modifier_type) //TESTING. + user.update_modifier_visuals() //Forces coloration to WORK. START_PROCESSING(SSobj, src) //Let's only bother draining power when we're being used! update_icon() @@ -240,6 +258,7 @@ to_chat(user, "The shield deactivates.!") user.remove_modifiers_of_type(/datum/modifier/shield_projection) STOP_PROCESSING(SSobj, src) + update_icon() @@ -384,30 +403,44 @@ // Mining belts /obj/item/device/personal_shield_generator/belt/mining - name = "mining personal shield generator" + name = "mining PSG" desc = "A personal shield generator designed for mining. It has a warning on the back: 'Do NOT expose the shield to stun-based weaponry.'" modifier_type = /datum/modifier/shield_projection/mining /obj/item/device/personal_shield_generator/belt/mining/loaded bcell = /obj/item/weapon/cell/device/shield_generator -/* +/obj/item/device/personal_shield_generator/belt/mining/update_icon() + if(shield_active) + icon_state = "shield_belt_mining_active" + else + icon_state = "shield_belt_mining" + +/obj/item/borg/upgrade/shield_upgrade + name = "mining PSG upgrade disk." + desc = "A upgrade disk that, when slotted into a mining shield generator, upgrades the efficiency of the internal software, providing a stronger shield \ + in exchange for being weaker to stun-based weaponry." + icon = 'icons/obj/objects_vr.dmi' + icon_state = "modkit" + w_class = ITEMSIZE_SMALL + /obj/item/device/personal_shield_generator/belt/mining/attackby(obj/item/weapon/W, mob/user, params) - if(modifier_type == /datum/modifier/shield_projection/mining/strong)) + if(modifier_type == /datum/modifier/shield_projection/mining/strong) to_chat(user, "This shield generator is already upgraded!") return - if(istype(W, /obj/item/borg/upgrade/modkit/shield_upgrade)) + if(istype(W, /obj/item/borg/upgrade/shield_upgrade)) modifier_type = /datum/modifier/shield_projection/mining/strong + to_chat(user, "You upgrade the [src] with the [W]!") user.drop_from_inventory(W) qdel(W) else ..() -*/ + //Security belts /obj/item/device/personal_shield_generator/belt/security - name = "security personal shield generator" + name = "security PSG" desc = "A personal shield generator designed for security." modifier_type = /datum/modifier/shield_projection/security/weak @@ -426,7 +459,7 @@ bcell = /obj/item/weapon/cell/device/shield_generator /obj/item/device/personal_shield_generator/belt/parry //The 'provides one second of pure immunity to brute/burn/halloss' belt. - name = "personal shield generator variant-P" //Not meant to be used in any serious capacity. + name = "PSG variant-P" //Not meant to be used in any serious capacity. desc = "A personal shield generator that sacrifices long-term usability in exchange for a strong, short-lived shield projection, enabling the user to be nigh \ impervious for a second." modifier_type = /datum/modifier/shield_projection/parry @@ -440,7 +473,7 @@ // HOWEVER, be careful with these. They come loaded with a gun in them, so they shouldn't be handed out willy-nilly. /obj/item/device/personal_shield_generator/security - name = "security personal shield generator" + name = "security PSG" desc = "A personal shield generator designed for security." modifier_type = /datum/modifier/shield_projection/security @@ -465,6 +498,7 @@ /obj/item/weapon/cell/device/shield_generator/backpack //The base power cell the backpack units come with. Double the charge vs the belt. maxcharge = 4800 + charge_amount = 160 /obj/item/weapon/cell/device/shield_generator/upgraded //A stronger version of the normal cell. Double the maxcharge, halved charge time. maxcharge = 4800 @@ -473,6 +507,5 @@ /obj/item/weapon/cell/device/shield_generator/parry //The cell for the 'parry' shield gen. maxcharge = 100 - self_recharge = TRUE charge_amount = 100 charge_delay = 20 //Starts charging two seconds after it's discharged. \ No newline at end of file diff --git a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm index c100a7a9bc9..09e5a692a6e 100644 --- a/code/modules/mining/ore_redemption_machine/equipment_vendor.dm +++ b/code/modules/mining/ore_redemption_machine/equipment_vendor.dm @@ -170,6 +170,7 @@ EQUIPMENT("Thalers - 1000", /obj/item/weapon/spacecash/c1000, 10000), EQUIPMENT("Umbrella", /obj/item/weapon/melee/umbrella/random, 200), EQUIPMENT("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 125), + EQUIPMENT("Mining PSG Upgrade Disk", /obj/item/borg/upgrade/shield_upgrade, 2500), ) prize_list["Extra"] = list() // Used in child vendors //VOREStation Edit End diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index 1f925a76b56..35de7983ae8 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -1,4 +1,7 @@ /datum/modifier + var/effect_color // Allows for coloring of modifiers. + var/coloration_applied = 0 // Tells the game is coloration has been applied already or not. + var/icon_override = 0 // Tells the game if it should use modifer_effects_vr.dmi or not. // ENERGY CODE. Variables to allow for energy based modifiers. var/energy_based // Sees if the modifier is based on something electronic based. var/energy_cost // How much the modifier uses per action/special effect blocked. For base values. @@ -91,9 +94,10 @@ on_created_text = "Your shield generator buzzes on." on_expired_text = "Your shield generator buzzes off." - mob_overlay_state = "repel_missiles" //Looks actually pretty good. Could use a better sprite, but that'll work! stacks = MODIFIER_STACK_FORBID //No stacking shields. If you put one one your belt and backpack it won't work. + icon_override = 1 + mob_overlay_state = "deflect" siemens_coefficient = 2 //Stun weapons drain 100% charge per point of damage. They're good at blocking lasers and bullets but not good at blocking stun beams! energy_based = 1 energy_cost = 99999 //This is changed to the shield_generator's energy_cost. @@ -128,7 +132,7 @@ var/obj/item/device/personal_shield_generator/shield_generator //This is the shield generator you're wearing! -/datum/modifier/shield_projection/on_applied() //Don't need to modify this! +/datum/modifier/shield_projection/on_applied() return /datum/modifier/shield_projection/on_expire() //Don't need to modify this! @@ -139,24 +143,24 @@ var/mob/living/carbon/human/H = holder if(istype(H.get_equipped_item(slot_back), /obj/item/device/personal_shield_generator)) shield_generator = H.get_equipped_item(slot_back) //Sets the var on the modifier that the shield gen is their back shield gen. - energy_source = shield_generator.bcell - energy_cost = shield_generator.generator_hit_cost - energy_modifier = shield_generator.energy_modifier else if(istype(H.get_equipped_item(slot_belt), /obj/item/device/personal_shield_generator)) shield_generator = H.get_equipped_item(slot_belt) //No need for other checks. If they got hit by this, they just turned it on. - energy_source = shield_generator.bcell - energy_cost = shield_generator.generator_hit_cost - energy_modifier = shield_generator.energy_modifier else if(istype(H.get_equipped_item(slot_s_store), /obj/item/device/personal_shield_generator) ) //Rigsuits. shield_generator = H.get_equipped_item(slot_s_store) + else + expire(silent = TRUE) + if(shield_generator) //Sanity. energy_source = shield_generator.bcell energy_cost = shield_generator.generator_hit_cost energy_modifier = shield_generator.energy_modifier - else - expire(silent = TRUE) + effect_color = shield_generator.effect_color + if(!coloration_applied) //Does a check if colors have been applied. If not, updates the color. + H.update_modifier_visuals() //This can only happen on the next tick, unfortunately, not the same tick the modifier is applied. Thus, must be done here. + coloration_applied = 1 else expire(silent = TRUE) + /datum/modifier/shield_projection/tick() //When the shield generator runs out of charge, it'll remove this naturally. if(holder.stat == DEAD) expire(silent = TRUE) //If you're dead the generator stops protecting you but keeps running. @@ -200,8 +204,8 @@ max_fire_resistance = 0.5 //SECURITY VARIANTS -/datum/modifier/shield_projection/security // Security backpack. 50% resistance at full charge. 90% resistance for the last shot taken. - max_brute_resistance = 0.5 +/datum/modifier/shield_projection/security // Security backpack. 50% resistance at full charge. 10% resistance for the last shot taken. + max_brute_resistance = 0.50 min_brute_resistance = 0.9 effective_brute_resistance = 1 @@ -213,6 +217,8 @@ min_hal_resistance = 0.9 effective_hal_resistance = 1 + disable_duration_percent = 0.75 + /datum/modifier/shield_projection/security/weak // Security belt. max_brute_resistance = 0.75 min_brute_resistance = 0.95 @@ -225,15 +231,16 @@ max_fire_resistance = 0.25 max_hal_resistance = 0.25 siemens_coefficient = 1.5 //Not as weak as normal, but still weak. + disable_duration_percent = 0.5 //MINING VARIANTS -/datum/modifier/shield_projection/mining //Base mining belt. 45% resistance that fades to 15% resistance - max_brute_resistance = 0.55 +/datum/modifier/shield_projection/mining //Base mining belt. 30% resistance that fades to 15% resistance + max_brute_resistance = 0.70 min_brute_resistance = 0.85 effective_brute_resistance = 1 - max_fire_resistance = 0.55 + max_fire_resistance = 0.70 min_brute_resistance = 0.85 effective_fire_resistance = 1 @@ -243,10 +250,10 @@ disable_duration_percent = 0.75 //Miners often come into contact with things that can stun them. -/datum/modifier/shield_projection/mining/strong // Mining belt, but upgraded. Even weaker to halloss! It also scales from .5 to .75 instead of back to 1.0! - max_brute_resistance = 0.5 +/datum/modifier/shield_projection/mining/strong // Mining belt, but upgraded. Even weaker to halloss! + max_brute_resistance = 0.55 min_brute_resistance = 0.75 - max_fire_resistance = 0.5 + max_fire_resistance = 0.55 min_fire_resistance = 0.75 disable_duration_percent = 0.5 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index c7350d39355..33fc69c562f 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -1127,8 +1127,14 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() var/image/effects = new() for(var/datum/modifier/M in modifiers) if(M.mob_overlay_state) - var/image/I = image(icon = 'icons/mob/modifier_effects.dmi', icon_state = M.mob_overlay_state) - effects.overlays += I // Leaving this as overlays += + if(M.icon_override) //VOREStation Edit. Override for the modifer icon. + var/image/I = image(icon = 'icons/mob/modifier_effects_vr.dmi', icon_state = M.mob_overlay_state) + I.color = M.effect_color + effects.overlays += I // Leaving this as overlays += + else + var/image/I = image(icon = 'icons/mob/modifier_effects.dmi', icon_state = M.mob_overlay_state) + I.color = M.effect_color + effects.overlays += I // Leaving this as overlays += overlays_standing[MODIFIER_EFFECTS_LAYER] = effects diff --git a/icons/mob/modifier_effects_vr.dmi b/icons/mob/modifier_effects_vr.dmi new file mode 100644 index 0000000000000000000000000000000000000000..108fff4f968d831fd6d52391211fe88de0627e0c GIT binary patch literal 1128 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 literal 6379 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 Date: Tue, 13 Sep 2022 19:53:05 -0400 Subject: [PATCH 09/17] Renames a var for clarity. Adds sec variant CODER SPRITE ALERT!!! CODER SPRITE ALERT!!! --- .../devices/personal_shield_generator_vr.dm | 23 ++++++++--- code/modules/mob/_modifiers/modifiers_vr.dm | 6 +-- .../mob/living/carbon/human/human_damage.dm | 38 +++++++++--------- code/modules/mob/living/damage_procs.dm | 14 +++---- code/modules/mob/living/living.dm | 22 +++++----- icons/obj/items_vr.dmi | Bin 7509 -> 8888 bytes 6 files changed, 57 insertions(+), 46 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 06e306c3e92..2d62570575c 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -33,7 +33,7 @@ var/generator_hit_cost = 100 // Power used when a special effect (such as a bullet being blocked) is performed! Could also be expanded to other things. var/generator_active_cost = 10 // Power used when turned on. - var/energy_modifier = 25 // 40 damage absorbed per 1000 charge. + var/damage_cost = 25 // 40 damage absorbed per 1000 charge. var/modifier_type = /datum/modifier/shield_projection // What type of modifier will it add? Used for variant modifiers! var/has_weapon = 1 // Backpack units generally have weapons. @@ -78,8 +78,8 @@ . = ..() if(Adjacent(user)) . += "The internal cell is [round(bcell.percent() )]% charged." - if(energy_modifier) //Prevention of dividing by 0 errors. - . += "It reads that it can take [bcell.charge/energy_modifier] more damage before the shield goes down." + if(damage_cost) //Prevention of dividing by 0 errors. + . += "It reads that it can take [bcell.charge/damage_cost] more damage before the shield goes down." if(bcell.self_recharge && bcell.charge_amount) . += "This model is self charging and will take [bcell.maxcharge/bcell.charge_amount] seconds to fully charge from empty." @@ -447,6 +447,12 @@ /obj/item/device/personal_shield_generator/belt/security/loaded bcell = /obj/item/weapon/cell/device/shield_generator +/obj/item/device/personal_shield_generator/belt/security/update_icon() + if(shield_active) + icon_state = "shield_belt_security_active" + else + icon_state = "shield_belt_security" + //Misc belts. Admin-spawn only atm. /obj/item/device/personal_shield_generator/belt/adminbus @@ -455,7 +461,7 @@ generator_hit_cost = 0 generator_active_cost = 0 shield_active = 0 - energy_modifier = 0 + damage_cost = 0 bcell = /obj/item/weapon/cell/device/shield_generator /obj/item/device/personal_shield_generator/belt/parry //The 'provides one second of pure immunity to brute/burn/halloss' belt. @@ -464,7 +470,7 @@ impervious for a second." modifier_type = /datum/modifier/shield_projection/parry generator_hit_cost = 0 //No cost for being hit. - energy_modifier = 0//No cost for blocking effects. + damage_cost = 0//No cost for blocking effects. generator_active_cost = 100 //However, it disables the tick immediately after being turned on. shield_active = 0 bcell = /obj/item/weapon/cell/device/shield_generator/parry @@ -474,7 +480,7 @@ /obj/item/device/personal_shield_generator/security name = "security PSG" - desc = "A personal shield generator designed for security." + desc = "A personal shield generator designed for security. Comes with a built in defense pistol." modifier_type = /datum/modifier/shield_projection/security /obj/item/device/personal_shield_generator/security/loaded @@ -486,6 +492,11 @@ /obj/item/device/personal_shield_generator/security/strong/loaded bcell = /obj/item/weapon/cell/device/shield_generator/backpack +/obj/item/device/personal_shield_generator/belt/security/update_icon() + if(shield_active) + icon_state = "shield_pack_security_active" + else + icon_state = "shield_pack_security" //Power cells. /obj/item/weapon/cell/device/shield_generator //The base power cell the shield gen comes with. diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index 35de7983ae8..40eab1378e8 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -5,7 +5,7 @@ // ENERGY CODE. Variables to allow for energy based modifiers. var/energy_based // Sees if the modifier is based on something electronic based. var/energy_cost // How much the modifier uses per action/special effect blocked. For base values. - var/energy_modifier // How much energy is used when numbers are involed. For values, such as taking damage. Ex: (Damage*energy_modifier) + var/damage_cost // How much energy is used when numbers are involed. For values, such as taking damage. Ex: (Damage*damage_cost) var/obj/item/weapon/cell/energy_source = null // The source of the above. // RESISTANCES CODE. Variable to enable external damage resistance modifiers. This is not unlike armor. @@ -101,7 +101,7 @@ siemens_coefficient = 2 //Stun weapons drain 100% charge per point of damage. They're good at blocking lasers and bullets but not good at blocking stun beams! energy_based = 1 energy_cost = 99999 //This is changed to the shield_generator's energy_cost. - energy_modifier = 50 //This is how much battery is used per damage unit absorbed. Higher damage means higher charge use per damage absorbed. Changed below! + damage_cost = 50 //This is how much battery is used per damage unit absorbed. Higher damage means higher charge use per damage absorbed. Changed below! //Not actually in use until effective resistances are set. Just here so it doesn't have to be placed down for all the variants. Less lines. max_damage_resistance = 1 @@ -152,7 +152,7 @@ if(shield_generator) //Sanity. energy_source = shield_generator.bcell energy_cost = shield_generator.generator_hit_cost - energy_modifier = shield_generator.energy_modifier + damage_cost = shield_generator.damage_cost effect_color = shield_generator.effect_color if(!coloration_applied) //Does a check if colors have been applied. If not, updates the color. H.update_modifier_visuals() //This can only happen on the next tick, unfortunately, not the same tick the modifier is applied. Thus, must be done here. diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 42ced726ba8..4829c3ee128 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -116,11 +116,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_brute_damage_percent if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(amount, 0) @@ -138,11 +138,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_fire_damage_percent if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage take_overall_damage(0, amount) @@ -162,11 +162,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_brute_damage_percent if(nif && nif.flag_check(NIF_C_BRUTEARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(amount, 0, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) @@ -188,11 +188,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_fire_damage_percent if(nif && nif.flag_check(NIF_C_BURNARMOR,NIF_FLAGS_COMBAT)){amount *= 0.7} //VOREStation Edit - NIF mod for damage resistance for this type of damage O.take_damage(0, amount, sharp=is_sharp(damage_source), edge=has_edge(damage_source), used_weapon=damage_source) @@ -478,37 +478,37 @@ This function restores all organs. for(var/datum/modifier/M in modifiers) //MODIFIER STUFF. It's best to do this RIGHT before armor is calculated, so it's done here! This is the 'forcefield' defence. if(damagetype == BRUTE && (!isnull(M.effective_brute_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_brute_resistance continue if((damagetype == BURN || damagetype == ELECTROCUTE) && (!isnull(M.effective_fire_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_fire_resistance continue if(damagetype == TOX && (!isnull(M.effective_tox_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_tox_resistance continue if(damagetype == OXY && (!isnull(M.effective_oxy_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_oxy_resistance continue if(damagetype == CLONE && (!isnull(M.effective_clone_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_clone_resistance continue if(damagetype == HALLOSS && (!isnull(M.effective_hal_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_hal_resistance continue if(damagetype == SEARING && (!isnull(M.effective_fire_resistance) || !isnull(M.effective_brute_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) var/damage_mitigation = 0//Used for dual calculations. if(!isnull(M.effective_fire_resistance)) damage_mitigation += round((1/3)*damage * M.effective_fire_resistance) @@ -561,11 +561,11 @@ This function restores all organs. for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*damage) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*damage) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_brute_damage_percent if(organ.take_damage(damage, 0, sharp, edge, used_weapon)) @@ -578,11 +578,11 @@ This function restores all organs. for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*damage) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*damage) + M.energy_source.use(M.damage_cost*damage) damage *= M.incoming_fire_damage_percent if(organ.take_damage(0, damage, sharp, edge, used_weapon)) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index a73b9818c20..a865a6b05d5 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -16,37 +16,37 @@ for(var/datum/modifier/M in modifiers) //MODIFIER STUFF. It's best to do this RIGHT before armor is calculated, so it's done here! This is the 'forcefield' defence. if(damagetype == BRUTE && (!isnull(M.effective_brute_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_brute_resistance continue if((damagetype == BURN || damagetype == ELECTROCUTE)&& (!isnull(M.effective_fire_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_fire_resistance continue if(damagetype == TOX && (!isnull(M.effective_tox_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_tox_resistance continue if(damagetype == OXY && (!isnull(M.effective_oxy_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_oxy_resistance continue if(damagetype == CLONE && (!isnull(M.effective_clone_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_clone_resistance continue if(damagetype == HALLOSS && (!isnull(M.effective_hal_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) damage = damage * M.effective_hal_resistance continue if(damagetype == SEARING && (!isnull(M.effective_fire_resistance) || !isnull(M.effective_brute_resistance))) if(M.energy_based) - M.energy_source.use(M.energy_modifier * damage) + M.energy_source.use(M.damage_cost * damage) var/damage_mitigation = 0//Used for dual calculations. if(!isnull(M.effective_fire_resistance)) damage_mitigation += round((1/3)*damage * M.effective_fire_resistance) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 2fe479ccafc..7f8be88a0c9 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -193,11 +193,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_brute_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_brute_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -224,11 +224,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_oxy_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_oxy_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -252,11 +252,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_tox_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_tox_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -286,11 +286,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_fire_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_fire_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -315,11 +315,11 @@ for(var/datum/modifier/M in modifiers) if(!isnull(M.incoming_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_damage_percent if(!isnull(M.incoming_clone_damage_percent)) if(M.energy_based) - M.energy_source.use(M.energy_modifier*amount) + M.energy_source.use(M.damage_cost*amount) amount *= M.incoming_clone_damage_percent else if(amount < 0) for(var/datum/modifier/M in modifiers) @@ -352,7 +352,7 @@ if(amount > 0) for(var/datum/modifier/M in modifiers) if(M.energy_based && (!isnull(M.incoming_hal_damage_percent) || !isnull(M.disable_duration_percent))) - M.energy_source.use(M.energy_modifier*amount) // Cost of the Damage absorbed. + M.energy_source.use(M.damage_cost*amount) // Cost of the Damage absorbed. M.energy_source.use(M.energy_cost) // Cost of the Effect absorbed. if(!isnull(M.incoming_damage_percent)) amount *= M.incoming_damage_percent diff --git a/icons/obj/items_vr.dmi b/icons/obj/items_vr.dmi index eaab38c51ee5bcccb18c4d004d3d1b323338f59d..8bfbe6655ad564068e3a13f9864b5ef5fdb835ac 100644 GIT binary patch literal 8888 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 From 26c18e448312041e6128aa2b27f5893329c56bab Mon Sep 17 00:00:00 2001 From: "C.L" Date: Tue, 13 Sep 2022 20:34:00 -0400 Subject: [PATCH 10/17] minor changes --- code/game/objects/items/devices/personal_shield_generator_vr.dm | 2 +- code/modules/mob/_modifiers/modifiers_vr.dm | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 2d62570575c..3d9d68fa229 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -43,7 +43,7 @@ /obj/item/device/personal_shield_generator/get_cell() return bcell -/obj/item/device/personal_shield_generator/New() //starts without a cell for rnd +/obj/item/device/personal_shield_generator/New() ..() if(ispath(bcell)) bcell = new bcell(src) diff --git a/code/modules/mob/_modifiers/modifiers_vr.dm b/code/modules/mob/_modifiers/modifiers_vr.dm index 40eab1378e8..2de03120d4f 100644 --- a/code/modules/mob/_modifiers/modifiers_vr.dm +++ b/code/modules/mob/_modifiers/modifiers_vr.dm @@ -225,6 +225,7 @@ max_fire_resistance = 0.75 min_fire_resistance = 0.95 max_hal_resistance = 0.75 + min_hal_resistance = 0.95 /datum/modifier/shield_projection/security/strong // Dunno. Upgraded variant of security backpack? max_brute_resistance = 0.25 From 5ff52f29f3a21ac5c0284d5b78a2bb6c0bcad94f Mon Sep 17 00:00:00 2001 From: "C.L" Date: Tue, 13 Sep 2022 21:00:06 -0400 Subject: [PATCH 11/17] No storing shield generators. --- code/modules/client/stored_item.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/client/stored_item.dm b/code/modules/client/stored_item.dm index 6f2ff849ac4..cd0f8829d29 100644 --- a/code/modules/client/stored_item.dm +++ b/code/modules/client/stored_item.dm @@ -253,4 +253,6 @@ /obj/item/weapon/spacecash persist_storable = FALSE /obj/item/weapon/spacecasinocash + persist_storable = FALSE +/obj/item/device/personal_shield_generator persist_storable = FALSE \ No newline at end of file From e7a88825521543f3ab0a5047fea8b0dfa610a655 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Wed, 14 Sep 2022 15:37:01 -0400 Subject: [PATCH 12/17] Sprites! Credit to Identity Crisis#2599 on discord for making the sprites! --- .../devices/personal_shield_generator_vr.dm | 22 +++++++++--------- icons/obj/items_vr.dmi | Bin 8888 -> 18471 bytes 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 3d9d68fa229..c0a4544ee9d 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -70,9 +70,9 @@ /obj/item/device/personal_shield_generator/update_icon() if(shield_active) - icon_state = "shield_back_active" + icon_state = "shieldpack_basic_on" else - icon_state = "shield_pack" + icon_state = "shieldpack_basic" /obj/item/device/personal_shield_generator/examine(mob/user) . = ..() @@ -392,9 +392,9 @@ /obj/item/device/personal_shield_generator/belt/update_icon() if(shield_active) - icon_state = "shield_belt_active" + icon_state = "shieldpack_basic_on" else - icon_state = "shield_belt" + icon_state = "shieldpack_basic" /obj/item/device/personal_shield_generator/belt/bruteburn //Example of a modified generator. modifier_type = /datum/modifier/shield_projection/bruteburn @@ -412,9 +412,9 @@ /obj/item/device/personal_shield_generator/belt/mining/update_icon() if(shield_active) - icon_state = "shield_belt_mining_active" + icon_state = "shieldpack_mining_on" else - icon_state = "shield_belt_mining" + icon_state = "shieldpack_mining" /obj/item/borg/upgrade/shield_upgrade name = "mining PSG upgrade disk." @@ -449,9 +449,9 @@ /obj/item/device/personal_shield_generator/belt/security/update_icon() if(shield_active) - icon_state = "shield_belt_security_active" + icon_state = "shieldpack_security_on" else - icon_state = "shield_belt_security" + icon_state = "shieldpack_security" //Misc belts. Admin-spawn only atm. @@ -492,11 +492,11 @@ /obj/item/device/personal_shield_generator/security/strong/loaded bcell = /obj/item/weapon/cell/device/shield_generator/backpack -/obj/item/device/personal_shield_generator/belt/security/update_icon() +/obj/item/device/personal_shield_generator/security/update_icon() if(shield_active) - icon_state = "shield_pack_security_active" + icon_state = "shieldpack_security_on" else - icon_state = "shield_pack_security" + icon_state = "shieldpack_security" //Power cells. /obj/item/weapon/cell/device/shield_generator //The base power cell the shield gen comes with. diff --git a/icons/obj/items_vr.dmi b/icons/obj/items_vr.dmi index 8bfbe6655ad564068e3a13f9864b5ef5fdb835ac..1833ff15146ce9bdef89a6118c044a96d3d098ad 100644 GIT binary patch literal 18471 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 Bv=aaT literal 8888 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 Date: Wed, 14 Sep 2022 16:21:56 -0400 Subject: [PATCH 13/17] Makes EMPs less horrible. Allows battery swap. - Allows you to remove the self charging battery from the shield generator, destroying the battery in the process but allowing you to swap the battery for another. --- .../devices/personal_shield_generator_vr.dm | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index c0a4544ee9d..5f18c5ac92d 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -105,10 +105,11 @@ /obj/item/device/personal_shield_generator/emp_act(severity) if(bcell) switch(severity) - if(1) //Point blank EMP shots have a good chance of burning the cell charge." + if(1) //Point blank EMP shots have a good chance of burning the cell charge. if(prob(50)) bcell.emp_act(severity) - bcell.corrupt() + if(prob(5)) //1 in 20% chance to fry the battery completly, which has a 1/10 chance of making the battery explode on next use. + bcell.corrupt() //Not too bad if you slotted a battery in. Disasterous if it has a self-charging battery. else if(prob(25)) bcell.emp_act(severity) @@ -158,8 +159,22 @@ else if(W.is_screwdriver()) if(bcell) if(istype(bcell, /obj/item/weapon/cell/device/shield_generator)) //No stealing self charging batteries! - to_chat(user, "You can not remove the cell from \the [src] without destroying the unit.") - return + var/choice = tgui_alert(user, "A popup appears on the device 'REMOVING THE INTERNAL CELL WILL DESTROY THE BATTERY. DO YOU WISH TO CONTINUE?'...Well, do you?", "Selection List", list("Cancel", "Remove")) + if(choice == "Remove") //Warned you... + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + bcell.forceMove(get_turf(src.loc)) + qdel(bcell) + bcell = null //Sanity. + if(active_weapon) + reattach_gun() //Put the gun back if it's out. No shooting if we don't have a cell! + active_weapon.power_supply = null //No power cell anymore! + to_chat(user, "You remove the cell from \the [src], destroying the battery.") + update_icon() + return + else + return else bcell.update_icon() bcell.forceMove(get_turf(src.loc)) From bcbc89a9aefcadbefe51ec4c7e7636eae7030018 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Wed, 14 Sep 2022 17:21:26 -0400 Subject: [PATCH 14/17] Multitool Mention --- code/modules/examine/descriptions/devices.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/examine/descriptions/devices.dm b/code/modules/examine/descriptions/devices.dm index 35933facf69..a929873e0ff 100644 --- a/code/modules/examine/descriptions/devices.dm +++ b/code/modules/examine/descriptions/devices.dm @@ -36,7 +36,7 @@ storage slot. It runs on an internal battery, which is usually self-charging. Some versions come with a gun. To active the shield, click the button in the upper \ right of the screen, use the 'Toggle Shield' command under your objects tab, or click the device itself while it is on you. Some units come with an active weapon \ which can be taken out at any time by Alt-clicking the device. If the device requires a cell, a screwdriver can be used. The shield slowly drains charge while \ - active and becomes weaker with each individual strike taken." + active and becomes weaker with each individual strike taken. Additonally, the device can be colored via use of a multitool." description_fluff = "A relatively new invention, made in a collaboration between Hephaestus Industries and a startup known as Kuznetsova Enterprise in the year \ 2322. Numerous variants of the device have been made for specific tasks, ranging from riot control, mining, biohazard containment, and search and rescue, among \ From c15914bc110a789018f36a8ec626dd999fb86e04 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Thu, 15 Sep 2022 17:28:23 -0400 Subject: [PATCH 15/17] Multiple bugfixes. - Fixes battery removal - Makes an alert when the cell is rigged. - Gives the user a warning if the cell is rigged. - Gives people that examine the unit a warning if the cell is rigged. - Makes it so you're incentivized to turn off your shield against EMP enemies. - Better process proc that deals with rigging properly and gives detailed warnings. --- .../devices/personal_shield_generator_vr.dm | 58 +++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 5f18c5ac92d..33f4a383815 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -57,6 +57,7 @@ active_weapon.power_supply = bcell else verbs -= /obj/item/device/personal_shield_generator/verb/weapon_toggle + STOP_PROCESSING(SSobj, src) //We do this so it doesn't start processing until it's first used. update_icon() /obj/item/device/personal_shield_generator/Destroy() @@ -77,11 +78,17 @@ /obj/item/device/personal_shield_generator/examine(mob/user) . = ..() if(Adjacent(user)) - . += "The internal cell is [round(bcell.percent() )]% charged." + if(bcell) + . += "The internal cell is [round(bcell.percent() )]% charged." + else + . += "The device has no cell installed." + return if(damage_cost) //Prevention of dividing by 0 errors. . += "It reads that it can take [bcell.charge/damage_cost] more damage before the shield goes down." if(bcell.self_recharge && bcell.charge_amount) . += "This model is self charging and will take [bcell.maxcharge/bcell.charge_amount] seconds to fully charge from empty." + if(bcell.rigged) + . += "A red flashing 'WARNING' is visible on the display, noting that the cell is unstable and requires replacement." /* //This would be cool, but we need sprites. @@ -103,13 +110,26 @@ */ /obj/item/device/personal_shield_generator/emp_act(severity) - if(bcell) + if(bcell && shield_active) switch(severity) if(1) //Point blank EMP shots have a good chance of burning the cell charge. if(prob(50)) bcell.emp_act(severity) if(prob(5)) //1 in 20% chance to fry the battery completly, which has a 1/10 chance of making the battery explode on next use. bcell.corrupt() //Not too bad if you slotted a battery in. Disasterous if it has a self-charging battery. + if(bcell.rigged) //Did the above just rig the cell? Turn it off. Don't immediately have it go boom. Instead have the cell blow soon-ish. + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, src) + s.start() + shield_active = 0 + if(bcell.charge_delay) //It WILL blow up soon. Downside of self-charging cells. + to_chat(src.loc, "Your shield generator sparks and suddenly goes down! A warning message pops up on screen: \ + 'WARNING, INTERNAL CELL MELTDOWN IMMINENT. TIME TILL EXPLOSION: [bcell.charge_delay/10] SECONDS. DISCARD UNIT IMMEDIATELY!'") + else //It won't blow up unless you turn it back on again. Upside of using non-charging cells. + to_chat(src.loc, "Your shield generator sparks and suddenly goes down! A warning message pops up on screen: \ + 'WARNING, INTERNAL CELL CRITICALLY DAMAGED. REPLACE CELL IMMEDIATELY.'") + STOP_PROCESSING(SSobj, src) + update_icon() else if(prob(25)) bcell.emp_act(severity) @@ -264,16 +284,46 @@ update_icon() //success /obj/item/device/personal_shield_generator/process() + if(!bcell) //They removed the battery midway. + if(istype(loc, /mob/living/carbon/human)) //We on someone? Tell them it turned off. + var/mob/living/carbon/human/user = loc + to_chat(user, "The shield deactivates! An error message pops up on screen: 'Cell missing. Cell replacement required.'") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + shield_active = 0 + STOP_PROCESSING(SSobj, src) + update_icon() + return + if(shield_active) - bcell.use(generator_active_cost) + if(bcell.rigged) //They turned it back on after it was rigged to go boom. + if(istype(loc, /mob/living/carbon/human)) //Deactivate the shield, first. You're not getting reduced damage... + var/mob/living/carbon/human/user = loc + to_chat(user, "The shield deactivates, an error message popping up on screen: 'Cell Reactor Critically damaged. Cell replacement required.'") + user.remove_modifiers_of_type(/datum/modifier/shield_projection) + + if(active_weapon) //Retract the gun. There's about to be no cell anymore. + reattach_gun() + active_weapon.power_supply = null + + bcell.use(generator_active_cost) //Causes it to go boom. + bcell = null + shield_active = 0 + STOP_PROCESSING(SSobj, src) + update_icon() + return + + else //Normal operation. + bcell.use(generator_active_cost) + if(bcell.charge < generator_hit_cost || bcell.charge < generator_active_cost) //Out of charge... shield_active = 0 if(istype(loc, /mob/living/carbon/human)) //We on someone? Tell them it turned off. var/mob/living/carbon/human/user = loc - to_chat(user, "The shield deactivates.!") + to_chat(user, "The shield deactivates, an error message popping up on screen: 'Cell out of charge.'") user.remove_modifiers_of_type(/datum/modifier/shield_projection) STOP_PROCESSING(SSobj, src) update_icon() + return From e4361a6688f7d9e79e295be8240e48813f52eb52 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Fri, 16 Sep 2022 23:36:14 -0400 Subject: [PATCH 16/17] 1 in 100 chance of mining crates having mining shield. Makes it so abandoned mining crates have a 1 in 100 chance of having a mining shield. Throw them a bone if they're ultra lucky. --- code/modules/mining/abandonedcrates.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/modules/mining/abandonedcrates.dm b/code/modules/mining/abandonedcrates.dm index d6e72e4e331..cf595a08216 100644 --- a/code/modules/mining/abandonedcrates.dm +++ b/code/modules/mining/abandonedcrates.dm @@ -19,7 +19,7 @@ generate_loot() /obj/structure/closet/crate/secure/loot/proc/generate_loot() - var/loot = rand(1, 99) + var/loot = rand(1, 100) switch(loot) if(1 to 5) // Common things go, 5% new/obj/item/weapon/reagent_containers/food/drinks/bottle/rum(src) @@ -140,6 +140,8 @@ if(99) new/obj/item/weapon/storage/belt/champion(src) new/obj/item/clothing/mask/luchador(src) + if(100) + new/obj/item/device/personal_shield_generator/belt/mining/loaded(src) /obj/structure/closet/crate/secure/loot/togglelock(mob/user as mob) if(!locked) From 6601951d1da6e572e4fc99a51de76d3462c90883 Mon Sep 17 00:00:00 2001 From: "C.L" Date: Sun, 18 Sep 2022 17:52:55 -0400 Subject: [PATCH 17/17] Adds sounds! Placeholder for now. Saberon&Saberoff sounds fine for a shield. *And* it's less spammable than an esword! --- .../devices/personal_shield_generator_vr.dm | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/code/game/objects/items/devices/personal_shield_generator_vr.dm b/code/game/objects/items/devices/personal_shield_generator_vr.dm index 33f4a383815..c09d7ae8c57 100644 --- a/code/game/objects/items/devices/personal_shield_generator_vr.dm +++ b/code/game/objects/items/devices/personal_shield_generator_vr.dm @@ -16,8 +16,8 @@ /obj/item/device/personal_shield_generator name = "personal shield generator" desc = "A personal shield generator." - icon = 'icons/obj/items_vr.dmi' //Placeholder - icon_state = "shield_pack" //Placeholder + icon = 'icons/obj/items_vr.dmi' + icon_state = "shield_pack" item_state = "defibunit" //Placeholder slot_flags = SLOT_BACK force = 5 @@ -211,7 +211,14 @@ else return ..() -/* //TODO +// TODO: EMAG ACT +// Perhaps make it so emagging the generator gives two options: One to rig the cell (stealthily) and one to disable the safeties (supercharge it) +// Disabling the safeties would make it a stronger variant but boost the 'damage_cost' perhaps. Dunno. +// We're an RP server so emags don't come into play except for random trash finds. Meaning it'd be RNG if you could 'supercharge' your shield genrator. +// This would kind of be like people being able to emag the NIFSoft for bloodletters & all the buffs that come with an emagged NIFSoft. +// Making it so emagging the weapon it comes with would also be a good idea. Different modes, perhaps? + +/* /obj/item/device/personal_shield_generator/emag_act(var/remaining_charges, var/mob/user) if(active_weapon) . = active_weapon.emag_act(user) @@ -245,13 +252,15 @@ to_chat(user, "You deactive the shield!") user.remove_modifiers_of_type(/datum/modifier/shield_projection) STOP_PROCESSING(SSobj, src) + playsound(src, 'sound/weapons/saberoff.ogg', 50, 1) //Shield turning off! PLACEHOLDER else shield_active = !shield_active to_chat(user, "You activate the shield!") user.remove_modifiers_of_type(/datum/modifier/shield_projection) //Just to make sure they aren't using two at once! - user.add_modifier(modifier_type) //TESTING. + user.add_modifier(modifier_type) user.update_modifier_visuals() //Forces coloration to WORK. START_PROCESSING(SSobj, src) //Let's only bother draining power when we're being used! + playsound(src, 'sound/weapons/saberon.ogg', 50, 1) //Shield turning off! PLACEHOLDER update_icon() /obj/item/device/personal_shield_generator/verb/weapon_toggle() //Make this work on Alt-Click @@ -292,6 +301,7 @@ shield_active = 0 STOP_PROCESSING(SSobj, src) update_icon() + playsound(src, 'sound/weapons/saberoff.ogg', 50, 1) //Shield turning off! PLACEHOLDER return if(shield_active) @@ -323,6 +333,7 @@ user.remove_modifiers_of_type(/datum/modifier/shield_projection) STOP_PROCESSING(SSobj, src) update_icon() + playsound(src, 'sound/weapons/saberoff.ogg', 50, 1) //Shield turning off! PLACEHOLDER return @@ -417,7 +428,10 @@ return 0 return 1 -/* //TODO: Emp act. +// TODO: EMP ACT +// The cell already gets hit and can have some nasty effects when EMP'd, so this isn't too much of a concern. + +/* /obj/item/weapon/gun/energy/gun/generator/emp_act(severity) ..() */