From 9d6da4410a29dcf0ccd5221711750b2e7e249e3e Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Mon, 18 Nov 2024 23:39:59 +0300 Subject: [PATCH 01/42] Skill implants. (Need help, on progress and dont merge that shit) --- code/__DEFINES/skills.dm | 3 +- .../objects/items/implants/implant_skill.dm | 262 ++++++++++++++++++ icons/obj/items/implants.dmi | Bin 2492 -> 5252 bytes tgmc.dme | 1 + 4 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 code/game/objects/items/implants/implant_skill.dm diff --git a/code/__DEFINES/skills.dm b/code/__DEFINES/skills.dm index 33d03067ff4..89b1454995c 100644 --- a/code/__DEFINES/skills.dm +++ b/code/__DEFINES/skills.dm @@ -137,7 +137,8 @@ #define SKILL_LEAD_BEGINNER 1 //All non-Standard Marines #define SKILL_LEAD_TRAINED 2 //PO, CMO, etc #define SKILL_LEAD_EXPERT 3 //SL, SO -#define SKILL_LEAD_MASTER 4 //XO, CO +#define SKILL_LEAD_MASTER 4 //XO, FC +#define SKILL_LEAD_SUPER 5 // implanted FC //melee_weapons skill //buff to melee weapon attack damage diff --git a/code/game/objects/items/implants/implant_skill.dm b/code/game/objects/items/implants/implant_skill.dm new file mode 100644 index 00000000000..8bcfb47bf1e --- /dev/null +++ b/code/game/objects/items/implants/implant_skill.dm @@ -0,0 +1,262 @@ +/obj/item/implantator + name = "skill" //teeeeest. + desc = "Used to implant occupants with skill implants." + icon = 'icons/obj/items/implants.dmi' + icon_state = "skill" + item_state = "syringe_0" + item_icons = list( + slot_l_hand_str = 'icons/mob/inhands/equipment/medical_left.dmi', + slot_r_hand_str = 'icons/mob/inhands/equipment/medical_right.dmi', + ) + throw_speed = 1 + throw_range = 5 + w_class = WEIGHT_CLASS_TINY + var/obj/item/implant/imp = /obj/item/implant/skill + var/allowed_limbs + +/obj/item/implantator/Initialize(mapload, ...) + . = ..() + name = name + " implanter" + desc = imp.desc + if(imp) + imp = new imp(src) + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts + +/obj/item/implantator/proc/update_spite() + icon_state = "skill0" + +/obj/item/implantator/Destroy() + QDEL_NULL(imp) + return ..() + +/obj/item/implantator/examine(mob/user, distance, infix, suffix) + . = ..() + . += "it contains [imp ? "a [imp.name]" : "no implant"]!" + +/obj/item/implantator/attack(mob/target, mob/user) + . = ..() + if(!ishuman(target)) + return FALSE + if(!imp) + to_chat(user, span_warning("There is no implant in the [src]! НЕТ ИМПЛАНТА")) + return FALSE + if(!(user.zone_selected in allowed_limbs)) + return FALSE + user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !imp) + to_chat(user, span_notice("You failed to implant [target].")) + return FALSE + if(imp.try_implant(target, user)) + target.visible_message(span_warning("[target] has been implanted by [user].")) + log_combat(user, target, "implanted", src) + imp = null + update_spite() + return TRUE + to_chat(user, span_notice("You fail to implant [target]. НИЧЕГО НЕ ПРОИЗОШЛО")) + return + +/obj/item/implant/skill + name = "skill" //teeeeeest. + desc = "Hey! You dont see it!" + icon = 'icons/obj/items/implants.dmi' + icon_state = "implant" + w_class = WEIGHT_CLASS_TINY + var/list/max_skills +//pamplet copy-past. :clueless: + var/cqc + var/melee_weapons + var/firearms + var/pistols + var/shotguns + var/rifles + var/smgs + var/heavy_weapons + var/swordplay + var/smartgun + var/engineer + var/construction + var/leadership + var/medical + var/surgery + var/pilot + var/police + var/powerloader + var/large_vehicle + var/stamina + +/obj/item/implant/skill/Initialize(mapload) + . = ..() + name = name + " implant" + if(flags_implant & GRANT_ACTIVATION_ACTION) + activation_action = new(src, src) + if(allow_reagents) + reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) + reagents.my_atom = WEAKREF(src) + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts + +/obj/item/implant/skill/try_implant(mob/living/carbon/human/target, var/mob/living/user) + if(!ishuman(target)) + return + if(target.zone_selected in implanted == TRUE) + to_chat(user, span_warning("You cannot implant this into that limb! УЖЕ ЕСТЬ ИМПЛАНТ")) + return FALSE + for(var/skill in max_skills) + if(user.skills.getRating(skill) >= max_skills[skill]) + balloon_alert(user, "You already know it!") + to_chat(user, span_warning("You already know it!")) + return FALSE + return FALSE + if(!(user.zone_selected in allowed_limbs)) + to_chat(user, span_warning("You cannot implant this into that limb! НЕ В СПИСКЕ КОНЕЧНОСТЕЙ")) + return FALSE + implanted = TRUE + implantated(target, user) + return + +/obj/item/implant/skill/proc/implantated(mob/living/carbon/human/target, var/mob/living/user) + SHOULD_CALL_PARENT(TRUE) + forceMove(target) + implant_owner = target + implanted = TRUE + var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) + var/datum/limb/affected = target.get_limb(limb_targeting) + if(!affected) + CRASH("[src] implanted into [target] [user ? "by [user]" : ""] but had no limb, despite being set to implant in [limb_targeting].") + affected.implants += src + part = affected + activation_action?.give_action(target) + embed_into(target, limb_targeting, TRUE) + target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ + engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) + return TRUE + +/obj/item/implant/skill/unembed_ourself() + . = ..() + unimplantated() + +/obj/item/implant/skill/proc/unimplantated() + SHOULD_CALL_PARENT(TRUE) + if(!implanted) + return FALSE + activation_action?.remove_action(implant_owner) + if(flags_implant & ACTIVATE_ON_HEAR) + UnregisterSignal(src, COMSIG_MOVABLE_HEAR) + implanted = FALSE + part.implants -= src + part = null + forceMove(get_turf(implant_owner)) + implant_owner = null + +/obj/item/implant/skill/Destroy(force) + unimplantated() + QDEL_NULL(activation_action) + part?.implants -= src + return ..() + +//////////////////////////////[IMPLANTS]////////////////////////////// + +/obj/item/implant/skill/combat + name = "combat implants" + desc = "Non-game" + icon_state = "combat_implant" + allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) + +/obj/item/implant/skill/combat/firearms + name = "aiming support" + desc = "integrated aiming support system! Update weapons skills!" + firearms = 1 + max_skills = list(SKILL_FIREARMS = SKILL_FIREARMS_TRAINED) + +/obj/item/implant/skill/combat/melee + name = "close combat codex" + desc = "integrated hit support system! Update melee skills!" + melee_weapons = 1 + max_skills = list(SKILL_MELEE = SKILL_MELEE_TRAINED) + +/obj/item/implant/skill/codex + name = "CODEX" + desc = "A support skill update-shit." + icon_state = "skill_implant" + allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) + +/obj/item/implant/skill/codex/medical + name = "medtech" + desc = "A compact device that electro-shakes you every time you apply bandages counterclockwise, right next to your heart! Update medical skills!" + medical = 1 + max_skills = list(SKILL_MEDICAL = SKILL_MEDICAL_COMPETENT) + +/obj/item/implant/skill/codex/surgery + name = "surgery assisting system" + desc = "compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" + surgery = 1 + max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) + +/obj/item/implant/skill/codex/engineer + name = "construction support system" + desc = "laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" + engineer = 1 + max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) + +/obj/item/implant/skill/oper_system + name = "HEAD SLOT!" + desc = "All non-sorted special shit (leadership, probaly SG and more)" + icon_state = "skill_implant" + allowed_limbs = list(BODY_ZONE_HEAD) + +/obj/item/implant/skill/oper_system/leadership + name = "command protocols 'Graiyor' codex" + desc = "uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" + leadership = 1 + max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) + +//////////////////////////////[IMPLANTERS]////////////////////////////// + +//////////////////////////////[COMBAT]////////////////////////////// + +/obj/item/implantator/combat + allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) + imp = /obj/item/implant/skill/combat + +/obj/item/implantator/combat/firearms + name = "aiming support" + icon_state = "weapon1" + imp = /obj/item/implant/skill/combat/firearms + +/obj/item/implantator/combat/melee + name = "close combat codex" + icon_state = "melee1" + imp = /obj/item/implant/skill/combat/melee + +//////////////////////////////[SUPPORT]////////////////////////////// + +/obj/item/implantator/codex + allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) + imp = /obj/item/implant/skill/codex + +/obj/item/implantator/codex/medical + name = "medtech" + icon_state = "medical1" + imp = /obj/item/implant/skill/codex/medical + +/obj/item/implantator/codex/surgery + name = "surgery assisting system" + icon_state = "surgery1" + imp = /obj/item/implant/skill/codex/surgery + +/obj/item/implantator/codex/engineer + name = "construction support system" + icon_state = "enginering1" + imp = /obj/item/implant/skill/codex/engineer + +//////////////////////////////[SPECIAL]////////////////////////////// + +/obj/item/implantator/oper_system + allowed_limbs = list(BODY_ZONE_HEAD) + imp = /obj/item/implant/skill/oper_system + +/obj/item/implantator/leadership + name = "command protocols 'Graiyor' codex" + icon_state = "leadership1" + imp = /obj/item/implant/skill/oper_system/leadership diff --git a/icons/obj/items/implants.dmi b/icons/obj/items/implants.dmi index 92b8042c0a8804af20cbea1713b4cc9a76139b70..7f173c6656d0c441f51b09d1c04fcb82fe6accf4 100644 GIT binary patch literal 5252 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 UJpH^!yj=tysOzfLs@O*S7k1V0_W%F@ literal 2492 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 Date: Tue, 19 Nov 2024 00:11:10 +0300 Subject: [PATCH 02/42] Update code/game/objects/items/implants/implant_skill.dm Co-authored-by: Helg2 <93882977+Helg2@users.noreply.github.com> Signed-off-by: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> --- code/game/objects/items/implants/implant_skill.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/implants/implant_skill.dm b/code/game/objects/items/implants/implant_skill.dm index 8bcfb47bf1e..4ad589a325e 100644 --- a/code/game/objects/items/implants/implant_skill.dm +++ b/code/game/objects/items/implants/implant_skill.dm @@ -115,7 +115,7 @@ implantated(target, user) return -/obj/item/implant/skill/proc/implantated(mob/living/carbon/human/target, var/mob/living/user) +/obj/item/implant/skill/proc/implantated(mob/living/carbon/human/target, mob/living/user) SHOULD_CALL_PARENT(TRUE) forceMove(target) implant_owner = target From c085b468ebc25dd838d3061234c3264bb918c500 Mon Sep 17 00:00:00 2001 From: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> Date: Tue, 19 Nov 2024 00:12:02 +0300 Subject: [PATCH 03/42] Update code/game/objects/items/implants/implant_skill.dm Co-authored-by: Helg2 <93882977+Helg2@users.noreply.github.com> Signed-off-by: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> --- code/game/objects/items/implants/implant_skill.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/implants/implant_skill.dm b/code/game/objects/items/implants/implant_skill.dm index 4ad589a325e..d25ef9176fc 100644 --- a/code/game/objects/items/implants/implant_skill.dm +++ b/code/game/objects/items/implants/implant_skill.dm @@ -96,7 +96,7 @@ if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts -/obj/item/implant/skill/try_implant(mob/living/carbon/human/target, var/mob/living/user) +/obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) if(!ishuman(target)) return if(target.zone_selected in implanted == TRUE) From a7a5f5cb0896b073833bb2122c81f7d38def4336 Mon Sep 17 00:00:00 2001 From: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> Date: Tue, 19 Nov 2024 00:12:24 +0300 Subject: [PATCH 04/42] Update code/game/objects/items/implants/implant_skill.dm Co-authored-by: Helg2 <93882977+Helg2@users.noreply.github.com> Signed-off-by: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> --- code/game/objects/items/implants/implant_skill.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/implants/implant_skill.dm b/code/game/objects/items/implants/implant_skill.dm index d25ef9176fc..03c497718ae 100644 --- a/code/game/objects/items/implants/implant_skill.dm +++ b/code/game/objects/items/implants/implant_skill.dm @@ -11,7 +11,7 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - var/obj/item/implant/imp = /obj/item/implant/skill + var/obj/item/implant/internal_implant = /obj/item/implant/skill var/allowed_limbs /obj/item/implantator/Initialize(mapload, ...) From 740410c6dc25304ed13b7b59861836e3ce73072a Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Tue, 19 Nov 2024 00:54:00 +0300 Subject: [PATCH 05/42] Minor FIX --- .../objects/items/implants/implant_skill.dm | 129 +----------------- .../items/implants/implantator_skill.dm | 102 ++++++++++++++ tgmc.dme | 1 + 3 files changed, 110 insertions(+), 122 deletions(-) create mode 100644 code/game/objects/items/implants/implantator_skill.dm diff --git a/code/game/objects/items/implants/implant_skill.dm b/code/game/objects/items/implants/implant_skill.dm index 03c497718ae..38c424c7cde 100644 --- a/code/game/objects/items/implants/implant_skill.dm +++ b/code/game/objects/items/implants/implant_skill.dm @@ -1,61 +1,3 @@ -/obj/item/implantator - name = "skill" //teeeeest. - desc = "Used to implant occupants with skill implants." - icon = 'icons/obj/items/implants.dmi' - icon_state = "skill" - item_state = "syringe_0" - item_icons = list( - slot_l_hand_str = 'icons/mob/inhands/equipment/medical_left.dmi', - slot_r_hand_str = 'icons/mob/inhands/equipment/medical_right.dmi', - ) - throw_speed = 1 - throw_range = 5 - w_class = WEIGHT_CLASS_TINY - var/obj/item/implant/internal_implant = /obj/item/implant/skill - var/allowed_limbs - -/obj/item/implantator/Initialize(mapload, ...) - . = ..() - name = name + " implanter" - desc = imp.desc - if(imp) - imp = new imp(src) - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts - -/obj/item/implantator/proc/update_spite() - icon_state = "skill0" - -/obj/item/implantator/Destroy() - QDEL_NULL(imp) - return ..() - -/obj/item/implantator/examine(mob/user, distance, infix, suffix) - . = ..() - . += "it contains [imp ? "a [imp.name]" : "no implant"]!" - -/obj/item/implantator/attack(mob/target, mob/user) - . = ..() - if(!ishuman(target)) - return FALSE - if(!imp) - to_chat(user, span_warning("There is no implant in the [src]! НЕТ ИМПЛАНТА")) - return FALSE - if(!(user.zone_selected in allowed_limbs)) - return FALSE - user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !imp) - to_chat(user, span_notice("You failed to implant [target].")) - return FALSE - if(imp.try_implant(target, user)) - target.visible_message(span_warning("[target] has been implanted by [user].")) - log_combat(user, target, "implanted", src) - imp = null - update_spite() - return TRUE - to_chat(user, span_notice("You fail to implant [target]. НИЧЕГО НЕ ПРОИЗОШЛО")) - return - /obj/item/implant/skill name = "skill" //teeeeeest. desc = "Hey! You dont see it!" @@ -85,8 +27,7 @@ var/large_vehicle var/stamina -/obj/item/implant/skill/Initialize(mapload) - . = ..() +/obj/item/implant/skill/proc/starting(mapload) name = name + " implant" if(flags_implant & GRANT_ACTIVATION_ACTION) activation_action = new(src, src) @@ -99,9 +40,6 @@ /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) if(!ishuman(target)) return - if(target.zone_selected in implanted == TRUE) - to_chat(user, span_warning("You cannot implant this into that limb! УЖЕ ЕСТЬ ИМПЛАНТ")) - return FALSE for(var/skill in max_skills) if(user.skills.getRating(skill) >= max_skills[skill]) balloon_alert(user, "You already know it!") @@ -112,11 +50,9 @@ to_chat(user, span_warning("You cannot implant this into that limb! НЕ В СПИСКЕ КОНЕЧНОСТЕЙ")) return FALSE implanted = TRUE - implantated(target, user) - return + return implant(target, user) -/obj/item/implant/skill/proc/implantated(mob/living/carbon/human/target, mob/living/user) - SHOULD_CALL_PARENT(TRUE) +/obj/item/implant/skill/implant(mob/living/carbon/human/target, mob/living/user) forceMove(target) implant_owner = target implanted = TRUE @@ -134,10 +70,9 @@ /obj/item/implant/skill/unembed_ourself() . = ..() - unimplantated() + unimplant() -/obj/item/implant/skill/proc/unimplantated() - SHOULD_CALL_PARENT(TRUE) +/obj/item/implant/skill/unimplant() if(!implanted) return FALSE activation_action?.remove_action(implant_owner) @@ -150,7 +85,7 @@ implant_owner = null /obj/item/implant/skill/Destroy(force) - unimplantated() + unimplant() QDEL_NULL(activation_action) part?.implants -= src return ..() @@ -173,7 +108,7 @@ name = "close combat codex" desc = "integrated hit support system! Update melee skills!" melee_weapons = 1 - max_skills = list(SKILL_MELEE = SKILL_MELEE_TRAINED) + max_skills = list(SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED) /obj/item/implant/skill/codex name = "CODEX" @@ -210,53 +145,3 @@ desc = "uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" leadership = 1 max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) - -//////////////////////////////[IMPLANTERS]////////////////////////////// - -//////////////////////////////[COMBAT]////////////////////////////// - -/obj/item/implantator/combat - allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) - imp = /obj/item/implant/skill/combat - -/obj/item/implantator/combat/firearms - name = "aiming support" - icon_state = "weapon1" - imp = /obj/item/implant/skill/combat/firearms - -/obj/item/implantator/combat/melee - name = "close combat codex" - icon_state = "melee1" - imp = /obj/item/implant/skill/combat/melee - -//////////////////////////////[SUPPORT]////////////////////////////// - -/obj/item/implantator/codex - allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) - imp = /obj/item/implant/skill/codex - -/obj/item/implantator/codex/medical - name = "medtech" - icon_state = "medical1" - imp = /obj/item/implant/skill/codex/medical - -/obj/item/implantator/codex/surgery - name = "surgery assisting system" - icon_state = "surgery1" - imp = /obj/item/implant/skill/codex/surgery - -/obj/item/implantator/codex/engineer - name = "construction support system" - icon_state = "enginering1" - imp = /obj/item/implant/skill/codex/engineer - -//////////////////////////////[SPECIAL]////////////////////////////// - -/obj/item/implantator/oper_system - allowed_limbs = list(BODY_ZONE_HEAD) - imp = /obj/item/implant/skill/oper_system - -/obj/item/implantator/leadership - name = "command protocols 'Graiyor' codex" - icon_state = "leadership1" - imp = /obj/item/implant/skill/oper_system/leadership diff --git a/code/game/objects/items/implants/implantator_skill.dm b/code/game/objects/items/implants/implantator_skill.dm new file mode 100644 index 00000000000..70120701b99 --- /dev/null +++ b/code/game/objects/items/implants/implantator_skill.dm @@ -0,0 +1,102 @@ +/obj/item/implantator + name = "skill" //teeeeest. + desc = "Used to implant occupants with skill implants." + icon = 'icons/obj/items/implants.dmi' + icon_state = "skill" + item_state = "syringe_0" + item_icons = list( + slot_l_hand_str = 'icons/mob/inhands/equipment/medical_left.dmi', + slot_r_hand_str = 'icons/mob/inhands/equipment/medical_right.dmi', + ) + throw_speed = 1 + throw_range = 5 + w_class = WEIGHT_CLASS_TINY + var/obj/item/implant/internal_implant = /obj/item/implant/skill + var/allowed_limbs + +/obj/item/implantator/Initialize(mapload, ...) + name = name + " implanter" + desc = internal_implant.desc + if(internal_implant) + internal_implant = new internal_implant(src) + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts + +/obj/item/implantator/Destroy() + QDEL_NULL(internal_implant) + return ..() + +/obj/item/implantator/examine(mob/user, distance, infix, suffix) + . = ..() + . += "it contains [internal_implant ? "a [internal_implant.name]" : "no implant"]!" + +/obj/item/implantator/attack(mob/target, mob/user) + if(!ishuman(target)) + return FALSE + if(!internal_implant) + to_chat(user, span_warning("There is no implant in the [src]! НЕТ ИМПЛАНТА")) + return FALSE + if(!(user.zone_selected in allowed_limbs)) + return FALSE + user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) + to_chat(user, span_notice("You failed to implant [target].")) + return FALSE + if(internal_implant.try_implant(target, user)) + target.visible_message(span_warning("[target] has been implanted by [user].")) + log_combat(user, target, "implanted", src) + internal_implant = null + icon_state = "skill0" + return TRUE + to_chat(user, span_notice("You fail to implant [target]. НИЧЕГО НЕ ПРОИЗОШЛО")) + return + +//////////////////////////////[IMPLANTERS]////////////////////////////// + +//////////////////////////////[COMBAT]////////////////////////////// + +/obj/item/implantator/combat + allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) + internal_implant = /obj/item/implant/skill/combat + +/obj/item/implantator/combat/firearms + name = "aiming support" + icon_state = "weapon1" + internal_implant = /obj/item/implant/skill/combat/firearms + +/obj/item/implantator/combat/melee + name = "close combat codex" + icon_state = "melee1" + internal_implant = /obj/item/implant/skill/combat/melee + +//////////////////////////////[SUPPORT]////////////////////////////// + +/obj/item/implantator/codex + allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) + internal_implant = /obj/item/implant/skill/codex + +/obj/item/implantator/codex/medical + name = "medtech" + icon_state = "medical1" + internal_implant = /obj/item/implant/skill/codex/medical + +/obj/item/implantator/codex/surgery + name = "surgery assisting system" + icon_state = "surgery1" + internal_implant = /obj/item/implant/skill/codex/surgery + +/obj/item/implantator/codex/engineer + name = "construction support system" + icon_state = "enginering1" + internal_implant = /obj/item/implant/skill/codex/engineer + +//////////////////////////////[SPECIAL]////////////////////////////// + +/obj/item/implantator/oper_system + allowed_limbs = list(BODY_ZONE_HEAD) + internal_implant = /obj/item/implant/skill/oper_system + +/obj/item/implantator/leadership + name = "command protocols 'Graiyor' codex" + icon_state = "leadership1" + internal_implant = /obj/item/implant/skill/oper_system/leadership diff --git a/tgmc.dme b/tgmc.dme index 4fef74fac66..af13d4c89a9 100644 --- a/tgmc.dme +++ b/tgmc.dme @@ -823,6 +823,7 @@ #include "code\game\objects\items\implants\implant_neurostim.dm" #include "code\game\objects\items\implants\implant_skill.dm" #include "code\game\objects\items\implants\implant_suicidedust.dm" +#include "code\game\objects\items\implants\implantator_skill.dm" #include "code\game\objects\items\implants\implantcase.dm" #include "code\game\objects\items\implants\implantchair.dm" #include "code\game\objects\items\implants\implanter.dm" From 73c37ab539bfca82dab1bb43b0a289655e6697f2 Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Tue, 19 Nov 2024 17:03:14 +0300 Subject: [PATCH 06/42] . = ..() --- code/game/objects/items/implants/implantator_skill.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/game/objects/items/implants/implantator_skill.dm b/code/game/objects/items/implants/implantator_skill.dm index 70120701b99..4a6e4cf9912 100644 --- a/code/game/objects/items/implants/implantator_skill.dm +++ b/code/game/objects/items/implants/implantator_skill.dm @@ -15,6 +15,7 @@ var/allowed_limbs /obj/item/implantator/Initialize(mapload, ...) + . = ..() name = name + " implanter" desc = internal_implant.desc if(internal_implant) @@ -31,6 +32,7 @@ . += "it contains [internal_implant ? "a [internal_implant.name]" : "no implant"]!" /obj/item/implantator/attack(mob/target, mob/user) + . = ..() if(!ishuman(target)) return FALSE if(!internal_implant) From eff6055c686a98ba38f7bcef0bebac9f5d3ffdac Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Tue, 19 Nov 2024 17:18:27 +0300 Subject: [PATCH 07/42] on works.... --- code/game/objects/items/implants/implant.dm | 8 ++++++++ code/game/objects/items/implants/implant_skill.dm | 15 ++------------- .../objects/items/implants/implantator_skill.dm | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index e3129754e7d..8aafa5d6c5e 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -35,6 +35,14 @@ if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts +/obj/item/implant/proc/on_initialize() + if(flags_implant & GRANT_ACTIVATION_ACTION) + activation_action = new(src, src) + if(allow_reagents) + reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) + reagents.my_atom = WEAKREF(src) + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts /obj/item/implant/Destroy(force) unimplant() diff --git a/code/game/objects/items/implants/implant_skill.dm b/code/game/objects/items/implants/implant_skill.dm index 38c424c7cde..fc858eedc08 100644 --- a/code/game/objects/items/implants/implant_skill.dm +++ b/code/game/objects/items/implants/implant_skill.dm @@ -27,15 +27,9 @@ var/large_vehicle var/stamina -/obj/item/implant/skill/proc/starting(mapload) +/obj/item/implant/skill/on_initialize() + . = ..() name = name + " implant" - if(flags_implant & GRANT_ACTIVATION_ACTION) - activation_action = new(src, src) - if(allow_reagents) - reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) - reagents.my_atom = WEAKREF(src) - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) if(!ishuman(target)) @@ -73,11 +67,6 @@ unimplant() /obj/item/implant/skill/unimplant() - if(!implanted) - return FALSE - activation_action?.remove_action(implant_owner) - if(flags_implant & ACTIVATE_ON_HEAR) - UnregisterSignal(src, COMSIG_MOVABLE_HEAR) implanted = FALSE part.implants -= src part = null diff --git a/code/game/objects/items/implants/implantator_skill.dm b/code/game/objects/items/implants/implantator_skill.dm index 4a6e4cf9912..07b835fde23 100644 --- a/code/game/objects/items/implants/implantator_skill.dm +++ b/code/game/objects/items/implants/implantator_skill.dm @@ -98,7 +98,7 @@ allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system -/obj/item/implantator/leadership +/obj/item/implantator/oper_system/leadership name = "command protocols 'Graiyor' codex" icon_state = "leadership1" internal_implant = /obj/item/implant/skill/oper_system/leadership From 9a833dfae94ef1fc46c41310c2f0336202b4eb73 Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Wed, 20 Nov 2024 01:48:47 +0300 Subject: [PATCH 08/42] Fix (minor) --- code/__DEFINES/loadout.dm | 22 +++++++ .../objects/items/implants/implantcase.dm | 38 ++++++++++++ code/game/objects/items/implants/implanter.dm | 32 +++++++++++ .../implant_code.dm} | 49 ++-------------- .../implants/skill_implants/implant_skill.dm | 47 +++++++++++++++ .../implantator_code.dm} | 54 ++++-------------- .../skill_implants/implantator_skill.dm | 45 +++++++++++++++ icons/obj/items/implants.dmi | Bin 5252 -> 7048 bytes tgmc.dme | 6 +- .../tgui/interfaces/MarineSelector.jsx | 5 ++ 10 files changed, 211 insertions(+), 87 deletions(-) rename code/game/objects/items/implants/{implant_skill.dm => skill_implants/implant_code.dm} (58%) create mode 100644 code/game/objects/items/implants/skill_implants/implant_skill.dm rename code/game/objects/items/implants/{implantator_skill.dm => skill_implants/implantator_code.dm} (57%) create mode 100644 code/game/objects/items/implants/skill_implants/implantator_skill.dm diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 93397daaae6..92c03defc42 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -89,6 +89,10 @@ GLOBAL_LIST_INIT(marine_selector_cats, list( #define SANDBAG_PRICE_IN_GEAR_VENDOR 3 GLOBAL_LIST_INIT(marine_gear_listed_products, list( + /obj/item/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 15, "cyan2"), + /obj/item/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 15, "cyan2"), + /obj/item/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), + /obj/item/implantator/codex/engineer = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), /obj/item/storage/backpack/marine/radiopack = list(CAT_MARINE, "Radio Pack", 5, "orange"), /obj/item/storage/belt/marine/auto_catch = list(CAT_MARINE, "M344 pattern ammo load rig", 10, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_MARINE, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -120,6 +124,9 @@ GLOBAL_LIST_INIT(robot_gear_listed_products, list( GLOBAL_LIST_INIT(engineer_gear_listed_products, list( /obj/effect/vendor_bundle/engi = list(CAT_ESS, "Essential Engineer Set", 0, "white"), + /obj/item/implantator/combat/firearms = list(CAT_ENGSUP, "Aiming support implanter", 25, "cyan2"), + /obj/item/implantator/combat/melee = list(CAT_ENGSUP, "Close combat codex implanter", 25, "cyan2"), + /obj/item/implantator/codex/engineer = list(CAT_ENGSUP, "Construction support system implanter", 20, "cyan2"), /obj/item/stack/sheet/metal/small_stack = list(CAT_ENGSUP, "Metal x10", METAL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sheet/plasteel/small_stack = list(CAT_ENGSUP, "Plasteel x10", PLASTEEL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_ENGSUP, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -162,6 +169,10 @@ GLOBAL_LIST_INIT(engineer_gear_listed_products, list( GLOBAL_LIST_INIT(medic_gear_listed_products, list( /obj/effect/vendor_bundle/medic = list(CAT_ESS, "Essential Medic Set", 0, "white"), + /obj/item/implantator/combat/firearms = list(CAT_MEDSUP, "Aiming support implanter", 25, "cyan2"), + /obj/item/implantator/combat/melee = list(CAT_MEDSUP, "Close combat codex implanter", 25, "cyan2"), + /obj/item/implantator/codex/medical = list(CAT_MEDSUP, "Medtech implanter", 20, "cyan2"), + /obj/item/implantator/codex/surgery = list(CAT_MEDSUP, "Surgery assisting system implanter", 20, "cyan2"), /obj/item/reagent_containers/glass/bottle/lemoline/doctor = list(CAT_MEDSUP, "Lemoline bottle", 14, "orange"), /obj/item/storage/pill_bottle/meralyne = list(CAT_MEDSUP, "Meralyne pills", 14, "orange"), /obj/item/storage/pill_bottle/dermaline = list(CAT_MEDSUP, "Dermaline pills", 14, "orange"), @@ -200,6 +211,11 @@ GLOBAL_LIST_INIT(medic_gear_listed_products, list( GLOBAL_LIST_INIT(leader_gear_listed_products, list( /obj/effect/vendor_bundle/leader = list(CAT_ESS, "Essential SL Set", 0, "white"), + /obj/item/implantator/combat/firearms = list(CAT_LEDSUP, "Aiming support implanter", 15, "cyan2"), + /obj/item/implantator/combat/melee = list(CAT_LEDSUP, "Close combat codex implanter", 15, "cyan2"), + /obj/item/implantator/codex/medical = list(CAT_LEDSUP, "Medtech implanter", 15, "cyan2"), + /obj/item/implantator/codex/engineer = list(CAT_LEDSUP, "Construction support system implanter", 15, "cyan2"), + /obj/item/implantator/oper_system/leadership = list(CAT_LEDSUP, "Command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/armor_module/module/valkyrie_autodoc = list(CAT_LEDSUP, "Valkyrie Automedical Armor System", 25,"white"), /obj/effect/vendor_bundle/tyr/two = list(CAT_LEDSUP, "Tyr 2 extra armor set", 25,"white"), /obj/effect/vendor_bundle/mimir/two = list(CAT_LEDSUP, "Mimir 2 extra armor set", 25,"white"), @@ -259,6 +275,12 @@ GLOBAL_LIST_INIT(leader_gear_listed_products, list( GLOBAL_LIST_INIT(commander_gear_listed_products, list( /obj/effect/vendor_bundle/commander = list(CAT_ESS, "Essential FC Set", 0, "white"), + /obj/item/implantator/combat/firearms = list(CAT_FCSUP, "Aiming support implanter", 15, "cyan2"), + /obj/item/implantator/combat/melee = list(CAT_FCSUP, "Close combat codex implanter", 15, "cyan2"), + /obj/item/implantator/codex/medical = list(CAT_FCSUP, "Medtech implanter", 15, "cyan2"), + /obj/item/implantator/codex/surgery = list(CAT_FCSUP, "Surgery assisting system implanter", 15, "cyan2"), + /obj/item/implantator/codex/engineer = list(CAT_FCSUP, "Construction support system implanter", 15, "cyan2"), + /obj/item/implantator/oper_system/leadership/delux = list(CAT_FCSUP, "Delux command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/beacon/supply_beacon = list(CAT_FCSUP, "Supply beacon", 5, "blue"), /obj/item/beacon/orbital_bombardment_beacon = list(CAT_FCSUP, "Orbital beacon", 5, "blue"), /obj/item/fulton_extraction_pack = list(CAT_FCSUP, "Fulton Extraction Pack", 5, "blue"), diff --git a/code/game/objects/items/implants/implantcase.dm b/code/game/objects/items/implants/implantcase.dm index bcb06fffdc1..377145a72d4 100644 --- a/code/game/objects/items/implants/implantcase.dm +++ b/code/game/objects/items/implants/implantcase.dm @@ -81,3 +81,41 @@ I.forceMove(src) imp = I update_icon() + +/obj/item/implantcase/cargo + name = "glass implant case" + desc = "A case containing an implant." + icon = 'icons/obj/items/implants.dmi' + icon_state = "implantcase-0" + var/obj/item/implant/skill/internal_implant + +/obj/item/implantcase/cargo/attackby(obj/item/I, mob/user, params) + . = ..() + if(istype(I, /obj/item/implantator)) + var/obj/item/implantator/M = I + + if(!do_after(user, 5 SECONDS, NONE, user, BUSY_ICON_GENERIC)) + to_chat(user, span_notice("You stop transfering [internal_implant]")) + return FALSE + + if(M.internal_implant) + if((internal_implant || M.internal_implant.implanted)) + return + M.internal_implant.forceMove(src) + internal_implant = M.internal_implant + M.internal_implant = null + + if(internal_implant) + if(M.internal_implant) + return + internal_implant.forceMove(M) + M.internal_implant = internal_implant + internal_implant = null + update_icon() + M.update_icon() + + else if(istype(I, /obj/item/implant/skill)) + user.temporarilyRemoveItemFromInventory(I) + I.forceMove(src) + internal_implant = I + update_icon() diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index c440f349ba4..d2180555071 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -74,3 +74,35 @@ /obj/item/implanter/suicide_dust name = "Self-Gibbing implant" imp = /obj/item/implant/suicide_dust + +/obj/item/implanter/cargo + name = "implanter" + icon_state = "cargo" + var/spent = FALSE + +/obj/item/implanter/cargo/Initialize(mapload, ...) + . = ..() + if(imp) + icon_state = icon_state + "_full" + imp = new imp(src) + +/obj/item/implanter/cargo/attack(mob/target, mob/user) + . = ..() + if(!ishuman(target)) + return FALSE + if(!imp) + to_chat(user, span_warning("There is no implant in the [src]!")) + return FALSE + user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) + + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !imp) + to_chat(user, span_notice("You failed to implant [target].")) + return + + if(imp.try_implant(target, user)) + target.visible_message(span_warning("[target] has been implanted by [user].")) + log_combat(user, target, "implanted", src) + imp = null + icon_state = icon_state + "_s" + return TRUE + to_chat(user, span_notice("You fail to implant [target].")) diff --git a/code/game/objects/items/implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm similarity index 58% rename from code/game/objects/items/implants/implant_skill.dm rename to code/game/objects/items/implants/skill_implants/implant_code.dm index fc858eedc08..564b429e69c 100644 --- a/code/game/objects/items/implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -36,12 +36,10 @@ return for(var/skill in max_skills) if(user.skills.getRating(skill) >= max_skills[skill]) - balloon_alert(user, "You already know it!") - to_chat(user, span_warning("You already know it!")) + to_chat(user, span_warning("You already know [skill]!")) return FALSE - return FALSE if(!(user.zone_selected in allowed_limbs)) - to_chat(user, span_warning("You cannot implant this into that limb! НЕ В СПИСКЕ КОНЕЧНОСТЕЙ")) + to_chat(user, span_warning("You cannot implant this into that limb!")) return FALSE implanted = TRUE return implant(target, user) @@ -68,6 +66,9 @@ /obj/item/implant/skill/unimplant() implanted = FALSE + for(var/skill in max_skills) + if(skill) + skill = -1 part.implants -= src part = null forceMove(get_turf(implant_owner)) @@ -79,58 +80,20 @@ part?.implants -= src return ..() -//////////////////////////////[IMPLANTS]////////////////////////////// - /obj/item/implant/skill/combat name = "combat implants" desc = "Non-game" icon_state = "combat_implant" allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) -/obj/item/implant/skill/combat/firearms - name = "aiming support" - desc = "integrated aiming support system! Update weapons skills!" - firearms = 1 - max_skills = list(SKILL_FIREARMS = SKILL_FIREARMS_TRAINED) - -/obj/item/implant/skill/combat/melee - name = "close combat codex" - desc = "integrated hit support system! Update melee skills!" - melee_weapons = 1 - max_skills = list(SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED) - /obj/item/implant/skill/codex name = "CODEX" desc = "A support skill update-shit." - icon_state = "skill_implant" + icon_state = "support_implant" allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) -/obj/item/implant/skill/codex/medical - name = "medtech" - desc = "A compact device that electro-shakes you every time you apply bandages counterclockwise, right next to your heart! Update medical skills!" - medical = 1 - max_skills = list(SKILL_MEDICAL = SKILL_MEDICAL_COMPETENT) - -/obj/item/implant/skill/codex/surgery - name = "surgery assisting system" - desc = "compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" - surgery = 1 - max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) - -/obj/item/implant/skill/codex/engineer - name = "construction support system" - desc = "laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" - engineer = 1 - max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) - /obj/item/implant/skill/oper_system name = "HEAD SLOT!" desc = "All non-sorted special shit (leadership, probaly SG and more)" icon_state = "skill_implant" allowed_limbs = list(BODY_ZONE_HEAD) - -/obj/item/implant/skill/oper_system/leadership - name = "command protocols 'Graiyor' codex" - desc = "uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" - leadership = 1 - max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm new file mode 100644 index 00000000000..d74066dfd32 --- /dev/null +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -0,0 +1,47 @@ + + +//////////////////////////////[IMPLANTS]////////////////////////////// + +/obj/item/implant/skill/combat/firearms + name = "aiming support" + desc = "integrated aiming support system! Update weapons skills!" + firearms = 1 + max_skills = list(SKILL_FIREARMS = SKILL_FIREARMS_TRAINED) + +/obj/item/implant/skill/combat/melee + name = "close combat codex" + desc = "integrated hit support system! Update melee skills!" + melee_weapons = 1 + max_skills = list(SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED) + +/obj/item/implant/skill/codex/medical + name = "medtech" + desc = "A compact device that electro-shakes you every time you apply bandages counterclockwise, right next to your heart! Update medical skills!" + medical = 1 + max_skills = list(SKILL_MEDICAL = SKILL_MEDICAL_COMPETENT) + +/obj/item/implant/skill/codex/surgery + name = "surgery assisting system" + desc = "compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" + surgery = 1 + max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) + +/obj/item/implant/skill/codex/engineer + name = "construction support system" + desc = "laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" + engineer = 1 + max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) + +/obj/item/implant/skill/oper_system/leadership + name = "command protocols 'Graiyor' codex" + desc = "uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" + icon_state = "leadership_implant" + leadership = 1 + max_skills = list(SKILL_LEAD = SKILL_LEAD_MASTER) + +/obj/item/implant/skill/oper_system/leadership/delux + name = "delux command protocols 'Graiyor' codex" + desc = "uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" + icon_state = "deluxleadership_implant" + leadership = 1 + max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) diff --git a/code/game/objects/items/implants/implantator_skill.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm similarity index 57% rename from code/game/objects/items/implants/implantator_skill.dm rename to code/game/objects/items/implants/skill_implants/implantator_code.dm index 07b835fde23..e359d0c12da 100644 --- a/code/game/objects/items/implants/implantator_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -3,6 +3,7 @@ desc = "Used to implant occupants with skill implants." icon = 'icons/obj/items/implants.dmi' icon_state = "skill" + var/empty_icon = "skill" item_state = "syringe_0" item_icons = list( slot_l_hand_str = 'icons/mob/inhands/equipment/medical_left.dmi', @@ -13,6 +14,7 @@ w_class = WEIGHT_CLASS_TINY var/obj/item/implant/internal_implant = /obj/item/implant/skill var/allowed_limbs + var/spented = FALSE /obj/item/implantator/Initialize(mapload, ...) . = ..() @@ -33,72 +35,40 @@ /obj/item/implantator/attack(mob/target, mob/user) . = ..() + if(spented == TRUE) + return FALSE if(!ishuman(target)) return FALSE if(!internal_implant) - to_chat(user, span_warning("There is no implant in the [src]! НЕТ ИМПЛАНТА")) + to_chat(user, span_warning("There is no implant in the [src]!")) return FALSE if(!(user.zone_selected in allowed_limbs)) + balloon_alert(user, "wrong limb!") return FALSE user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC)) to_chat(user, span_notice("You failed to implant [target].")) return FALSE if(internal_implant.try_implant(target, user)) target.visible_message(span_warning("[target] has been implanted by [user].")) log_combat(user, target, "implanted", src) internal_implant = null - icon_state = "skill0" + name = name + "used" + desc = desc + "It's spent." + icon_state = empty_icon + "_s" + spented = TRUE return TRUE - to_chat(user, span_notice("You fail to implant [target]. НИЧЕГО НЕ ПРОИЗОШЛО")) + to_chat(user, span_notice("You fail to implant [target].")) return -//////////////////////////////[IMPLANTERS]////////////////////////////// - -//////////////////////////////[COMBAT]////////////////////////////// - /obj/item/implantator/combat allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) internal_implant = /obj/item/implant/skill/combat -/obj/item/implantator/combat/firearms - name = "aiming support" - icon_state = "weapon1" - internal_implant = /obj/item/implant/skill/combat/firearms - -/obj/item/implantator/combat/melee - name = "close combat codex" - icon_state = "melee1" - internal_implant = /obj/item/implant/skill/combat/melee - -//////////////////////////////[SUPPORT]////////////////////////////// - /obj/item/implantator/codex allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) internal_implant = /obj/item/implant/skill/codex -/obj/item/implantator/codex/medical - name = "medtech" - icon_state = "medical1" - internal_implant = /obj/item/implant/skill/codex/medical - -/obj/item/implantator/codex/surgery - name = "surgery assisting system" - icon_state = "surgery1" - internal_implant = /obj/item/implant/skill/codex/surgery - -/obj/item/implantator/codex/engineer - name = "construction support system" - icon_state = "enginering1" - internal_implant = /obj/item/implant/skill/codex/engineer - -//////////////////////////////[SPECIAL]////////////////////////////// - /obj/item/implantator/oper_system allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system - -/obj/item/implantator/oper_system/leadership - name = "command protocols 'Graiyor' codex" - icon_state = "leadership1" - internal_implant = /obj/item/implant/skill/oper_system/leadership diff --git a/code/game/objects/items/implants/skill_implants/implantator_skill.dm b/code/game/objects/items/implants/skill_implants/implantator_skill.dm new file mode 100644 index 00000000000..b2069ba6f00 --- /dev/null +++ b/code/game/objects/items/implants/skill_implants/implantator_skill.dm @@ -0,0 +1,45 @@ + +//////////////////////////////[IMPLANTERS]////////////////////////////// + +//////////////////////////////[COMBAT]////////////////////////////// + +/obj/item/implantator/combat/firearms + name = "aiming support" + icon_state = "weapon" + internal_implant = /obj/item/implant/skill/combat/firearms + +/obj/item/implantator/combat/melee + name = "close combat codex" + icon_state = "melee" + internal_implant = /obj/item/implant/skill/combat/melee + +//////////////////////////////[SUPPORT]////////////////////////////// + +/obj/item/implantator/codex/medical + name = "medtech" + icon_state = "medical" + internal_implant = /obj/item/implant/skill/codex/medical + +/obj/item/implantator/codex/surgery + name = "surgery assisting system" + icon_state = "surgery" + internal_implant = /obj/item/implant/skill/codex/surgery + +/obj/item/implantator/codex/engineer + name = "construction support system" + icon_state = "enginering" + internal_implant = /obj/item/implant/skill/codex/engineer + +//////////////////////////////[SPECIAL]////////////////////////////// + +/obj/item/implantator/oper_system/leadership + name = "command protocols 'Graiyor' codex" + icon_state = "leadership" + empty_icon = "leadership" + internal_implant = /obj/item/implant/skill/oper_system/leadership + +/obj/item/implantator/oper_system/leadership/delux + name = "delux command protocols 'Graiyor' codex" + icon_state = "deluxleadership" + empty_icon = "deluxleadership" + internal_implant = /obj/item/implant/skill/oper_system/leadership/delux diff --git a/icons/obj/items/implants.dmi b/icons/obj/items/implants.dmi index 7f173c6656d0c441f51b09d1c04fcb82fe6accf4..868903ea96e40e5c539b7848c838b2f6df971f15 100644 GIT binary patch literal 7048 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 B!`1)* literal 5252 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 UJpH^!yj=tysOzfLs@O*S7k1V0_W%F@ diff --git a/tgmc.dme b/tgmc.dme index af13d4c89a9..85a0edc06fe 100644 --- a/tgmc.dme +++ b/tgmc.dme @@ -821,9 +821,11 @@ #include "code\game\objects\items\implants\implant_cloak.dm" #include "code\game\objects\items\implants\implant_items.dm" #include "code\game\objects\items\implants\implant_neurostim.dm" -#include "code\game\objects\items\implants\implant_skill.dm" +#include "code\game\objects\items\implants\skill_implants\implant_code.dm" +#include "code\game\objects\items\implants\skill_implants\implant_skill.dm" #include "code\game\objects\items\implants\implant_suicidedust.dm" -#include "code\game\objects\items\implants\implantator_skill.dm" +#include "code\game\objects\items\implants\skill_implants\implantator_code.dm" +#include "code\game\objects\items\implants\skill_implants\implantator_skill.dm" #include "code\game\objects\items\implants\implantcase.dm" #include "code\game\objects\items\implants\implantchair.dm" #include "code\game\objects\items\implants\implanter.dm" diff --git a/tgui/packages/tgui/interfaces/MarineSelector.jsx b/tgui/packages/tgui/interfaces/MarineSelector.jsx index ed5c92d3d89..32e4cc15aa9 100644 --- a/tgui/packages/tgui/interfaces/MarineSelector.jsx +++ b/tgui/packages/tgui/interfaces/MarineSelector.jsx @@ -189,6 +189,11 @@ const ItemLine = (props) => { Medicine )} + {prod_color === 'cyan2' && ( + + Implant + + )} {prod_color === 'red' && ( Weapon From 614642f23a688cab5311024e57c22b8b755cf28b Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Fri, 22 Nov 2024 16:41:33 +0300 Subject: [PATCH 09/42] Fix again. --- code/game/objects/items/implants/implanter.dm | 13 ++- .../implants/skill_implants/implant_code.dm | 100 ++++++++++++++++-- .../implants/skill_implants/implant_skill.dm | 1 - .../skill_implants/implantator_code.dm | 5 + tgmc.dme | 2 +- 5 files changed, 110 insertions(+), 11 deletions(-) diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index d2180555071..00a2eeaff34 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -79,30 +79,39 @@ name = "implanter" icon_state = "cargo" var/spent = FALSE + var/allowed_limbs /obj/item/implanter/cargo/Initialize(mapload, ...) . = ..() if(imp) icon_state = icon_state + "_full" + desc = imp.desc imp = new imp(src) + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts /obj/item/implanter/cargo/attack(mob/target, mob/user) . = ..() if(!ishuman(target)) return FALSE + if(spent == TRUE) + balloon_alert(user, "already used!") + return FALSE if(!imp) to_chat(user, span_warning("There is no implant in the [src]!")) return FALSE + if(!(user.zone_selected in allowed_limbs)) + balloon_alert(user, "wrong limb!") + return FALSE user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !imp) to_chat(user, span_notice("You failed to implant [target].")) return - if(imp.try_implant(target, user)) target.visible_message(span_warning("[target] has been implanted by [user].")) log_combat(user, target, "implanted", src) imp = null + spent = TRUE icon_state = icon_state + "_s" return TRUE to_chat(user, span_notice("You fail to implant [target].")) diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index 564b429e69c..714e015abcb 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -5,6 +5,7 @@ icon_state = "implant" w_class = WEIGHT_CLASS_TINY var/list/max_skills + var/storage_skill = null //pamplet copy-past. :clueless: var/cqc var/melee_weapons @@ -34,10 +35,6 @@ /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) if(!ishuman(target)) return - for(var/skill in max_skills) - if(user.skills.getRating(skill) >= max_skills[skill]) - to_chat(user, span_warning("You already know [skill]!")) - return FALSE if(!(user.zone_selected in allowed_limbs)) to_chat(user, span_warning("You cannot implant this into that limb!")) return FALSE @@ -48,6 +45,7 @@ forceMove(target) implant_owner = target implanted = TRUE + skillmod(implant_owner) var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) var/datum/limb/affected = target.get_limb(limb_targeting) if(!affected) @@ -65,15 +63,103 @@ unimplant() /obj/item/implant/skill/unimplant() + if(!implanted) + return FALSE + activation_action?.remove_action(implant_owner) implanted = FALSE - for(var/skill in max_skills) - if(skill) - skill = -1 part.implants -= src part = null + skillmod(implant_owner) + implant_owner.set_skills(implant_owner.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ + engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) forceMove(get_turf(implant_owner)) implant_owner = null +/obj/item/implant/skill/proc/skillmod(mob/living/carbon/human/target, mob/living/user) + if(!implanted) + if(cqc == 1) + cqc = -1 + if(melee_weapons == 1) + melee_weapons = -1 + if(firearms == 1) + firearms = -1 + if(pistols == 1) + pistols = -1 + if(shotguns == 1) + shotguns = -1 + if(rifles == 1) + rifles = -1 + if(smgs == 1) + smgs = -1 + if(heavy_weapons == 1) + heavy_weapons = -1 + if(swordplay == 1) + swordplay = -1 + if(smartgun == 1) + smartgun = -1 + if(engineer == 1) + engineer = -1 + if(construction == 1) + construction = -1 + if(leadership == 1) + leadership = -1 + if(medical == 1) + medical = -1 + if(surgery == 1) + surgery = -1 + if(pilot == 1) + pilot = -1 + if(police == 1) + police = -1 + if(powerloader == 1) + powerloader = -1 + if(large_vehicle == 1) + large_vehicle = -1 + if(stamina == 1) + stamina = -1 + else + if(cqc == -1) + cqc = 1 + if(melee_weapons == -1) + melee_weapons = 1 + if(firearms == -1) + firearms = 1 + if(pistols == -1) + pistols = 1 + if(shotguns == -1) + shotguns = 1 + if(rifles == -1) + rifles = 1 + if(smgs == -1) + smgs = 1 + if(heavy_weapons == -1) + heavy_weapons = 1 + if(swordplay == -1) + swordplay = 1 + if(smartgun == -1) + smartgun = 1 + if(engineer == -1) + engineer = 1 + if(construction == -1) + construction = 1 + if(leadership == -1) + leadership = 1 + if(medical == -1) + medical = 1 + if(surgery == -1) + surgery = 1 + if(pilot == -1) + pilot = 1 + if(police == -1) + police = 1 + if(powerloader == -1) + powerloader = 1 + if(large_vehicle == -1) + large_vehicle = 1 + if(stamina == -1) + stamina = 1 + return + /obj/item/implant/skill/Destroy(force) unimplant() QDEL_NULL(activation_action) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index d74066dfd32..368d000c33d 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -43,5 +43,4 @@ name = "delux command protocols 'Graiyor' codex" desc = "uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" icon_state = "deluxleadership_implant" - leadership = 1 max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index e359d0c12da..5fb27b926b0 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -15,6 +15,7 @@ var/obj/item/implant/internal_implant = /obj/item/implant/skill var/allowed_limbs var/spented = FALSE + var/max_skills /obj/item/implantator/Initialize(mapload, ...) . = ..() @@ -45,6 +46,10 @@ if(!(user.zone_selected in allowed_limbs)) balloon_alert(user, "wrong limb!") return FALSE + for(var/skill in max_skills) + if(user.skills.getRating(skill) >= max_skills[skill]) + to_chat(user, span_warning("You already know [skill]!")) + return FALSE user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC)) to_chat(user, span_notice("You failed to implant [target].")) diff --git a/tgmc.dme b/tgmc.dme index 85a0edc06fe..65aaeecb5ed 100644 --- a/tgmc.dme +++ b/tgmc.dme @@ -823,9 +823,9 @@ #include "code\game\objects\items\implants\implant_neurostim.dm" #include "code\game\objects\items\implants\skill_implants\implant_code.dm" #include "code\game\objects\items\implants\skill_implants\implant_skill.dm" -#include "code\game\objects\items\implants\implant_suicidedust.dm" #include "code\game\objects\items\implants\skill_implants\implantator_code.dm" #include "code\game\objects\items\implants\skill_implants\implantator_skill.dm" +#include "code\game\objects\items\implants\implant_suicidedust.dm" #include "code\game\objects\items\implants\implantcase.dm" #include "code\game\objects\items\implants\implantchair.dm" #include "code\game\objects\items\implants\implanter.dm" From 1d21c98ff3056c52add8ef0c9b38de7188e6daf7 Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Sat, 23 Nov 2024 20:57:34 +0300 Subject: [PATCH 10/42] I BECOME MADNESS --- code/game/objects/items/implants/implanter.dm | 28 ++++++++++++++++--- .../skill_implants/implantator_code.dm | 17 +++++++---- tgmc.dme | 8 +++--- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 00a2eeaff34..434c71f66bf 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -80,17 +80,33 @@ icon_state = "cargo" var/spent = FALSE var/allowed_limbs + var/list/implants /obj/item/implanter/cargo/Initialize(mapload, ...) . = ..() + update_icon_state() if(imp) - icon_state = icon_state + "_full" + update_icon_state() desc = imp.desc imp = new imp(src) if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts -/obj/item/implanter/cargo/attack(mob/target, mob/user) +/obj/item/implanter/cargo/update_icon_state() + . = ..() + icon_state = "cargo" + if(imp) + icon_state = "cargo_full" + if(!imp) + icon_state = "cargo_s" + +/obj/item/implanter/cargo/proc/has_implant(datum/limb/targetlimb) + for (var/obj/item/implant/skill/I in targetlimb.implants) + if(!is_type_in_list(I, GLOB.known_implants)) + return TRUE + return FALSE + +/obj/item/implanter/cargo/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) . = ..() if(!ishuman(target)) return FALSE @@ -103,15 +119,19 @@ if(!(user.zone_selected in allowed_limbs)) balloon_alert(user, "wrong limb!") return FALSE + for(i in user.zone_selected) + has_implant(targetlimb) + balloon_alert(user, "limb already implanted!") + return FALSE user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !imp) to_chat(user, span_notice("You failed to implant [target].")) - return + return FALSE if(imp.try_implant(target, user)) target.visible_message(span_warning("[target] has been implanted by [user].")) log_combat(user, target, "implanted", src) imp = null spent = TRUE - icon_state = icon_state + "_s" + update_icon_state() return TRUE to_chat(user, span_notice("You fail to implant [target].")) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 5fb27b926b0..6979108267b 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -16,6 +16,7 @@ var/allowed_limbs var/spented = FALSE var/max_skills + var/list/implants /obj/item/implantator/Initialize(mapload, ...) . = ..() @@ -34,7 +35,13 @@ . = ..() . += "it contains [internal_implant ? "a [internal_implant.name]" : "no implant"]!" -/obj/item/implantator/attack(mob/target, mob/user) +/obj/item/implantator/proc/has_implant(datum/limb/targetlimb) + for (var/obj/item/implant/skill/I in targetlimb.implants) + if(!is_type_in_list(I, GLOB.known_implants)) + return TRUE + return FALSE + +/obj/item/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) . = ..() if(spented == TRUE) return FALSE @@ -46,10 +53,10 @@ if(!(user.zone_selected in allowed_limbs)) balloon_alert(user, "wrong limb!") return FALSE - for(var/skill in max_skills) - if(user.skills.getRating(skill) >= max_skills[skill]) - to_chat(user, span_warning("You already know [skill]!")) - return FALSE + for(i in user.zone_selected) + has_implant(targetlimb) + balloon_alert(user, "limb already implanted!") + return FALSE user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC)) to_chat(user, span_notice("You failed to implant [target].")) diff --git a/tgmc.dme b/tgmc.dme index 65aaeecb5ed..647c3e437d4 100644 --- a/tgmc.dme +++ b/tgmc.dme @@ -821,15 +821,15 @@ #include "code\game\objects\items\implants\implant_cloak.dm" #include "code\game\objects\items\implants\implant_items.dm" #include "code\game\objects\items\implants\implant_neurostim.dm" -#include "code\game\objects\items\implants\skill_implants\implant_code.dm" -#include "code\game\objects\items\implants\skill_implants\implant_skill.dm" -#include "code\game\objects\items\implants\skill_implants\implantator_code.dm" -#include "code\game\objects\items\implants\skill_implants\implantator_skill.dm" #include "code\game\objects\items\implants\implant_suicidedust.dm" #include "code\game\objects\items\implants\implantcase.dm" #include "code\game\objects\items\implants\implantchair.dm" #include "code\game\objects\items\implants\implanter.dm" #include "code\game\objects\items\implants\implantpad.dm" +#include "code\game\objects\items\implants\skill_implants\implant_code.dm" +#include "code\game\objects\items\implants\skill_implants\implant_skill.dm" +#include "code\game\objects\items\implants\skill_implants\implantator_code.dm" +#include "code\game\objects\items\implants\skill_implants\implantator_skill.dm" #include "code\game\objects\items\radio\beacon.dm" #include "code\game\objects\items\radio\detpack.dm" #include "code\game\objects\items\radio\electropack.dm" From f243683bbf2972153d5f133b1c6226837934804c Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Sat, 23 Nov 2024 21:02:45 +0300 Subject: [PATCH 11/42] Fix --- code/game/objects/items/implants/implant.dm | 2 -- code/game/objects/items/implants/skill_implants/implant_code.dm | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 8aafa5d6c5e..1017ee866e3 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -41,8 +41,6 @@ if(allow_reagents) reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) reagents.my_atom = WEAKREF(src) - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts /obj/item/implant/Destroy(force) unimplant() diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index 714e015abcb..b1fa90a79b8 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -31,6 +31,8 @@ /obj/item/implant/skill/on_initialize() . = ..() name = name + " implant" + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) if(!ishuman(target)) From abdb988cdedff20a5d1027014bfe141fea805aec Mon Sep 17 00:00:00 2001 From: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:34:58 +0300 Subject: [PATCH 12/42] Update code/game/objects/items/implants/skill_implants/implant_skill.dm Co-authored-by: Helg2 <93882977+Helg2@users.noreply.github.com> Signed-off-by: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> --- .../objects/items/implants/skill_implants/implant_skill.dm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index 368d000c33d..4a75c3c2c90 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -1,7 +1,3 @@ - - -//////////////////////////////[IMPLANTS]////////////////////////////// - /obj/item/implant/skill/combat/firearms name = "aiming support" desc = "integrated aiming support system! Update weapons skills!" From 4b8a61775c3cdaacb91c6d74e510b89169d3fea2 Mon Sep 17 00:00:00 2001 From: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> Date: Mon, 25 Nov 2024 16:35:14 +0300 Subject: [PATCH 13/42] Update code/game/objects/items/implants/skill_implants/implantator_skill.dm Co-authored-by: Helg2 <93882977+Helg2@users.noreply.github.com> Signed-off-by: Dark-Umbrella <105446446+Dark-Umbrella@users.noreply.github.com> --- .../objects/items/implants/skill_implants/implantator_skill.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/game/objects/items/implants/skill_implants/implantator_skill.dm b/code/game/objects/items/implants/skill_implants/implantator_skill.dm index b2069ba6f00..c6c7e85866b 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_skill.dm @@ -1,6 +1,3 @@ - -//////////////////////////////[IMPLANTERS]////////////////////////////// - //////////////////////////////[COMBAT]////////////////////////////// /obj/item/implantator/combat/firearms From a72db2988378878e377213a86a1fd56d430f2b5f Mon Sep 17 00:00:00 2001 From: Dark-Umbrella Date: Mon, 25 Nov 2024 16:59:00 +0300 Subject: [PATCH 14/42] Fix --- code/__DEFINES/loadout.dm | 44 ++++---- .../objects/items/implants/implantcase.dm | 47 ++++---- code/game/objects/items/implants/implanter.dm | 50 ++++----- .../implants/skill_implants/implant_code.dm | 106 +----------------- .../skill_implants/implantator_code.dm | 30 ++--- .../skill_implants/implantator_skill.dm | 14 +-- 6 files changed, 95 insertions(+), 196 deletions(-) diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 92c03defc42..5402447fc7b 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -89,10 +89,10 @@ GLOBAL_LIST_INIT(marine_selector_cats, list( #define SANDBAG_PRICE_IN_GEAR_VENDOR 3 GLOBAL_LIST_INIT(marine_gear_listed_products, list( - /obj/item/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 15, "cyan2"), - /obj/item/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 15, "cyan2"), - /obj/item/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), - /obj/item/implantator/codex/engineer = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 15, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), /obj/item/storage/backpack/marine/radiopack = list(CAT_MARINE, "Radio Pack", 5, "orange"), /obj/item/storage/belt/marine/auto_catch = list(CAT_MARINE, "M344 pattern ammo load rig", 10, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_MARINE, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -124,9 +124,9 @@ GLOBAL_LIST_INIT(robot_gear_listed_products, list( GLOBAL_LIST_INIT(engineer_gear_listed_products, list( /obj/effect/vendor_bundle/engi = list(CAT_ESS, "Essential Engineer Set", 0, "white"), - /obj/item/implantator/combat/firearms = list(CAT_ENGSUP, "Aiming support implanter", 25, "cyan2"), - /obj/item/implantator/combat/melee = list(CAT_ENGSUP, "Close combat codex implanter", 25, "cyan2"), - /obj/item/implantator/codex/engineer = list(CAT_ENGSUP, "Construction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_ENGSUP, "Aiming support implanter", 25, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_ENGSUP, "Close combat codex implanter", 25, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_ENGSUP, "Construction support system implanter", 20, "cyan2"), /obj/item/stack/sheet/metal/small_stack = list(CAT_ENGSUP, "Metal x10", METAL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sheet/plasteel/small_stack = list(CAT_ENGSUP, "Plasteel x10", PLASTEEL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_ENGSUP, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -169,10 +169,10 @@ GLOBAL_LIST_INIT(engineer_gear_listed_products, list( GLOBAL_LIST_INIT(medic_gear_listed_products, list( /obj/effect/vendor_bundle/medic = list(CAT_ESS, "Essential Medic Set", 0, "white"), - /obj/item/implantator/combat/firearms = list(CAT_MEDSUP, "Aiming support implanter", 25, "cyan2"), - /obj/item/implantator/combat/melee = list(CAT_MEDSUP, "Close combat codex implanter", 25, "cyan2"), - /obj/item/implantator/codex/medical = list(CAT_MEDSUP, "Medtech implanter", 20, "cyan2"), - /obj/item/implantator/codex/surgery = list(CAT_MEDSUP, "Surgery assisting system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_MEDSUP, "Aiming support implanter", 25, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_MEDSUP, "Close combat codex implanter", 25, "cyan2"), + /obj/item/implanter/implantator/codex/medical = list(CAT_MEDSUP, "Medtech implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/surgery = list(CAT_MEDSUP, "Surgery assisting system implanter", 20, "cyan2"), /obj/item/reagent_containers/glass/bottle/lemoline/doctor = list(CAT_MEDSUP, "Lemoline bottle", 14, "orange"), /obj/item/storage/pill_bottle/meralyne = list(CAT_MEDSUP, "Meralyne pills", 14, "orange"), /obj/item/storage/pill_bottle/dermaline = list(CAT_MEDSUP, "Dermaline pills", 14, "orange"), @@ -211,11 +211,11 @@ GLOBAL_LIST_INIT(medic_gear_listed_products, list( GLOBAL_LIST_INIT(leader_gear_listed_products, list( /obj/effect/vendor_bundle/leader = list(CAT_ESS, "Essential SL Set", 0, "white"), - /obj/item/implantator/combat/firearms = list(CAT_LEDSUP, "Aiming support implanter", 15, "cyan2"), - /obj/item/implantator/combat/melee = list(CAT_LEDSUP, "Close combat codex implanter", 15, "cyan2"), - /obj/item/implantator/codex/medical = list(CAT_LEDSUP, "Medtech implanter", 15, "cyan2"), - /obj/item/implantator/codex/engineer = list(CAT_LEDSUP, "Construction support system implanter", 15, "cyan2"), - /obj/item/implantator/oper_system/leadership = list(CAT_LEDSUP, "Command protocols 'Graiyor' codex loader", 20, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_LEDSUP, "Aiming support implanter", 15, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_LEDSUP, "Close combat codex implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/medical = list(CAT_LEDSUP, "Medtech implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_LEDSUP, "Construction support system implanter", 15, "cyan2"), + /obj/item/implanter/implantator/oper_system/leadership = list(CAT_LEDSUP, "Command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/armor_module/module/valkyrie_autodoc = list(CAT_LEDSUP, "Valkyrie Automedical Armor System", 25,"white"), /obj/effect/vendor_bundle/tyr/two = list(CAT_LEDSUP, "Tyr 2 extra armor set", 25,"white"), /obj/effect/vendor_bundle/mimir/two = list(CAT_LEDSUP, "Mimir 2 extra armor set", 25,"white"), @@ -275,12 +275,12 @@ GLOBAL_LIST_INIT(leader_gear_listed_products, list( GLOBAL_LIST_INIT(commander_gear_listed_products, list( /obj/effect/vendor_bundle/commander = list(CAT_ESS, "Essential FC Set", 0, "white"), - /obj/item/implantator/combat/firearms = list(CAT_FCSUP, "Aiming support implanter", 15, "cyan2"), - /obj/item/implantator/combat/melee = list(CAT_FCSUP, "Close combat codex implanter", 15, "cyan2"), - /obj/item/implantator/codex/medical = list(CAT_FCSUP, "Medtech implanter", 15, "cyan2"), - /obj/item/implantator/codex/surgery = list(CAT_FCSUP, "Surgery assisting system implanter", 15, "cyan2"), - /obj/item/implantator/codex/engineer = list(CAT_FCSUP, "Construction support system implanter", 15, "cyan2"), - /obj/item/implantator/oper_system/leadership/delux = list(CAT_FCSUP, "Delux command protocols 'Graiyor' codex loader", 20, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_FCSUP, "Aiming support implanter", 15, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_FCSUP, "Close combat codex implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/medical = list(CAT_FCSUP, "Medtech implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/surgery = list(CAT_FCSUP, "Surgery assisting system implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_FCSUP, "Construction support system implanter", 15, "cyan2"), + /obj/item/implanter/implantator/oper_system/leadership/delux = list(CAT_FCSUP, "Delux command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/beacon/supply_beacon = list(CAT_FCSUP, "Supply beacon", 5, "blue"), /obj/item/beacon/orbital_bombardment_beacon = list(CAT_FCSUP, "Orbital beacon", 5, "blue"), /obj/item/fulton_extraction_pack = list(CAT_FCSUP, "Fulton Extraction Pack", 5, "blue"), diff --git a/code/game/objects/items/implants/implantcase.dm b/code/game/objects/items/implants/implantcase.dm index 377145a72d4..abd3aae02a2 100644 --- a/code/game/objects/items/implants/implantcase.dm +++ b/code/game/objects/items/implants/implantcase.dm @@ -11,23 +11,23 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - var/obj/item/implant/imp + var/obj/item/implant/internal_implant -/obj/item/implantcase/Initialize(mapload, imp) +/obj/item/implantcase/Initialize(mapload, internal_implant) . = ..() - if(imp) - imp = new imp(src) + if(internal_implant) + internal_implant = new internal_implant(src) update_icon() /obj/item/implantcase/Destroy() - QDEL_NULL(imp) + QDEL_NULL(internal_implant) return ..() /obj/item/implantcase/update_icon_state() . = ..() - if(imp) - icon_state = "implantcase-[imp.implant_color]" + if(internal_implant) + icon_state = "implantcase-[internal_implant.implant_color]" else icon_state = "implantcase-0" @@ -47,31 +47,31 @@ name = initial(name) else if(istype(I, /obj/item/reagent_containers/syringe)) - if(!imp?.allow_reagents) + if(!internal_implant?.allow_reagents) return - if(imp.reagents.total_volume >= imp.reagents.maximum_volume) + if(internal_implant.reagents.total_volume >= internal_implant.reagents.maximum_volume) to_chat(user, span_warning("[src] is full.")) return - I.reagents.trans_to(imp, 5) + I.reagents.trans_to(internal_implant, 5) to_chat(user, span_notice("You inject 5 units of the solution. The syringe now contains [I.reagents.total_volume] units.")) else if(istype(I, /obj/item/implanter)) var/obj/item/implanter/M = I - if(M.imp) - if((imp || M.imp.implanted)) + if(M.internal_implant) + if((internal_implant || M.internal_implant.implanted)) return - M.imp.forceMove(src) - imp = M.imp - M.imp = null + M.internal_implant.forceMove(src) + internal_implant = M.internal_implant + M.internal_implant = null - else if(imp) - if(M.imp) + else if(internal_implant) + if(M.internal_implant) return - imp.forceMove(M) - M.imp = imp - imp = null + internal_implant.forceMove(M) + M.internal_implant = internal_implant + internal_implant = null update_icon() M.update_icon() @@ -79,7 +79,7 @@ else if(istype(I, /obj/item/implant)) user.temporarilyRemoveItemFromInventory(I) I.forceMove(src) - imp = I + internal_implant = I update_icon() /obj/item/implantcase/cargo @@ -87,12 +87,11 @@ desc = "A case containing an implant." icon = 'icons/obj/items/implants.dmi' icon_state = "implantcase-0" - var/obj/item/implant/skill/internal_implant /obj/item/implantcase/cargo/attackby(obj/item/I, mob/user, params) . = ..() - if(istype(I, /obj/item/implantator)) - var/obj/item/implantator/M = I + if(istype(I, /obj/item/implanter/implantator)) + var/obj/item/implanter/implantator/M = I if(!do_after(user, 5 SECONDS, NONE, user, BUSY_ICON_GENERIC)) to_chat(user, span_notice("You stop transfering [internal_implant]")) diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 434c71f66bf..001c01ee8c2 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -10,70 +10,70 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - var/obj/item/implant/imp = null + var/obj/item/implant/internal_implant = null /obj/item/implanter/Initialize(mapload, ...) . = ..() - if(imp) - imp = new imp(src) + if(internal_implant) + internal_implant = new internal_implant(src) update_icon() /obj/item/implanter/Destroy() - QDEL_NULL(imp) + QDEL_NULL(internal_implant) return ..() /obj/item/implanter/update_icon_state() . = ..() - icon_state = "implanter[imp?"1":"0"]" + icon_state = "implanter[internal_implant?"1":"0"]" /obj/item/implanter/examine(mob/user, distance, infix, suffix) . = ..() - . += "it contains [imp ? "a [imp.name]" : "no implant"]!" + . += "it contains [internal_implant ? "a [internal_implant.name]" : "no implant"]!" /obj/item/implanter/attack(mob/target, mob/user) . = ..() if(!ishuman(target)) return FALSE - if(!imp) + if(!internal_implant) to_chat(user, span_warning("There is no implant in the [src]!")) return FALSE user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !imp) + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) to_chat(user, span_notice("You failed to implant [target].")) return - if(imp.try_implant(target, user)) + if(internal_implant.try_implant(target, user)) target.visible_message(span_warning("[target] has been implanted by [user].")) log_combat(user, target, "implanted", src) - imp = null + internal_implant = null update_icon() return TRUE to_chat(user, span_notice("You fail to implant [target].")) /obj/item/implanter/neurostim name = "neurostim implanter" - imp = /obj/item/implant/neurostim + internal_implant = /obj/item/implant/neurostim /obj/item/implanter/chem name = "chem implant implanter" - imp = /obj/item/implant/chem + internal_implant = /obj/item/implant/chem /obj/item/implanter/chem/blood name = "blood recovery implant implanter" - imp = /obj/item/implant/chem/blood + internal_implant = /obj/item/implant/chem/blood /obj/item/implanter/cloak name = "cloak implant implanter" - imp = /obj/item/implant/cloak + internal_implant = /obj/item/implant/cloak /obj/item/implanter/blade name = "blade implant implanter" - imp = /obj/item/implant/deployitem/blade + internal_implant = /obj/item/implant/deployitem/blade /obj/item/implanter/suicide_dust name = "Self-Gibbing implant" - imp = /obj/item/implant/suicide_dust + internal_implant = /obj/item/implant/suicide_dust /obj/item/implanter/cargo name = "implanter" @@ -85,19 +85,19 @@ /obj/item/implanter/cargo/Initialize(mapload, ...) . = ..() update_icon_state() - if(imp) + if(internal_implant) update_icon_state() - desc = imp.desc - imp = new imp(src) + desc = internal_implant.desc + internal_implant = new internal_implant(src) if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts /obj/item/implanter/cargo/update_icon_state() . = ..() icon_state = "cargo" - if(imp) + if(internal_implant) icon_state = "cargo_full" - if(!imp) + if(!internal_implant) icon_state = "cargo_s" /obj/item/implanter/cargo/proc/has_implant(datum/limb/targetlimb) @@ -113,7 +113,7 @@ if(spent == TRUE) balloon_alert(user, "already used!") return FALSE - if(!imp) + if(!internal_implant) to_chat(user, span_warning("There is no implant in the [src]!")) return FALSE if(!(user.zone_selected in allowed_limbs)) @@ -124,13 +124,13 @@ balloon_alert(user, "limb already implanted!") return FALSE user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !imp) + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) to_chat(user, span_notice("You failed to implant [target].")) return FALSE - if(imp.try_implant(target, user)) + if(internal_implant.try_implant(target, user)) target.visible_message(span_warning("[target] has been implanted by [user].")) log_combat(user, target, "implanted", src) - imp = null + internal_implant = null spent = TRUE update_icon_state() return TRUE diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index b1fa90a79b8..df77e8fd37d 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -28,12 +28,15 @@ var/large_vehicle var/stamina -/obj/item/implant/skill/on_initialize() +/obj/item/implant/skill/Initialize() . = ..() name = name + " implant" if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts +/obj/item/implant/skill/on_initialize() + return + /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) if(!ishuman(target)) return @@ -47,7 +50,6 @@ forceMove(target) implant_owner = target implanted = TRUE - skillmod(implant_owner) var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) var/datum/limb/affected = target.get_limb(limb_targeting) if(!affected) @@ -60,10 +62,6 @@ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) return TRUE -/obj/item/implant/skill/unembed_ourself() - . = ..() - unimplant() - /obj/item/implant/skill/unimplant() if(!implanted) return FALSE @@ -71,103 +69,11 @@ implanted = FALSE part.implants -= src part = null - skillmod(implant_owner) - implant_owner.set_skills(implant_owner.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ - engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) + implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -swordplay, -smartgun,\ + -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -stamina)) forceMove(get_turf(implant_owner)) implant_owner = null -/obj/item/implant/skill/proc/skillmod(mob/living/carbon/human/target, mob/living/user) - if(!implanted) - if(cqc == 1) - cqc = -1 - if(melee_weapons == 1) - melee_weapons = -1 - if(firearms == 1) - firearms = -1 - if(pistols == 1) - pistols = -1 - if(shotguns == 1) - shotguns = -1 - if(rifles == 1) - rifles = -1 - if(smgs == 1) - smgs = -1 - if(heavy_weapons == 1) - heavy_weapons = -1 - if(swordplay == 1) - swordplay = -1 - if(smartgun == 1) - smartgun = -1 - if(engineer == 1) - engineer = -1 - if(construction == 1) - construction = -1 - if(leadership == 1) - leadership = -1 - if(medical == 1) - medical = -1 - if(surgery == 1) - surgery = -1 - if(pilot == 1) - pilot = -1 - if(police == 1) - police = -1 - if(powerloader == 1) - powerloader = -1 - if(large_vehicle == 1) - large_vehicle = -1 - if(stamina == 1) - stamina = -1 - else - if(cqc == -1) - cqc = 1 - if(melee_weapons == -1) - melee_weapons = 1 - if(firearms == -1) - firearms = 1 - if(pistols == -1) - pistols = 1 - if(shotguns == -1) - shotguns = 1 - if(rifles == -1) - rifles = 1 - if(smgs == -1) - smgs = 1 - if(heavy_weapons == -1) - heavy_weapons = 1 - if(swordplay == -1) - swordplay = 1 - if(smartgun == -1) - smartgun = 1 - if(engineer == -1) - engineer = 1 - if(construction == -1) - construction = 1 - if(leadership == -1) - leadership = 1 - if(medical == -1) - medical = 1 - if(surgery == -1) - surgery = 1 - if(pilot == -1) - pilot = 1 - if(police == -1) - police = 1 - if(powerloader == -1) - powerloader = 1 - if(large_vehicle == -1) - large_vehicle = 1 - if(stamina == -1) - stamina = 1 - return - -/obj/item/implant/skill/Destroy(force) - unimplant() - QDEL_NULL(activation_action) - part?.implants -= src - return ..() - /obj/item/implant/skill/combat name = "combat implants" desc = "Non-game" diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 6979108267b..5efbacfc394 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -1,4 +1,4 @@ -/obj/item/implantator +/obj/item/implanter/implantator name = "skill" //teeeeest. desc = "Used to implant occupants with skill implants." icon = 'icons/obj/items/implants.dmi' @@ -12,36 +12,30 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - var/obj/item/implant/internal_implant = /obj/item/implant/skill - var/allowed_limbs + obj/item/implant/internal_implant = /obj/item/implant/skill + allowed_limbs var/spented = FALSE var/max_skills var/list/implants + var/allowed_limbs -/obj/item/implantator/Initialize(mapload, ...) +/obj/item/implanter/implantator/Initialize(mapload, ...) . = ..() name = name + " implanter" desc = internal_implant.desc - if(internal_implant) - internal_implant = new internal_implant(src) if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts -/obj/item/implantator/Destroy() - QDEL_NULL(internal_implant) - return ..() - -/obj/item/implantator/examine(mob/user, distance, infix, suffix) - . = ..() - . += "it contains [internal_implant ? "a [internal_implant.name]" : "no implant"]!" +/obj/item/implanter/update_icon_state() + return -/obj/item/implantator/proc/has_implant(datum/limb/targetlimb) +/obj/item/implanter/implantator/proc/has_implant(datum/limb/targetlimb) for (var/obj/item/implant/skill/I in targetlimb.implants) if(!is_type_in_list(I, GLOB.known_implants)) return TRUE return FALSE -/obj/item/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) +/obj/item/implanter/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) . = ..() if(spented == TRUE) return FALSE @@ -73,14 +67,14 @@ to_chat(user, span_notice("You fail to implant [target].")) return -/obj/item/implantator/combat +/obj/item/implanter/implantator/combat allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) internal_implant = /obj/item/implant/skill/combat -/obj/item/implantator/codex +/obj/item/implanter/implantator/codex allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) internal_implant = /obj/item/implant/skill/codex -/obj/item/implantator/oper_system +/obj/item/implanter/implantator/oper_system allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system diff --git a/code/game/objects/items/implants/skill_implants/implantator_skill.dm b/code/game/objects/items/implants/skill_implants/implantator_skill.dm index c6c7e85866b..a91480e3288 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_skill.dm @@ -1,41 +1,41 @@ //////////////////////////////[COMBAT]////////////////////////////// -/obj/item/implantator/combat/firearms +/obj/item/implanter/implantator/combat/firearms name = "aiming support" icon_state = "weapon" internal_implant = /obj/item/implant/skill/combat/firearms -/obj/item/implantator/combat/melee +/obj/item/implanter/implantator/combat/melee name = "close combat codex" icon_state = "melee" internal_implant = /obj/item/implant/skill/combat/melee //////////////////////////////[SUPPORT]////////////////////////////// -/obj/item/implantator/codex/medical +/obj/item/implanter/implantator/codex/medical name = "medtech" icon_state = "medical" internal_implant = /obj/item/implant/skill/codex/medical -/obj/item/implantator/codex/surgery +/obj/item/implanter/implantator/codex/surgery name = "surgery assisting system" icon_state = "surgery" internal_implant = /obj/item/implant/skill/codex/surgery -/obj/item/implantator/codex/engineer +/obj/item/implanter/implantator/codex/engineer name = "construction support system" icon_state = "enginering" internal_implant = /obj/item/implant/skill/codex/engineer //////////////////////////////[SPECIAL]////////////////////////////// -/obj/item/implantator/oper_system/leadership +/obj/item/implanter/implantator/oper_system/leadership name = "command protocols 'Graiyor' codex" icon_state = "leadership" empty_icon = "leadership" internal_implant = /obj/item/implant/skill/oper_system/leadership -/obj/item/implantator/oper_system/leadership/delux +/obj/item/implanter/implantator/oper_system/leadership/delux name = "delux command protocols 'Graiyor' codex" icon_state = "deluxleadership" empty_icon = "deluxleadership" From cb50f1bf4c9fe798f768dae5158eb73ff8c74c37 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 7 Dec 2024 05:58:44 +1000 Subject: [PATCH 15/42] FixMB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Попробывал пофиксить --- code/game/objects/items/implants/implant.dm | 7 --- .../implants/skill_implants/implant_code.dm | 49 +++++------------- .../implants/skill_implants/implant_skill.dm | 23 +++++---- .../skill_implants/implantator_code.dm | 51 ++----------------- .../skill_implants/implantator_skill.dm | 14 ++--- code/modules/unit_tests/implanting.dm | 4 +- 6 files changed, 39 insertions(+), 109 deletions(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 1017ee866e3..e60760c42b4 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -35,13 +35,6 @@ if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts -/obj/item/implant/proc/on_initialize() - if(flags_implant & GRANT_ACTIVATION_ACTION) - activation_action = new(src, src) - if(allow_reagents) - reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) - reagents.my_atom = WEAKREF(src) - /obj/item/implant/Destroy(force) unimplant() QDEL_NULL(activation_action) diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index df77e8fd37d..fe38ca3564a 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -31,52 +31,31 @@ /obj/item/implant/skill/Initialize() . = ..() name = name + " implant" - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts -/obj/item/implant/skill/on_initialize() - return - -/obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) - if(!ishuman(target)) - return - if(!(user.zone_selected in allowed_limbs)) - to_chat(user, span_warning("You cannot implant this into that limb!")) - return FALSE - implanted = TRUE - return implant(target, user) +/obj/item/implant/skill/Destroy(force) + unimplant() + QDEL_NULL(activation_action) + part?.implants -= src + return ..() /obj/item/implant/skill/implant(mob/living/carbon/human/target, mob/living/user) - forceMove(target) - implant_owner = target - implanted = TRUE - var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) - var/datum/limb/affected = target.get_limb(limb_targeting) - if(!affected) - CRASH("[src] implanted into [target] [user ? "by [user]" : ""] but had no limb, despite being set to implant in [limb_targeting].") - affected.implants += src - part = affected - activation_action?.give_action(target) - embed_into(target, limb_targeting, TRUE) + for(var/skill in max_skills) + if(user.skills.getRating(skill) >= max_skills[skill]) + balloon_alert(user, "Nothing to learn!") + return + . = ..() target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) return TRUE /obj/item/implant/skill/unimplant() - if(!implanted) - return FALSE - activation_action?.remove_action(implant_owner) - implanted = FALSE - part.implants -= src - part = null implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -swordplay, -smartgun,\ -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -stamina)) - forceMove(get_turf(implant_owner)) - implant_owner = null + . = ..() /obj/item/implant/skill/combat - name = "combat implants" - desc = "Non-game" + name = "Combat implants" + desc = "All combat" icon_state = "combat_implant" allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) @@ -87,7 +66,7 @@ allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) /obj/item/implant/skill/oper_system - name = "HEAD SLOT!" + name = "Leader slot" desc = "All non-sorted special shit (leadership, probaly SG and more)" icon_state = "skill_implant" allowed_limbs = list(BODY_ZONE_HEAD) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index 4a75c3c2c90..1d1f7af632f 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -1,42 +1,43 @@ /obj/item/implant/skill/combat/firearms - name = "aiming support" + name = "Aiming support" desc = "integrated aiming support system! Update weapons skills!" firearms = 1 max_skills = list(SKILL_FIREARMS = SKILL_FIREARMS_TRAINED) /obj/item/implant/skill/combat/melee - name = "close combat codex" + name = "Close combat codex" desc = "integrated hit support system! Update melee skills!" melee_weapons = 1 max_skills = list(SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED) /obj/item/implant/skill/codex/medical - name = "medtech" + name = "Medtech" desc = "A compact device that electro-shakes you every time you apply bandages counterclockwise, right next to your heart! Update medical skills!" medical = 1 max_skills = list(SKILL_MEDICAL = SKILL_MEDICAL_COMPETENT) /obj/item/implant/skill/codex/surgery - name = "surgery assisting system" - desc = "compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" + name = "Surgery assisting system" + desc = "Compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" surgery = 1 max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) /obj/item/implant/skill/codex/engineer - name = "construction support system" - desc = "laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" + name = "Construction support system" + desc = "Laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" engineer = 1 max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) /obj/item/implant/skill/oper_system/leadership - name = "command protocols 'Graiyor' codex" - desc = "uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" + name = "Command protocols 'Graiyor' codex" + desc = "Uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" icon_state = "leadership_implant" leadership = 1 max_skills = list(SKILL_LEAD = SKILL_LEAD_MASTER) /obj/item/implant/skill/oper_system/leadership/delux - name = "delux command protocols 'Graiyor' codex" - desc = "uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" + name = "Delux command protocols 'Graiyor' codex" + desc = "Uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" icon_state = "deluxleadership_implant" + leadership = 2 max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 5efbacfc394..1b2faae1448 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -1,5 +1,5 @@ /obj/item/implanter/implantator - name = "skill" //teeeeest. + name = "skill" desc = "Used to implant occupants with skill implants." icon = 'icons/obj/items/implants.dmi' icon_state = "skill" @@ -12,69 +12,26 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - obj/item/implant/internal_implant = /obj/item/implant/skill - allowed_limbs - var/spented = FALSE var/max_skills var/list/implants - var/allowed_limbs /obj/item/implanter/implantator/Initialize(mapload, ...) . = ..() - name = name + " implanter" - desc = internal_implant.desc - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts + +/obj/item/implanter/implantator/Destroy() + return ..() /obj/item/implanter/update_icon_state() return -/obj/item/implanter/implantator/proc/has_implant(datum/limb/targetlimb) - for (var/obj/item/implant/skill/I in targetlimb.implants) - if(!is_type_in_list(I, GLOB.known_implants)) - return TRUE - return FALSE - /obj/item/implanter/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) . = ..() - if(spented == TRUE) - return FALSE - if(!ishuman(target)) - return FALSE - if(!internal_implant) - to_chat(user, span_warning("There is no implant in the [src]!")) - return FALSE - if(!(user.zone_selected in allowed_limbs)) - balloon_alert(user, "wrong limb!") - return FALSE - for(i in user.zone_selected) - has_implant(targetlimb) - balloon_alert(user, "limb already implanted!") - return FALSE - user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC)) - to_chat(user, span_notice("You failed to implant [target].")) - return FALSE - if(internal_implant.try_implant(target, user)) - target.visible_message(span_warning("[target] has been implanted by [user].")) - log_combat(user, target, "implanted", src) - internal_implant = null - name = name + "used" - desc = desc + "It's spent." - icon_state = empty_icon + "_s" - spented = TRUE - return TRUE - to_chat(user, span_notice("You fail to implant [target].")) - return /obj/item/implanter/implantator/combat - allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) internal_implant = /obj/item/implant/skill/combat /obj/item/implanter/implantator/codex - allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) internal_implant = /obj/item/implant/skill/codex /obj/item/implanter/implantator/oper_system - allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system diff --git a/code/game/objects/items/implants/skill_implants/implantator_skill.dm b/code/game/objects/items/implants/skill_implants/implantator_skill.dm index a91480e3288..2a45a71a40d 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_skill.dm @@ -1,42 +1,42 @@ //////////////////////////////[COMBAT]////////////////////////////// /obj/item/implanter/implantator/combat/firearms - name = "aiming support" + name = "Aiming support" icon_state = "weapon" internal_implant = /obj/item/implant/skill/combat/firearms /obj/item/implanter/implantator/combat/melee - name = "close combat codex" + name = "Close combat codex" icon_state = "melee" internal_implant = /obj/item/implant/skill/combat/melee //////////////////////////////[SUPPORT]////////////////////////////// /obj/item/implanter/implantator/codex/medical - name = "medtech" + name = "Medtech" icon_state = "medical" internal_implant = /obj/item/implant/skill/codex/medical /obj/item/implanter/implantator/codex/surgery - name = "surgery assisting system" + name = "Surgery assisting system" icon_state = "surgery" internal_implant = /obj/item/implant/skill/codex/surgery /obj/item/implanter/implantator/codex/engineer - name = "construction support system" + name = "Construction support system" icon_state = "enginering" internal_implant = /obj/item/implant/skill/codex/engineer //////////////////////////////[SPECIAL]////////////////////////////// /obj/item/implanter/implantator/oper_system/leadership - name = "command protocols 'Graiyor' codex" + name = "Command protocols 'Graiyor' codex" icon_state = "leadership" empty_icon = "leadership" internal_implant = /obj/item/implant/skill/oper_system/leadership /obj/item/implanter/implantator/oper_system/leadership/delux - name = "delux command protocols 'Graiyor' codex" + name = "Delux command protocols 'Graiyor' codex" icon_state = "deluxleadership" empty_icon = "deluxleadership" internal_implant = /obj/item/implant/skill/oper_system/leadership/delux diff --git a/code/modules/unit_tests/implanting.dm b/code/modules/unit_tests/implanting.dm index cf96e38c718..6bf7893958f 100644 --- a/code/modules/unit_tests/implanting.dm +++ b/code/modules/unit_tests/implanting.dm @@ -5,12 +5,12 @@ var/mob/living/carbon/human/implanted_guy = allocate(/mob/living/carbon/human) var/obj/item/implanter/implanter_to_inject = allocate(/obj/item/implanter/cloak) - var/obj/item/implant/implant_in_planter = implanter_to_inject.imp + var/obj/item/implant/implant_in_planter = implanter_to_inject.internal_implant implanted_guy.put_in_active_hand(implanter_to_inject) TEST_ASSERT(implanter_to_inject.attack(implanted_guy, implanted_guy), "[implanted_guy] failed to inject himself with [implanter_to_inject]") - TEST_ASSERT(!implanter_to_inject.imp, "[implanter_to_inject] still has an implant in its implanter, despite being injected into [implanted_guy]") + TEST_ASSERT(!implanter_to_inject.internal_implant, "[implanter_to_inject] still has an implant in its implanter, despite being injected into [implanted_guy]") qdel(implanted_guy) TEST_ASSERT(QDELETED(implant_in_planter), "[implant_in_planter] has been injected into [implanted_guy], who has been deleted, but the implant still exists.") From 33f011feede6fa43a6224f9c673300164d300445 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 7 Dec 2024 06:11:56 +1000 Subject: [PATCH 16/42] delete garbage --- code/game/objects/items/implants/implanter.dm | 61 ------------------- .../skill_implants/implantator_code.dm | 3 +- 2 files changed, 1 insertion(+), 63 deletions(-) diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 001c01ee8c2..58af45ca573 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -74,64 +74,3 @@ /obj/item/implanter/suicide_dust name = "Self-Gibbing implant" internal_implant = /obj/item/implant/suicide_dust - -/obj/item/implanter/cargo - name = "implanter" - icon_state = "cargo" - var/spent = FALSE - var/allowed_limbs - var/list/implants - -/obj/item/implanter/cargo/Initialize(mapload, ...) - . = ..() - update_icon_state() - if(internal_implant) - update_icon_state() - desc = internal_implant.desc - internal_implant = new internal_implant(src) - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts - -/obj/item/implanter/cargo/update_icon_state() - . = ..() - icon_state = "cargo" - if(internal_implant) - icon_state = "cargo_full" - if(!internal_implant) - icon_state = "cargo_s" - -/obj/item/implanter/cargo/proc/has_implant(datum/limb/targetlimb) - for (var/obj/item/implant/skill/I in targetlimb.implants) - if(!is_type_in_list(I, GLOB.known_implants)) - return TRUE - return FALSE - -/obj/item/implanter/cargo/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) - . = ..() - if(!ishuman(target)) - return FALSE - if(spent == TRUE) - balloon_alert(user, "already used!") - return FALSE - if(!internal_implant) - to_chat(user, span_warning("There is no implant in the [src]!")) - return FALSE - if(!(user.zone_selected in allowed_limbs)) - balloon_alert(user, "wrong limb!") - return FALSE - for(i in user.zone_selected) - has_implant(targetlimb) - balloon_alert(user, "limb already implanted!") - return FALSE - user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) - to_chat(user, span_notice("You failed to implant [target].")) - return FALSE - if(internal_implant.try_implant(target, user)) - target.visible_message(span_warning("[target] has been implanted by [user].")) - log_combat(user, target, "implanted", src) - internal_implant = null - spent = TRUE - update_icon_state() - return TRUE - to_chat(user, span_notice("You fail to implant [target].")) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 1b2faae1448..a325930b544 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -13,7 +13,6 @@ throw_range = 5 w_class = WEIGHT_CLASS_TINY var/max_skills - var/list/implants /obj/item/implanter/implantator/Initialize(mapload, ...) . = ..() @@ -24,7 +23,7 @@ /obj/item/implanter/update_icon_state() return -/obj/item/implanter/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) +/obj/item/implanter/implantator/attack(mob/living/target, mob/living/user) . = ..() /obj/item/implanter/implantator/combat From b56fee3c8add89bbc29a2457a66d141eec83a383 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 7 Dec 2024 18:21:24 +1000 Subject: [PATCH 17/42] Revert "delete garbage" This reverts commit 33f011feede6fa43a6224f9c673300164d300445. --- code/game/objects/items/implants/implanter.dm | 61 +++++++++++++++++++ .../skill_implants/implantator_code.dm | 3 +- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 58af45ca573..001c01ee8c2 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -74,3 +74,64 @@ /obj/item/implanter/suicide_dust name = "Self-Gibbing implant" internal_implant = /obj/item/implant/suicide_dust + +/obj/item/implanter/cargo + name = "implanter" + icon_state = "cargo" + var/spent = FALSE + var/allowed_limbs + var/list/implants + +/obj/item/implanter/cargo/Initialize(mapload, ...) + . = ..() + update_icon_state() + if(internal_implant) + update_icon_state() + desc = internal_implant.desc + internal_implant = new internal_implant(src) + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts + +/obj/item/implanter/cargo/update_icon_state() + . = ..() + icon_state = "cargo" + if(internal_implant) + icon_state = "cargo_full" + if(!internal_implant) + icon_state = "cargo_s" + +/obj/item/implanter/cargo/proc/has_implant(datum/limb/targetlimb) + for (var/obj/item/implant/skill/I in targetlimb.implants) + if(!is_type_in_list(I, GLOB.known_implants)) + return TRUE + return FALSE + +/obj/item/implanter/cargo/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) + . = ..() + if(!ishuman(target)) + return FALSE + if(spent == TRUE) + balloon_alert(user, "already used!") + return FALSE + if(!internal_implant) + to_chat(user, span_warning("There is no implant in the [src]!")) + return FALSE + if(!(user.zone_selected in allowed_limbs)) + balloon_alert(user, "wrong limb!") + return FALSE + for(i in user.zone_selected) + has_implant(targetlimb) + balloon_alert(user, "limb already implanted!") + return FALSE + user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) + to_chat(user, span_notice("You failed to implant [target].")) + return FALSE + if(internal_implant.try_implant(target, user)) + target.visible_message(span_warning("[target] has been implanted by [user].")) + log_combat(user, target, "implanted", src) + internal_implant = null + spent = TRUE + update_icon_state() + return TRUE + to_chat(user, span_notice("You fail to implant [target].")) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index a325930b544..1b2faae1448 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -13,6 +13,7 @@ throw_range = 5 w_class = WEIGHT_CLASS_TINY var/max_skills + var/list/implants /obj/item/implanter/implantator/Initialize(mapload, ...) . = ..() @@ -23,7 +24,7 @@ /obj/item/implanter/update_icon_state() return -/obj/item/implanter/implantator/attack(mob/living/target, mob/living/user) +/obj/item/implanter/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) . = ..() /obj/item/implanter/implantator/combat From 38a8a3c703eb5aded117ab0519eed495f5a6bd46 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 7 Dec 2024 18:21:45 +1000 Subject: [PATCH 18/42] Revert "FixMB" This reverts commit cb50f1bf4c9fe798f768dae5158eb73ff8c74c37. --- code/game/objects/items/implants/implant.dm | 7 +++ .../implants/skill_implants/implant_code.dm | 49 +++++++++++++----- .../implants/skill_implants/implant_skill.dm | 23 ++++----- .../skill_implants/implantator_code.dm | 51 +++++++++++++++++-- .../skill_implants/implantator_skill.dm | 14 ++--- code/modules/unit_tests/implanting.dm | 4 +- 6 files changed, 109 insertions(+), 39 deletions(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index e60760c42b4..1017ee866e3 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -35,6 +35,13 @@ if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts +/obj/item/implant/proc/on_initialize() + if(flags_implant & GRANT_ACTIVATION_ACTION) + activation_action = new(src, src) + if(allow_reagents) + reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) + reagents.my_atom = WEAKREF(src) + /obj/item/implant/Destroy(force) unimplant() QDEL_NULL(activation_action) diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index fe38ca3564a..df77e8fd37d 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -31,31 +31,52 @@ /obj/item/implant/skill/Initialize() . = ..() name = name + " implant" + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts -/obj/item/implant/skill/Destroy(force) - unimplant() - QDEL_NULL(activation_action) - part?.implants -= src - return ..() +/obj/item/implant/skill/on_initialize() + return + +/obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) + if(!ishuman(target)) + return + if(!(user.zone_selected in allowed_limbs)) + to_chat(user, span_warning("You cannot implant this into that limb!")) + return FALSE + implanted = TRUE + return implant(target, user) /obj/item/implant/skill/implant(mob/living/carbon/human/target, mob/living/user) - for(var/skill in max_skills) - if(user.skills.getRating(skill) >= max_skills[skill]) - balloon_alert(user, "Nothing to learn!") - return - . = ..() + forceMove(target) + implant_owner = target + implanted = TRUE + var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) + var/datum/limb/affected = target.get_limb(limb_targeting) + if(!affected) + CRASH("[src] implanted into [target] [user ? "by [user]" : ""] but had no limb, despite being set to implant in [limb_targeting].") + affected.implants += src + part = affected + activation_action?.give_action(target) + embed_into(target, limb_targeting, TRUE) target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) return TRUE /obj/item/implant/skill/unimplant() + if(!implanted) + return FALSE + activation_action?.remove_action(implant_owner) + implanted = FALSE + part.implants -= src + part = null implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -swordplay, -smartgun,\ -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -stamina)) - . = ..() + forceMove(get_turf(implant_owner)) + implant_owner = null /obj/item/implant/skill/combat - name = "Combat implants" - desc = "All combat" + name = "combat implants" + desc = "Non-game" icon_state = "combat_implant" allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) @@ -66,7 +87,7 @@ allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) /obj/item/implant/skill/oper_system - name = "Leader slot" + name = "HEAD SLOT!" desc = "All non-sorted special shit (leadership, probaly SG and more)" icon_state = "skill_implant" allowed_limbs = list(BODY_ZONE_HEAD) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index 1d1f7af632f..4a75c3c2c90 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -1,43 +1,42 @@ /obj/item/implant/skill/combat/firearms - name = "Aiming support" + name = "aiming support" desc = "integrated aiming support system! Update weapons skills!" firearms = 1 max_skills = list(SKILL_FIREARMS = SKILL_FIREARMS_TRAINED) /obj/item/implant/skill/combat/melee - name = "Close combat codex" + name = "close combat codex" desc = "integrated hit support system! Update melee skills!" melee_weapons = 1 max_skills = list(SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED) /obj/item/implant/skill/codex/medical - name = "Medtech" + name = "medtech" desc = "A compact device that electro-shakes you every time you apply bandages counterclockwise, right next to your heart! Update medical skills!" medical = 1 max_skills = list(SKILL_MEDICAL = SKILL_MEDICAL_COMPETENT) /obj/item/implant/skill/codex/surgery - name = "Surgery assisting system" - desc = "Compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" + name = "surgery assisting system" + desc = "compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" surgery = 1 max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) /obj/item/implant/skill/codex/engineer - name = "Construction support system" - desc = "Laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" + name = "construction support system" + desc = "laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" engineer = 1 max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) /obj/item/implant/skill/oper_system/leadership - name = "Command protocols 'Graiyor' codex" - desc = "Uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" + name = "command protocols 'Graiyor' codex" + desc = "uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" icon_state = "leadership_implant" leadership = 1 max_skills = list(SKILL_LEAD = SKILL_LEAD_MASTER) /obj/item/implant/skill/oper_system/leadership/delux - name = "Delux command protocols 'Graiyor' codex" - desc = "Uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" + name = "delux command protocols 'Graiyor' codex" + desc = "uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" icon_state = "deluxleadership_implant" - leadership = 2 max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 1b2faae1448..5efbacfc394 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -1,5 +1,5 @@ /obj/item/implanter/implantator - name = "skill" + name = "skill" //teeeeest. desc = "Used to implant occupants with skill implants." icon = 'icons/obj/items/implants.dmi' icon_state = "skill" @@ -12,26 +12,69 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY + obj/item/implant/internal_implant = /obj/item/implant/skill + allowed_limbs + var/spented = FALSE var/max_skills var/list/implants + var/allowed_limbs /obj/item/implanter/implantator/Initialize(mapload, ...) . = ..() - -/obj/item/implanter/implantator/Destroy() - return ..() + name = name + " implanter" + desc = internal_implant.desc + if(!allowed_limbs) + allowed_limbs = GLOB.human_body_parts /obj/item/implanter/update_icon_state() return +/obj/item/implanter/implantator/proc/has_implant(datum/limb/targetlimb) + for (var/obj/item/implant/skill/I in targetlimb.implants) + if(!is_type_in_list(I, GLOB.known_implants)) + return TRUE + return FALSE + /obj/item/implanter/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) . = ..() + if(spented == TRUE) + return FALSE + if(!ishuman(target)) + return FALSE + if(!internal_implant) + to_chat(user, span_warning("There is no implant in the [src]!")) + return FALSE + if(!(user.zone_selected in allowed_limbs)) + balloon_alert(user, "wrong limb!") + return FALSE + for(i in user.zone_selected) + has_implant(targetlimb) + balloon_alert(user, "limb already implanted!") + return FALSE + user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) + if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC)) + to_chat(user, span_notice("You failed to implant [target].")) + return FALSE + if(internal_implant.try_implant(target, user)) + target.visible_message(span_warning("[target] has been implanted by [user].")) + log_combat(user, target, "implanted", src) + internal_implant = null + name = name + "used" + desc = desc + "It's spent." + icon_state = empty_icon + "_s" + spented = TRUE + return TRUE + to_chat(user, span_notice("You fail to implant [target].")) + return /obj/item/implanter/implantator/combat + allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) internal_implant = /obj/item/implant/skill/combat /obj/item/implanter/implantator/codex + allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) internal_implant = /obj/item/implant/skill/codex /obj/item/implanter/implantator/oper_system + allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system diff --git a/code/game/objects/items/implants/skill_implants/implantator_skill.dm b/code/game/objects/items/implants/skill_implants/implantator_skill.dm index 2a45a71a40d..a91480e3288 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_skill.dm @@ -1,42 +1,42 @@ //////////////////////////////[COMBAT]////////////////////////////// /obj/item/implanter/implantator/combat/firearms - name = "Aiming support" + name = "aiming support" icon_state = "weapon" internal_implant = /obj/item/implant/skill/combat/firearms /obj/item/implanter/implantator/combat/melee - name = "Close combat codex" + name = "close combat codex" icon_state = "melee" internal_implant = /obj/item/implant/skill/combat/melee //////////////////////////////[SUPPORT]////////////////////////////// /obj/item/implanter/implantator/codex/medical - name = "Medtech" + name = "medtech" icon_state = "medical" internal_implant = /obj/item/implant/skill/codex/medical /obj/item/implanter/implantator/codex/surgery - name = "Surgery assisting system" + name = "surgery assisting system" icon_state = "surgery" internal_implant = /obj/item/implant/skill/codex/surgery /obj/item/implanter/implantator/codex/engineer - name = "Construction support system" + name = "construction support system" icon_state = "enginering" internal_implant = /obj/item/implant/skill/codex/engineer //////////////////////////////[SPECIAL]////////////////////////////// /obj/item/implanter/implantator/oper_system/leadership - name = "Command protocols 'Graiyor' codex" + name = "command protocols 'Graiyor' codex" icon_state = "leadership" empty_icon = "leadership" internal_implant = /obj/item/implant/skill/oper_system/leadership /obj/item/implanter/implantator/oper_system/leadership/delux - name = "Delux command protocols 'Graiyor' codex" + name = "delux command protocols 'Graiyor' codex" icon_state = "deluxleadership" empty_icon = "deluxleadership" internal_implant = /obj/item/implant/skill/oper_system/leadership/delux diff --git a/code/modules/unit_tests/implanting.dm b/code/modules/unit_tests/implanting.dm index 6bf7893958f..cf96e38c718 100644 --- a/code/modules/unit_tests/implanting.dm +++ b/code/modules/unit_tests/implanting.dm @@ -5,12 +5,12 @@ var/mob/living/carbon/human/implanted_guy = allocate(/mob/living/carbon/human) var/obj/item/implanter/implanter_to_inject = allocate(/obj/item/implanter/cloak) - var/obj/item/implant/implant_in_planter = implanter_to_inject.internal_implant + var/obj/item/implant/implant_in_planter = implanter_to_inject.imp implanted_guy.put_in_active_hand(implanter_to_inject) TEST_ASSERT(implanter_to_inject.attack(implanted_guy, implanted_guy), "[implanted_guy] failed to inject himself with [implanter_to_inject]") - TEST_ASSERT(!implanter_to_inject.internal_implant, "[implanter_to_inject] still has an implant in its implanter, despite being injected into [implanted_guy]") + TEST_ASSERT(!implanter_to_inject.imp, "[implanter_to_inject] still has an implant in its implanter, despite being injected into [implanted_guy]") qdel(implanted_guy) TEST_ASSERT(QDELETED(implant_in_planter), "[implant_in_planter] has been injected into [implanted_guy], who has been deleted, but the implant still exists.") From d63b1ea902a4cb7019cebd04d4ccfb50bf8ac518 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 7 Dec 2024 20:19:13 +1000 Subject: [PATCH 19/42] well? --- code/game/objects/items/implants/implant.dm | 7 -- code/game/objects/items/implants/implanter.dm | 77 +++---------------- .../implants/skill_implants/implant_code.dm | 48 ++++-------- .../implants/skill_implants/implant_skill.dm | 12 +-- .../skill_implants/implantator_code.dm | 68 ++++++++-------- code/modules/unit_tests/implanting.dm | 4 +- 6 files changed, 66 insertions(+), 150 deletions(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 1017ee866e3..e60760c42b4 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -35,13 +35,6 @@ if(!allowed_limbs) allowed_limbs = GLOB.human_body_parts -/obj/item/implant/proc/on_initialize() - if(flags_implant & GRANT_ACTIVATION_ACTION) - activation_action = new(src, src) - if(allow_reagents) - reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) - reagents.my_atom = WEAKREF(src) - /obj/item/implant/Destroy(force) unimplant() QDEL_NULL(activation_action) diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 001c01ee8c2..0d8d4f79975 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -32,11 +32,9 @@ /obj/item/implanter/attack(mob/target, mob/user) . = ..() - if(!ishuman(target)) - return FALSE - if(!internal_implant) - to_chat(user, span_warning("There is no implant in the [src]!")) - return FALSE + if(!can_implant(target, user)) + return + user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) @@ -51,6 +49,14 @@ return TRUE to_chat(user, span_notice("You fail to implant [target].")) +/obj/item/implanter/proc/can_implant(mob/target, mob/user) + if(!ishuman(target)) + return FALSE + if(!internal_implant) + to_chat(user, span_warning("There is no implant in the [src]!")) + return FALSE + return TRUE + /obj/item/implanter/neurostim name = "neurostim implanter" internal_implant = /obj/item/implant/neurostim @@ -74,64 +80,3 @@ /obj/item/implanter/suicide_dust name = "Self-Gibbing implant" internal_implant = /obj/item/implant/suicide_dust - -/obj/item/implanter/cargo - name = "implanter" - icon_state = "cargo" - var/spent = FALSE - var/allowed_limbs - var/list/implants - -/obj/item/implanter/cargo/Initialize(mapload, ...) - . = ..() - update_icon_state() - if(internal_implant) - update_icon_state() - desc = internal_implant.desc - internal_implant = new internal_implant(src) - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts - -/obj/item/implanter/cargo/update_icon_state() - . = ..() - icon_state = "cargo" - if(internal_implant) - icon_state = "cargo_full" - if(!internal_implant) - icon_state = "cargo_s" - -/obj/item/implanter/cargo/proc/has_implant(datum/limb/targetlimb) - for (var/obj/item/implant/skill/I in targetlimb.implants) - if(!is_type_in_list(I, GLOB.known_implants)) - return TRUE - return FALSE - -/obj/item/implanter/cargo/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) - . = ..() - if(!ishuman(target)) - return FALSE - if(spent == TRUE) - balloon_alert(user, "already used!") - return FALSE - if(!internal_implant) - to_chat(user, span_warning("There is no implant in the [src]!")) - return FALSE - if(!(user.zone_selected in allowed_limbs)) - balloon_alert(user, "wrong limb!") - return FALSE - for(i in user.zone_selected) - has_implant(targetlimb) - balloon_alert(user, "limb already implanted!") - return FALSE - user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) - to_chat(user, span_notice("You failed to implant [target].")) - return FALSE - if(internal_implant.try_implant(target, user)) - target.visible_message(span_warning("[target] has been implanted by [user].")) - log_combat(user, target, "implanted", src) - internal_implant = null - spent = TRUE - update_icon_state() - return TRUE - to_chat(user, span_notice("You fail to implant [target].")) diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index df77e8fd37d..4f176d90310 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -31,33 +31,24 @@ /obj/item/implant/skill/Initialize() . = ..() name = name + " implant" - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts -/obj/item/implant/skill/on_initialize() - return +/obj/item/implant/Destroy(force) + unimplant() + QDEL_NULL(activation_action) + part?.implants -= src + return ..() /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) - if(!ishuman(target)) - return - if(!(user.zone_selected in allowed_limbs)) - to_chat(user, span_warning("You cannot implant this into that limb!")) - return FALSE - implanted = TRUE - return implant(target, user) + . = ..() /obj/item/implant/skill/implant(mob/living/carbon/human/target, mob/living/user) - forceMove(target) - implant_owner = target - implanted = TRUE - var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) - var/datum/limb/affected = target.get_limb(limb_targeting) - if(!affected) - CRASH("[src] implanted into [target] [user ? "by [user]" : ""] but had no limb, despite being set to implant in [limb_targeting].") - affected.implants += src - part = affected - activation_action?.give_action(target) - embed_into(target, limb_targeting, TRUE) + for(var/skill in max_skills) + if(user.skills.getRating(skill) >= max_skills[skill]) + balloon_alert(user, "Nothing to learn!") + return + . = ..() + if(!.) + return target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) return TRUE @@ -65,29 +56,24 @@ /obj/item/implant/skill/unimplant() if(!implanted) return FALSE - activation_action?.remove_action(implant_owner) - implanted = FALSE - part.implants -= src - part = null implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -swordplay, -smartgun,\ -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -stamina)) - forceMove(get_turf(implant_owner)) - implant_owner = null + . = ..() /obj/item/implant/skill/combat name = "combat implants" - desc = "Non-game" + desc = "" icon_state = "combat_implant" allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) /obj/item/implant/skill/codex name = "CODEX" - desc = "A support skill update-shit." + desc = "" icon_state = "support_implant" allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) /obj/item/implant/skill/oper_system name = "HEAD SLOT!" - desc = "All non-sorted special shit (leadership, probaly SG and more)" + desc = "" icon_state = "skill_implant" allowed_limbs = list(BODY_ZONE_HEAD) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index 4a75c3c2c90..bb09e0f9988 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -1,12 +1,12 @@ /obj/item/implant/skill/combat/firearms name = "aiming support" - desc = "integrated aiming support system! Update weapons skills!" + desc = "Integrated aiming support system! Update weapons skills!" firearms = 1 max_skills = list(SKILL_FIREARMS = SKILL_FIREARMS_TRAINED) /obj/item/implant/skill/combat/melee name = "close combat codex" - desc = "integrated hit support system! Update melee skills!" + desc = "Integrated hit support system! Update melee skills!" melee_weapons = 1 max_skills = list(SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED) @@ -18,25 +18,25 @@ /obj/item/implant/skill/codex/surgery name = "surgery assisting system" - desc = "compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" + desc = "Compensates for hand trembling from Parkinson's syndrome, thanks to the reliable suspension of the shoulder joints! Update surgery skills!" surgery = 1 max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) /obj/item/implant/skill/codex/engineer name = "construction support system" - desc = "laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" + desc = "Laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" engineer = 1 max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) /obj/item/implant/skill/oper_system/leadership name = "command protocols 'Graiyor' codex" - desc = "uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" + desc = "Uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" icon_state = "leadership_implant" leadership = 1 max_skills = list(SKILL_LEAD = SKILL_LEAD_MASTER) /obj/item/implant/skill/oper_system/leadership/delux name = "delux command protocols 'Graiyor' codex" - desc = "uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" + desc = "Uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" icon_state = "deluxleadership_implant" max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 5efbacfc394..bc3db893555 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -1,5 +1,5 @@ /obj/item/implanter/implantator - name = "skill" //teeeeest. + name = "skill" desc = "Used to implant occupants with skill implants." icon = 'icons/obj/items/implants.dmi' icon_state = "skill" @@ -12,60 +12,52 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - obj/item/implant/internal_implant = /obj/item/implant/skill - allowed_limbs var/spented = FALSE var/max_skills - var/list/implants var/allowed_limbs /obj/item/implanter/implantator/Initialize(mapload, ...) . = ..() name = name + " implanter" - desc = internal_implant.desc - if(!allowed_limbs) - allowed_limbs = GLOB.human_body_parts + +/obj/item/implanter/Destroy() + return ..() /obj/item/implanter/update_icon_state() return -/obj/item/implanter/implantator/proc/has_implant(datum/limb/targetlimb) - for (var/obj/item/implant/skill/I in targetlimb.implants) - if(!is_type_in_list(I, GLOB.known_implants)) - return TRUE - return FALSE +/obj/item/implanter/implantator/attack(mob/target, mob/living/user) + if(!can_implant(target, user)) + return + . = ..() + if(.) + name = name + " used" + desc = desc + " It's spent." + icon_state = empty_icon + "_s" + spented = TRUE + return TRUE + return -/obj/item/implanter/implantator/attack(mob/living/target, mob/living/user, list/implants, datum/limb/targetlimb, var/obj/item/implant/skill/i) +/obj/item/implanter/implantator/can_implant(mob/target, mob/user) . = ..() - if(spented == TRUE) - return FALSE - if(!ishuman(target)) - return FALSE - if(!internal_implant) - to_chat(user, span_warning("There is no implant in the [src]!")) + if(!.) + return + var/mob/living/carbon/human/human = target + if(spented) return FALSE if(!(user.zone_selected in allowed_limbs)) - balloon_alert(user, "wrong limb!") - return FALSE - for(i in user.zone_selected) - has_implant(targetlimb) - balloon_alert(user, "limb already implanted!") + balloon_alert(user, "Wrong limb!") return FALSE - user.visible_message(span_warning("[user] is attemping to implant [target]."), span_notice("You're attemping to implant [target].")) - if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC)) - to_chat(user, span_notice("You failed to implant [target].")) + if(has_implant(human.get_limb(user.zone_selected))) + balloon_alert(user, "Limb already implanted!") return FALSE - if(internal_implant.try_implant(target, user)) - target.visible_message(span_warning("[target] has been implanted by [user].")) - log_combat(user, target, "implanted", src) - internal_implant = null - name = name + "used" - desc = desc + "It's spent." - icon_state = empty_icon + "_s" - spented = TRUE - return TRUE - to_chat(user, span_notice("You fail to implant [target].")) - return + return TRUE + +/obj/item/implanter/implantator/proc/has_implant(datum/limb/targetlimb) + for (var/obj/item/implant/skill/implant in targetlimb.implants) + if(!is_type_in_list(implant, /obj/item/implant/skill)) + return TRUE + return FALSE /obj/item/implanter/implantator/combat allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) diff --git a/code/modules/unit_tests/implanting.dm b/code/modules/unit_tests/implanting.dm index cf96e38c718..6bf7893958f 100644 --- a/code/modules/unit_tests/implanting.dm +++ b/code/modules/unit_tests/implanting.dm @@ -5,12 +5,12 @@ var/mob/living/carbon/human/implanted_guy = allocate(/mob/living/carbon/human) var/obj/item/implanter/implanter_to_inject = allocate(/obj/item/implanter/cloak) - var/obj/item/implant/implant_in_planter = implanter_to_inject.imp + var/obj/item/implant/implant_in_planter = implanter_to_inject.internal_implant implanted_guy.put_in_active_hand(implanter_to_inject) TEST_ASSERT(implanter_to_inject.attack(implanted_guy, implanted_guy), "[implanted_guy] failed to inject himself with [implanter_to_inject]") - TEST_ASSERT(!implanter_to_inject.imp, "[implanter_to_inject] still has an implant in its implanter, despite being injected into [implanted_guy]") + TEST_ASSERT(!implanter_to_inject.internal_implant, "[implanter_to_inject] still has an implant in its implanter, despite being injected into [implanted_guy]") qdel(implanted_guy) TEST_ASSERT(QDELETED(implant_in_planter), "[implant_in_planter] has been injected into [implanted_guy], who has been deleted, but the implant still exists.") From 9a75c9f3f10cecd3c65e8973183bf6ade6808a3a Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Wed, 11 Dec 2024 03:08:58 +1000 Subject: [PATCH 20/42] fix review day 96535 --- .../implants/skill_implants/implant_code.dm | 2 +- .../implants/skill_implants/implantator_code.dm | 17 +++++------------ 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index 4f176d90310..c16054cf432 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -30,7 +30,7 @@ /obj/item/implant/skill/Initialize() . = ..() - name = name + " implant" + name += " implant" /obj/item/implant/Destroy(force) unimplant() diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index bc3db893555..8ad7b6b088f 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -27,12 +27,9 @@ return /obj/item/implanter/implantator/attack(mob/target, mob/living/user) - if(!can_implant(target, user)) - return . = ..() if(.) - name = name + " used" - desc = desc + " It's spent." + name += " used" icon_state = empty_icon + "_s" spented = TRUE return TRUE @@ -48,16 +45,12 @@ if(!(user.zone_selected in allowed_limbs)) balloon_alert(user, "Wrong limb!") return FALSE - if(has_implant(human.get_limb(user.zone_selected))) - balloon_alert(user, "Limb already implanted!") - return FALSE - return TRUE - -/obj/item/implanter/implantator/proc/has_implant(datum/limb/targetlimb) + var/datum/limb/targetlimb = human.get_limb(user.zone_selected) for (var/obj/item/implant/skill/implant in targetlimb.implants) if(!is_type_in_list(implant, /obj/item/implant/skill)) - return TRUE - return FALSE + balloon_alert(user, "Limb already implanted!") + return FALSE + return TRUE /obj/item/implanter/implantator/combat allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) From 735d3c509fd28706684353e75f8fc3b28939d3a1 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Wed, 11 Dec 2024 03:15:29 +1000 Subject: [PATCH 21/42] uh, and why that exist now? --- .../objects/items/implants/skill_implants/implantator_code.dm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 8ad7b6b088f..d4c9c439d44 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -12,7 +12,6 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY - var/spented = FALSE var/max_skills var/allowed_limbs @@ -31,7 +30,6 @@ if(.) name += " used" icon_state = empty_icon + "_s" - spented = TRUE return TRUE return @@ -40,8 +38,6 @@ if(!.) return var/mob/living/carbon/human/human = target - if(spented) - return FALSE if(!(user.zone_selected in allowed_limbs)) balloon_alert(user, "Wrong limb!") return FALSE From 0e7f346e40986e9212ca12230874eb6017c88eb8 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Thu, 12 Dec 2024 15:02:22 +1000 Subject: [PATCH 22/42] i need sleep --- .../objects/items/implants/skill_implants/implantator_code.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index d4c9c439d44..054a34984bd 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -17,7 +17,7 @@ /obj/item/implanter/implantator/Initialize(mapload, ...) . = ..() - name = name + " implanter" + name += " implanter" /obj/item/implanter/Destroy() return ..() From b7f4f6b06443138a67dd36b30bf43b0bf19dc263 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sun, 15 Dec 2024 01:41:42 +1000 Subject: [PATCH 23/42] ogore --- .../objects/items/implants/skill_implants/implant_skill.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index bb09e0f9988..db520242fd7 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -33,10 +33,10 @@ desc = "Uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" icon_state = "leadership_implant" leadership = 1 - max_skills = list(SKILL_LEAD = SKILL_LEAD_MASTER) + max_skills = list(SKILL_LEADERSHIP = SKILL_LEAD_MASTER) /obj/item/implant/skill/oper_system/leadership/delux name = "delux command protocols 'Graiyor' codex" desc = "Uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" icon_state = "deluxleadership_implant" - max_skills = list(SKILL_LEAD = SKILL_LEAD_SUPER) + max_skills = list(SKILL_LEADERSHIP = SKILL_LEAD_SUPER) From 1fd0e6dadfc267a6561973012b4919d16028cec0 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Mon, 16 Dec 2024 15:59:03 +1000 Subject: [PATCH 24/42] minor --- .../items/implants/skill_implants/implant_code.dm | 5 +++-- .../items/implants/skill_implants/implant_skill.dm | 2 +- .../implants/skill_implants/implantator_code.dm | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index c16054cf432..6291c3ec51c 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -26,6 +26,7 @@ var/police var/powerloader var/large_vehicle + var/mech_pilot var/stamina /obj/item/implant/skill/Initialize() @@ -50,14 +51,14 @@ if(!.) return target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ - engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, stamina)) + engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, mech_pilot, stamina)) return TRUE /obj/item/implant/skill/unimplant() if(!implanted) return FALSE implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -swordplay, -smartgun,\ - -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -stamina)) + -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -mech_pilot, -stamina)) . = ..() /obj/item/implant/skill/combat diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index db520242fd7..691b3236d29 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -23,7 +23,7 @@ max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) /obj/item/implant/skill/codex/engineer - name = "construction support system" + name = "enginering implants system" desc = "Laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" engineer = 1 max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 054a34984bd..7e92dad4b5d 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -19,10 +19,20 @@ . = ..() name += " implanter" -/obj/item/implanter/Destroy() +/obj/item/implanter/implantator/examine(mob/user, distance, infix, suffix) + . = ..() + var/obj/item/implant/skill/implant = src?.internal_implant + for(var/skill in implant.max_skills) + if(user.skills.getRating(skill) < implant.max_skills[skill]) + . += " You can increase your knowleadge to [implant.max_skills[skill]] level" + return + else + . += " You know everything about this, you can't learn more... But you can give it another man " + +/obj/item/implanter/implantator/Destroy() return ..() -/obj/item/implanter/update_icon_state() +/obj/item/implanter/implantator/update_icon_state() return /obj/item/implanter/implantator/attack(mob/target, mob/living/user) From 12b268efad4ae43f4452067abeccefca89ce1340 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Wed, 18 Dec 2024 06:22:35 +1000 Subject: [PATCH 25/42] some.. --- code/__DEFINES/loadout.dm | 14 +++++--- code/game/objects/items/implants/implant.dm | 4 ++- code/game/objects/items/implants/implanter.dm | 2 +- .../implants/skill_implants/implant_code.dm | 36 ++++++++++--------- .../implants/skill_implants/implant_skill.dm | 22 ++++++------ .../skill_implants/implantator_code.dm | 26 +++++++++----- .../skill_implants/implantator_skill.dm | 23 ++++++------ 7 files changed, 72 insertions(+), 55 deletions(-) diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 5673d05ca46..77efdc40ffe 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -92,7 +92,8 @@ GLOBAL_LIST_INIT(marine_gear_listed_products, list( /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 15, "cyan2"), /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), - /obj/item/implanter/implantator/codex/engineer = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_MARINE, "Engineering support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_MARINE, "Consturction support system implanter", 20, "cyan2"), /obj/item/storage/backpack/marine/radiopack = list(CAT_MARINE, "Radio Pack", 5, "orange"), /obj/item/storage/belt/marine/auto_catch = list(CAT_MARINE, "M344 pattern ammo load rig", 10, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_MARINE, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -127,7 +128,8 @@ GLOBAL_LIST_INIT(engineer_gear_listed_products, list( /obj/effect/vendor_bundle/engi = list(CAT_ESS, "Essential Engineer Set", 0, "white"), /obj/item/implanter/implantator/combat/firearms = list(CAT_ENGSUP, "Aiming support implanter", 25, "cyan2"), /obj/item/implanter/implantator/combat/melee = list(CAT_ENGSUP, "Close combat codex implanter", 25, "cyan2"), - /obj/item/implanter/implantator/codex/engineer = list(CAT_ENGSUP, "Construction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_ENGSUP, "Engineering support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_ENGSUP, "Consturction support system implanter", 20, "cyan2"), /obj/item/stack/sheet/metal/small_stack = list(CAT_ENGSUP, "Metal x10", METAL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sheet/plasteel/small_stack = list(CAT_ENGSUP, "Plasteel x10", PLASTEEL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_ENGSUP, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -215,7 +217,8 @@ GLOBAL_LIST_INIT(leader_gear_listed_products, list( /obj/item/implanter/implantator/combat/firearms = list(CAT_LEDSUP, "Aiming support implanter", 15, "cyan2"), /obj/item/implanter/implantator/combat/melee = list(CAT_LEDSUP, "Close combat codex implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_LEDSUP, "Medtech implanter", 15, "cyan2"), - /obj/item/implanter/implantator/codex/engineer = list(CAT_LEDSUP, "Construction support system implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_LEDSUP, "Engineering support system implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_LEDSUP, "Consturction support system implanter", 15, "cyan2"), /obj/item/implanter/implantator/oper_system/leadership = list(CAT_LEDSUP, "Command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/armor_module/module/valkyrie_autodoc = list(CAT_LEDSUP, "Valkyrie Automedical Armor System", 25,"white"), /obj/effect/vendor_bundle/tyr/two = list(CAT_LEDSUP, "Tyr 2 extra armor set", 25,"white"), @@ -280,8 +283,9 @@ GLOBAL_LIST_INIT(commander_gear_listed_products, list( /obj/item/implanter/implantator/combat/melee = list(CAT_FCSUP, "Close combat codex implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_FCSUP, "Medtech implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/surgery = list(CAT_FCSUP, "Surgery assisting system implanter", 15, "cyan2"), - /obj/item/implanter/implantator/codex/engineer = list(CAT_FCSUP, "Construction support system implanter", 15, "cyan2"), - /obj/item/implanter/implantator/oper_system/leadership/delux = list(CAT_FCSUP, "Delux command protocols 'Graiyor' codex loader", 20, "cyan2"), + /obj/item/implanter/implantator/codex/engineer = list(CAT_FCSUP, "Engineering support system implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_FCSUP, "Consturction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/oper_system/leadership = list(CAT_FCSUP, "Command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/beacon/supply_beacon = list(CAT_FCSUP, "Supply beacon", 5, "blue"), /obj/item/beacon/orbital_bombardment_beacon = list(CAT_FCSUP, "Orbital beacon", 5, "blue"), /obj/item/fulton_extraction_pack = list(CAT_FCSUP, "Fulton Extraction Pack", 5, "blue"), diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index e60760c42b4..be152a1087f 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -59,7 +59,7 @@ if(!(user.zone_selected in allowed_limbs)) to_chat(user, span_warning("You cannot implant this into that limb!")) return FALSE - return implant(target, user) + return TRUE /** * What does the implant do upon injection? @@ -67,6 +67,8 @@ */ /obj/item/implant/proc/implant(mob/living/carbon/human/target, mob/living/user) SHOULD_CALL_PARENT(TRUE) + if(!try_implant(target, user)) + return forceMove(target) implant_owner = target implanted = TRUE diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 0d8d4f79975..0da26b595d9 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -41,7 +41,7 @@ to_chat(user, span_notice("You failed to implant [target].")) return - if(internal_implant.try_implant(target, user)) + if(internal_implant.implant(target, user)) target.visible_message(span_warning("[target] has been implanted by [user].")) log_combat(user, target, "implanted", src) internal_implant = null diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index 6291c3ec51c..5acd93e23f9 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -1,12 +1,8 @@ /obj/item/implant/skill - name = "skill" //teeeeeest. - desc = "Hey! You dont see it!" - icon = 'icons/obj/items/implants.dmi' - icon_state = "implant" w_class = WEIGHT_CLASS_TINY +// Maximum skill a user can possess var/list/max_skills - var/storage_skill = null -//pamplet copy-past. :clueless: +//vars for update skills var/cqc var/melee_weapons var/firearms @@ -31,7 +27,6 @@ /obj/item/implant/skill/Initialize() . = ..() - name += " implant" /obj/item/implant/Destroy(force) unimplant() @@ -39,17 +34,24 @@ part?.implants -= src return ..() +/obj/item/implant/skill/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/implanter/implantator/cargo)) + var/obj/item/implanter/implantator/cargo = I + cargo.allowed_limbs = src.allowed_limbs + src.forceMove(cargo) + cargo.internal_implant = src + cargo.icon_state = "cargo_full" + return + /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) . = ..() - -/obj/item/implant/skill/implant(mob/living/carbon/human/target, mob/living/user) for(var/skill in max_skills) if(user.skills.getRating(skill) >= max_skills[skill]) balloon_alert(user, "Nothing to learn!") return + +/obj/item/implant/skill/implant(mob/living/carbon/human/target, mob/living/user) . = ..() - if(!.) - return target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, mech_pilot, stamina)) return TRUE @@ -62,19 +64,19 @@ . = ..() /obj/item/implant/skill/combat - name = "combat implants" - desc = "" + name = "Сombat implants" + desc = "An implant from a line of implants that enhances combat skills" icon_state = "combat_implant" allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) /obj/item/implant/skill/codex - name = "CODEX" - desc = "" + name = "CODEX implants" + desc = "Implant from a line of implants that increases basic knowledge" icon_state = "support_implant" allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) /obj/item/implant/skill/oper_system - name = "HEAD SLOT!" - desc = "" + name = "Tactics implants" + desc = "An implant from the line of implants that increases knowledge of battle tactics" icon_state = "skill_implant" allowed_limbs = list(BODY_ZONE_HEAD) diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index 691b3236d29..4d8e85425da 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -1,17 +1,17 @@ /obj/item/implant/skill/combat/firearms - name = "aiming support" + name = "aiming support implant system" desc = "Integrated aiming support system! Update weapons skills!" firearms = 1 max_skills = list(SKILL_FIREARMS = SKILL_FIREARMS_TRAINED) /obj/item/implant/skill/combat/melee - name = "close combat codex" + name = "close combat codex implant system" desc = "Integrated hit support system! Update melee skills!" melee_weapons = 1 max_skills = list(SKILL_MELEE_WEAPONS = SKILL_MELEE_TRAINED) /obj/item/implant/skill/codex/medical - name = "medtech" + name = "medtech implant system" desc = "A compact device that electro-shakes you every time you apply bandages counterclockwise, right next to your heart! Update medical skills!" medical = 1 max_skills = list(SKILL_MEDICAL = SKILL_MEDICAL_COMPETENT) @@ -23,20 +23,20 @@ max_skills = list(SKILL_SURGERY = SKILL_SURGERY_PROFESSIONAL) /obj/item/implant/skill/codex/engineer - name = "enginering implants system" - desc = "Laying brickwork has never been easier than with this corrective endoskeleton! Update engineering skills!" + name = "engineering implants system" + desc = "Working with welding has become much easier! Update engineering skills!" engineer = 1 max_skills = list(SKILL_ENGINEER = SKILL_ENGINEER_MASTER) +/obj/item/implant/skill/codex/construct + name = "construct implants system" + desc = "Working with welding has become much easier! Update construct skills!" + construction = 1 + max_skills = list(SKILL_CONSTRUCTION = SKILL_CONSTRUCTION_MASTER) + /obj/item/implant/skill/oper_system/leadership name = "command protocols 'Graiyor' codex" desc = "Uploading knowledge of advanced mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills!" icon_state = "leadership_implant" leadership = 1 - max_skills = list(SKILL_LEADERSHIP = SKILL_LEAD_MASTER) - -/obj/item/implant/skill/oper_system/leadership/delux - name = "delux command protocols 'Graiyor' codex" - desc = "Uploading advanced knowledge of futuristic mnemonics of inspiration and persuasion to the brain so that people around go under bullets even more willingly! Update leadership skills even more!" - icon_state = "deluxleadership_implant" max_skills = list(SKILL_LEADERSHIP = SKILL_LEAD_SUPER) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 7e92dad4b5d..4eb2014581a 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -3,7 +3,6 @@ desc = "Used to implant occupants with skill implants." icon = 'icons/obj/items/implants.dmi' icon_state = "skill" - var/empty_icon = "skill" item_state = "syringe_0" item_icons = list( slot_l_hand_str = 'icons/mob/inhands/equipment/medical_left.dmi', @@ -11,7 +10,8 @@ ) throw_speed = 1 throw_range = 5 - w_class = WEIGHT_CLASS_TINY + var/spented = FALSE + var/empty_icon = "skill" var/max_skills var/allowed_limbs @@ -21,25 +21,28 @@ /obj/item/implanter/implantator/examine(mob/user, distance, infix, suffix) . = ..() - var/obj/item/implant/skill/implant = src?.internal_implant + if(isnull(internal_implant)) + return + var/obj/item/implant/skill/implant = internal_implant for(var/skill in implant.max_skills) if(user.skills.getRating(skill) < implant.max_skills[skill]) - . += " You can increase your knowleadge to [implant.max_skills[skill]] level" + . += "You can increase your knowleadge to [implant.max_skills[skill]] level" return else - . += " You know everything about this, you can't learn more... But you can give it another man " + . += "You know everything about this, you can't learn more... But you can gift it..." + return /obj/item/implanter/implantator/Destroy() return ..() /obj/item/implanter/implantator/update_icon_state() - return + icon_state = "[internal_implant ? "[icon_state]" : "[empty_icon]_s"]" /obj/item/implanter/implantator/attack(mob/target, mob/living/user) . = ..() if(.) name += " used" - icon_state = empty_icon + "_s" + spented = TRUE return TRUE return @@ -47,12 +50,14 @@ . = ..() if(!.) return + if(spented) + return var/mob/living/carbon/human/human = target if(!(user.zone_selected in allowed_limbs)) balloon_alert(user, "Wrong limb!") return FALSE var/datum/limb/targetlimb = human.get_limb(user.zone_selected) - for (var/obj/item/implant/skill/implant in targetlimb.implants) + for(var/obj/item/implant/skill/implant in targetlimb.implants) if(!is_type_in_list(implant, /obj/item/implant/skill)) balloon_alert(user, "Limb already implanted!") return FALSE @@ -69,3 +74,8 @@ /obj/item/implanter/implantator/oper_system allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system + +/obj/item/implanter/implantator/cargo + icon_state = "cargo" + empty_icon = "cargo_full" + internal_implant = null diff --git a/code/game/objects/items/implants/skill_implants/implantator_skill.dm b/code/game/objects/items/implants/skill_implants/implantator_skill.dm index a91480e3288..b722c7da205 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_skill.dm @@ -1,42 +1,41 @@ //////////////////////////////[COMBAT]////////////////////////////// /obj/item/implanter/implantator/combat/firearms - name = "aiming support" + name = "Aiming support" icon_state = "weapon" internal_implant = /obj/item/implant/skill/combat/firearms /obj/item/implanter/implantator/combat/melee - name = "close combat codex" + name = "Close combat codex" icon_state = "melee" internal_implant = /obj/item/implant/skill/combat/melee //////////////////////////////[SUPPORT]////////////////////////////// /obj/item/implanter/implantator/codex/medical - name = "medtech" + name = "Medtech assisting system" icon_state = "medical" internal_implant = /obj/item/implant/skill/codex/medical /obj/item/implanter/implantator/codex/surgery - name = "surgery assisting system" + name = "Surgery assisting system" icon_state = "surgery" internal_implant = /obj/item/implant/skill/codex/surgery /obj/item/implanter/implantator/codex/engineer - name = "construction support system" + name = "Engineering support system" icon_state = "enginering" internal_implant = /obj/item/implant/skill/codex/engineer +/obj/item/implanter/implantator/codex/construct + name = "Construst support system" + icon_state = "enginering" + internal_implant = /obj/item/implant/skill/codex/construct + //////////////////////////////[SPECIAL]////////////////////////////// /obj/item/implanter/implantator/oper_system/leadership - name = "command protocols 'Graiyor' codex" + name = "Command protocols 'Graiyor' codex" icon_state = "leadership" empty_icon = "leadership" internal_implant = /obj/item/implant/skill/oper_system/leadership - -/obj/item/implanter/implantator/oper_system/leadership/delux - name = "delux command protocols 'Graiyor' codex" - icon_state = "deluxleadership" - empty_icon = "deluxleadership" - internal_implant = /obj/item/implant/skill/oper_system/leadership/delux From 999c96adafc7e076b27ee6bfc5d196ebb8c98f49 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Wed, 18 Dec 2024 14:25:24 +1000 Subject: [PATCH 26/42] Update implant.dm --- code/game/objects/items/implants/implant.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index be152a1087f..b8fa7333af9 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -56,7 +56,8 @@ SHOULD_CALL_PARENT(TRUE) if(!ishuman(target)) return FALSE - if(!(user.zone_selected in allowed_limbs)) + var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) + if(!(limb_targeting in allowed_limbs)) to_chat(user, span_warning("You cannot implant this into that limb!")) return FALSE return TRUE From 3df8e0b6a25d4d2bb633706dd87301e5a5c17e31 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Wed, 18 Dec 2024 16:41:40 +1000 Subject: [PATCH 27/42] some some --- code/game/objects/items/implants/implant.dm | 2 +- .../implants/skill_implants/implant_code.dm | 16 +++++------ .../skill_implants/implantator_code.dm | 27 ++++++++++--------- code/modules/reqs/supplypacks/medical.dm | 6 +++++ 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index b8fa7333af9..2d2df8f3699 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -69,7 +69,7 @@ /obj/item/implant/proc/implant(mob/living/carbon/human/target, mob/living/user) SHOULD_CALL_PARENT(TRUE) if(!try_implant(target, user)) - return + return FALSE forceMove(target) implant_owner = target implanted = TRUE diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index 5acd93e23f9..e734e6f0330 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -34,24 +34,20 @@ part?.implants -= src return ..() -/obj/item/implant/skill/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/implanter/implantator/cargo)) - var/obj/item/implanter/implantator/cargo = I - cargo.allowed_limbs = src.allowed_limbs - src.forceMove(cargo) - cargo.internal_implant = src - cargo.icon_state = "cargo_full" - return - /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) . = ..() + if(!.) + return for(var/skill in max_skills) if(user.skills.getRating(skill) >= max_skills[skill]) balloon_alert(user, "Nothing to learn!") - return + return FALSE + return TRUE /obj/item/implant/skill/implant(mob/living/carbon/human/target, mob/living/user) . = ..() + if(!.) + return target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, mech_pilot, stamina)) return TRUE diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 4eb2014581a..6f983136036 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -1,5 +1,5 @@ /obj/item/implanter/implantator - name = "skill" + name = "Skill" desc = "Used to implant occupants with skill implants." icon = 'icons/obj/items/implants.dmi' icon_state = "skill" @@ -10,7 +10,6 @@ ) throw_speed = 1 throw_range = 5 - var/spented = FALSE var/empty_icon = "skill" var/max_skills var/allowed_limbs @@ -38,20 +37,10 @@ /obj/item/implanter/implantator/update_icon_state() icon_state = "[internal_implant ? "[icon_state]" : "[empty_icon]_s"]" -/obj/item/implanter/implantator/attack(mob/target, mob/living/user) - . = ..() - if(.) - name += " used" - spented = TRUE - return TRUE - return - /obj/item/implanter/implantator/can_implant(mob/target, mob/user) . = ..() if(!.) return - if(spented) - return var/mob/living/carbon/human/human = target if(!(user.zone_selected in allowed_limbs)) balloon_alert(user, "Wrong limb!") @@ -75,6 +64,20 @@ allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system +/obj/item/implanter/implantator/cargo/attackby(obj/item/I, mob/user, params) + . = ..() + if(istype(I, /obj/item/implant/skill)) + var/obj/item/implanter/implantator/cargo/cargo = src + var/obj/item/implant/skill/skill = I + if(cargo.icon_state == "cargo_full_s") + balloon_alert(user, "Implantator already used!") + return + cargo.allowed_limbs = skill.allowed_limbs + skill.forceMove(cargo) + cargo.internal_implant = skill + cargo.icon_state = "cargo_full" + return + /obj/item/implanter/implantator/cargo icon_state = "cargo" empty_icon = "cargo_full" diff --git a/code/modules/reqs/supplypacks/medical.dm b/code/modules/reqs/supplypacks/medical.dm index e047d97a555..e77f19d5aee 100644 --- a/code/modules/reqs/supplypacks/medical.dm +++ b/code/modules/reqs/supplypacks/medical.dm @@ -385,3 +385,9 @@ /obj/item/clothing/mask/breath/medical, /obj/item/tank/anesthetic, ) + +/datum/supply_packs/medical/implanter + name = "Implanter" + notes = "contains an implanter for reinsertion of the implant." + contains = list(/obj/item/implanter/implantator/cargo) + cost = 90 From 29af37b7b6bd9ecca619b7875133c6e9ff78df31 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Thu, 19 Dec 2024 04:29:08 +1000 Subject: [PATCH 28/42] 1 day before shitpost --- code/__DEFINES/loadout.dm | 8 ++-- .../objects/items/implants/implantcase.dm | 37 ------------------- .../implants/skill_implants/implant_code.dm | 5 +-- .../skill_implants/implantator_code.dm | 19 +++------- 4 files changed, 11 insertions(+), 58 deletions(-) diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index 77efdc40ffe..430b039bd85 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -93,7 +93,7 @@ GLOBAL_LIST_INIT(marine_gear_listed_products, list( /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), /obj/item/implanter/implantator/codex/engineer = list(CAT_MARINE, "Engineering support system implanter", 20, "cyan2"), - /obj/item/implanter/implantator/codex/construct = list(CAT_MARINE, "Consturction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), /obj/item/storage/backpack/marine/radiopack = list(CAT_MARINE, "Radio Pack", 5, "orange"), /obj/item/storage/belt/marine/auto_catch = list(CAT_MARINE, "M344 pattern ammo load rig", 10, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_MARINE, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -129,7 +129,7 @@ GLOBAL_LIST_INIT(engineer_gear_listed_products, list( /obj/item/implanter/implantator/combat/firearms = list(CAT_ENGSUP, "Aiming support implanter", 25, "cyan2"), /obj/item/implanter/implantator/combat/melee = list(CAT_ENGSUP, "Close combat codex implanter", 25, "cyan2"), /obj/item/implanter/implantator/codex/engineer = list(CAT_ENGSUP, "Engineering support system implanter", 20, "cyan2"), - /obj/item/implanter/implantator/codex/construct = list(CAT_ENGSUP, "Consturction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_ENGSUP, "Construction support system implanter", 20, "cyan2"), /obj/item/stack/sheet/metal/small_stack = list(CAT_ENGSUP, "Metal x10", METAL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sheet/plasteel/small_stack = list(CAT_ENGSUP, "Plasteel x10", PLASTEEL_PRICE_IN_GEAR_VENDOR, "orange"), /obj/item/stack/sandbags_empty/half = list(CAT_ENGSUP, "Sandbags x25", SANDBAG_PRICE_IN_GEAR_VENDOR, "orange"), @@ -218,7 +218,7 @@ GLOBAL_LIST_INIT(leader_gear_listed_products, list( /obj/item/implanter/implantator/combat/melee = list(CAT_LEDSUP, "Close combat codex implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_LEDSUP, "Medtech implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/engineer = list(CAT_LEDSUP, "Engineering support system implanter", 15, "cyan2"), - /obj/item/implanter/implantator/codex/construct = list(CAT_LEDSUP, "Consturction support system implanter", 15, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_LEDSUP, "Construction support system implanter", 15, "cyan2"), /obj/item/implanter/implantator/oper_system/leadership = list(CAT_LEDSUP, "Command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/armor_module/module/valkyrie_autodoc = list(CAT_LEDSUP, "Valkyrie Automedical Armor System", 25,"white"), /obj/effect/vendor_bundle/tyr/two = list(CAT_LEDSUP, "Tyr 2 extra armor set", 25,"white"), @@ -284,7 +284,7 @@ GLOBAL_LIST_INIT(commander_gear_listed_products, list( /obj/item/implanter/implantator/codex/medical = list(CAT_FCSUP, "Medtech implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/surgery = list(CAT_FCSUP, "Surgery assisting system implanter", 15, "cyan2"), /obj/item/implanter/implantator/codex/engineer = list(CAT_FCSUP, "Engineering support system implanter", 15, "cyan2"), - /obj/item/implanter/implantator/codex/construct = list(CAT_FCSUP, "Consturction support system implanter", 20, "cyan2"), + /obj/item/implanter/implantator/codex/construct = list(CAT_FCSUP, "Construction support system implanter", 15, "cyan2"), /obj/item/implanter/implantator/oper_system/leadership = list(CAT_FCSUP, "Command protocols 'Graiyor' codex loader", 20, "cyan2"), /obj/item/beacon/supply_beacon = list(CAT_FCSUP, "Supply beacon", 5, "blue"), /obj/item/beacon/orbital_bombardment_beacon = list(CAT_FCSUP, "Orbital beacon", 5, "blue"), diff --git a/code/game/objects/items/implants/implantcase.dm b/code/game/objects/items/implants/implantcase.dm index abd3aae02a2..c7470418a4a 100644 --- a/code/game/objects/items/implants/implantcase.dm +++ b/code/game/objects/items/implants/implantcase.dm @@ -81,40 +81,3 @@ I.forceMove(src) internal_implant = I update_icon() - -/obj/item/implantcase/cargo - name = "glass implant case" - desc = "A case containing an implant." - icon = 'icons/obj/items/implants.dmi' - icon_state = "implantcase-0" - -/obj/item/implantcase/cargo/attackby(obj/item/I, mob/user, params) - . = ..() - if(istype(I, /obj/item/implanter/implantator)) - var/obj/item/implanter/implantator/M = I - - if(!do_after(user, 5 SECONDS, NONE, user, BUSY_ICON_GENERIC)) - to_chat(user, span_notice("You stop transfering [internal_implant]")) - return FALSE - - if(M.internal_implant) - if((internal_implant || M.internal_implant.implanted)) - return - M.internal_implant.forceMove(src) - internal_implant = M.internal_implant - M.internal_implant = null - - if(internal_implant) - if(M.internal_implant) - return - internal_implant.forceMove(M) - M.internal_implant = internal_implant - internal_implant = null - update_icon() - M.update_icon() - - else if(istype(I, /obj/item/implant/skill)) - user.temporarilyRemoveItemFromInventory(I) - I.forceMove(src) - internal_implant = I - update_icon() diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index e734e6f0330..e0ce11877b1 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -25,9 +25,6 @@ var/mech_pilot var/stamina -/obj/item/implant/skill/Initialize() - . = ..() - /obj/item/implant/Destroy(force) unimplant() QDEL_NULL(activation_action) @@ -57,7 +54,7 @@ return FALSE implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -swordplay, -smartgun,\ -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -mech_pilot, -stamina)) - . = ..() + return ..() /obj/item/implant/skill/combat name = "Сombat implants" diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 6f983136036..6d95fc4133f 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -26,13 +26,8 @@ for(var/skill in implant.max_skills) if(user.skills.getRating(skill) < implant.max_skills[skill]) . += "You can increase your knowleadge to [implant.max_skills[skill]] level" - return else . += "You know everything about this, you can't learn more... But you can gift it..." - return - -/obj/item/implanter/implantator/Destroy() - return ..() /obj/item/implanter/implantator/update_icon_state() icon_state = "[internal_implant ? "[icon_state]" : "[empty_icon]_s"]" @@ -47,7 +42,7 @@ return FALSE var/datum/limb/targetlimb = human.get_limb(user.zone_selected) for(var/obj/item/implant/skill/implant in targetlimb.implants) - if(!is_type_in_list(implant, /obj/item/implant/skill)) + if(!istype(implant, /obj/item/implant/skill)) balloon_alert(user, "Limb already implanted!") return FALSE return TRUE @@ -65,17 +60,15 @@ internal_implant = /obj/item/implant/skill/oper_system /obj/item/implanter/implantator/cargo/attackby(obj/item/I, mob/user, params) - . = ..() if(istype(I, /obj/item/implant/skill)) - var/obj/item/implanter/implantator/cargo/cargo = src var/obj/item/implant/skill/skill = I - if(cargo.icon_state == "cargo_full_s") + if(icon_state == "cargo_full_s") balloon_alert(user, "Implantator already used!") return - cargo.allowed_limbs = skill.allowed_limbs - skill.forceMove(cargo) - cargo.internal_implant = skill - cargo.icon_state = "cargo_full" + allowed_limbs = skill.allowed_limbs + internal_implant = skill + skill.forceMove(src) + icon_state = "cargo_full" return /obj/item/implanter/implantator/cargo From d4885329c845e1a18397ef29f531002f2383c806 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Thu, 19 Dec 2024 05:10:09 +1000 Subject: [PATCH 29/42] 1984 kill AKULISHEV if(user.ckey == "akulishov") // https://discord.com/channels/1235677154084126861/1235677154084126865/1319014221836582932 user.gib() // 1984 --- code/__DEFINES/dcs/helpers.dm | 4 ++++ code/__DEFINES/dcs/signals.dm | 7 +++++++ code/__DEFINES/implants.dm | 7 +++++++ code/__DEFINES/is_helpers.dm | 2 ++ .../items/implants/skill_implants/implantator_code.dm | 2 ++ 5 files changed, 22 insertions(+) diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm index 70092d117b8..bfd82bc572a 100644 --- a/code/__DEFINES/dcs/helpers.dm +++ b/code/__DEFINES/dcs/helpers.dm @@ -22,6 +22,10 @@ /// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments #define AddComponent(arguments...) _AddComponent(list(##arguments)) +/// A wrapper for _AddComonent that passes in a source. +/// Necessary if dupe_mode is set to COMPONENT_DUPE_SOURCES. +#define AddComponentFrom(source, arguments...) _AddComponent(list(##arguments), source) + /// A wrapper for _LoadComponent that allows us to pretend we're using normal named arguments #define LoadComponent(arguments...) _LoadComponent(list(##arguments)) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 761a54f1e17..875be460ff3 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -500,6 +500,10 @@ #define COMSIG_MOB_PAINLOSS_CHANGED "mob_painloss_changed" /// from mob/get_status_tab_items(): (list/items) #define COMSIG_MOB_GET_STATUS_TAB_ITEMS "mob_get_status_tab_items" +///From mob/do_after_coefficent() +#define MOB_GET_DO_AFTER_COEFFICIENT "mob_get_do_after_coefficient" +///From get_zone_with_miss_chance +#define MOB_GET_MISS_CHANCE_MOD "mob_get_miss_chance_mod" //mob/dead/observer #define COMSIG_OBSERVER_CLICKON "observer_clickon" //from mob/dead/observer/ClickOn(): (atom/A, params) @@ -964,6 +968,9 @@ #define COMSIG_WEAPONABILITY_AXESWEEP "weaponability_axesweep" #define COMSIG_WEAPONABILITY_SWORDLUNGE "weaponability_swordlunge" +//Implant abilities +#define COMSIG_IMPLANT_ABILITY_SANDEVISTAN "implant_ability_sandevistan" + // human modules signals for keybindings #define COMSIG_KB_VALI_CONFIGURE "keybinding_vali_configure" #define COMSIG_KB_VALI_HEAL "keybinding_vali_heal" diff --git a/code/__DEFINES/implants.dm b/code/__DEFINES/implants.dm index d7810266e4a..d538b3b3a2d 100644 --- a/code/__DEFINES/implants.dm +++ b/code/__DEFINES/implants.dm @@ -1,6 +1,13 @@ //Generic /obj/item/implant flags #define GRANT_ACTIVATION_ACTION (1<<0) +///Some kind of hearing/voice activation #define ACTIVATE_ON_HEAR (1<<1) +///The implant is something you want +#define BENEFICIAL_IMPLANT (1<<2) +///Can have more than one of the same implant in a limb +#define DUPLICATE_IMPLANT_ALLOWED (1<<3) +///Only one implant can be in a limb +#define HIGHLANDER_IMPLANT (1<<4) #define MALFUNCTION_NONE 0 #define MALFUNCTION_TEMPORARY 1 diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 2c294e70237..5f203de0c7d 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -269,6 +269,8 @@ #define issentry(A) (istype(A, /obj/machinery/deployable/mounted/sentry)) +#define isimplant(A) (istype(A, /obj/item/implant)) + //Assemblies #define isassembly(O) (istype(O, /obj/item/assembly)) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 6d95fc4133f..7fec58b3b5c 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -45,6 +45,8 @@ if(!istype(implant, /obj/item/implant/skill)) balloon_alert(user, "Limb already implanted!") return FALSE + if(user.ckey == "akulishov") // https://discord.com/channels/1235677154084126861/1235677154084126865/1319014221836582932 + user.gib() // 1984 return TRUE /obj/item/implanter/implantator/combat From 6d9482baee845a21ea6a4c9f9a375d3898e986d9 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Thu, 19 Dec 2024 07:15:57 +1000 Subject: [PATCH 30/42] in process --- code/__DEFINES/keybind.dm | 1 + code/__HELPERS/mobs.dm | 9 +- code/datums/components/_component.dm | 178 ++++++++++++------ code/datums/components/after_image.dm | 111 +++++++++++ code/datums/components/jump.dm | 2 +- code/datums/elements/shrapnel_removal.dm | 14 +- code/datums/keybinding/cyberware.dm | 10 + .../temporary_visuals/miscellaneous.dm | 25 ++- code/game/objects/items.dm | 4 + code/game/objects/items/embedding.dm | 4 - code/game/objects/items/implants/implant.dm | 44 +++-- .../objects/items/implants/implant_chem.dm | 2 +- .../objects/items/implants/implant_cloak.dm | 1 - .../items/implants/implant_neurostim.dm | 2 +- code/game/objects/items/implants/implanter.dm | 36 +++- .../objects/items/implants/sandevistan.dm | 169 +++++++++++++++++ .../implants/skill_implants/implant_code.dm | 7 +- .../skill_implants/implantator_code.dm | 2 - code/game/objects/items/scanners.dm | 4 +- code/game/objects/items/weapons/blades.dm | 2 +- code/game/objects/machinery/autodoc.dm | 24 +-- .../xenomorph/castes/bull/abilities_bull.dm | 4 +- .../castes/crusher/abilities_crusher.dm | 2 +- .../castes/hunter/abilities_hunter.dm | 2 +- .../castes/panther/abilities_panther.dm | 4 +- .../castes/runner/abilities_runner.dm | 4 +- .../modules/mob/living/living_health_procs.dm | 6 +- code/modules/mob/mob_helpers.dm | 6 +- .../equipment/weapons/greyscale_weapons.dm | 4 +- icons/obj/items/implants.dmi | Bin 7048 -> 6637 bytes sound/effects/spinal_implant_off.ogg | Bin 0 -> 31936 bytes sound/effects/spinal_implant_on.ogg | Bin 0 -> 30958 bytes tgmc.dme | 3 + 33 files changed, 546 insertions(+), 140 deletions(-) create mode 100644 code/datums/components/after_image.dm create mode 100644 code/datums/keybinding/cyberware.dm create mode 100644 code/game/objects/items/implants/sandevistan.dm create mode 100644 sound/effects/spinal_implant_off.ogg create mode 100644 sound/effects/spinal_implant_on.ogg diff --git a/code/__DEFINES/keybind.dm b/code/__DEFINES/keybind.dm index 2740ea4b8a3..386efdd8a31 100644 --- a/code/__DEFINES/keybind.dm +++ b/code/__DEFINES/keybind.dm @@ -10,6 +10,7 @@ #define CATEGORY_PSIONIC "PSIONIC" #define CATEGORY_WEAPON "WEAPON" #define CATEGORY_ITEM "ITEM" +#define CATEGORY_CYBERWARE "CYBERWARE" #define CATEGORY_MISC "MISC" #define CATEGORY_EMOTE "EMOTE" #define CATEGORY_CUSTOM_EMOTE "CUSTOM_EMOTE" diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 8e4f980bbe7..5ea6e522263 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -110,9 +110,14 @@ LAZYDECREMENT(user.do_actions, target) -/mob/proc/do_after_coefficent() // This gets added to the delay on a do_after, default 1 +///Multiplier on all do_afters for this mob +/mob/proc/do_after_coefficent() . = 1 - + var/list/mod_list = list() + SEND_SIGNAL(src, MOB_GET_DO_AFTER_COEFFICIENT, mod_list) + for(var/num in mod_list) + . += num + . = max(0, .) /proc/random_unique_name(gender, attempts_to_find_unique_name = 10) for(var/i in 1 to attempts_to_find_unique_name) diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index 320ba8425dd..f2ccd8145a0 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -38,6 +38,9 @@ */ var/can_transfer = FALSE + /// A lazy list of the sources for this component + var/list/sources + /** * Create a new component. * @@ -157,6 +160,28 @@ /datum/component/proc/UnregisterFromParent() return +/** + * Called when the component has a new source registered. + * Return COMPONENT_INCOMPATIBLE to signal that the source is incompatible and should not be added + */ +/datum/component/proc/on_source_add(source, ...) + SHOULD_CALL_PARENT(TRUE) + if(dupe_mode != COMPONENT_DUPE_SOURCES) + return COMPONENT_INCOMPATIBLE + LAZYOR(sources, source) + +/** + * Called when the component has a source removed. + * You probably want to call parent after you do your logic because at the end of this we qdel if we have no sources remaining! + */ +/datum/component/proc/on_source_remove(source) + SHOULD_CALL_PARENT(TRUE) + if(dupe_mode != COMPONENT_DUPE_SOURCES) + CRASH("Component '[type]' does not use sources but is trying to remove a source") + LAZYREMOVE(sources, source) + if(!LAZYLEN(sources)) + qdel(src) + /** * Called on a component when a component of the same type was added to the same parent * @@ -280,70 +305,113 @@ * * Properly handles duplicate situations based on the `dupe_mode` var */ -/datum/proc/_AddComponent(list/raw_args) - var/new_type = raw_args[1] - var/datum/component/nt = new_type - var/dm = initial(nt.dupe_mode) - var/dt = initial(nt.dupe_type) - - var/datum/component/old_comp - var/datum/component/new_comp - - if(ispath(nt)) - if(nt == /datum/component) - CRASH("[nt] attempted instantiation!") - else - new_comp = nt - nt = new_comp.type - raw_args[1] = src +/datum/proc/_AddComponent(list/raw_args, source) + var/original_type = raw_args[1] + var/datum/component/component_type = original_type - if(dm != COMPONENT_DUPE_ALLOWED) - if(!dt) - old_comp = GetExactComponent(nt) + if(QDELING(src)) + CRASH("Attempted to add a new component of type \[[component_type]\] to a qdeleting parent of type \[[type]\]!") + + var/datum/component/new_component + + if(!ispath(component_type, /datum/component)) + if(!istype(component_type, /datum/component)) + CRASH("Attempted to instantiate \[[component_type]\] as a component added to parent of type \[[type]\]!") else - old_comp = GetComponent(dt) - if(old_comp) - switch(dm) + new_component = component_type + component_type = new_component.type + else if(component_type == /datum/component) + CRASH("[component_type] attempted instantiation!") + + var/dupe_mode = initial(component_type.dupe_mode) + var/dupe_type = initial(component_type.dupe_type) + var/uses_sources = (dupe_mode == COMPONENT_DUPE_SOURCES) + if(uses_sources && !source) + CRASH("Attempted to add a sourced component of type '[component_type]' to '[type]' without a source!") + else if(!uses_sources && source) + CRASH("Attempted to add a normal component of type '[component_type]' to '[type]' with a source!") + + var/datum/component/old_component + + raw_args[1] = src + if(dupe_mode != COMPONENT_DUPE_ALLOWED && dupe_mode != COMPONENT_DUPE_SELECTIVE && dupe_mode != COMPONENT_DUPE_SOURCES) + if(!dupe_type) + old_component = GetExactComponent(component_type) + else + old_component = GetComponent(dupe_type) + + if(old_component) + switch(dupe_mode) if(COMPONENT_DUPE_UNIQUE) - if(!new_comp) - new_comp = new nt(raw_args) - if(!QDELETED(new_comp)) - old_comp.InheritComponent(new_comp, TRUE) - QDEL_NULL(new_comp) + if(!new_component) + new_component = new component_type(raw_args) + if(!QDELETED(new_component)) + old_component.InheritComponent(new_component, TRUE) + QDEL_NULL(new_component) + if(COMPONENT_DUPE_HIGHLANDER) - if(!new_comp) - new_comp = new nt(raw_args) - if(!QDELETED(new_comp)) - new_comp.InheritComponent(old_comp, FALSE) - QDEL_NULL(old_comp) + if(!new_component) + new_component = new component_type(raw_args) + if(!QDELETED(new_component)) + new_component.InheritComponent(old_component, FALSE) + QDEL_NULL(old_component) + if(COMPONENT_DUPE_UNIQUE_PASSARGS) - if(!new_comp) + if(!new_component) var/list/arguments = raw_args.Copy(2) arguments.Insert(1, null, TRUE) - old_comp.InheritComponent(arglist(arguments)) + old_component.InheritComponent(arglist(arguments)) else - old_comp.InheritComponent(new_comp, TRUE) - if(COMPONENT_DUPE_SELECTIVE) - var/list/arguments = raw_args.Copy() - arguments[1] = new_comp - var/make_new_component = TRUE - for(var/datum/component/existing_component as anything in GetComponents(new_type)) - if(existing_component.CheckDupeComponent(arglist(arguments))) - make_new_component = FALSE - QDEL_NULL(new_comp) - break - if(!new_comp && make_new_component) - new_comp = new nt(raw_args) - else if(!new_comp) - new_comp = new nt(raw_args) // There's a valid dupe mode but there's no old component, act like normal - else if(!new_comp) - new_comp = new nt(raw_args) // Dupes are allowed, act like normal - - if(!old_comp && !QDELETED(new_comp)) // Nothing related to duplicate components happened and the new component is healthy - SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_comp) - return new_comp - return old_comp + old_component.InheritComponent(new_component, TRUE) + + if(COMPONENT_DUPE_SOURCES) + if(source in old_component.sources) + return old_component // source already registered, no work to do + + if(old_component.on_source_add(arglist(list(source) + raw_args.Copy(2))) == COMPONENT_INCOMPATIBLE) + stack_trace("incompatible source added to a [old_component.type]. Args: [json_encode(raw_args)]") + return null + + else if(!new_component) + new_component = new component_type(raw_args) // There's a valid dupe mode but there's no old component, act like normal + + else if(dupe_mode == COMPONENT_DUPE_SELECTIVE) + var/list/arguments = raw_args.Copy() + arguments[1] = new_component + var/make_new_component = TRUE + for(var/datum/component/existing_component as anything in GetComponents(original_type)) + if(existing_component.CheckDupeComponent(arglist(arguments))) + make_new_component = FALSE + QDEL_NULL(new_component) + break + if(!new_component && make_new_component) + new_component = new component_type(raw_args) + + else if(dupe_mode == COMPONENT_DUPE_SOURCES) + new_component = new component_type(raw_args) + if(new_component.on_source_add(arglist(list(source) + raw_args.Copy(2))) == COMPONENT_INCOMPATIBLE) + stack_trace("incompatible source added to a [new_component.type]. Args: [json_encode(raw_args)]") + return null + + else if(!new_component) + new_component = new component_type(raw_args) // Dupes are allowed, act like normal + + if(!old_component && !QDELETED(new_component)) // Nothing related to duplicate components happened and the new component is healthy + SEND_SIGNAL(src, COMSIG_COMPONENT_ADDED, new_component) + return new_component + + return old_component + +/** + * Removes a component source from this datum + */ +/datum/proc/RemoveComponentSource(source, datum/component/component_type) + if(ispath(component_type)) + component_type = GetExactComponent(component_type) + if(!component_type) + return + component_type.on_source_remove(source) /** * Get existing component of type, or create it and return a reference to it diff --git a/code/datums/components/after_image.dm b/code/datums/components/after_image.dm new file mode 100644 index 00000000000..768bb797aa1 --- /dev/null +++ b/code/datums/components/after_image.dm @@ -0,0 +1,111 @@ +/datum/component/after_image + //dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + dupe_mode = COMPONENT_DUPE_SOURCES + ///How frequently an image is made + var/loop_delay = 0.1 SECONDS + ///How long an image lasts + var/image_duration = 1.5 SECONDS + ///Holds the loop timer + var/loop_timer = null + ///Last loc of owner. Used for estimating the pixel_x and pixel_y of the target + var/turf/previous_loc + ///Last move time of owner + var/last_movement = 0 + ///Last dir faced by owner + var/last_direction = NORTH + ///Current glide_size of the owner + var/glide_size = 8 + ///Mob we are making images of + var/mob/owner + var/jump_height = 0 + var/jump_duration = 0 + var/jump_start_time = 0 + + ///Whether we make a rainbow colour cycle + var/color_cycle = FALSE + ///Last world time we cycled a colour + var/last_colour_time = 0 + ///Current colour of the after image + var/list/hsv + COOLDOWN_DECLARE(imagecooldown) + +/datum/component/after_image/Initialize(image_duration = 1.5 SECONDS, loop_delay = 0.1 SECONDS, color_cycle = FALSE) + if(!ismovable(parent)) + return COMPONENT_INCOMPATIBLE + owner = parent + src.loop_delay = loop_delay + src.image_duration = image_duration + src.color_cycle = color_cycle + last_colour_time = world.time + +/datum/component/after_image/RegisterWithParent() + loop_timer = addtimer(CALLBACK(src, PROC_REF(spawn_image)), loop_delay, TIMER_LOOP|TIMER_UNIQUE|TIMER_STOPPABLE) + START_PROCESSING(SSobj, src) + RegisterSignal(parent, COMSIG_MOVABLE_PRE_MOVE, PROC_REF(update_step)) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(update_glide)) + RegisterSignal(parent, COMSIG_ELEMENT_JUMP_STARTED, PROC_REF(handle_jump)) + owner = parent + +/datum/component/after_image/UnregisterFromParent() + deltimer(loop_timer) + UnregisterSignal(parent, list(COMSIG_MOVABLE_PRE_MOVE, COMSIG_MOVABLE_MOVED, COMSIG_ELEMENT_JUMP_STARTED)) + +///Updates prev loc and move time when starting a step +/datum/component/after_image/proc/update_step(mob/living/mover, dir) + SIGNAL_HANDLER + previous_loc = get_turf(mover) + last_movement = world.time + +///Updates last dir and glidesize after making a step +/datum/component/after_image/proc/update_glide(mob/living/mover) + SIGNAL_HANDLER + last_direction = get_dir(previous_loc, get_turf(mover)) + glide_size = owner.glide_size + +///Records jump details +/datum/component/after_image/proc/handle_jump(mob/living/mover, jump_height, jump_duration) + SIGNAL_HANDLER + jump_start_time = world.time + src.jump_height = jump_height + src.jump_duration = jump_duration + +///Creates the after image +/datum/component/after_image/proc/spawn_image() + if(!previous_loc || get_turf(owner) == previous_loc) + return + + var/obj/effect/temp_visual/after_image/after_image = new(previous_loc, owner, image_duration) + after_image.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + after_image.layer = BELOW_MOB_LAYER + + //need to recalculate position based on glide_size since it's not possible to get otherwise + var/per_step = glide_size * 2 //i don't know why i need to multiply by 2, but that's what seems to make it line up properly + var/since_last = world.time - last_movement + + var/x_modifier = 0 + if(last_direction & EAST) + x_modifier = 1 + else if(last_direction & WEST) + x_modifier = -1 + var/y_modifier = 0 + if(last_direction & NORTH) + y_modifier = 1 + else if(last_direction & SOUTH) + y_modifier = -1 + + var/traveled = per_step * since_last + if(traveled > 32) //don't spawn it if the player is stationary + qdel(after_image) + return + after_image.pixel_x = (traveled * x_modifier) + owner.pixel_x + after_image.pixel_y = (traveled * y_modifier) + owner.pixel_y + if((jump_start_time < world.time) && (jump_start_time + jump_duration) > world.time) + after_image.pixel_y += jump_height * sin(TODEGREES((PI * (world.time - jump_start_time)) / jump_duration)) + + if(!color_cycle) + return + if(!hsv) + hsv = RGBtoHSV(rgb(255, 0, 0)) + hsv = RotateHue(hsv, (world.time - last_colour_time) * 15) + last_colour_time = world.time + after_image.color = HSVtoRGB(hsv) diff --git a/code/datums/components/jump.dm b/code/datums/components/jump.dm index 3ced4562305..295560b4801 100644 --- a/code/datums/components/jump.dm +++ b/code/datums/components/jump.dm @@ -66,7 +66,7 @@ var/original_layer = jumper.layer var/original_pass_flags = jumper.pass_flags - SEND_SIGNAL(jumper, COMSIG_ELEMENT_JUMP_STARTED) + SEND_SIGNAL(jumper, COMSIG_ELEMENT_JUMP_STARTED, jump_height, jump_duration) jumper.adjustStaminaLoss(stamina_cost) jumper.pass_flags |= jumper_allow_pass_flags ADD_TRAIT(jumper, TRAIT_SILENT_FOOTSTEPS, JUMP_COMPONENT) diff --git a/code/datums/elements/shrapnel_removal.dm b/code/datums/elements/shrapnel_removal.dm index 0e068d79240..beaf4eac75f 100644 --- a/code/datums/elements/shrapnel_removal.dm +++ b/code/datums/elements/shrapnel_removal.dm @@ -61,20 +61,20 @@ ///returns TRUE if the argument limb has any shrapnel in it /datum/element/shrapnel_removal/proc/has_shrapnel(datum/limb/targetlimb) - for (var/obj/item/I in targetlimb.implants) - if(!is_type_in_list(I, GLOB.known_implants)) + for(var/obj/item/embedded AS in targetlimb.implants) + if(!embedded.is_beneficial_implant()) return TRUE return FALSE /datum/element/shrapnel_removal/proc/remove_shrapnel(mob/living/user, mob/living/target, datum/limb/targetlimb, skill) - for(var/obj/item/I AS in targetlimb.implants) - if(is_type_in_list(I, GLOB.known_implants)) + for(var/obj/item/embedded AS in targetlimb.implants) + if(embedded.is_beneficial_implant()) continue - I.unembed_ourself(FALSE) + embedded.unembed_ourself(FALSE) if(skill < SKILL_MEDICAL_PRACTICED) - user.visible_message(span_notice("[user] violently rips out [I] from [target]!"), span_notice("You violently rip out [I] from [target]!")) + user.visible_message(span_notice("[user] violently rips out [embedded] from [target]!"), span_notice("You violently rip out [embedded] from [target]!")) targetlimb.take_damage_limb(5 + additional_damage * (SKILL_MEDICAL_PRACTICED - skill), 0, FALSE, FALSE) else - user.visible_message(span_notice("[user] pulls out [I] from [target]!"), span_notice("You pull out [I] from [target]!")) + user.visible_message(span_notice("[user] pulls out [embedded] from [target]!"), span_notice("You pull out [embedded] from [target]!")) targetlimb.take_damage_limb(rand(3, 7), 0, FALSE, FALSE) break diff --git a/code/datums/keybinding/cyberware.dm b/code/datums/keybinding/cyberware.dm new file mode 100644 index 00000000000..aeb594f9b5f --- /dev/null +++ b/code/datums/keybinding/cyberware.dm @@ -0,0 +1,10 @@ +/datum/keybinding/cyberware + category = CATEGORY_CYBERWARE + weight = WEIGHT_MOB + +/datum/keybinding/cyberware/sandevistan + name = "Sandevistan" + full_name = "Activate Sandevistan" + description = "Overclock your nervous system for increased speed and dexterity." + keybind_signal = COMSIG_IMPLANT_ABILITY_SANDEVISTAN + hotkey_keys = list("I") diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index b2122619c6a..5556aef67cf 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -105,23 +105,30 @@ GLOBAL_LIST_EMPTY(blood_particles) duration = 0.5 SECONDS -/obj/effect/temp_visual/xenomorph/afterimage +/obj/effect/temp_visual/after_image name = "afterimage" - layer = MOB_LAYER + layer = BELOW_MOB_LAYER alpha = 64 //Translucent - duration = 0.5 SECONDS density = FALSE opacity = FALSE anchored = FALSE animate_movement = SLIDE_STEPS + randomdir = FALSE + vis_flags = VIS_INHERIT_LAYER | VIS_INHERIT_PLANE | VIS_INHERIT_ID -/obj/effect/temp_visual/xenomorph/afterimage/Initialize(mapload, atom/owner) +/obj/effect/temp_visual/after_image/Initialize(mapload, atom/owner, _duration = 0.5 SECONDS) . = ..() - appearance = owner.appearance - setDir(owner.dir) - alpha = initial(alpha) - layer = initial(layer) - mouse_opacity = MOUSE_OPACITY_TRANSPARENT + var/mutable_appearance/after_image = new() + after_image.appearance = owner.appearance + after_image.render_target = null + after_image.density = initial(density) + after_image.alpha = initial(alpha) + after_image.appearance_flags = RESET_COLOR|RESET_ALPHA|PASS_MOUSE + after_image.setDir(owner.dir) + after_image.pixel_x = owner.pixel_x + after_image.pixel_y = owner.pixel_y + appearance = after_image + duration = _duration animate(src, alpha = 0, time = duration) /obj/effect/temp_visual/ob_impact diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 728c761485b..014b0c403b1 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -1464,3 +1464,7 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. var/target = get_turf_in_angle(Get_Angle(user, src), src, 7) throw_at(target, 4 + psi_power, psi_power, user, TRUE) return list(3 SECONDS, 10) + +///Returns whether this is considered beneficial if embedded in a mob +/obj/item/proc/is_beneficial_implant() + return FALSE diff --git a/code/game/objects/items/embedding.dm b/code/game/objects/items/embedding.dm index a4ed6eaeac3..809b3dc4a5c 100644 --- a/code/game/objects/items/embedding.dm +++ b/code/game/objects/items/embedding.dm @@ -83,10 +83,6 @@ stack_trace("limb_embed called for TRAIT_NODROP or DELONDROP [embedding]") embedding.unembed_ourself() return FALSE - //RUTGMC EDIT START - if(embedding.w_class >= WEIGHT_CLASS_NORMAL) - return FALSE - //RUTGMC EDIT END if(limb_status & LIMB_DESTROYED) return FALSE if(!silent) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 2d2df8f3699..0afc2ba6629 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -16,11 +16,13 @@ ///What level of malfunction/breakage this implant is at, used for functionality checks var/malfunction = MALFUNCTION_NONE ///Implant secific flags - var/flags_implant = GRANT_ACTIVATION_ACTION + var/flags_implant = GRANT_ACTIVATION_ACTION|BENEFICIAL_IMPLANT ///Whitelist for llimbs that this implavnt is allowed to be inserted into, all limbs by default var/list/allowed_limbs + ///Type of action to give + var/action_type = /datum/action/item_action/implant ///Activation_action reference - var/datum/action/item_action/implant/activation_action + var/datum/action/activation_action ///Cooldown between usages of the implant var/cooldown_time = 1 SECONDS COOLDOWN_DECLARE(activation_cooldown) @@ -28,7 +30,7 @@ /obj/item/implant/Initialize(mapload) . = ..() if(flags_implant & GRANT_ACTIVATION_ACTION) - activation_action = new(src, src) + activation_action = new action_type(src, src) if(allow_reagents) reagents = new /datum/reagents(MAX_IMPLANT_REAGENTS) reagents.my_atom = WEAKREF(src) @@ -36,7 +38,8 @@ allowed_limbs = GLOB.human_body_parts /obj/item/implant/Destroy(force) - unimplant() + if(implanted) + unembed_ourself() QDEL_NULL(activation_action) part?.implants -= src return ..() @@ -44,6 +47,13 @@ /obj/item/implant/ui_action_click(mob/user, datum/action/item_action/action) activate() +/obj/item/implant/is_beneficial_implant() + return flags_implant & BENEFICIAL_IMPLANT + +/obj/item/implant/unembed_ourself() + . = ..() + unimplant() + ///Handles the actual activation of the implant/it's effects. Returns TRUE on succesful activation and FALSE on failure for parentcalls /obj/item/implant/proc/activate() if(!COOLDOWN_CHECK(src, activation_cooldown)) @@ -60,6 +70,8 @@ if(!(limb_targeting in allowed_limbs)) to_chat(user, span_warning("You cannot implant this into that limb!")) return FALSE + if((flags_implant & DUPLICATE_IMPLANT_ALLOWED)) + return return TRUE /** @@ -70,25 +82,29 @@ SHOULD_CALL_PARENT(TRUE) if(!try_implant(target, user)) return FALSE - forceMove(target) - implant_owner = target - implanted = TRUE var/limb_targeting = (user ? user.zone_selected : BODY_ZONE_CHEST) var/datum/limb/affected = target.get_limb(limb_targeting) if(!affected) CRASH("[src] implanted into [target] [user ? "by [user]" : ""] but had no limb, despite being set to implant in [limb_targeting].") - affected.implants += src + for(var/obj/item/implant/embedded in affected.implants) + if((flags_implant & HIGHLANDER_IMPLANT) || (embedded.flags_implant & HIGHLANDER_IMPLANT)) + to_chat(user, span_warning("Cannot fit the [name] due to the [embedded.name] already there!")) + return FALSE + if(!(embedded.type == type) || (flags_implant & DUPLICATE_IMPLANT_ALLOWED)) + continue + to_chat(user, span_warning("There is already another [name] in this limb!")) + return FALSE + if(!embed_into(target, limb_targeting, TRUE)) + return FALSE + implant_owner = target + implanted = TRUE part = affected if(flags_implant & ACTIVATE_ON_HEAR) RegisterSignal(src, COMSIG_MOVABLE_HEAR, PROC_REF(on_hear)) activation_action?.give_action(target) - embed_into(target, limb_targeting, TRUE) return TRUE -/obj/item/implant/unembed_ourself() - . = ..() - unimplant() - +///Cleans up on being removed from a mob /obj/item/implant/proc/unimplant() SHOULD_CALL_PARENT(TRUE) if(!implanted) @@ -97,9 +113,7 @@ if(flags_implant & ACTIVATE_ON_HEAR) UnregisterSignal(src, COMSIG_MOVABLE_HEAR) implanted = FALSE - part.implants -= src part = null - forceMove(get_turf(implant_owner)) implant_owner = null ///Returns info about a implant concerning its usage and such diff --git a/code/game/objects/items/implants/implant_chem.dm b/code/game/objects/items/implants/implant_chem.dm index b8224c063a7..eb141390a7f 100644 --- a/code/game/objects/items/implants/implant_chem.dm +++ b/code/game/objects/items/implants/implant_chem.dm @@ -2,7 +2,7 @@ name = "chemical implant" desc = "A chemical implant containing a single use chemical cocktail which is added via syringe." allow_reagents = TRUE - flags_implant = ACTIVATE_ON_HEAR|GRANT_ACTIVATION_ACTION + flags_implant = ACTIVATE_ON_HEAR|GRANT_ACTIVATION_ACTION|BENEFICIAL_IMPLANT var/used = FALSE var/activation_phrase = "aaaaaa help i dying help maint" diff --git a/code/game/objects/items/implants/implant_cloak.dm b/code/game/objects/items/implants/implant_cloak.dm index d4eeddf5553..51287dcd2a5 100644 --- a/code/game/objects/items/implants/implant_cloak.dm +++ b/code/game/objects/items/implants/implant_cloak.dm @@ -5,7 +5,6 @@ name = "cloak implant" desc = "A top of the line nanotrasen implant, designed for infiltration." icon_state = "gripper" - flags_implant = GRANT_ACTIVATION_ACTION cooldown_time = 0 var/deactivation_timer diff --git a/code/game/objects/items/implants/implant_neurostim.dm b/code/game/objects/items/implants/implant_neurostim.dm index 7d4292baa0b..8ed853278db 100644 --- a/code/game/objects/items/implants/implant_neurostim.dm +++ b/code/game/objects/items/implants/implant_neurostim.dm @@ -2,7 +2,7 @@ name = "neurostimulator implant" desc = "An implant which regulates nociception and sensory function. Benefits include pain reduction, improved balance, and improved resistance to overstimulation and disoritentation. To encourage compliance, negative stimulus is applied if the implant hears a (non-radio) spoken codeprhase. Implant may be degraded by the body's immune system over time, and thus may occasionally malfunction." icon_state = "implant_evil" - flags_implant = ACTIVATE_ON_HEAR + flags_implant = ACTIVATE_ON_HEAR|BENEFICIAL_IMPLANT var/phrase = "supercalifragilisticexpialidocious" /obj/item/implant/neurostim/get_data() diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index 0da26b595d9..d4016cca847 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -10,6 +10,7 @@ throw_speed = 1 throw_range = 5 w_class = WEIGHT_CLASS_TINY + ///The implant itself var/obj/item/implant/internal_implant = null /obj/item/implanter/Initialize(mapload, ...) @@ -39,15 +40,17 @@ if(!do_after(user, 5 SECONDS, NONE, target, BUSY_ICON_GENERIC) || !internal_implant) to_chat(user, span_notice("You failed to implant [target].")) - return + return FALSE - if(internal_implant.implant(target, user)) - target.visible_message(span_warning("[target] has been implanted by [user].")) - log_combat(user, target, "implanted", src) - internal_implant = null - update_icon() - return TRUE - to_chat(user, span_notice("You fail to implant [target].")) + if(!internal_implant.implant(target, user)) + to_chat(user, span_notice("You fail to implant [target].")) + return FALSE + + target.visible_message(span_warning("[target] has been implanted by [user].")) + log_combat(user, target, "implanted", src) + internal_implant = null + update_icon() + return TRUE /obj/item/implanter/proc/can_implant(mob/target, mob/user) if(!ishuman(target)) @@ -80,3 +83,20 @@ /obj/item/implanter/suicide_dust name = "Self-Gibbing implant" internal_implant = /obj/item/implant/suicide_dust + + +/obj/item/implanter/sandevistan + name = "sandevistan implanter" + icon_state = "internal_implant_spinal" + w_class = WEIGHT_CLASS_NORMAL + internal_implant = /obj/item/implant/sandevistan + +/obj/item/implanter/sandevistan/update_icon_state() + . = ..() + icon_state = initial(icon_state) + +/obj/item/implanter/sandevistan/attack(mob/target, mob/user) + . = ..() + if(!.) + return + qdel(src) diff --git a/code/game/objects/items/implants/sandevistan.dm b/code/game/objects/items/implants/sandevistan.dm new file mode 100644 index 00000000000..cae0c9bcc2e --- /dev/null +++ b/code/game/objects/items/implants/sandevistan.dm @@ -0,0 +1,169 @@ +#define SANDEVISTAN_IMPLANT "sandevistan_implant" + +/obj/item/implant/sandevistan + name = "sandevistan spinal implant" + desc = "Overloads your central nervous system in order to do everything faster. Careful not to overuse it." + icon_state = "internal_implant_spinal" + implant_color = null + w_class = WEIGHT_CLASS_NORMAL + allowed_limbs = list(BODY_ZONE_CHEST) + cooldown_time = 5 SECONDS + action_type = /datum/action/ability/activable/sandevistan + ///How long its been on for. Slowly goes down over time + var/time_on = 0 + ///If you're pushing it to the edge + var/exerted = FALSE + ///modifier to multiplier on move delay and do_after + var/action_modifier = 0.3 + ///Movement speed modifier + var/speed_modifier = -1 + ///Gun scatter modifier + var/scatter_mod = 5 + ///Gun accuracy modifier + var/accuracy_mod = 30 + ///Modifier for melee/throw miss chance + var/miss_chance_mod = 30 + COOLDOWN_DECLARE(alertcooldown) + +/obj/item/implant/sandevistan/unimplant() + if(active) + toggle() + return ..() + +/obj/item/implant/sandevistan/activate() + return toggle() + +/obj/item/implant/sandevistan/update_icon_state() + if(active) + icon_state = initial(icon_state) + "_on" + else + icon_state = initial(icon_state) + +/obj/item/implant/sandevistan/get_data() + return {" + Implant Specifications:
+ Name: Nanotrasen CDPR Sandevistan Implant
+
+ Implant Details:
+ Function: Upon activation, this implant increases neural impulse speed, allowing the user's brain to process information, and react quicker than would be normally possible.
+ The practical result in an increase in mobility and dexterity. WARNING Usage of the sandevistan is extremely taxing on the body, and prolonged use can lead to catastrophic injury or death."} + +/obj/item/implant/sandevistan/process() + if(!active) + time_on -= 0.1 SECONDS + if(time_on > 0) + return + time_on = 0 + STOP_PROCESSING(SSfastprocess, src) + if(exerted) + to_chat(implant_owner, "Your brains feels normal again.") + exerted = FALSE + return + + if(implant_owner.stat != CONSCIOUS) + toggle(TRUE) + time_on += 0.2 SECONDS + switch(time_on) + if(1 SECONDS to 2 SECONDS) + if(COOLDOWN_CHECK(src, alertcooldown)) + to_chat(implant_owner, span_alert("You feel your spine tingle.")) + COOLDOWN_START(src, alertcooldown, 10 SECONDS) + implant_owner.hallucination += 2 + implant_owner.adjustFireLoss(1) + if(2.1 SECONDS to 5 SECONDS) + if(COOLDOWN_CHECK(src, alertcooldown) || !exerted) + to_chat(implant_owner, span_userdanger("Your spine and brain feel like they're burning!")) + COOLDOWN_START(src, alertcooldown, 5 SECONDS) + exerted = TRUE + implant_owner.set_drugginess(10) + implant_owner.hallucination += 10 + if(time_on > 3.6 SECONDS) + implant_owner.adjustCloneLoss(1) + implant_owner.adjustFireLoss(1) + else + implant_owner.adjustFireLoss(2) + if(5.1 SECONDS to INFINITY)//no infinite abuse + to_chat(implant_owner, span_userdanger("You feel a slight sense of shame as your brain and spine rip themselves apart from overexertion.")) + implant_owner.gib() + return + + if(!exerted) + return + var/side_effect_roll = rand(1, 100) + (time_on * 0.5) + if((side_effect_roll > 90) && iscarbon(implant_owner)) + var/mob/living/carbon/carbon_owner = implant_owner + carbon_owner.emote("me", 1, "coughs up blood!") + carbon_owner.drip(10) + if(side_effect_roll > 96) + implant_owner.Stagger(1 SECONDS) + if(side_effect_roll > 126) + implant_owner.Stun(0.5 SECONDS) + +///Turns it off or on +/obj/item/implant/sandevistan/proc/toggle(silent = FALSE) + if(!active) + playsound(implant_owner, 'sound/effects/spinal_implant_on.ogg', 60) + implant_owner.add_movespeed_modifier(type, priority = 100, multiplicative_slowdown = speed_modifier) + implant_owner.next_move_modifier -= action_modifier + RegisterSignal(implant_owner, MOB_GET_DO_AFTER_COEFFICIENT, PROC_REF(apply_do_after_mod)) + RegisterSignal(implant_owner, MOB_GET_MISS_CHANCE_MOD, PROC_REF(apply_miss_chance_mod)) + implant_owner.AddComponentFrom(SANDEVISTAN_IMPLANT, /datum/component/after_image, 2 SECONDS, 0.5, TRUE) + implant_owner.adjust_mob_scatter(scatter_mod) + implant_owner.adjust_mob_accuracy(accuracy_mod) + START_PROCESSING(SSfastprocess, src) + else + playsound(implant_owner, 'sound/effects/spinal_implant_off.ogg', 70) + implant_owner.next_move_modifier += action_modifier + UnregisterSignal(implant_owner, list(MOB_GET_DO_AFTER_COEFFICIENT, MOB_GET_MISS_CHANCE_MOD)) + implant_owner.remove_movespeed_modifier(type) + implant_owner.RemoveComponentSource(SANDEVISTAN_IMPLANT, /datum/component/after_image) + implant_owner.adjust_mob_scatter(-scatter_mod) + implant_owner.adjust_mob_accuracy(-accuracy_mod) + toggle_active(!active) + if(!silent) + to_chat(implant_owner, span_notice("You turn your spinal implant [active? "on" : "off"].")) + update_icon() + activation_action.update_button_icon() + return TRUE + +///Modifies do_after delays +/obj/item/implant/sandevistan/proc/apply_do_after_mod(datum/source, list/mod_list) + mod_list += -action_modifier + +///Modifies miss chance mod for melee/throw hits +/obj/item/implant/sandevistan/proc/apply_miss_chance_mod(datum/source, list/mod_list) + mod_list += miss_chance_mod + +//todo: make a generic activable/implant parent type +/datum/action/ability/activable/sandevistan + action_icon = 'icons/obj/items/implants.dmi' + keybind_flags = ABILITY_KEYBIND_USE_ABILITY|ABILITY_IGNORE_SELECTED_ABILITY + use_state_flags = ABILITY_USE_STAGGERED|ABILITY_USE_INCAP|ABILITY_USE_LYING|ABILITY_USE_BUCKLED|ABILITY_USE_BUSY + keybinding_signals = list( + KEYBINDING_NORMAL = COMSIG_IMPLANT_ABILITY_SANDEVISTAN, + ) + +/datum/action/ability/activable/sandevistan/New(Target) + . = ..() + var/obj/item/implant/implant = Target + name = implant.name + action_icon_state = implant.icon_state + cooldown_duration = implant.cooldown_time + +/datum/action/ability/activable/sandevistan/update_button_icon() + if(!target) + return + var/obj/item/implant/implant = target + action_icon_state = implant.icon_state + return ..() + +/datum/action/ability/activable/sandevistan/use_ability() + if(!target) + return FALSE + var/obj/item/implant/implant = target + . = implant.activate() + if(!.) + return + if(!implant.active) + add_cooldown() + update_button_icon() diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index e0ce11877b1..5a5bbe43de8 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -1,4 +1,5 @@ /obj/item/implant/skill + flags_implant = GRANT_ACTIVATION_ACTION|BENEFICIAL_IMPLANT|HIGHLANDER_IMPLANT w_class = WEIGHT_CLASS_TINY // Maximum skill a user can possess var/list/max_skills @@ -25,12 +26,6 @@ var/mech_pilot var/stamina -/obj/item/implant/Destroy(force) - unimplant() - QDEL_NULL(activation_action) - part?.implants -= src - return ..() - /obj/item/implant/skill/try_implant(mob/living/carbon/human/target, mob/living/user) . = ..() if(!.) diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 7fec58b3b5c..6d95fc4133f 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -45,8 +45,6 @@ if(!istype(implant, /obj/item/implant/skill)) balloon_alert(user, "Limb already implanted!") return FALSE - if(user.ckey == "akulishov") // https://discord.com/channels/1235677154084126861/1235677154084126865/1319014221836582932 - user.gib() // 1984 return TRUE /obj/item/implanter/implantator/combat diff --git a/code/game/objects/items/scanners.dm b/code/game/objects/items/scanners.dm index e7eb800107a..ad9f156bbd4 100644 --- a/code/game/objects/items/scanners.dm +++ b/code/game/objects/items/scanners.dm @@ -248,8 +248,8 @@ REAGENT SCANNER unknown_implants++ var/implant = FALSE if(length(limb.implants)) - for(var/I in limb.implants) - if(is_type_in_list(I, GLOB.known_implants)) + for(var/obj/item/embedded AS in limb.implants) + if(embedded.is_beneficial_implant()) continue unknown_implants++ implant = TRUE diff --git a/code/game/objects/items/weapons/blades.dm b/code/game/objects/items/weapons/blades.dm index 17381822bc1..bf5670a4ffd 100644 --- a/code/game/objects/items/weapons/blades.dm +++ b/code/game/objects/items/weapons/blades.dm @@ -79,7 +79,7 @@ ///Create an after image /datum/action/ability/activable/weapon_skill/sword_lunge/proc/movement_fx() SIGNAL_HANDLER - new /obj/effect/temp_visual/xenomorph/afterimage(get_turf(owner), owner) + new /obj/effect/temp_visual/after_image(get_turf(owner), owner) ///Unregisters signals after lunge complete /datum/action/ability/activable/weapon_skill/sword_lunge/proc/charge_complete() diff --git a/code/game/objects/machinery/autodoc.dm b/code/game/objects/machinery/autodoc.dm index e6c22b16bd5..78889d56fcd 100644 --- a/code/game/objects/machinery/autodoc.dm +++ b/code/game/objects/machinery/autodoc.dm @@ -259,11 +259,12 @@ surgery_list += create_autodoc_surgery(L,LIMB_SURGERY,ADSURGERY_NECRO) var/skip_embryo_check = FALSE if(length(L.implants)) - for(var/I in L.implants) - if(!is_type_in_list(I,GLOB.known_implants)) - surgery_list += create_autodoc_surgery(L,LIMB_SURGERY,ADSURGERY_SHRAPNEL) - if(L.body_part == CHEST) - skip_embryo_check = TRUE + for(var/obj/item/embedded AS in L.implants) + if(embedded.is_beneficial_implant()) + continue + surgery_list += create_autodoc_surgery(L,LIMB_SURGERY,ADSURGERY_SHRAPNEL) + if(L.body_part == CHEST) + skip_embryo_check = TRUE var/obj/item/alien_embryo/A = locate() in M if(A && L.body_part == CHEST && !skip_embryo_check) //If we're not already doing a shrapnel removal surgery on the chest, add an extraction surgery to remove it surgery_list += create_autodoc_surgery(L,LIMB_SURGERY,ADSURGERY_SHRAPNEL) @@ -564,12 +565,13 @@ occupant.status_flags &= ~XENO_HOST qdel(A) if(length(S.limb_ref.implants)) - for(var/obj/item/I in S.limb_ref.implants) + for(var/obj/item/embedded AS in S.limb_ref.implants) if(!surgery) break - if(!is_type_in_list(I, GLOB.known_implants)) - sleep(HEMOSTAT_REMOVE_MAX_DURATION*surgery_mod) - I.unembed_ourself(TRUE) + if(embedded.is_beneficial_implant()) + continue + sleep(HEMOSTAT_REMOVE_MAX_DURATION*surgery_mod) + embedded.unembed_ourself(TRUE) if(S.limb_ref.body_part == CHEST || S.limb_ref.body_part == HEAD) close_encased(occupant, S.limb_ref) if(!surgery) @@ -1263,8 +1265,8 @@ var/datum/limb/L = i var/skip_embryo_check = FALSE var/obj/item/alien_embryo/A = locate() in connected.occupant - for(var/I in L.implants) - if(is_type_in_list(I, GLOB.known_implants)) + for(var/obj/item/embedded AS in L.implants) + if(embedded.is_beneficial_implant()) continue N.fields["autodoc_manual"] += create_autodoc_surgery(L, LIMB_SURGERY,ADSURGERY_SHRAPNEL) needed++ diff --git a/code/modules/mob/living/carbon/xenomorph/castes/bull/abilities_bull.dm b/code/modules/mob/living/carbon/xenomorph/castes/bull/abilities_bull.dm index 0d0b5ff15b0..a16a22edf5a 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/bull/abilities_bull.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/bull/abilities_bull.dm @@ -1,7 +1,7 @@ /datum/action/ability/xeno_action/proc/acid_puddle(atom/A, atom/OldLoc, Dir, Forced) SIGNAL_HANDLER var/mob/living/carbon/xenomorph/X = owner - new/obj/effect/temp_visual/xenomorph/afterimage(get_turf(X), X) + new/obj/effect/temp_visual/after_image(get_turf(X), X) new /obj/effect/xenomorph/spray(get_turf(X), 5 SECONDS, XENO_ACID_CHARGE_DAMAGE) for(var/obj/O in get_turf(X)) O.acid_spray_act(X) @@ -10,7 +10,7 @@ /datum/action/ability/xeno_action/proc/afterimage(atom/A, atom/OldLoc, Dir, Forced) SIGNAL_HANDLER var/mob/living/carbon/xenomorph/X = owner - new/obj/effect/temp_visual/xenomorph/afterimage(get_turf(X), X) + new/obj/effect/temp_visual/after_image(get_turf(X), X) playsound(X, SFX_ALIEN_FOOTSTEP_LARGE, 50) // *************************************** diff --git a/code/modules/mob/living/carbon/xenomorph/castes/crusher/abilities_crusher.dm b/code/modules/mob/living/carbon/xenomorph/castes/crusher/abilities_crusher.dm index e587c94ab66..2454a8feb99 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/crusher/abilities_crusher.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/crusher/abilities_crusher.dm @@ -224,7 +224,7 @@ charge.charge_dir = aimdir //Set dir so check_momentum() does not cuck us for(var/i=0 to max(get_dist(X, A), advance_range)) if(i % 2) - new /obj/effect/temp_visual/xenomorph/afterimage(get_turf(X), X) + new /obj/effect/temp_visual/after_image(get_turf(X), X) X.Move(get_step(X, aimdir), aimdir) aimdir = get_dir(X, A) succeed_activate() diff --git a/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm b/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm index 843d5fe9f40..7febd5b6360 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/hunter/abilities_hunter.dm @@ -325,7 +325,7 @@ /datum/action/ability/activable/xeno/pounce/proc/movement_fx() SIGNAL_HANDLER - new /obj/effect/temp_visual/xenomorph/afterimage(get_turf(owner), owner) //Create the after image. + new /obj/effect/temp_visual/after_image(get_turf(owner), owner) //Create the after image. /datum/action/ability/activable/xeno/pounce/proc/object_hit(datum/source, obj/object_target, speed) SIGNAL_HANDLER diff --git a/code/modules/mob/living/carbon/xenomorph/castes/panther/abilities_panther.dm b/code/modules/mob/living/carbon/xenomorph/castes/panther/abilities_panther.dm index 15cefd0b167..6137e74b881 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/panther/abilities_panther.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/panther/abilities_panther.dm @@ -458,9 +458,9 @@ var/turf/our_turf = get_turf(xenomorph_owner) //location of after image SFX playsound(our_turf, pick('sound/effects/throw.ogg','sound/effects/alien/tail_swipe1.ogg', 'sound/effects/alien/tail_swipe2.ogg'), 25, 1) //sound effects - var/obj/effect/temp_visual/xenomorph/afterimage/our_afterimage + var/obj/effect/temp_visual/after_image/our_afterimage for(var/i = 0 to 2) //number of after images - our_afterimage = new /obj/effect/temp_visual/xenomorph/afterimage(our_turf, owner) //Create the after image. + our_afterimage = new /obj/effect/temp_visual/after_image(our_turf, owner) //Create the after image. our_afterimage.pixel_x = pick(rand(xenomorph_owner.pixel_x * 3, xenomorph_owner.pixel_x * 1.5), rand(0, xenomorph_owner.pixel_x * -1)) //Variation on the xenomorph_owner position // *************************************** diff --git a/code/modules/mob/living/carbon/xenomorph/castes/runner/abilities_runner.dm b/code/modules/mob/living/carbon/xenomorph/castes/runner/abilities_runner.dm index 19657b78405..093e7e34365 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/runner/abilities_runner.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/runner/abilities_runner.dm @@ -255,9 +255,9 @@ action_activate() var/turf/current_turf = get_turf(xeno_owner) //location of after image SFX playsound(current_turf, pick('sound/effects/throw.ogg','sound/effects/alien/tail_swipe1.ogg', 'sound/effects/alien/tail_swipe2.ogg'), 25, 1) //sound effects - var/obj/effect/temp_visual/xenomorph/afterimage/after_image + var/obj/effect/temp_visual/after_image/after_image for(var/i=0 to 2) //number of after images - after_image = new /obj/effect/temp_visual/xenomorph/afterimage(current_turf, owner) //Create the after image. + after_image = new /obj/effect/temp_visual/after_image(current_turf, owner) //Create the after image. after_image.pixel_x = pick(randfloat(xeno_owner.pixel_x * 3, xeno_owner.pixel_x * 1.5), rand(0, xeno_owner.pixel_x * -1)) //Variation on the X position diff --git a/code/modules/mob/living/living_health_procs.dm b/code/modules/mob/living/living_health_procs.dm index 38f7a321bec..80321575386 100644 --- a/code/modules/mob/living/living_health_procs.dm +++ b/code/modules/mob/living/living_health_procs.dm @@ -256,10 +256,10 @@ GLOB.dead_xeno_list -= src /mob/living/proc/revive(admin_revive = FALSE) - for(var/i in embedded_objects) - var/obj/item/embedded = i + for(var/obj/item/embedded AS in embedded_objects) + if(embedded.is_beneficial_implant()) + continue embedded.unembed_ourself() - // shut down various types of badness setStaminaLoss(-50) setToxLoss(0) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 1dc60661422..bc382411320 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -102,8 +102,12 @@ GLOBAL_LIST_INIT(organ_rel_size, list( // you can only miss if your target is standing and not restrained if(!target.buckled && !target.lying_angle) var/miss_chance = 10 - if (zone in GLOB.base_miss_chance) + if(zone in GLOB.base_miss_chance) miss_chance = GLOB.base_miss_chance[zone] + var/list/mod_list = list() + SEND_SIGNAL(target, MOB_GET_MISS_CHANCE_MOD, mod_list) + for(var/num in mod_list) + miss_chance += num miss_chance = max(miss_chance + miss_chance_mod, 0) if(prob(miss_chance)) if(prob(70)) diff --git a/code/modules/vehicles/mecha/equipment/weapons/greyscale_weapons.dm b/code/modules/vehicles/mecha/equipment/weapons/greyscale_weapons.dm index 30de54780b4..85a93f5d419 100644 --- a/code/modules/vehicles/mecha/equipment/weapons/greyscale_weapons.dm +++ b/code/modules/vehicles/mecha/equipment/weapons/greyscale_weapons.dm @@ -470,7 +470,7 @@ chassis.add_filter("dash_blur", 1, radial_blur_filter(0.3)) icon_state += "_on" chassis.update_icon() - new /obj/effect/temp_visual/xenomorph/afterimage(chassis.loc, chassis) + new /obj/effect/temp_visual/after_image(chassis.loc, chassis) RegisterSignal(chassis, COMSIG_MOVABLE_POST_THROW, PROC_REF(end_dash)) cutter = source chassis.flags_atom |= DIRLOCK @@ -481,7 +481,7 @@ ///signal handler, drops afterimage every move executed while dashing /obj/item/mecha_parts/mecha_equipment/laser_sword/proc/drop_afterimage(datum/source) SIGNAL_HANDLER - new /obj/effect/temp_visual/xenomorph/afterimage(chassis.loc, chassis) + new /obj/effect/temp_visual/after_image(chassis.loc, chassis) ///Ends dash and executes attack /obj/item/mecha_parts/mecha_equipment/laser_sword/proc/end_dash(datum/source) diff --git a/icons/obj/items/implants.dmi b/icons/obj/items/implants.dmi index 868903ea96e40e5c539b7848c838b2f6df971f15..394fa043c51e6cb97cd95a34932de71167199c13 100644 GIT binary patch literal 6637 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 B!`1)* diff --git a/sound/effects/spinal_implant_off.ogg b/sound/effects/spinal_implant_off.ogg new file mode 100644 index 0000000000000000000000000000000000000000..336124276882b611b1a50a6c85fb1636bd3e73b8 GIT binary patch literal 31936 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 literal 0 HcmV?d00001 diff --git a/sound/effects/spinal_implant_on.ogg b/sound/effects/spinal_implant_on.ogg new file mode 100644 index 0000000000000000000000000000000000000000..301b968bf5e0958ec68ad2b21863e3b79623e541 GIT binary patch literal 30958 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 Date: Thu, 19 Dec 2024 21:45:37 +1000 Subject: [PATCH 31/42] final, port this pr https://github.com/tgstation/TerraGov-Marine-Corps/pull/15649 https://github.com/tgstation/TerraGov-Marine-Corps/pull/15649 --- code/datums/jobs/job/other.dm | 1 + code/game/objects/items/implants/sandevistan.dm | 2 +- .../items/implants/skill_implants/implant_code.dm | 13 ++++++++++++- .../implants/skill_implants/implantator_code.dm | 12 ------------ code/modules/surgery/implant.dm | 13 +++++++------ .../PlayerPreferences/KeybindSettings.tsx | 6 ++++++ 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/code/datums/jobs/job/other.dm b/code/datums/jobs/job/other.dm index 37d00fdcd2e..cdbc48d9d8f 100644 --- a/code/datums/jobs/job/other.dm +++ b/code/datums/jobs/job/other.dm @@ -67,6 +67,7 @@ glasses = /obj/item/clothing/glasses/sunglasses/sa/nodrop back = /obj/item/storage/backpack/marine/satchel ears = /obj/item/radio/headset/mainship/spatial + implants = list(/obj/item/implant/sandevistan) /datum/job/spatial_agent/galaxy_red outfit = /datum/outfit/job/other/spatial_agent/galaxy_red diff --git a/code/game/objects/items/implants/sandevistan.dm b/code/game/objects/items/implants/sandevistan.dm index cae0c9bcc2e..bede20144d8 100644 --- a/code/game/objects/items/implants/sandevistan.dm +++ b/code/game/objects/items/implants/sandevistan.dm @@ -1,7 +1,7 @@ #define SANDEVISTAN_IMPLANT "sandevistan_implant" /obj/item/implant/sandevistan - name = "sandevistan spinal implant" + name = "Sandevistan spinal implant" desc = "Overloads your central nervous system in order to do everything faster. Careful not to overuse it." icon_state = "internal_implant_spinal" implant_color = null diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index 5a5bbe43de8..0c4cbc22f86 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -1,5 +1,5 @@ /obj/item/implant/skill - flags_implant = GRANT_ACTIVATION_ACTION|BENEFICIAL_IMPLANT|HIGHLANDER_IMPLANT + flags_implant = BENEFICIAL_IMPLANT|HIGHLANDER_IMPLANT w_class = WEIGHT_CLASS_TINY // Maximum skill a user can possess var/list/max_skills @@ -68,3 +68,14 @@ desc = "An implant from the line of implants that increases knowledge of battle tactics" icon_state = "skill_implant" allowed_limbs = list(BODY_ZONE_HEAD) + +/obj/item/implant/skill/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/implanter/implantator/cargo)) + var/obj/item/implanter/implantator/cargo/cargo = I + if(cargo.icon_state == "cargo_full_s") + balloon_alert(user, "Implantator already used!") + return + cargo.allowed_limbs = allowed_limbs + cargo.internal_implant = src + src.forceMove(cargo) + cargo.icon_state = "cargo_full" diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 6d95fc4133f..533cc0f1d73 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -59,18 +59,6 @@ allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system -/obj/item/implanter/implantator/cargo/attackby(obj/item/I, mob/user, params) - if(istype(I, /obj/item/implant/skill)) - var/obj/item/implant/skill/skill = I - if(icon_state == "cargo_full_s") - balloon_alert(user, "Implantator already used!") - return - allowed_limbs = skill.allowed_limbs - internal_implant = skill - skill.forceMove(src) - icon_state = "cargo_full" - return - /obj/item/implanter/implantator/cargo icon_state = "cargo" empty_icon = "cargo_full" diff --git a/code/modules/surgery/implant.dm b/code/modules/surgery/implant.dm index 6324c7620cd..086236629fc 100644 --- a/code/modules/surgery/implant.dm +++ b/code/modules/surgery/implant.dm @@ -32,12 +32,13 @@ /datum/surgery_step/implant_removal/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/limb/affected) if(length(affected.implants)) - - var/obj/item/implantfound = affected.implants[1] - user.visible_message(span_notice("[user] takes something out of incision on [target]'s [affected.display_name] with \the [tool]."), \ - span_notice("You take [implantfound] out of incision on [target]'s [affected.display_name]s with \the [tool].")) - target.balloon_alert_to_viewers("Implant found") - implantfound.unembed_ourself() + var/choosen_object = show_radial_menu(user, target, affected.implants, radius = 50, require_near = TRUE, tooltips = TRUE) + if(choosen_object) + var/obj/item/implant_inside = choosen_object + implant_inside.unembed_ourself() + user.visible_message(span_notice("[user] takes something out of incision on [target]'s [affected.display_name] with \the [tool]."), \ + span_notice("You take [choosen_object] out of incision on [target]'s [affected.display_name]s with \the [tool].")) + target.balloon_alert_to_viewers("Implant found") else if(affected.hidden) user.visible_message(span_notice("[user] takes something out of incision on [target]'s [affected.display_name] with \the [tool]."), \ diff --git a/tgui/packages/tgui/interfaces/PlayerPreferences/KeybindSettings.tsx b/tgui/packages/tgui/interfaces/PlayerPreferences/KeybindSettings.tsx index f7c8ca5a01c..0ff0b3eb210 100644 --- a/tgui/packages/tgui/interfaces/PlayerPreferences/KeybindSettings.tsx +++ b/tgui/packages/tgui/interfaces/PlayerPreferences/KeybindSettings.tsx @@ -153,6 +153,12 @@ export const KeybindSettings = (props) => { {all_keybindings['ITEM'] ?.filter(filterSearch) .map((kb) => )} + +

