diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index f9be57a01d0..677d220cd5e 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -208,6 +208,19 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( use(1) else to_chat(user, "You can't improve [D] any further!") + else if(isrobot(target)) + var/mob/living/silicon/robot/R = target + if(istype(R.module, /obj/item/robot_module/miner)) + var/datum/armor/current_armor = R.armor + if(current_armor.getRating(MELEE) < 60) + R.armor = current_armor.setRating(melee_value = min(current_armor.getRating(MELEE) + 10, 60)) + to_chat(user, "You strengthen [target], improving its resistance against melee attacks.") + use(1) + else + to_chat(user, "You can't improve [R] any further!") + else + to_chat(user, "[R]'s armor can not be improved!") + /obj/item/stack/sheet/animalhide/ashdrake name = "ash drake hide" diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 60cdacafe29..31baf65f7dc 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -493,6 +493,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( modtype = selected_module designation = selected_module module.add_languages(src) + module.add_armor(src) module.add_subsystems_and_actions(src) if(!static_radio_channels) radio.config(module.channels) @@ -541,6 +542,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list( add_language("Robot Talk", TRUE) if("lava" in weather_immunities) // Remove the lava-immunity effect given by a printable upgrade weather_immunities -= "lava" + armor = getArmor(arglist(initial(armor))) status_flags |= CANPUSH diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 95e40f14323..b2e234ba5b7 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -5,6 +5,7 @@ w_class = 100 item_state = "electronic" flags = CONDUCT + var/module_armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0) /// Has the AI hacked the borg module, allowing access to the malf AI exclusive item. var/malfhacked = FALSE @@ -85,7 +86,9 @@ QDEL_LIST_CONTENTS(special_rechargables) return ..() - +/obj/item/robot_module/Initialize(mapload) + . = ..() + module_armor = getArmor(arglist(module_armor)) /** * Searches through the various module lists for the given `item_type`, deletes and removes the item from all supplied lists, if the item is found. * @@ -263,6 +266,11 @@ R.add_language("Clownish", 0) R.add_language("Tkachi", 0) +///Adds armor to a cyborg. Normaly resets it to 0 across the board, unless the module has an armor defined. +/obj/item/robot_module/proc/add_armor(mob/living/silicon/robot/R) + R.armor = module_armor + + /// Adds anything in `subsystems` to the robot's verbs, and grants any actions that are in `module_actions`. /obj/item/robot_module/proc/add_subsystems_and_actions(mob/living/silicon/robot/R) R.verbs |= subsystems @@ -539,6 +547,7 @@ /obj/item/robot_module/miner name = "miner robot module" module_type = "Miner" + module_armor = list(MELEE = 20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0) module_actions = list(/datum/action/innate/robot_sight/meson) custom_removals = list("KA modkits") basic_modules = list( diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 398686060a1..81cc4b5ccca 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -6,6 +6,12 @@ weather_immunities = list("ash") mob_biotypes = MOB_ROBOTIC flags_2 = RAD_PROTECT_CONTENTS_2 | RAD_NO_CONTAMINATE_2 + + // You can define armor as a list in datum definition (e.g. `armor = list("fire" = 80, "brute" = 10)`), + // which would be converted to armor datum during initialization. + // Setting `armor` to a list on an *existing* object would inevitably runtime. Use `getArmor()` instead. + var/datum/armor/armor + var/syndicate = FALSE var/const/MAIN_CHANNEL = "Main Frequency" var/lawchannel = MAIN_CHANNEL // Default channel on which to state laws @@ -49,6 +55,12 @@ diag_hud.add_to_hud(src) diag_hud_set_status() diag_hud_set_health() + if(islist(armor)) + armor = getArmor(arglist(armor)) + else if(!armor) + armor = getArmor() + else if(!istype(armor, /datum/armor)) + stack_trace("Invalid type [armor.type] found in .armor during /obj Initialize()") /mob/living/silicon/med_hud_set_health() @@ -211,19 +223,39 @@ /mob/living/silicon/bullet_act(obj/item/projectile/Proj) - - if(!Proj.nodamage) + var/damage = run_armor(Proj.damage, Proj.damage_type, Proj.flag, 0, Proj.armour_penetration_flat, Proj.armour_penetration_percentage) switch(Proj.damage_type) if(BRUTE) - adjustBruteLoss(Proj.damage) + adjustBruteLoss(damage) if(BURN) - adjustFireLoss(Proj.damage) + adjustFireLoss(damage) Proj.on_hit(src,2) return 2 +/mob/living/silicon/attacked_by(obj/item/I, mob/living/user, def_zone) + send_item_attack_message(I, user) + if(I.force) + var/bonus_damage = 0 + if(ishuman(user)) + var/mob/living/carbon/human/H = user + bonus_damage = H.physiology.melee_bonus + var/damage = run_armor(I.force + bonus_damage, I.damtype, MELEE, 0, I.armour_penetration_flat, I.armour_penetration_percentage) + apply_damage(damage, I.damtype, def_zone) + +///returns the damage value of the attack after processing the silicons's various armor protections +/mob/living/silicon/proc/run_armor(damage_amount, damage_type, damage_flag = 0, attack_dir, armour_penetration_flat = 0, armour_penetration_percentage = 0) + if(damage_type != BRUTE && damage_type != BURN) + return 0 + var/armor_protection = 0 + if(damage_flag) + armor_protection = armor.getRating(damage_flag) + if(armor_protection) //Only apply weak-against-armor/hollowpoint effects if there actually IS armor. + armor_protection = clamp((armor_protection * ((100 - armour_penetration_percentage) / 100)) - armour_penetration_flat, min(armor_protection, 0), 100) + return round(damage_amount * (100 - armor_protection) * 0.01, DAMAGE_PRECISION) + /mob/living/silicon/apply_effect(effect = 0, effecttype = STUN, blocked = 0) return FALSE //The only effect that can hit them atm is flashes and they still directly edit so this works for now diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index 36d11b0f2a2..7cf7fec5fd2 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -10,6 +10,7 @@ if(prob(8)) flash_eyes(affect_silicon = 1) add_attack_logs(M, src, "Alien attacked") + damage = run_armor(damage, BRUTE, MELEE) adjustBruteLoss(damage) updatehealth() else @@ -22,6 +23,7 @@ . = ..() if(.) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) + damage = run_armor(damage, M.melee_damage_type, MELEE, 0, M.armour_penetration_flat, M.armour_penetration_percentage) switch(M.melee_damage_type) if(BRUTE) adjustBruteLoss(damage) @@ -47,7 +49,7 @@ to_chat(user, "You don't want to hurt [src]!") return FALSE ..(user, TRUE) - adjustBruteLoss(rand(10, 15)) + adjustBruteLoss(run_armor(rand(10, 15), BRUTE, MELEE)) playsound(loc, "punch", 25, 1, -1) visible_message("[user] has punched [src]!", "[user] has punched [src]!") return TRUE