/obj/vehicle/sealed/mecha/proc/get_armour_facing(relative_dir) switch(relative_dir) if(180) // BACKSTAB! return facing_modifiers[MECHA_BACK_ARMOUR] if(0, 45) // direct or 45 degrees off return facing_modifiers[MECHA_FRONT_ARMOUR] return facing_modifiers[MECHA_SIDE_ARMOUR] //if its not a front hit or back hit then assume its from the side /obj/vehicle/sealed/mecha/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() if(. && obj_integrity > 0) spark_system.start() switch(damage_flag) if(FIRE) check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL)) if(MELEE) check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) else check_for_internal_damage(list(MECHA_INT_FIRE,MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST,MECHA_INT_SHORT_CIRCUIT)) if(. >= 5 || prob(33)) to_chat(occupants, "[icon2html(src, occupants)]Taking damage!") log_message("Took [damage_amount] points of damage. Damage type: [damage_type]", LOG_MECHA) /obj/vehicle/sealed/mecha/run_obj_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) . = ..() if(!damage_amount) return FALSE var/booster_deflection_modifier = 1 var/booster_damage_modifier = 1 if(damage_flag == BULLET || damage_flag == LASER || damage_flag == ENERGY) for(var/obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster/B in equipment) if(B.projectile_react()) booster_deflection_modifier = B.deflect_coeff booster_damage_modifier = B.damage_coeff break else if(damage_flag == MELEE) for(var/obj/item/mecha_parts/mecha_equipment/anticcw_armor_booster/B in equipment) if(B.attack_react()) booster_deflection_modifier *= B.deflect_coeff booster_damage_modifier *= B.damage_coeff break if(attack_dir) var/facing_modifier = get_armour_facing(abs(dir2angle(dir) - dir2angle(attack_dir))) booster_damage_modifier /= facing_modifier booster_deflection_modifier *= facing_modifier if(prob(deflect_chance * booster_deflection_modifier)) visible_message("[src]'s armour deflects the attack!") log_message("Armor saved.", LOG_MECHA) return FALSE if(.) . *= booster_damage_modifier /obj/vehicle/sealed/mecha/attack_hand(mob/living/user) . = ..() if(.) return user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) playsound(loc, 'sound/weapons/tap.ogg', 40, TRUE, -1) user.visible_message("[user] hits [name]. Nothing happens.", null, null, COMBAT_MESSAGE_RANGE) log_message("Attack by hand/paw. Attacker - [user].", LOG_MECHA, color="red") /obj/vehicle/sealed/mecha/attack_paw(mob/user as mob) return attack_hand(user) /obj/vehicle/sealed/mecha/attack_alien(mob/living/user) log_message("Attack by alien. Attacker - [user].", LOG_MECHA, color="red") playsound(src.loc, 'sound/weapons/slash.ogg', 100, TRUE) attack_generic(user, 15, BRUTE, MELEE, 0) /obj/vehicle/sealed/mecha/attack_animal(mob/living/simple_animal/user) log_message("Attack by simple animal. Attacker - [user].", LOG_MECHA, color="red") if(!user.melee_damage_upper && !user.obj_damage) user.emote("custom", message = "[user.friendly_verb_continuous] [src].") return FALSE else var/play_soundeffect = 1 if(user.environment_smash) play_soundeffect = 0 playsound(src, 'sound/effects/bang.ogg', 50, TRUE) var/animal_damage = rand(user.melee_damage_lower,user.melee_damage_upper) if(user.obj_damage) animal_damage = user.obj_damage animal_damage = min(animal_damage, 20*user.environment_smash) log_combat(user, src, "attacked") attack_generic(user, animal_damage, user.melee_damage_type, MELEE, play_soundeffect) return TRUE /obj/vehicle/sealed/mecha/hulk_damage() return 15 /obj/vehicle/sealed/mecha/attack_hulk(mob/living/carbon/human/user) . = ..() if(.) log_message("Attack by hulk. Attacker - [user].", LOG_MECHA, color="red") log_combat(user, src, "punched", "hulk powers") /obj/vehicle/sealed/mecha/blob_act(obj/structure/blob/B) log_message("Attack by blob. Attacker - [B].", LOG_MECHA, color="red") take_damage(30, BRUTE, MELEE, 0, get_dir(src, B)) /obj/vehicle/sealed/mecha/attack_tk() return /obj/vehicle/sealed/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper log_message("Hit by [AM].", LOG_MECHA, color="red") return ..() /obj/vehicle/sealed/mecha/bullet_act(obj/item/projectile/Proj) //wrapper if(!enclosed && LAZYLEN(occupants) && !(mecha_flags & SILICON_PILOT) && !Proj.force_hit && (Proj.def_zone == BODY_ZONE_HEAD || Proj.def_zone == BODY_ZONE_CHEST)) //allows bullets to hit the pilot of open-canopy mechs for(var/m in occupants) var/mob/living/hitmob = m hitmob.bullet_act(Proj) //If the sides are open, the occupant can be hit return BULLET_ACT_HIT log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).", LOG_MECHA, color="red") . = ..() /obj/vehicle/sealed/mecha/ex_act(severity, target) log_message("Affected by explosion of severity: [severity].", LOG_MECHA, color="red") if(prob(deflect_chance)) severity++ log_message("Armor saved, changing severity to [severity]", LOG_MECHA) . = ..() /obj/vehicle/sealed/mecha/contents_explosion(severity, target, origin) severity++ for(var/X in equipment) var/obj/item/mecha_parts/mecha_equipment/ME = X ME.ex_act(severity, target, origin) for(var/Y in trackers) var/obj/item/mecha_parts/mecha_tracking/MT = Y MT.ex_act(severity, target, origin) for(var/Z in occupants) var/mob/living/occupant = Z occupant.ex_act(severity, target, origin) /obj/vehicle/sealed/mecha/handle_atom_del(atom/A) if(A in occupants) LAZYREMOVE(occupants, A) icon_state = initial(icon_state)+"-open" setDir(dir_in) /obj/vehicle/sealed/mecha/emp_act(severity) . = ..() if (. & EMP_PROTECT_SELF) return if(get_charge()) use_power((cell.charge/3)*(severity*0.005)) take_damage(severity/3, BURN, ENERGY, 1) log_message("EMP detected", LOG_MECHA, color="red") if(istype(src, /obj/vehicle/sealed/mecha/combat)) mouse_pointer = 'icons/effects/mouse_pointers/mecha_mouse-disable.dmi' for(var/occus in occupants) var/mob/living/occupant = occus occupant.update_mouse_pointer() if(!equipment_disabled && LAZYLEN(occupants)) //prevent spamming this message with back-to-back EMPs to_chat(occupants, "Error -- Connection to equipment control unit has been lost.") addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/vehicle/sealed/mecha, restore_equipment)), 3 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE) equipment_disabled = 1 /obj/vehicle/sealed/mecha/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume) if(exposed_temperature>max_temperature) log_message("Exposed to dangerous temperature.", LOG_MECHA, color="red") take_damage(5, BURN, 0, 1) /obj/vehicle/sealed/mecha/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/mmi)) if(mmi_move_inside(W,user)) to_chat(user, "[src]-[W] interface initialized successfully.") else to_chat(user, "[src]-[W] interface initialization failed.") return if(istype(W, /obj/item/mecha_ammo)) ammo_resupply(W, user) return if(W.GetID()) if((mecha_flags & ADDING_ACCESS_POSSIBLE) || (mecha_flags & ADDING_MAINT_ACCESS_POSSIBLE)) if(internals_access_allowed(user)) var/obj/item/card/id/id_card if(istype(W, /obj/item/card/id)) id_card = W else var/obj/item/pda/pda = W id_card = pda.id output_maintenance_dialog(id_card, user) return to_chat(user, "Invalid ID: Access denied.") return to_chat(user, "Maintenance protocols disabled by operator.") return if(istype(W, /obj/item/stock_parts/cell)) if(construction_state == MECHA_OPEN_HATCH) if(!cell) if(!user.transferItemToLoc(W, src, silent = FALSE)) return var/obj/item/stock_parts/cell/C = W to_chat(user, "You install the power cell.") playsound(src, 'sound/items/screwdriver2.ogg', 50, FALSE) cell = C log_message("Power cell installed", LOG_MECHA) else to_chat(user, "There's already a power cell installed!") return if(istype(W, /obj/item/stock_parts/scanning_module)) if(construction_state == MECHA_OPEN_HATCH) if(!scanmod) if(!user.transferItemToLoc(W, src)) return to_chat(user, "You install the scanning module.") playsound(src, 'sound/items/screwdriver2.ogg', 50, FALSE) scanmod = W log_message("[W] installed", LOG_MECHA) update_part_values() else to_chat(user, "There's already a scanning module installed!") return if(istype(W, /obj/item/stock_parts/capacitor)) if(construction_state == MECHA_OPEN_HATCH) if(!capacitor) if(!user.transferItemToLoc(W, src)) return to_chat(user, "You install the capacitor.") playsound(src, 'sound/items/screwdriver2.ogg', 50, FALSE) capacitor = W log_message("[W] installed", LOG_MECHA) update_part_values() else to_chat(user, "There's already a capacitor installed!") return if(istype(W, /obj/item/stack/cable_coil)) if(construction_state == MECHA_OPEN_HATCH && (internal_damage & MECHA_INT_SHORT_CIRCUIT)) var/obj/item/stack/cable_coil/CC = W if(CC.use(2)) clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) to_chat(user, "You replace the fused wires.") else to_chat(user, "You need two lengths of cable to fix this mech!") return if(istype(W, /obj/item/mecha_parts)) var/obj/item/mecha_parts/P = W P.try_attach_part(user, src) return if(istype(W, /obj/item/analyzer)) if(construction_state) var/datum/gas_mixture/GasNux = internal_tank.return_air() atmosanalyzer_scan(GasNux,user,src,TRUE) else atmosanalyzer_scan(cabin_air,user,src,TRUE) return log_message("Attacked by [W]. Attacker - [user]", LOG_MECHA) return ..() /obj/vehicle/sealed/mecha/wrench_act(mob/living/user, obj/item/I) ..() . = TRUE if(construction_state == MECHA_SECURE_BOLTS) construction_state = MECHA_LOOSE_BOLTS to_chat(user, "You undo the securing bolts.") return if(construction_state == MECHA_LOOSE_BOLTS) construction_state = MECHA_SECURE_BOLTS to_chat(user, "You tighten the securing bolts.") /obj/vehicle/sealed/mecha/crowbar_act(mob/living/user, obj/item/I) ..() . = TRUE if(construction_state == MECHA_LOOSE_BOLTS) construction_state = MECHA_OPEN_HATCH to_chat(user, "You open the hatch to the power unit.") return if(construction_state == MECHA_OPEN_HATCH) construction_state = MECHA_LOOSE_BOLTS to_chat(user, "You close the hatch to the power unit.") /obj/vehicle/sealed/mecha/screwdriver_act(mob/living/user, obj/item/I) ..() . = TRUE if(internal_damage & MECHA_INT_TEMP_CONTROL) clearInternalDamage(MECHA_INT_TEMP_CONTROL) to_chat(user, "You repair the damaged temperature controller.") return /obj/vehicle/sealed/mecha/welder_act(mob/living/user, obj/item/W) . = ..() if(user.a_intent == INTENT_HARM) return . = TRUE if(internal_damage & MECHA_INT_TANK_BREACH) if(!W.use_tool(src, user, 0, volume=50, amount=1)) return clearInternalDamage(MECHA_INT_TANK_BREACH) to_chat(user, "You repair the damaged gas tank.") return if(obj_integrity < max_integrity) if(!W.use_tool(src, user, 0, volume=50, amount=1)) return user.visible_message("[user] repairs some damage to [name].", "You repair some damage to [src].") obj_integrity += min(10, max_integrity-obj_integrity) if(obj_integrity == max_integrity) to_chat(user, "It looks to be fully repaired now.") return to_chat(user, "The [name] is at full integrity!") /obj/vehicle/sealed/mecha/proc/mech_toxin_damage(mob/living/target) playsound(src, 'sound/effects/spray2.ogg', 50, TRUE) if(target.reagents) if(target.reagents.get_reagent_amount(/datum/reagent/cryptobiolin) + force < force*2) target.reagents.add_reagent(/datum/reagent/cryptobiolin, force/2) if(target.reagents.get_reagent_amount(/datum/reagent/toxin) + force < force*2) target.reagents.add_reagent(/datum/reagent/toxin, force/2.5) /obj/vehicle/sealed/mecha/mech_melee_attack(obj/vehicle/sealed/mecha/M, mob/user) if(!has_charge(melee_energy_drain)) return NONE use_power(melee_energy_drain) if(M.damtype == BRUTE || M.damtype == BURN) log_combat(user, src, "attacked", M, "(INTENT: [uppertext(user.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])") . = ..() /obj/vehicle/sealed/mecha/proc/full_repair(charge_cell) obj_integrity = max_integrity if(cell && charge_cell) cell.charge = cell.maxcharge if(internal_damage & MECHA_INT_FIRE) clearInternalDamage(MECHA_INT_FIRE) if(internal_damage & MECHA_INT_TEMP_CONTROL) clearInternalDamage(MECHA_INT_TEMP_CONTROL) if(internal_damage & MECHA_INT_SHORT_CIRCUIT) clearInternalDamage(MECHA_INT_SHORT_CIRCUIT) if(internal_damage & MECHA_INT_TANK_BREACH) clearInternalDamage(MECHA_INT_TANK_BREACH) if(internal_damage & MECHA_INT_CONTROL_LOST) clearInternalDamage(MECHA_INT_CONTROL_LOST) /obj/vehicle/sealed/mecha/narsie_act() emp_act(80) /obj/vehicle/sealed/mecha/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!no_effect) if(selected) used_item = selected else if(!visual_effect_icon) visual_effect_icon = ATTACK_EFFECT_SMASH if(damtype == BURN) visual_effect_icon = ATTACK_EFFECT_MECHFIRE else if(damtype == TOX) visual_effect_icon = ATTACK_EFFECT_MECHTOXIN ..() /obj/vehicle/sealed/mecha/obj_destruction() if(wreckage) var/mob/living/silicon/ai/AI for(var/crew in occupants) if(isAI(crew)) if(AI) var/mob/living/silicon/ai/unlucky_ais = crew unlucky_ais.gib() continue AI = crew var/obj/structure/mecha_wreckage/WR = new wreckage(loc, AI) for(var/obj/item/mecha_parts/mecha_equipment/E in equipment) if(E.salvageable && prob(30)) WR.crowbar_salvage += E E.detach(WR) //detaches from src into WR E.equip_ready = 1 else E.detach(loc) qdel(E) if(cell) WR.crowbar_salvage += cell cell.forceMove(WR) cell.charge = rand(0, cell.charge) cell = null if(internal_tank) WR.crowbar_salvage += internal_tank internal_tank.forceMove(WR) cell = null . = ..()