From de792bb8105468e25ed1d7818d5eaf3d8fe8f1eb Mon Sep 17 00:00:00 2001 From: RikuTheKiller <88713943+RikuTheKiller@users.noreply.github.com> Date: Tue, 8 Oct 2024 23:51:57 +0300 Subject: [PATCH] [BOUNTY] Adds contraband dual wielding implants (#3611) * its a start * right, it works now --- .../signals/signals_mob/signals_mob_main.dm | 2 +- code/_onclick/item_attack.dm | 6 +- .../cybernetics/augments/chest_augments.dm | 91 ++++++++++++++++++ .../cybernetics/augments/uplink/uplink.dm | 14 ++- .../black_markets/aftermarket_implants.dm | 9 ++ .../modules/cybernetics/icons/implants.dmi | Bin 1176 -> 2944 bytes .../cybernetics/implant_items/autosurgeons.dm | 3 + .../implant_items/weapons/mantis_blade.dm | 5 +- .../icons/obj/medical/organs/organs.dmi | Bin 38492 -> 33844 bytes 9 files changed, 121 insertions(+), 9 deletions(-) diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 51b79ec9eb10..2b607c99a6fb 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -164,7 +164,7 @@ #define COMSIG_TABLE_SLAMMED "table_slammed" ///from base of atom/attack_hand(): (mob/user, modifiers) #define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" -///from base of /obj/item/attack(): (mob/M, mob/user) +///from base of /obj/item/attack(): (mob/M, mob/user, params, obj/item/weapon) #define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" ///from base of obj/item/afterattack(): (atom/target, obj/item/weapon, proximity_flag, click_parameters) #define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 539dcb585ab2..f344092cf70c 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -223,7 +223,7 @@ if(signal_return & COMPONENT_SKIP_ATTACK) return - SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, target_mob, user, params) + SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, target_mob, user, params, src) // monkestation edit if(item_flags & NOBLUDGEON) return @@ -243,7 +243,7 @@ if(force && target_mob == user && user.client) user.client.give_award(/datum/award/achievement/misc/selfouch, user) - user.do_attack_animation(target_mob) + user.do_attack_animation(target_mob, used_item = src) // MONKESTATION EDIT: Okay so why the FUCK was an attack proc on *item* not passing the fucking *item* to this? WHY?! target_mob.attacked_by(src, user) log_combat(user, target_mob, "attacked", src.name, "(ISTATE: [user.log_istate()]) (DAMTYPE: [uppertext(damtype)])") @@ -265,7 +265,7 @@ if(signal_return & COMPONENT_SKIP_ATTACK) return - SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, target_mob, user, params) + SEND_SIGNAL(user, COMSIG_MOB_ITEM_ATTACK, target_mob, user, params, src) // monkestation edit if(item_flags & NOBLUDGEON) return diff --git a/monkestation/code/modules/cybernetics/augments/chest_augments.dm b/monkestation/code/modules/cybernetics/augments/chest_augments.dm index a488bad79baa..105f50750292 100644 --- a/monkestation/code/modules/cybernetics/augments/chest_augments.dm +++ b/monkestation/code/modules/cybernetics/augments/chest_augments.dm @@ -555,3 +555,94 @@ owner.SetKnockdown(1.5 SECONDS) return TRUE + +/datum/bodypart_overlay/simple/dualwield + icon = 'monkestation/code/modules/cybernetics/icons/implants.dmi' + icon_state = "ccms_overlay" + layers = EXTERNAL_ADJACENT + +/obj/item/organ/internal/cyberimp/chest/dualwield + name = "C.C.M.S implant" + desc = "Short for Complementary Combat Maneuvering System, it processes spinal nerve signals and enacts forced complementary maneuvers on the opposite side of the user's body when they attack. In layman's terms, it lets you dual wield." + icon = 'monkestation/code/modules/cybernetics/icons/implants.dmi' + icon_state = "ccms" + encode_info = AUGMENT_SYNDICATE_LEVEL + + visual_implant = TRUE + bodypart_overlay = /datum/bodypart_overlay/simple/dualwield + +/obj/item/organ/internal/cyberimp/chest/dualwield/on_insert(mob/living/carbon/organ_owner, special) + . = ..() + register() + +/obj/item/organ/internal/cyberimp/chest/dualwield/on_remove(mob/living/carbon/organ_owner, special) + . = ..() + unregister() + +/obj/item/organ/internal/cyberimp/chest/dualwield/proc/register() + RegisterSignal(owner, COMSIG_MOB_ITEM_ATTACK, PROC_REF(on_item_attack)) + +/obj/item/organ/internal/cyberimp/chest/dualwield/proc/unregister() + UnregisterSignal(owner, COMSIG_MOB_ITEM_ATTACK) + +/obj/item/organ/internal/cyberimp/chest/dualwield/proc/on_item_attack(datum/source, mob/target, mob/user, params, obj/item/weapon) + SIGNAL_HANDLER + + if(!(owner.istate & ISTATE_HARM)) // No dual wielding outside of combat mode. + return + + if(weapon != owner.get_active_held_item()) // Just to be extra careful about loops. + return + + var/item = owner.get_inactive_held_item() + + if(!item) + return + + var/attack_time = (user.next_move - world.time) * 0.5 // Allows us to attack in the "gaps" between our owner's attacks, because it looks cool as fuck. + + addtimer(CALLBACK(src, PROC_REF(complement_attack), item, target), attack_time, TIMER_UNIQUE) // TIMER_UNIQUE makes sure this will never go exponential even if a loop is found. + +/obj/item/organ/internal/cyberimp/chest/dualwield/proc/complement_attack(obj/item/item, mob/target) + if(QDELETED(owner) || QDELETED(target)) + return + + if(owner.get_inactive_held_item() != item) + return + + if(handle_side_effects(item, target)) // If handle_side_effects returns true, that means we misfired. + return + + if(owner.CanReach(target, item)) + unregister() // Prevent looping in on ourselves if the user switches items during the delay. + item.attack(target, owner) + register() + +/obj/item/organ/internal/cyberimp/chest/dualwield/proc/handle_side_effects(obj/item/item, mob/target) + return FALSE // Returning true means we misfired, i.e. failed to dual wield even though it should have triggered under normal circumstances. + +/datum/bodypart_overlay/simple/dualwield/refurbished + icon_state = "ccms_overlay_refurbished" + +/obj/item/organ/internal/cyberimp/chest/dualwield/refurbished + name = "refurbished C.C.M.S implant" + desc = "A refurbished dual wielding implant. It looks old and the nerve filaments have degraded, but it's still functional." + icon_state = "ccms_refurbished" + + bodypart_overlay = /datum/bodypart_overlay/simple/dualwield/refurbished + +/obj/item/organ/internal/cyberimp/chest/dualwield/refurbished/handle_side_effects(obj/item/item, mob/target) + if(prob(20)) // Low probability for it to not work at all. + owner.visible_message( + message = span_warning("[owner]'s arm twitches."), + self_message = span_danger("Your C.C.M.S misfires!") + ) + return TRUE // Cancels the complementary attack. + + if(prob(30)) // And if it does work, it might cause some damage. + owner.visible_message( + message = span_warning("[owner]'s arm spazzes out!"), + self_message = span_danger("Your arm spazzes out!") + ) + var/obj/item/bodypart/arm = owner.get_holding_bodypart_of_item(item) + arm?.receive_damage(brute = 10, wound_bonus = 10, sharpness = NONE) // You can get away with like 5 spazzes before you get a dislocation. diff --git a/monkestation/code/modules/cybernetics/augments/uplink/uplink.dm b/monkestation/code/modules/cybernetics/augments/uplink/uplink.dm index 95f69294b6fb..f7bd12401280 100644 --- a/monkestation/code/modules/cybernetics/augments/uplink/uplink.dm +++ b/monkestation/code/modules/cybernetics/augments/uplink/uplink.dm @@ -1,6 +1,6 @@ /datum/uplink_item/bundles_tc/sandy name = "Sandevistan Bundle" - desc = "A box containing various implants" + desc = "A box containing autosurgeons for a cyberlink and a sandevistan, allowing you to outspeed targets." item = /obj/item/storage/box/syndie_kit/sandy cost = 12 purchasable_from = UPLINK_TRAITORS @@ -12,7 +12,7 @@ /datum/uplink_item/bundles_tc/mantis name = "Mantis Blade Bundle" - desc = "A box containing various implants" + desc = "A box containing autosurgeons for a cyberlink and two mantis blade implants, one for each arm." item = /obj/item/storage/box/syndie_kit/mantis cost = 12 purchasable_from = UPLINK_TRAITORS @@ -22,3 +22,13 @@ new /obj/item/autosurgeon/organ/syndicate/syndie_mantis(src) new /obj/item/autosurgeon/organ/syndicate/syndie_mantis/l(src) +/datum/uplink_item/bundles_tc/dualwield + name = "C.C.M.S Bundle" + desc = "A box containing autosurgeons for a cyberlink and a C.C.M.S implant that lets you dual wield melee weapons." + item = /obj/item/storage/box/syndie_kit/dualwield + cost = 12 + purchasable_from = UPLINK_TRAITORS + +/obj/item/storage/box/syndie_kit/dualwield/PopulateContents() + new /obj/item/autosurgeon/organ/cyberlink_syndicate(src) + new /obj/item/autosurgeon/organ/syndicate/dualwield(src) diff --git a/monkestation/code/modules/cybernetics/black_markets/aftermarket_implants.dm b/monkestation/code/modules/cybernetics/black_markets/aftermarket_implants.dm index 626412b23ba0..7d0fdbd32442 100644 --- a/monkestation/code/modules/cybernetics/black_markets/aftermarket_implants.dm +++ b/monkestation/code/modules/cybernetics/black_markets/aftermarket_implants.dm @@ -38,6 +38,15 @@ price_min = CARGO_CRATE_VALUE * 5 price_max = CARGO_CRATE_VALUE * 7 +/datum/market_item/auction/shoddy_implant/chest/dualwield + name = "refurbished C.C.M.S implant" + desc = "A refurbished dual wielding implant. It's old and might misfire, but it's still functional." + item = /obj/item/organ/internal/cyberimp/chest/dualwield/refurbished + auction_weight = 1 // It practically doubles your damage. + + price_min = CARGO_CRATE_VALUE * 6 + price_max = CARGO_CRATE_VALUE * 8 + /datum/market_item/auction/shoddy_implant/arm category = "Arm Implants" diff --git a/monkestation/code/modules/cybernetics/icons/implants.dmi b/monkestation/code/modules/cybernetics/icons/implants.dmi index 5957db3cab2ccc758b7d9aaf0407e84c7b96a741..f0facbdc278be5e0ffe2699c1d0fdc2705669325 100644 GIT binary patch literal 2944 zcmbW3X*AT28pnS#L(RxC_AJ9BSwa)a8pf6-*>^(Omoav-&Y&zUqw+`H)Km!B{tA(q zA)&I2HTzP^*al^gZRWc7o^#)I&OP@z=lOhJeBV9idCvFAvbHqg;t=Hk0D#NP)X4Tw zTMnBDJ#t7_Iqxfn(jRZ{9A)Gi=^YUm78QsM1%NovU-zlpsb@Jms4Mb9jbf~@&1=Y; zY0cm=>q#lj!OK~?B#1>{=~#1JS2cYE%eA96RxCo;mVYM|ICh%+wLh^n)iUqms1NBH z9(`TF&*BXzP38oakMLMQ+qT_{W(dRns$SpVpe zH$;aU1hp83&7iQAH_kUR?zksguPqm~eHw8Vk@XO`^MojwGGM5AHTqfFo0$A$cCr}v z)YJ8C`L$O!FMRs;l|%B`$M)%am%?8I07sCSk-mN0IK40>Oxyv{;#q@K&b56csfM?{ z2O2mnQd2*yMO0FY0YUn6<5q9e>maeQJ7Qjg~}NBauja>^WZM z0bn!$umS%9Zbc;NeVqTwr@7(aY6)wrYR!v;@?MkOn0Vk%~zYD16=>1v|iT9UrvsMFtnM~ds0SLZZZZ^lJISfduPIn+<%WCL ztkk;>F2Gld8H-Ar!lZvwG_J2lQl={HXQoWpM`JGeOR3df$v3)+}+`@fv239ORjkyrWL#_9xO*RsBo#FjFO4Z|Dxw63)^E_Ubl^Nou-Z_{M)Oaw2ISCzY*p zMUa+@o~bVNjf{C$9I+FOP^g!4JC(`J478IiLuhZ8o)7-=o1@0()BPdctLE@wSxDz5fQL4qof25e1ygH_)4K^xd_8^5Ab0N~uAaS@a zjPEFjp*&f)D^VBh^h%*+Qh~sHXAhNX$(7$+S}JzBAw{$ouRX8*1S_%aXbvc4Wb&2* zsf@(=3Tjy06Bp4RZv4BOvyF@;eJDH{_B^dR^xI-NX6;rGGqs((HWR@bAJWx7I?GR3 zi~3$Cj0%lfK4|l-vYG#o8FlwXiq2UX_jmQ5bZ%~-3PekR`yiiJkST%Lmn^-Qoa191 zS1gap;gxP);yFuVUH0X^*iGNE=~N(j>Vi3i7aC31(Mg352!PFYi`H*8J3t3I46#nE32z9-_KVc^hT$dBVViZA-*H@$WuCZv$L~XRB^GB&)ECYo8W$yDLn}!ZHMf* z1~JQWsE@1SAm?2Pfn$rQ+L@eib&xc)C(!i3`KU($cwt4x8&BpLDe`0Yy=WbjQYhcX zhpum;7Y{v5_%^D)mmaT_a~V|2HEFTOt_;1~#AYT-WWym(>5qB?)#)li>s1g_x?~&XXz9}2rFIV2Du zZVq3&zRr*AHZHaBCEf`fjmr0mgZT=5RA|YF-^+E+SCa31cM$7R<^byU5|-v)U@1I2 zG2<|+k&Bd>H_p`hjZy5l5_@2~{gd8M>1Y)?qg6C=FvNKHc~W+v4xk7Ipc<=8X;C=8 zHlC5uvDN&_kg??BI&xbcC-1L;oyE;_qA(R{)Q)KM0B-?iwg;G}@farS9O*GS<4qm) zs14?R8;LOWSJlqtvB^b-f4ea+YH}t)GjdC{jP^Zfwg#1+8>5bDG;1gfw{y@CX_1-7 zX@}wkjbVJU(~0%1_l`-RycSjMx>8RT%y?uwJdrI`{HTVC~W?CRc=E7}(T{H5op1>Q7Xf&JJ@7f#swd}M@-ugU|r>&l{$uZoJ7~^LHMDTiz z^MX1mcAt$W_rxZh>TA_I=#?xp>>|I6VN+_+^nPsB%X}0cKc=2|=%uWdKP{t#?B1}Y ziW>k>OW^AK4PosUy0J_+tb2AXg#oLJ?vgZsk=vb=qFk-yB&F~o`9V_NmtL#+Pvk&~%$(Lb>b2 zAouOI_lgPRuwQ=%9_?t)4rP6nIfe8AX)Om2a%W?p>+hUq%(dk#Q-J}dO_Xky@T}X6 z$5(OPq2g}Nv+)+iO?$HHuA02dtEBeDr9}t7Bc+NcyIWPw^2&JhkxV?`cO=sQP=!d_ z04nGY;2h9%K^!OiZ@>o^z>b6%Nw*k3C3TmTD@vZ@8Xp^eA+a}?=4fd&SI5=+_E)+7 zAn|B|mct;TCyOJUkhDM8JHy)YPo1d;Qaz5rL#jXl3|CxE(Rm;<>oAefwRg&eUE_Az zSNEz@aK^|?H13fdH3|~O>Y|$P;e>k&mdLC;j5aT@a_o`95Khq&q;WsCK%d8v-(!q4+7azcyc~S zb^>fj2yi$7WdDEhHy9cb8?egBl_mJ6{ZEV&-fD7@bG^m&5jZR}V@snd1FzJ70%tZM AcmMzZ literal 1176 zcmV;J1ZVq+P)004jp0{{R3ySh9CGTfjW_}E}s8Y+k+EhmXxD_31KG(!6F)}=2gcfDOyRAEU+T#AaG!okVw>+3%g zDc#hAtN;K20d!JMQvg8b*k%9#0IqseSad{Xb7OL8aCB*JZU6vyoRyKy3c@fDgwM%S zg!V4}^y)=gN)PrG!qRR{Fim6=4Epp&dl5w1-e#6>XJIxMr>bsRQJx!qNAlWPaTLX7 z%URTYP{|zjoGH{76(-{Y1WYm`csh!jFypM(Ur6Q^Kf7m+%w(SN32(^0m%;)JGO2ps!9YAat7>4;>gcOJ4 zVOtGKYnA$a9H(iLMjlV6)~1D&QnV}cfV}fLrEt6eBM5AdppeFxyuvDn6iSTsjT3~> zSkoRs)CUTQy=xo-iLVOB%M{L$i=fCmm=(CrAr*%Z;#WEfEzBu|@EiCL`qnw5x2 zM_lKtkC21{QAHYSEfK*AhxGTL#U7)=jD^?P%|Rd(2!+`sDLV8sc@qMMDQDsAo&w#R zyaXes5i&uVr2djaph$mH7~g~i3yT70XXONWFiD%f0LpLl}h^!N-2Fm6ut^9MabPyAm#v;5~sg8wD^J+yIWEqWH1Q8 zEl%}E(&|U1L=mhJh~0=aq`>)VAQKFDv0C6$&Z871Ny)-+0YZ@XAnNx0AaMb~;Y2VFmE&HfXd#}#3rz3(x<|-v z2nF7i-*N)6KZLK*KvJ}D@KX^%_vFr9{d5Zp)ZtO-sr~r{=UZ_%U9>PXoEeJe(2?Tt zWF3l^tkF6iMv$z96&#Kb!KT?{+%YD}T3EsHJEsyg*662q>^vyzZo&FyP2^3*!4ayJCfMiR;Y^MMHJF3@Y4~rfsPSBdt~oW_t0mv zBmRcqOR%tgbk5X{IGmQP_oerzSk@1lRuF%MFN?Pp!Y~ZOFbu;m48!~}RxZb+mr>vM z7AJ0h_X1b07n$S|-uo7v;`Y}zosM9WnELh^hG7_nVHk#C7=~e(ZFu7!w8_6