diff --git a/code/game/mecha/combat/combat.dm b/code/game/mecha/combat/combat.dm index 55b43891927d..be61ee233321 100644 --- a/code/game/mecha/combat/combat.dm +++ b/code/game/mecha/combat/combat.dm @@ -1,5 +1,5 @@ /obj/mecha/combat - force = 30 + force = 25 internals_req_access = list(ACCESS_MECH_SCIENCE, ACCESS_MECH_SECURITY) internal_damage_threshold = 50 armor = list(MELEE = 30, BULLET = 30, LASER = 15, ENERGY = 20, BOMB = 20, BIO = 0, RAD = 0, FIRE = 100, ACID = 100) diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm index 67262d563064..cd141160b7bb 100644 --- a/code/game/mecha/combat/durand.dm +++ b/code/game/mecha/combat/durand.dm @@ -9,7 +9,7 @@ armor = list(MELEE = 40, BULLET = 35, LASER = 15, ENERGY = 10, BOMB = 20, BIO = 100, RAD = 50, FIRE = 100, ACID = 100) max_temperature = 30000 infra_luminosity = 8 - force = 40 + force = 35 wreckage = /obj/structure/mecha_wreckage/durand /obj/mecha/combat/durand/GrantActions(mob/living/user, human_occupant = 0) diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm index bc659de5417a..32260ee80cf0 100644 --- a/code/game/mecha/combat/marauder.dm +++ b/code/game/mecha/combat/marauder.dm @@ -14,7 +14,7 @@ wreckage = /obj/structure/mecha_wreckage/marauder add_req_access = 0 internal_damage_threshold = 25 - force = 45 + force = 40 max_equip = 4 bumpsmash = 1 @@ -52,7 +52,7 @@ max_integrity = 550 wreckage = /obj/structure/mecha_wreckage/seraph internal_damage_threshold = 20 - force = 55 + force = 50 max_equip = 5 /obj/mecha/combat/marauder/seraph/Initialize() @@ -76,7 +76,7 @@ operation_req_access = list(ACCESS_SYNDICATE) internals_req_access = list(ACCESS_SYNDICATE) wreckage = /obj/structure/mecha_wreckage/mauler - max_equip = 5 + max_equip = 6 destruction_sleep_duration = 20 /obj/mecha/combat/marauder/mauler/loaded/Initialize() @@ -91,6 +91,8 @@ ME.attach(src) ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src) ME.attach(src) + ME = new /obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe(src) //NOT BECAUSE IT'S USEFUL, BUT BECAUSE IT'S AWESOME + ME.attach(src) max_ammo() diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 51092af81e53..4eb6ab9b55cb 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -27,7 +27,8 @@ var/destroy_sound = 'sound/mecha/critdestr.ogg' /// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this. var/mech_flags = NONE - + //Special melee override for melee weapons + var/melee_override = FALSE /obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page() if(chassis) send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) @@ -43,6 +44,8 @@ /obj/item/mecha_parts/mecha_equipment/Destroy() if(chassis) + if(chassis.selected == src) //If it's the active equipment, we lose any passive effects + on_deselect() chassis.equipment -= src if(chassis.selected == src) chassis.selected = null @@ -140,6 +143,8 @@ return /obj/item/mecha_parts/mecha_equipment/proc/detach(atom/moveto=null) + if(chassis.selected == src) + src.on_deselect() moveto = moveto || get_turf(chassis) if(src.Move(moveto)) chassis.equipment -= src @@ -178,10 +183,18 @@ /obj/item/mecha_parts/mecha_equipment/proc/rearm() return 0 - /obj/item/mecha_parts/mecha_equipment/proc/needs_rearm() return 0 + +//used for equipment, such as melee weapons, that have passive effects +/obj/item/mecha_parts/mecha_equipment/proc/on_select() + return 0 + +/obj/item/mecha_parts/mecha_equipment/proc/on_deselect() + return 0 + // Is the occupant wearing a pilot suit? /obj/item/mecha_parts/mecha_equipment/proc/check_eva() return chassis?.check_eva() + diff --git a/code/game/mecha/equipment/weapons/melee_weapons.dm b/code/game/mecha/equipment/weapons/melee_weapons.dm new file mode 100644 index 000000000000..b6096d1e55d9 --- /dev/null +++ b/code/game/mecha/equipment/weapons/melee_weapons.dm @@ -0,0 +1,264 @@ +/obj/item/mecha_parts/mecha_equipment/melee_weapon + name = "mecha melee weapon" + icon_state = "mecha_generic_melee" + range = MECHA_MELEE|MECHA_RANGED //so we can do stuff at range and in melee + destroy_sound = 'sound/mecha/weapdestr.ogg' + mech_flags = EXOSUIT_MODULE_COMBAT + melee_override = TRUE + var/restricted = TRUE //for our special hugbox exofabs + //If we have a longer range weapon, such as a spear or whatever capable of hitting people further away, this is how much extra range it has + var/extended_range = 0 + //Attack speed modifier for a weapon. Big weapons will have a longer delay between attacks, while smaller ones will be faster + var/attack_speed_modifier = 1 + //Attack sound for the weapon + var/attack_sound = 'sound/weapons/mechasword.ogg' + //Attack types - Note that at least one of these must be true otherwise it'll only have passive effects (if any) + //By default we assume we're using a small weapon with only a special single-target attack + //If the weapon has an AOE attack + var/cleave = FALSE + //If the weapon has a single-target strike + var/precise_attacks = TRUE + + //Damage type for the weapon + var/dam_type = BRUTE + //If it's sharp or not + var/attack_sharpness = SHARP_NONE + //Damage the weapon will do. Note this is ADDED to the base mecha attack damage (usually) + var/weapon_damage = 0 + //If we have both cleave and precise attacks, the precise may have more damage + var/precise_weapon_damage = 0 + //Bonus deflection chance for using a melee weapon capable of blocking attacks + var/deflect_bonus = 0 + //Base armor piercing value of the weapon + var/base_armor_piercing = 0 + //Fauna bonus damage, if any + var/fauna_damage_bonus = 0 + //Structure damage multiplier, for stuff like big ol' smashy hammers. Base structure damage multiplier for mech melee attacks is 3. + var/structure_damage_mult = 3 + + var/cleave_effect = /obj/effect/temp_visual/dir_setting/firing_effect/mecha_swipe + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/can_attach(obj/mecha/M) + if(!..()) + return FALSE + if(istype(M, /obj/mecha/combat)) + return TRUE + if((locate(/obj/item/mecha_parts/concealed_weapon_bay) in M.contents) && !((locate(/obj/item/mecha_parts/mecha_equipment/melee_weapon) in M.equipment) || (locate(/obj/item/mecha_parts/mecha_equipment/weapon) in M.equipment) )) + return TRUE + return FALSE + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/start_cooldown() + set_ready_state(0) + chassis.use_power(energy_drain) + addtimer(CALLBACK(src, .proc/set_ready_state, 1), chassis.melee_cooldown * attack_speed_modifier * (check_eva() ? EVA_MODIFIER : 1)) //Guns only shoot so fast, but weapons can be used as fast as the chassis can swing it! + +//Melee weapon attacks are a little different in that they'll override the standard melee attack +/obj/item/mecha_parts/mecha_equipment/melee_weapon/action(atom/target, params) + if(!action_checks(target)) + return 0 + + var/turf/curloc = get_turf(chassis) + var/turf/targloc = get_turf(target) + if (!targloc || !istype(targloc) || !curloc) + return 0 + if (targloc == curloc) + return 0 + + + if(target == targloc && !(chassis.occupant.a_intent == INTENT_HELP) && cleave) //If we are targetting a location, not an object or mob, and we're not in a passive stance + cleave_attack() + else if(precise_attacks && (get_dist(src,target) <= (1 + extended_range))) //If we are targetting not a turf and they're within reach + precise_attack(target) //We stab it if we can + else if(cleave) + cleave_attack() //Or swing wildly + chassis.log_message("Attacked with [src.name], targeting [target].", LOG_MECHA) + return 1 + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/proc/precise_attack(atom/target) //No special attack by default. These will be set in the weapons themselves + return 0 + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/proc/cleave_attack() + return 0 + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/on_select() + if(deflect_bonus) + chassis.deflect_chance += deflect_bonus + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/on_deselect() + if(deflect_bonus) + chassis.deflect_chance -= deflect_bonus + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword + name = "generic mech sword" + desc = "Generic mech sword! It's a bit too big to use yourself." + cleave = TRUE + precise_attacks = TRUE + attack_sharpness = SHARP_EDGED + attack_sound = 'sound/weapons/mechasword.ogg' //Recorded from Respawn/EA's Titanfall 2 (Ronin broadsword swing). Apparently they don't care so we're probably good + harmful = TRUE //DO NOT give to children. Or do, I'm not the police. + var/minimum_damage = 0 //Baby mechs with a secret combat module get a little boost + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/shortsword //Our bread-and-butter mech shortsword for both slicing and stabbing baddies + name = "\improper GD6 \"Jaeger\" shortsword" + desc = "An extendable arm-mounted blade with a nasty edge. It is small and fast enough to deflect some incoming attacks." + energy_drain = 20 + weapon_damage = 15 + precise_weapon_damage = 20 + fauna_damage_bonus = 30 //because why not + deflect_bonus = 15 + base_armor_piercing = 15 + structure_damage_mult = 2.5 //Sword is not as smashy + minimum_damage = 25 + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/cleave_attack() //use this for basic cleaving attacks, tweak as needed + playsound(chassis, attack_sound, 50, 1) + var/turf/M = get_turf(chassis) + for(var/i = 0 to 2) + var/it_turn = 45*(1-i) + var/turf/T = get_step(M,turn(chassis.dir, it_turn)) //+45, +0, and -45 will get the three front tiles + for(var/atom/A in T.contents) + if(isliving(A)) + var/mob/living/L = A + + if(iscarbon(L)) //If we're a carbon we can get armor and jazz + var/mob/living/carbon/C = L + var/obj/item/bodypart/body_part = pick(C.bodyparts) //Cleave attack isn't very precise + var/armor_block = C.run_armor_check(body_part, MELEE, armour_penetration = base_armor_piercing) + C.apply_damage(max(chassis.force + weapon_damage, minimum_damage), dam_type, body_part, armor_block, sharpness = attack_sharpness) + else //Regular mobs just take damage + L.apply_damage(max(chassis.force + weapon_damage, minimum_damage), dam_type) + if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid)) //If we're hitting fauna, because heck those guys + L.apply_damage(fauna_damage_bonus, dam_type) + + L.visible_message(span_danger("[chassis.name] strikes [L] with a wide swing of [src]!"), \ + span_userdanger("[chassis.name] strikes you with [src]!")) + chassis.log_message("Hit [L] with [src.name] (cleave attack).", LOG_MECHA) + playsound(L, 'sound/weapons/bladeslice.ogg', 50) + + else if(isstructure(A) || ismachinery(A) || istype(A, /obj/mecha)) //if it's something we can otherwise still hit + var/obj/O = A + if(!O.density) //Make sure it's not an open door or something + continue + var/object_damage = max(chassis.force + weapon_damage, minimum_damage) * structure_damage_mult + O.take_damage(object_damage, dam_type, "melee", 0) + if(istype(O, /obj/structure/window)) + playsound(O,'sound/effects/Glasshit.ogg', 50) //glass bonk noise + else + if(istype(A, /obj/mecha)) + O.visible_message(span_danger("[chassis.name] strikes [O] with a wide swing of [src]!")) //Don't really need to make a message for EVERY object, just important ones + playsound(O,'sound/weapons/smash.ogg', 50) //metallic bonk noise + + var/turf/cleave_effect_loc = get_step(get_turf(src), SOUTHWEST) + new cleave_effect(cleave_effect_loc, chassis.dir) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/precise_attack(atom/target) + if(isliving(target)) + var/mob/living/L = target + + if(iscarbon(L)) + var/mob/living/carbon/C = L + var/obj/item/bodypart/body_part = chassis.occupant.zone_selected + var/armor_block = C.run_armor_check(body_part, MELEE, armour_penetration = base_armor_piercing * 2) //and get more AP + C.apply_damage(max(chassis.force + precise_weapon_damage, minimum_damage), dam_type, body_part, armor_block, sharpness = attack_sharpness) + else + L.apply_damage(max(chassis.force + precise_weapon_damage, minimum_damage), dam_type) + if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid)) //Stab them harder + L.apply_damage(fauna_damage_bonus, dam_type) + + L.visible_message(span_danger("[chassis.name] strikes [L] with [src]!"), \ + span_userdanger("[chassis.name] strikes you with [src]!")) + chassis.log_message("Hit [L] with [src.name] (precise attack).", LOG_MECHA) + + else if(isstructure(target) || ismachinery(target) || istype(target, /obj/mecha)) //If the initial target is a big object, hit it even if it's not dense. + var/obj/O = target + var/object_damage = max(chassis.force + precise_weapon_damage, minimum_damage) * structure_damage_mult + O.take_damage(object_damage, dam_type, "melee", 0) + else + return + chassis.do_attack_animation(target, ATTACK_EFFECT_SLASH) + playsound(chassis, attack_sound, 50, 1) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe + name = "\improper SH-NT \"Killerhurtz\" energy axe" + desc = "An oversized, destructive-looking axe with a powered edge. While far too big for use by an individual, an exosuit might be able to wield it." + icon_state = "mecha_energy_axe" + precise_attacks = FALSE //This is not a weapon of precision, it is a weapon of destruction + energy_drain = 40 + weapon_damage = 30 + fauna_damage_bonus = 30 //If you're fighting fauna with this thing, why? I mean it works, I guess. + base_armor_piercing = 40 + structure_damage_mult = 4 //Think obi-wan cutting through a bulkhead with his lightsaber but he's a giant mech with a huge terrifying axe + minimum_damage = 40 + attack_speed_modifier = 1.5 //Kinda chunky + light_color = LIGHT_COLOR_RED + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe/cleave_attack() //Mostly copy-pasted sword cleave code with minor tweaks. + playsound(chassis, attack_sound, 50, 1) //Not hard to change some of this to be based on vars if you REALLY wanted to + var/turf/M = get_turf(src) + for(var/i = 0 to 2) + var/it_turn = 45*(1-i) + var/turf/T = get_step(M,turn(chassis.dir, it_turn)) //+45, +0, and -45 will get the three front tiles + for(var/atom/A in T.contents) + if(isliving(A)) + var/mob/living/L = A + + if(iscarbon(L)) //If we're a carbon we can get armor and jazz + var/mob/living/carbon/C = L + var/obj/item/bodypart/body_part = pick(C.bodyparts) //Cleave attack isn't very precise + var/armor_block = C.run_armor_check(body_part, MELEE, armour_penetration = base_armor_piercing) + C.apply_damage(max(chassis.force + weapon_damage, minimum_damage), dam_type, body_part, armor_block, sharpness = attack_sharpness) + else //Regular mobs just take damage + L.apply_damage(max(chassis.force + weapon_damage, minimum_damage), dam_type) + if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid)) //If we're hitting fauna, because heck those guys + L.apply_damage(fauna_damage_bonus, dam_type) + + L.visible_message(span_danger("[chassis.name] strikes [L] with a wide swing of [src]!"), \ + span_userdanger("[chassis.name] strikes you with [src]!")) + chassis.log_message("Hit [L] with [src.name] (cleave attack).", LOG_MECHA) + playsound(L, 'sound/weapons/blade1.ogg', 50) + + else if(isstructure(A) || ismachinery(A) || istype(A, /obj/mecha)) //if it's something we can otherwise still hit + var/obj/O = A + if(!O.density) //Make sure it's not an open door or something + continue + var/object_damage = max(chassis.force + weapon_damage, minimum_damage) * structure_damage_mult + O.take_damage(object_damage, dam_type, "melee", 0) + if(istype(O, /obj/structure/window)) + playsound(O,'sound/effects/Glasshit.ogg', 50) //glass bonk noise + else + if(istype(A, /obj/mecha)) + O.visible_message(span_danger("[chassis.name] strikes [O] with a wide swing of [src]!")) + playsound(O,'sound/weapons/smash.ogg', 50) //metallic bonk noise + + if(istype(T, /turf/closed/wall)) //IT BREAKS WALLS TOO + var/turf/closed/wall/W = T + W.dismantle_wall() + + var/turf/cleave_effect_loc = get_step(get_turf(src), SOUTHWEST) //Big sprite needs to be centered properly + new cleave_effect(cleave_effect_loc, chassis.dir) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe/on_select() + START_PROCESSING(SSobj, src) + set_light(5) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe/on_deselect() + STOP_PROCESSING(SSobj, src) + set_light(0) + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/rocket_fist //Passive upgrade weapon when selected, makes your mech punch harder AND faster + name = "\improper DD-2 \"Atom Smasher\" rocket fist" + desc = "A large metal fist fitted to the arm of an exosuit, it uses repurposed maneuvering thrusters from a Raven battlecruiser to give a little more oomph to every punch. Also helps increase the speed at which the mech is able to return to a ready stance after each swing." + icon_state = "mecha_rocket_fist" + melee_override = FALSE //We'll just buff the regular punch + precise_attacks = FALSE + cleave = FALSE + range = null //This should just make the mech punch stuff, which is what we want! + weapon_damage = 20 + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/rocket_fist/on_select() + chassis.force += weapon_damage //PUNCH HARDER + chassis.melee_cooldown *= 0.8 //PUNCH FASTER + +/obj/item/mecha_parts/mecha_equipment/melee_weapon/rocket_fist/on_deselect() + chassis.force -= weapon_damage //Return to babby fist + chassis.melee_cooldown /= 0.8 diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 3b757e0461f6..861ba1fae2e2 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -26,7 +26,7 @@ return FALSE if(istype(M, /obj/mecha/combat)) return TRUE - if((locate(/obj/item/mecha_parts/concealed_weapon_bay) in M.contents) && !(locate(/obj/item/mecha_parts/mecha_equipment/weapon) in M.equipment)) + if((locate(/obj/item/mecha_parts/concealed_weapon_bay) in M.contents) && !((locate(/obj/item/mecha_parts/mecha_equipment/melee_weapon) in M.equipment) || (locate(/obj/item/mecha_parts/mecha_equipment/weapon) in M.equipment) )) return TRUE return FALSE diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 9207897e7f44..60abdb172242 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -114,7 +114,7 @@ //Action vars var/thrusters_active = FALSE var/defence_mode = FALSE - var/defence_mode_deflect_chance = 35 + var/defence_mode_deflect_chance = 15 var/leg_overload_mode = FALSE var/leg_overload_coeff = 100 var/zoom_mode = FALSE @@ -519,6 +519,11 @@ if(isliving(target) && selected.harmful && HAS_TRAIT(L, TRAIT_PACIFISM)) to_chat(user, span_warning("You don't want to harm other living beings!")) return + if(istype(selected, /obj/item/mecha_parts/mecha_equipment/melee_weapon)) //Need to make a special check for melee weapons with cleave attacks + var/obj/item/mecha_parts/mecha_equipment/melee_weapon/W = selected + if(HAS_TRAIT(L, TRAIT_PACIFISM) && W.cleave) + to_chat(user, span_warning("You don't want to harm other living beings!")) + return if(selected.action(target,params)) selected.start_cooldown() else @@ -656,13 +661,14 @@ /obj/mecha/Bump(var/atom/obstacle) var/turf/newloc = get_step(src,dir) var/area/newarea = newloc.loc - if(newloc.flags_1 & NOJAUNT_1) - to_chat(occupant, span_warning("Some strange aura is blocking the way.")) - return - if(newarea.noteleport || SSmapping.level_trait(newloc.z, ZTRAIT_NOPHASE)) + if(phasing && ((newloc.flags_1 & NOJAUNT_1) || newarea.noteleport || SSmapping.level_trait(newloc.z, ZTRAIT_NOPHASE))) to_chat(occupant, span_warning("Some strange aura is blocking the way.")) - return + return //If we're trying to phase and it's NOT ALLOWED, don't bump + + if(istype(newloc, /turf/closed/indestructible)) + return //If the turf is indestructible don't bother trying + if(phasing && get_charge() >= phasing_energy_drain && !throwing) spawn() if(can_move) diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm index cc3b32b359f3..7b02750b506f 100644 --- a/code/game/mecha/mecha_actions.dm +++ b/code/game/mecha/mecha_actions.dm @@ -78,6 +78,7 @@ return if(!chassis.selected) chassis.selected = available_equipment[1] + chassis.selected.on_select() chassis.occupant_message("You select [chassis.selected]") send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) button_icon_state = "mech_cycle_equip_on" @@ -86,13 +87,17 @@ var/number = 0 for(var/A in available_equipment) number++ - if(A == chassis.selected) + if(A == chassis.selected) //Swapping to no equipment from something if(available_equipment.len == number) + chassis.selected.on_deselect() chassis.selected = null chassis.occupant_message("You switch to no equipment") button_icon_state = "mech_cycle_equip_off" else + if(chassis.selected) //If we're swapping off of an equipment, remove effects + chassis.selected.on_deselect() chassis.selected = available_equipment[number+1] + chassis.selected.on_select() chassis.occupant_message("You switch to [chassis.selected]") button_icon_state = "mech_cycle_equip_on" send_byjax(chassis.occupant,"exosuit.browser","eq_list",chassis.get_equipment_list()) @@ -179,10 +184,10 @@ chassis.defence_mode = !chassis.defence_mode button_icon_state = "mech_defense_mode_[chassis.defence_mode ? "on" : "off"]" if(chassis.defence_mode) - chassis.deflect_chance = chassis.defence_mode_deflect_chance + chassis.deflect_chance += chassis.defence_mode_deflect_chance chassis.occupant_message(span_notice("You enable [chassis] defence mode.")) else - chassis.deflect_chance = initial(chassis.deflect_chance) + chassis.deflect_chance -= chassis.defence_mode_deflect_chance chassis.occupant_message(span_danger("You disable [chassis] defence mode.")) chassis.log_message("Toggled defence mode.", LOG_MECHA) UpdateButtonIcon() diff --git a/code/game/mecha/mecha_topic.dm b/code/game/mecha/mecha_topic.dm index b6fdd2d91e2c..acca56424b83 100644 --- a/code/game/mecha/mecha_topic.dm +++ b/code/game/mecha/mecha_topic.dm @@ -296,7 +296,11 @@ if(href_list["select_equip"]) var/obj/item/mecha_parts/mecha_equipment/equip = locate(href_list["select_equip"]) in src if(equip && equip.selectable) + if(selected) + var/obj/item/mecha_parts/mecha_equipment/unequip = selected //What we're lowering + unequip.on_deselect() selected = equip + equip.on_select() occupant_message("You switch to [equip]") visible_message("[src] raises [equip]") send_byjax(usr,"exosuit.browser","eq_list",src.get_equipment_list()) diff --git a/code/game/objects/effects/temporary_visuals/miscellaneous.dm b/code/game/objects/effects/temporary_visuals/miscellaneous.dm index a6bee91e747b..edd83109c1e6 100644 --- a/code/game/objects/effects/temporary_visuals/miscellaneous.dm +++ b/code/game/objects/effects/temporary_visuals/miscellaneous.dm @@ -85,6 +85,11 @@ icon_state = "shieldsparkles" duration = 0.3 SECONDS +/obj/effect/temp_visual/dir_setting/firing_effect/mecha_swipe + icon = 'icons/effects/96x96.dmi' + icon_state = "big_slash" + duration = 0.3 SECONDS + /obj/effect/temp_visual/dir_setting/ninja name = "ninja shadow" icon = 'icons/mob/mob.dmi' diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 62661a111aac..5a641a270a61 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -379,8 +379,9 @@ apply_damage(damage, BRUTE, affecting, armor_block, wound_bonus=wound_mod) /mob/living/carbon/human/mech_melee_attack(obj/mecha/M) - - if(M.occupant.a_intent == INTENT_HARM) + if(M.selected?.melee_override) + M.selected.action(src) + else if(M.occupant.a_intent == INTENT_HARM) M.do_attack_animation(src) if(M.damtype == BRUTE) step_away(src,M,15) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index f07d0075c740..5eb3786fd392 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -100,7 +100,9 @@ /mob/living/mech_melee_attack(obj/mecha/M) - if(M.occupant.a_intent == INTENT_HARM) + if(M.selected?.melee_override) + M.selected.action(src) + else if(M.occupant.a_intent == INTENT_HARM) last_damage = "grand blunt trauma" M.do_attack_animation(src) if(M.damtype == "brute") diff --git a/code/modules/research/designs/mecha_designs.dm b/code/modules/research/designs/mecha_designs.dm index ae0d0c5bd348..f8c29c4c7f76 100644 --- a/code/modules/research/designs/mecha_designs.dm +++ b/code/modules/research/designs/mecha_designs.dm @@ -488,3 +488,21 @@ construction_time = 250 build_path = /obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam category = list("Exosuit Equipment") + +/datum/design/mech_rocket_fist + name = "Exosuit Weapon (DD-2 \"Atom Smasher\" Rocket Fist)" + id = "mech_rocket_fist" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/melee_weapon/rocket_fist + materials = list(/datum/material/iron=20000,/datum/material/plasma=10000) + construction_time = 100 + category = list("Exosuit Equipment") + +/datum/design/mech_shortsword + name = "Exosuit Weapon (GD6 \"Jaeger\" Shortsword)" + id = "mech_shortsword" + build_type = MECHFAB + build_path = /obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/shortsword + materials = list(/datum/material/iron=15000,/datum/material/titanium=10000,/datum/material/plasma=10000) + construction_time = 100 + category = list("Exosuit Equipment") diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 979c8662c86d..eb6fe079ae70 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -925,6 +925,22 @@ design_ids = list("mech_diamond_drill") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) +/datum/techweb_node/mech_rocket_fist + id = "mech_rocket_fist" + display_name = "Exosuit Weapon (DD-2 \"Atom Smasher\" Rocket Fist)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_mecha","weaponry") + design_ids = list("mech_rocket_fist") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + +/datum/techweb_node/mech_shortsword + id = "mech_shortsword" + display_name = "Exosuit Weapon (GD6 \"Jaeger\" Shortsword)" + description = "An advanced piece of mech weaponry" + prereq_ids = list("adv_mecha","adv_weaponry") + design_ids = list("mech_shortsword") + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + /////////////////////////Nanites///////////////////////// /datum/techweb_node/nanite_base id = "nanite_base" diff --git a/code/modules/research/techweb/layout.dm b/code/modules/research/techweb/layout.dm index 8d8dac950469..39adfe8d6762 100644 --- a/code/modules/research/techweb/layout.dm +++ b/code/modules/research/techweb/layout.dm @@ -599,6 +599,14 @@ ui_x = -640 ui_y = -896 +/datum/techweb_node/mech_rocket_fist + ui_x = -576 + ui_y = 32 + +/datum/techweb_node/mech_shortsword + ui_x = -640 + ui_y = 32 + /datum/techweb_node/bshipc ui_x = -224 ui_y = 32 diff --git a/icons/effects/96x96.dmi b/icons/effects/96x96.dmi index 9818a648366f..60d1b9678ba5 100644 Binary files a/icons/effects/96x96.dmi and b/icons/effects/96x96.dmi differ diff --git a/icons/mecha/mecha_equipment.dmi b/icons/mecha/mecha_equipment.dmi index 7035d8b41e65..da630574358c 100644 Binary files a/icons/mecha/mecha_equipment.dmi and b/icons/mecha/mecha_equipment.dmi differ diff --git a/sound/weapons/mechasword.ogg b/sound/weapons/mechasword.ogg new file mode 100644 index 000000000000..3acc2389bca8 Binary files /dev/null and b/sound/weapons/mechasword.ogg differ diff --git a/yogstation.dme b/yogstation.dme index dc802efaff88..eb6d1537e00c 100644 --- a/yogstation.dme +++ b/yogstation.dme @@ -885,6 +885,7 @@ #include "code\game\mecha\equipment\tools\weapon_bay.dm" #include "code\game\mecha\equipment\tools\work_tools.dm" #include "code\game\mecha\equipment\weapons\mecha_ammo.dm" +#include "code\game\mecha\equipment\weapons\melee_weapons.dm" #include "code\game\mecha\equipment\weapons\weapons.dm" #include "code\game\mecha\medical\medical.dm" #include "code\game\mecha\medical\odysseus.dm"