Cyberware

+
+ {all_keybindings['CYBERWARE'] + ?.filter(filterSearch) + .map((kb) => )} From 6c0d7b41d8c6107fce0e72ebf7825a670e2a2d67 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Thu, 19 Dec 2024 22:10:34 +1000 Subject: [PATCH 32/42] fix --- code/modules/reqs/supplypacks/medical.dm | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/code/modules/reqs/supplypacks/medical.dm b/code/modules/reqs/supplypacks/medical.dm index 7e2743cbe20..21c43b6f48d 100644 --- a/code/modules/reqs/supplypacks/medical.dm +++ b/code/modules/reqs/supplypacks/medical.dm @@ -153,6 +153,12 @@ containertype = /obj/structure/closet/crate/secure/surgery access = ACCESS_MARINE_MEDBAY +/datum/supply_packs/medical/implanter + name = "Implanter" + notes = "contains an implanter for reinsertion of the implant." + contains = list(/obj/item/implanter/implantator/cargo) + cost = 90 + /datum/supply_packs/medical/defibrillator_gloves name = "Advanced defibrillator medical gloves" notes = "contains advanced defibrillator medical gloves." @@ -367,9 +373,3 @@ /obj/item/clothing/mask/breath/medical, /obj/item/tank/anesthetic, ) - -/datum/supply_packs/medical/implanter - name = "Implanter" - notes = "contains an implanter for reinsertion of the implant." - contains = list(/obj/item/implanter/implantator/cargo) - cost = 90 From 0ceafc928fa500e2fbfbe159c9ca55c4e6931146 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Fri, 20 Dec 2024 00:00:25 +1000 Subject: [PATCH 33/42] vrode work --- code/__DEFINES/dcs/helpers.dm | 2 +- code/datums/elements/shrapnel_removal.dm | 6 +++--- code/game/objects/items/implants/implant.dm | 2 +- code/game/objects/items/implants/implanter.dm | 1 - code/game/objects/items/implants/sandevistan.dm | 5 +++-- .../objects/items/implants/skill_implants/implant_code.dm | 3 ++- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm index bfd82bc572a..8649947666f 100644 --- a/code/__DEFINES/dcs/helpers.dm +++ b/code/__DEFINES/dcs/helpers.dm @@ -22,7 +22,7 @@ /// A wrapper for _AddComponent that allows us to pretend we're using normal named arguments #define AddComponent(arguments...) _AddComponent(list(##arguments)) -/// A wrapper for _AddComonent that passes in a source. +/// A wrapper for _AddComponent that passes in a source. /// Necessary if dupe_mode is set to COMPONENT_DUPE_SOURCES. #define AddComponentFrom(source, arguments...) _AddComponent(list(##arguments), source) diff --git a/code/datums/elements/shrapnel_removal.dm b/code/datums/elements/shrapnel_removal.dm index beaf4eac75f..78479f1f2e6 100644 --- a/code/datums/elements/shrapnel_removal.dm +++ b/code/datums/elements/shrapnel_removal.dm @@ -62,9 +62,9 @@ ///returns TRUE if the argument limb has any shrapnel in it /datum/element/shrapnel_removal/proc/has_shrapnel(datum/limb/targetlimb) for(var/obj/item/embedded AS in targetlimb.implants) - if(!embedded.is_beneficial_implant()) - return TRUE - return FALSE + if(embedded.is_beneficial_implant()) + continue + return TRUE /datum/element/shrapnel_removal/proc/remove_shrapnel(mob/living/user, mob/living/target, datum/limb/targetlimb, skill) for(var/obj/item/embedded AS in targetlimb.implants) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 0afc2ba6629..6c627c1cbd9 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -87,7 +87,7 @@ if(!affected) CRASH("[src] implanted into [target] [user ? "by [user]" : ""] but had no limb, despite being set to implant in [limb_targeting].") for(var/obj/item/implant/embedded in affected.implants) - if((flags_implant & HIGHLANDER_IMPLANT) || (embedded.flags_implant & HIGHLANDER_IMPLANT)) + if(flags_implant & HIGHLANDER_IMPLANT || embedded.flags_implant & HIGHLANDER_IMPLANT) to_chat(user, span_warning("Cannot fit the [name] due to the [embedded.name] already there!")) return FALSE if(!(embedded.type == type) || (flags_implant & DUPLICATE_IMPLANT_ALLOWED)) diff --git a/code/game/objects/items/implants/implanter.dm b/code/game/objects/items/implants/implanter.dm index d4016cca847..d31930321df 100644 --- a/code/game/objects/items/implants/implanter.dm +++ b/code/game/objects/items/implants/implanter.dm @@ -84,7 +84,6 @@ name = "Self-Gibbing implant" internal_implant = /obj/item/implant/suicide_dust - /obj/item/implanter/sandevistan name = "sandevistan implanter" icon_state = "internal_implant_spinal" diff --git a/code/game/objects/items/implants/sandevistan.dm b/code/game/objects/items/implants/sandevistan.dm index bede20144d8..c2b6eeea8cb 100644 --- a/code/game/objects/items/implants/sandevistan.dm +++ b/code/game/objects/items/implants/sandevistan.dm @@ -161,9 +161,10 @@ if(!target) return FALSE var/obj/item/implant/implant = target - . = implant.activate() - if(!.) + if(!implant.activate()) return if(!implant.active) add_cooldown() update_button_icon() + +#undef SANDEVISTAN_IMPLANT diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index 0c4cbc22f86..fb889ee8eb9 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -70,6 +70,7 @@ allowed_limbs = list(BODY_ZONE_HEAD) /obj/item/implant/skill/attackby(obj/item/I, mob/user, params) + . = ..() if(istype(I, /obj/item/implanter/implantator/cargo)) var/obj/item/implanter/implantator/cargo/cargo = I if(cargo.icon_state == "cargo_full_s") @@ -77,5 +78,5 @@ return cargo.allowed_limbs = allowed_limbs cargo.internal_implant = src - src.forceMove(cargo) + forceMove(cargo) cargo.icon_state = "cargo_full" From de0426afa244daf5612c6bb47f5b90445ba0d3fb Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Fri, 20 Dec 2024 00:51:56 +1000 Subject: [PATCH 34/42] =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/__DEFINES/loadout.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index d30affd3b4a..d78d8a5882d 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -89,8 +89,8 @@ GLOBAL_LIST_INIT(marine_selector_cats, list( #define SANDBAG_PRICE_IN_GEAR_VENDOR 3 GLOBAL_LIST_INIT(marine_gear_listed_products, list( - /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 15, "cyan2"), - /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 15, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 30, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 25, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), /obj/item/implanter/implantator/codex/engineer = list(CAT_MARINE, "Engineering support system implanter", 20, "cyan2"), /obj/item/implanter/implantator/codex/construct = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), From e7c5bdfc4d9a6568a529d0f36f914f826e280d34 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Fri, 20 Dec 2024 00:53:09 +1000 Subject: [PATCH 35/42] imba dlya marov --- code/__DEFINES/loadout.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index d78d8a5882d..a2e13307dcb 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -89,8 +89,8 @@ GLOBAL_LIST_INIT(marine_selector_cats, list( #define SANDBAG_PRICE_IN_GEAR_VENDOR 3 GLOBAL_LIST_INIT(marine_gear_listed_products, list( - /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 30, "cyan2"), - /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 25, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 40, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 30, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), /obj/item/implanter/implantator/codex/engineer = list(CAT_MARINE, "Engineering support system implanter", 20, "cyan2"), /obj/item/implanter/implantator/codex/construct = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), From 04755b14770812e4f6bd677f8d9ce74402016c02 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 21 Dec 2024 03:51:14 +1000 Subject: [PATCH 36/42] helg zachem ti skazal eto sdelat...( --- code/datums/elements/shrapnel_removal.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/datums/elements/shrapnel_removal.dm b/code/datums/elements/shrapnel_removal.dm index 78479f1f2e6..39d2cf38d82 100644 --- a/code/datums/elements/shrapnel_removal.dm +++ b/code/datums/elements/shrapnel_removal.dm @@ -63,8 +63,8 @@ /datum/element/shrapnel_removal/proc/has_shrapnel(datum/limb/targetlimb) for(var/obj/item/embedded AS in targetlimb.implants) if(embedded.is_beneficial_implant()) - continue - return TRUE + return TRUE + return FALSE /datum/element/shrapnel_removal/proc/remove_shrapnel(mob/living/user, mob/living/target, datum/limb/targetlimb, skill) for(var/obj/item/embedded AS in targetlimb.implants) From 7ca4b6e8250e96eb46eff9cb9ab2e60f11f68d43 Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 21 Dec 2024 20:34:12 +1000 Subject: [PATCH 37/42] balance and add implant in valhalla vendors --- code/__DEFINES/loadout.dm | 4 ++-- .../objects/machinery/vending/marine_vending.dm | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/loadout.dm b/code/__DEFINES/loadout.dm index a2e13307dcb..b9b87435cb8 100644 --- a/code/__DEFINES/loadout.dm +++ b/code/__DEFINES/loadout.dm @@ -89,8 +89,8 @@ GLOBAL_LIST_INIT(marine_selector_cats, list( #define SANDBAG_PRICE_IN_GEAR_VENDOR 3 GLOBAL_LIST_INIT(marine_gear_listed_products, list( - /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 40, "cyan2"), - /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 30, "cyan2"), + /obj/item/implanter/implantator/combat/firearms = list(CAT_MARINE, "Aiming support implanter", 35, "cyan2"), + /obj/item/implanter/implantator/combat/melee = list(CAT_MARINE, "Close combat codex implanter", 25, "cyan2"), /obj/item/implanter/implantator/codex/medical = list(CAT_MARINE, "Medtech implanter", 20, "cyan2"), /obj/item/implanter/implantator/codex/engineer = list(CAT_MARINE, "Engineering support system implanter", 20, "cyan2"), /obj/item/implanter/implantator/codex/construct = list(CAT_MARINE, "Construction support system implanter", 20, "cyan2"), diff --git a/code/game/objects/machinery/vending/marine_vending.dm b/code/game/objects/machinery/vending/marine_vending.dm index 8443eaa2e15..ad384464dad 100644 --- a/code/game/objects/machinery/vending/marine_vending.dm +++ b/code/game/objects/machinery/vending/marine_vending.dm @@ -1604,6 +1604,22 @@ /obj/item/ammo_magazine/tank/secondary_cupola = -1, /obj/item/ammo_magazine/tank/flamer = -1, ), + "Implants" = list( + /obj/item/implanter/sandevistan = -1, + /obj/item/implanter/suicide_dust = -1, + /obj/item/implanter/blade = -1, + /obj/item/implanter/cloak = -1, + /obj/item/implanter/chem/blood = -1, + /obj/item/implanter/chem = -1, + /obj/item/implanter/neurostim = -1, + /obj/item/implanter/implantator/combat/firearms = -1, + /obj/item/implanter/implantator/combat/melee = -1, + /obj/item/implanter/implantator/codex/medical = -1, + /obj/item/implanter/implantator/codex/surgery = -1, + /obj/item/implanter/implantator/codex/engineer = -1, + /obj/item/implanter/implantator/codex/construct = -1, + /obj/item/implanter/implantator/oper_system/leadership = -1, + ), ) /obj/machinery/vending/valhalla_seasonal_req From 4c2e086cc6dffb74ab7edeb10f66da4a006a1adb Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sat, 21 Dec 2024 22:33:12 +1000 Subject: [PATCH 38/42] transfer --- code/game/objects/machinery/vending/marine_vending.dm | 3 --- 1 file changed, 3 deletions(-) diff --git a/code/game/objects/machinery/vending/marine_vending.dm b/code/game/objects/machinery/vending/marine_vending.dm index ad384464dad..f99c4a62306 100644 --- a/code/game/objects/machinery/vending/marine_vending.dm +++ b/code/game/objects/machinery/vending/marine_vending.dm @@ -1590,9 +1590,6 @@ /obj/item/clothing/suit/storage/marine/riot = -1, /obj/item/clothing/head/helmet/marine/riot = -1, /obj/item/clothing/suit/storage/marine/boomvest = -1, - /obj/item/implanter/cloak = -1, - /obj/item/implanter/chem/blood = -1, - /obj/item/implanter/blade = -1, ), "Assault Vehicle" = list( /obj/item/armored_weapon = -1, From 1b33b2d34d9378a1f8bffb9e2f93d202886d036d Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Sun, 22 Dec 2024 01:26:44 +1000 Subject: [PATCH 39/42] Extra ultra giga fix --- code/datums/elements/shrapnel_removal.dm | 2 +- code/datums/skills.dm | 2 +- .../objects/items/implants/skill_implants/implant_code.dm | 5 ++--- code/game/objects/items/pamphlets.dm | 3 +-- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/code/datums/elements/shrapnel_removal.dm b/code/datums/elements/shrapnel_removal.dm index 39d2cf38d82..beaf4eac75f 100644 --- a/code/datums/elements/shrapnel_removal.dm +++ b/code/datums/elements/shrapnel_removal.dm @@ -62,7 +62,7 @@ ///returns TRUE if the argument limb has any shrapnel in it /datum/element/shrapnel_removal/proc/has_shrapnel(datum/limb/targetlimb) for(var/obj/item/embedded AS in targetlimb.implants) - if(embedded.is_beneficial_implant()) + if(!embedded.is_beneficial_implant()) return TRUE return FALSE diff --git a/code/datums/skills.dm b/code/datums/skills.dm index ed19ef18c53..409e796bc75 100644 --- a/code/datums/skills.dm +++ b/code/datums/skills.dm @@ -164,7 +164,7 @@ engineer, construction, leadership, medical, surgery, pilot, police, powerloader /// acts as [/proc/modifyRating] but sets the rating directly rather than modify it /datum/skills/proc/setRating(cqc, melee_weapons,\ -firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ +firearms, pistols, shotguns, rifles, smgs, heavy_weapons, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, mech_pilot, stamina) return getSkills((isnull(cqc) ? src.cqc : cqc),\ (isnull(melee_weapons) ? src.melee_weapons : melee_weapons),\ diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index fb889ee8eb9..fd750932017 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -12,7 +12,6 @@ var/rifles var/smgs var/heavy_weapons - var/swordplay var/smartgun var/engineer var/construction @@ -40,14 +39,14 @@ . = ..() if(!.) return - target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ + target.set_skills(target.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, mech_pilot, stamina)) return TRUE /obj/item/implant/skill/unimplant() if(!implanted) return FALSE - implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -swordplay, -smartgun,\ + implant_owner.set_skills(implant_owner.skills.modifyRating(-cqc, -melee_weapons, -firearms, -pistols, -shotguns, -rifles, -smgs, -heavy_weapons, -smartgun,\ -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -mech_pilot, -stamina)) return ..() diff --git a/code/game/objects/items/pamphlets.dm b/code/game/objects/items/pamphlets.dm index 3e08bb2a782..142b33eb123 100644 --- a/code/game/objects/items/pamphlets.dm +++ b/code/game/objects/items/pamphlets.dm @@ -13,7 +13,6 @@ var/rifles var/smgs var/heavy_weapons - var/swordplay var/smartgun var/engineer var/construction @@ -38,7 +37,7 @@ return if(!do_after(user, 5 SECONDS, NONE, user)) return - user.set_skills(user.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, swordplay, smartgun,\ + user.set_skills(user.skills.modifyRating(cqc, melee_weapons, firearms, pistols, shotguns, rifles, smgs, heavy_weapons, smartgun,\ engineer, construction, leadership, medical, surgery, pilot, police, powerloader, large_vehicle, mech_pilot, stamina)) user.temporarilyRemoveItemFromInventory(src) qdel(src) From d70d9d7863ce5f4abfedf3efe7b19b9dc29190aa Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Fri, 10 Jan 2025 00:56:19 +1000 Subject: [PATCH 40/42] review --- code/game/objects/items/implants/implant.dm | 4 ++-- .../implants/skill_implants/implant_code.dm | 19 ------------------- .../implants/skill_implants/implant_skill.dm | 18 ++++++++++++++++++ .../skill_implants/implantator_code.dm | 10 +--------- 4 files changed, 21 insertions(+), 30 deletions(-) diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 6c627c1cbd9..07b2b791245 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -70,7 +70,7 @@ if(!(limb_targeting in allowed_limbs)) to_chat(user, span_warning("You cannot implant this into that limb!")) return FALSE - if((flags_implant & DUPLICATE_IMPLANT_ALLOWED)) + if(flags_implant & DUPLICATE_IMPLANT_ALLOWED) return return TRUE @@ -90,7 +90,7 @@ if(flags_implant & HIGHLANDER_IMPLANT || embedded.flags_implant & HIGHLANDER_IMPLANT) to_chat(user, span_warning("Cannot fit the [name] due to the [embedded.name] already there!")) return FALSE - if(!(embedded.type == type) || (flags_implant & DUPLICATE_IMPLANT_ALLOWED)) + if(embedded.type != type || flags_implant & DUPLICATE_IMPLANT_ALLOWED) continue to_chat(user, span_warning("There is already another [name] in this limb!")) return FALSE diff --git a/code/game/objects/items/implants/skill_implants/implant_code.dm b/code/game/objects/items/implants/skill_implants/implant_code.dm index fd750932017..f7ecdb5dff4 100644 --- a/code/game/objects/items/implants/skill_implants/implant_code.dm +++ b/code/game/objects/items/implants/skill_implants/implant_code.dm @@ -50,24 +50,6 @@ -engineer, -construction, -leadership, -medical, -surgery, -pilot, -police, -powerloader, -large_vehicle, -mech_pilot, -stamina)) return ..() -/obj/item/implant/skill/combat - name = "Сombat implants" - desc = "An implant from a line of implants that enhances combat skills" - icon_state = "combat_implant" - allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) - -/obj/item/implant/skill/codex - name = "CODEX implants" - desc = "Implant from a line of implants that increases basic knowledge" - icon_state = "support_implant" - allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) - -/obj/item/implant/skill/oper_system - name = "Tactics implants" - desc = "An implant from the line of implants that increases knowledge of battle tactics" - icon_state = "skill_implant" - allowed_limbs = list(BODY_ZONE_HEAD) - /obj/item/implant/skill/attackby(obj/item/I, mob/user, params) . = ..() if(istype(I, /obj/item/implanter/implantator/cargo)) @@ -75,7 +57,6 @@ if(cargo.icon_state == "cargo_full_s") balloon_alert(user, "Implantator already used!") return - cargo.allowed_limbs = allowed_limbs cargo.internal_implant = src forceMove(cargo) cargo.icon_state = "cargo_full" diff --git a/code/game/objects/items/implants/skill_implants/implant_skill.dm b/code/game/objects/items/implants/skill_implants/implant_skill.dm index 4d8e85425da..6b2c9b18877 100644 --- a/code/game/objects/items/implants/skill_implants/implant_skill.dm +++ b/code/game/objects/items/implants/skill_implants/implant_skill.dm @@ -1,3 +1,21 @@ +/obj/item/implant/skill/combat + name = "Сombat implants" + desc = "An implant from a line of implants that enhances combat skills" + icon_state = "combat_implant" + allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) + +/obj/item/implant/skill/codex + name = "CODEX implants" + desc = "Implant from a line of implants that increases basic knowledge" + icon_state = "support_implant" + allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) + +/obj/item/implant/skill/oper_system + name = "Tactics implants" + desc = "An implant from the line of implants that increases knowledge of battle tactics" + icon_state = "skill_implant" + allowed_limbs = list(BODY_ZONE_HEAD) + /obj/item/implant/skill/combat/firearms name = "aiming support implant system" desc = "Integrated aiming support system! Update weapons skills!" diff --git a/code/game/objects/items/implants/skill_implants/implantator_code.dm b/code/game/objects/items/implants/skill_implants/implantator_code.dm index 533cc0f1d73..9d3f9eaebbd 100644 --- a/code/game/objects/items/implants/skill_implants/implantator_code.dm +++ b/code/game/objects/items/implants/skill_implants/implantator_code.dm @@ -12,11 +12,6 @@ throw_range = 5 var/empty_icon = "skill" var/max_skills - var/allowed_limbs - -/obj/item/implanter/implantator/Initialize(mapload, ...) - . = ..() - name += " implanter" /obj/item/implanter/implantator/examine(mob/user, distance, infix, suffix) . = ..() @@ -37,7 +32,7 @@ if(!.) return var/mob/living/carbon/human/human = target - if(!(user.zone_selected in allowed_limbs)) + if(!(user.zone_selected in internal_implant.allowed_limbs)) balloon_alert(user, "Wrong limb!") return FALSE var/datum/limb/targetlimb = human.get_limb(user.zone_selected) @@ -48,15 +43,12 @@ return TRUE /obj/item/implanter/implantator/combat - allowed_limbs = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM) internal_implant = /obj/item/implant/skill/combat /obj/item/implanter/implantator/codex - allowed_limbs = list(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_GROIN) internal_implant = /obj/item/implant/skill/codex /obj/item/implanter/implantator/oper_system - allowed_limbs = list(BODY_ZONE_HEAD) internal_implant = /obj/item/implant/skill/oper_system /obj/item/implanter/implantator/cargo From 33bc9981e91e277ba65245f87d14bd1e21e03d8d Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Fri, 10 Jan 2025 14:12:34 +1000 Subject: [PATCH 41/42] Update living_health_procs.dm --- code/modules/mob/living/living_health_procs.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/mob/living/living_health_procs.dm b/code/modules/mob/living/living_health_procs.dm index 80321575386..6c0c72b8243 100644 --- a/code/modules/mob/living/living_health_procs.dm +++ b/code/modules/mob/living/living_health_procs.dm @@ -257,6 +257,7 @@ /mob/living/proc/revive(admin_revive = FALSE) for(var/obj/item/embedded AS in embedded_objects) + if(embedded.is_beneficial_implant()) continue embedded.unembed_ourself() From 149b99fd1ab7ebe9646fa3c651f67687da28e9bf Mon Sep 17 00:00:00 2001 From: MalorMorfin Date: Fri, 10 Jan 2025 14:12:42 +1000 Subject: [PATCH 42/42] Update living_health_procs.dm --- code/modules/mob/living/living_health_procs.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/mob/living/living_health_procs.dm b/code/modules/mob/living/living_health_procs.dm index 6c0c72b8243..80321575386 100644 --- a/code/modules/mob/living/living_health_procs.dm +++ b/code/modules/mob/living/living_health_procs.dm @@ -257,7 +257,6 @@ /mob/living/proc/revive(admin_revive = FALSE) for(var/obj/item/embedded AS in embedded_objects) - if(embedded.is_beneficial_implant()) continue embedded.unembed_ourself()