diff --git a/code/game/mecha/micro/micro.dm b/code/game/mecha/micro/micro.dm new file mode 100644 index 0000000000..558509c17e --- /dev/null +++ b/code/game/mecha/micro/micro.dm @@ -0,0 +1,147 @@ +/obj/mecha/micro + icon = 'icons/mecha/micro.dmi' + force = 10 //still a robot + anchored = 0 //light enough to push and pull, but you still can't just walk past them. Like people on non-help. + opacity = 0 //small enough to see around, like people. + step_energy_drain = 2 // They're light and small. A compact is gonna get better MPG than a truck. + var/melee_cooldown = 10 + var/melee_can_hit = 1 + var/list/destroyable_obj = list(/obj/mecha, /obj/structure/window, /obj/structure/grille, /turf/simulated/wall) + internal_damage_threshold = 50 + maint_access = 0 + //add_req_access = 0 + //operation_req_access = list(access_hos) + damage_absorption = list("brute"=1,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) + var/am = "d3c2fbcadca903a41161ccc9df9cf948" + + +/obj/mecha/micro/melee_action(target as obj|mob|turf) + if(internal_damage&MECHA_INT_CONTROL_LOST) + target = safepick(oview(1,src)) + if(!melee_can_hit || !istype(target, /atom)) return + if(istype(target, /mob/living)) + var/mob/living/M = target + if(src.occupant.a_intent == I_HURT) + playsound(src, 'sound/weapons/punch4.ogg', 50, 1) + if(damtype == "brute") + step_away(M,src,15) + + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + // if (M.health <= 0) return + + var/obj/item/organ/external/temp = H.get_organ(pick(BP_TORSO, BP_TORSO, BP_TORSO, BP_HEAD)) + if(temp) + var/update = 0 + switch(damtype) + if("brute") + H.Paralyse(1) + update |= temp.take_damage(rand(force/2, force), 0) + if("fire") + update |= temp.take_damage(0, rand(force/2, force)) + if("tox") + if(H.reagents) + if(H.reagents.get_reagent_amount("carpotoxin") + force < force*2) + H.reagents.add_reagent("carpotoxin", force) + if(H.reagents.get_reagent_amount("cryptobiolin") + force < force*2) + H.reagents.add_reagent("cryptobiolin", force) + else + return + if(update) H.UpdateDamageIcon() + H.updatehealth() + + else + switch(damtype) + if("brute") + M.Paralyse(1) + M.take_overall_damage(rand(force/2, force)) + if("fire") + M.take_overall_damage(0, rand(force/2, force)) + if("tox") + if(M.reagents) + if(M.reagents.get_reagent_amount("carpotoxin") + force < force*2) + M.reagents.add_reagent("carpotoxin", force) + if(M.reagents.get_reagent_amount("cryptobiolin") + force < force*2) + M.reagents.add_reagent("cryptobiolin", force) + else + return + M.updatehealth() + src.occupant_message("You hit [target].") + src.visible_message("[src.name] hits [target].") + else + step_away(M,src) + src.occupant_message("You push [target] out of the way.") + src.visible_message("[src] pushes [target] out of the way.") + + melee_can_hit = 0 + if(do_after(melee_cooldown)) + melee_can_hit = 1 + return + + else + if(damtype == "brute") + for(var/target_type in src.destroyable_obj) + if(istype(target, target_type) && hascall(target, "attackby")) + src.occupant_message("You hit [target].") + src.visible_message("[src.name] hits [target]") + if(!istype(target, /turf/simulated/wall)) + target:attackby(src,src.occupant) + else if(prob(5)) + target:dismantle_wall(1) + src.occupant_message("You smash through the wall.") + src.visible_message("[src.name] smashes through the wall") + playsound(src, 'sound/weapons/smash.ogg', 50, 1) + melee_can_hit = 0 + if(do_after(melee_cooldown)) + melee_can_hit = 1 + break + return + + +/obj/mecha/micro/Topic(href,href_list) + ..() + var/datum/topic_input/filter = new (href,href_list) + if(filter.get("close")) + am = null + return + +// override move_inside() so only micro crew can use them + +/obj/mecha/micro/move_inside() + var/mob/living/carbon/C = usr + if (C.size_multiplier >= 0.5) + C << "You can't fit in this suit!" + return + else + ..() + +/obj/mecha/micro/move_inside_passenger() + var/mob/living/carbon/C = usr + if (C.size_multiplier >= 0.5) + C << "You can't fit in this suit!" + return + else + ..() + +// override move/turn procs so they play more appropriate sounds. Placeholder sounds for now, but mechmove04 at least sounds like tracks for the poleat. + +/obj/mecha/micro/mechturn(direction) + set_dir(direction) + playsound(src,'sound/mecha/mechmove03.ogg',40,1) + return 1 + +/obj/mecha/micro/mechstep(direction) + var/result = step(src,direction) + if(result) + playsound(src,'sound/mecha/mechmove04.ogg',40,1) + return result + +/obj/mecha/micro/mechsteprand() + var/result = step_rand(src) + if(result) + playsound(src,'sound/mecha/mechmove04.ogg',40,1) + return result + +/obj/effect/decal/mecha_wreckage/micro + icon = 'icons/mecha/micro.dmi' + diff --git a/code/game/mecha/micro/micro_equipment.dm b/code/game/mecha/micro/micro_equipment.dm new file mode 100644 index 0000000000..c1ef53a59d --- /dev/null +++ b/code/game/mecha/micro/micro_equipment.dm @@ -0,0 +1,221 @@ +//DO NOT ADD MECHA PARTS TO THE GAME WITH THE DEFAULT "SPRITE ME" SPRITE! + +///////////////////////////// +//// WEAPONS BELOW //// +///////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/microlaser + w_class = ITEMSIZE_LARGE + desc = "A mounted laser-carbine for light exosuits." + equip_cooldown = 10 // same as the laser carbine + name = "\improper WS-19 \"Torch\" laser carbine" + icon = 'icons/mecha/mecha_equipment_vr.dmi' + icon_state = "micromech_laser" + energy_drain = 50 + projectile = /obj/item/projectile/beam + fire_sound = 'sound/weapons/Laser.ogg' + required_type = list(/obj/mecha/micro/sec) + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser/microheavy + w_class = ITEMSIZE_LARGE + desc = "A mounted laser cannon for light exosuits." + equip_cooldown = 30 // same as portable + name = "\improper PC-20 \"Lance\" light laser cannon" + icon = 'icons/mecha/mecha_equipment_vr.dmi' + icon_state = "micromech_lasercannon" + energy_drain = 120 + projectile = /obj/item/projectile/beam/heavylaser + fire_sound = 'sound/weapons/lasercannonfire.ogg' + required_type = list(/obj/mecha/micro/sec) + +/obj/item/mecha_parts/mecha_equipment/weapon/energy/microtaser + w_class = ITEMSIZE_LARGE + desc = "A mounted taser for light exosuits." + name = "\improper TS-12 \"Suppressor\" integrated taser" + icon = 'icons/mecha/mecha_equipment_vr.dmi' + icon_state = "micromech_taser" + energy_drain = 40 + equip_cooldown = 10 + projectile = /obj/item/projectile/beam/stun + fire_sound = 'sound/weapons/Taser.ogg' + required_type = list(/obj/mecha/micro/sec) + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/microshotgun + w_class = ITEMSIZE_LARGE + desc = "A mounted combat shotgun with integrated ammo-lathe." + name = "\improper Remington C-12 \"Boomstick\"" + icon = 'icons/mecha/mecha_equipment_vr.dmi' + icon_state = "micromech_shotgun" + equip_cooldown = 15 + var/mode = 0 //0 - buckshot, 1 - beanbag, 2 - slug. + projectile = /obj/item/projectile/bullet/pellet/shotgun + fire_sound = 'sound/weapons/shotgun.ogg' + fire_volume = 80 + projectiles = 6 + projectiles_per_shot = 1 + deviation = 0.7 + projectile_energy_cost = 100 + required_type = list(/obj/mecha/micro/sec) + + Topic(href,href_list) + ..() + if(href_list["mode"]) + mode = text2num(href_list["mode"]) + switch(mode) + if(0) + occupant_message("Now firing buckshot.") + projectile = /obj/item/projectile/bullet/pellet/shotgun + if(1) + occupant_message("Now firing beanbags.") + projectile = /obj/item/projectile/bullet/shotgun/beanbag + if(2) + occupant_message("Now firing slugs.") + projectile = /obj/item/projectile/bullet/shotgun + + return + + get_equip_info() + return "[..()] \[BS|BB|S\]" + + +/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/microflashbang + w_class = ITEMSIZE_LARGE + desc = "A mounted grenade launcher for smaller mechs." + name = "\improper FP-20 mounted grenade launcher" + icon = 'icons/mecha/mecha_equipment_vr.dmi' + icon_state = "micromech_launcher" + projectiles = 1 + missile_speed = 1.5 + projectile_energy_cost = 800 + equip_cooldown = 30 + det_time = 15 + required_type = list(/obj/mecha/micro/sec) + + +///////////////////////////// +//// UTILITY TOOLS BELOW //// +///////////////////////////// + +/obj/item/mecha_parts/mecha_equipment/tool/drill/micro + w_class = ITEMSIZE_LARGE + name = "drill" + desc = "This is the drill that'll sorta poke holes in the heavens!" + icon = 'icons/mecha/mecha_equipment_vr.dmi' + icon_state = "microdrill" + equip_cooldown = 30 + energy_drain = 10 + force = 15 + required_type = list(/obj/mecha/micro/utility) + + action(atom/target) + if(!action_checks(target)) return + if(isobj(target)) + var/obj/target_obj = target + if(!target_obj.vars.Find("unacidable") || target_obj.unacidable) return + set_ready_state(0) + chassis.use_power(energy_drain) + chassis.visible_message("[chassis] starts to drill [target]", "You hear the drill.") + occupant_message("You start to drill [target]") + var/T = chassis.loc + var/C = target.loc //why are these backwards? we may never know -Pete + if(do_after_cooldown(target)) + if(T == chassis.loc && src == chassis.selected) + if(istype(target, /turf/simulated/wall)) + var/turf/simulated/wall/W = target + if(W.reinf_material) + occupant_message("[target] is too durable to drill through.") + else + log_message("Drilled through [target]") + target.ex_act(2) + else if(istype(target, /turf/simulated/mineral)) + for(var/turf/simulated/mineral/M in range(chassis,1)) + if(get_dir(chassis,M)&chassis.dir) + M.GetDrilled() + log_message("Drilled through [target]") + var/obj/item/mecha_parts/mecha_equipment/tool/micro/orescoop/ore_box = (locate(/obj/item/mecha_parts/mecha_equipment/tool/micro/orescoop) in chassis.equipment) + if(ore_box) + for(var/obj/item/weapon/ore/ore in range(chassis,1)) + if(get_dir(chassis,ore)&chassis.dir) + if (ore_box.contents.len >= ore_box.orecapacity) + occupant_message("The ore compartment is full.") + return 1 + else + ore.Move(ore_box) + else if(target.loc == C) + log_message("Drilled through [target]") + target.ex_act(2) + return 1 + + +/obj/item/mecha_parts/mecha_equipment/tool/micro/orescoop + w_class = ITEMSIZE_LARGE + name = "Mounted ore box" + desc = "A mounted ore scoop and hopper, for gathering ores." + icon = 'icons/mecha/mecha_equipment_vr.dmi' + icon_state = "microscoop" + equip_cooldown = 5 + energy_drain = 0 + required_type = list(/obj/mecha/micro/utility) + var/orecapacity = 500 + + action(atom/target) + if(!action_checks(target)) return + set_ready_state(0) + chassis.use_power(energy_drain) + chassis.visible_message("[chassis] sweeps around with its ore scoop.") + occupant_message("You sweep around the area with the scoop.") + var/T = chassis.loc + //var/C = target.loc //why are these backwards? we may never know -Pete + if(do_after_cooldown(target)) + if(T == chassis.loc && src == chassis.selected) + for(var/obj/item/weapon/ore/ore in range(chassis,1)) + if(get_dir(chassis,ore)&chassis.dir) + if (contents.len >= orecapacity) + occupant_message("The ore compartment is full.") + return 1 + else + ore.Move(src) + return 1 + + Topic(href,href_list) + ..() + if (href_list["empty_box"]) + if(contents.len < 1) + occupant_message("The ore compartment is empty.") + return + for (var/obj/item/weapon/ore/O in contents) + contents -= O + O.loc = chassis.loc + occupant_message("Ore compartment emptied.") + + get_equip_info() + return "[..()]
Empty ore compartment" + +/obj/item/mecha_parts/mecha_equipment/tool/orescoop/verb/empty_box() //so you can still get the ore out if someone detaches it from the mech + set name = "Empty Ore compartment" + set category = "Object" + set src in view(1) + + if(!istype(usr, /mob/living/carbon/human)) //Only living, intelligent creatures with hands can empty ore boxes. + usr << "\red You are physically incapable of emptying the ore box." + return + + if( usr.stat || usr.restrained() ) + return + + if(!Adjacent(usr)) //You can only empty the box if you can physically reach it + usr << "You cannot reach the ore box." + return + + add_fingerprint(usr) + + if(contents.len < 1) + usr << "\red The ore box is empty" + return + + for (var/obj/item/weapon/ore/O in contents) + contents -= O + O.loc = src.loc + usr << "\blue You empty the ore box" + + return diff --git a/code/game/mecha/micro/security.dm b/code/game/mecha/micro/security.dm new file mode 100644 index 0000000000..e3b43846d2 --- /dev/null +++ b/code/game/mecha/micro/security.dm @@ -0,0 +1,58 @@ +/obj/mecha/micro/sec/moved_inside(var/mob/living/carbon/human/H as mob) + if(..()) + if(H.client) + H.client.mouse_pointer_icon = file("icons/mecha/mecha_mouse.dmi") + return 1 + else + return 0 + +/obj/mecha/micro/sec/go_out() + if(src.occupant && src.occupant.client) + src.occupant.client.mouse_pointer_icon = initial(src.occupant.client.mouse_pointer_icon) + ..() + return + +/obj/mecha/micro/sec/polecat //figured give 'em the names of small predatory critters + desc = "A hardened security vehicle for micro crewmembers. To them, it's a superheavy tank. To everyone else, it's kinda cute." + name = "Polecat" + icon_state = "polecat" + initial_icon = "polecat" + step_in = 2 // human running speed + dir_in = 2 //Facing south. + health = 150 + step_energy_drain = 4 // less efficient than base micromech, but still a micromech. + deflect_chance = 10 + damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1) + max_temperature = 15000 + infra_luminosity = 6 + var/overload = 0 + var/overload_coeff = 2 + wreckage = /obj/effect/decal/mecha_wreckage/micro/sec/polecat + internal_damage_threshold = 35 + max_equip = 3 + +/obj/effect/decal/mecha_wreckage/micro/sec/polecat + name = "Polecat wreckage" + icon_state = "polecat-broken" + +/obj/mecha/micro/sec/weasel + desc = "A light scout exosuit for micro crewmembers, built for fast reconnaisance." + name = "Weasel" + icon_state = "weasel" + initial_icon = "weasel" + step_in = 1 // zoom zoom + dir_in = 2 //Facing south. + health = 100 + deflect_chance = 5 + damage_absorption = list("brute"=1,"fire"=1,"bullet"=0.9,"laser"=0.8,"energy"=0.85,"bomb"=1) + max_temperature = 5000 + infra_luminosity = 6 + var/overload = 0 + var/overload_coeff = 2 + wreckage = /obj/effect/decal/mecha_wreckage/micro/sec/weasel + internal_damage_threshold = 20 + max_equip = 2 + +/obj/effect/decal/mecha_wreckage/micro/sec/weasel + name = "Weasel wreckage" + icon_state = "weasel-broken" diff --git a/code/game/mecha/micro/utility.dm b/code/game/mecha/micro/utility.dm new file mode 100644 index 0000000000..d2bbe7d507 --- /dev/null +++ b/code/game/mecha/micro/utility.dm @@ -0,0 +1,24 @@ + + +/obj/mecha/micro/utility/gopher //small digging creature, to keep the theme + desc = "A tough little utility mech for micro crewmembers, based on a miner borg chassis." + name = "Gopher" + icon_state = "gopher" + initial_icon = "gopher" + step_in = 3 + dir_in = 2 //Facing south. + health = 100 + deflect_chance = 10 + damage_absorption = list("brute"=0.9,"fire"=1,"bullet"=1,"laser"=1,"energy"=1,"bomb"=1) + max_temperature = 15000 + infra_luminosity = 6 + var/overload = 0 + var/overload_coeff = 2 + wreckage = /obj/effect/decal/mecha_wreckage/micro/utility/gopher + internal_damage_threshold = 35 + max_equip = 2 + +/obj/effect/decal/mecha_wreckage/micro/utility/gopher + name = "Gopher wreckage" + icon_state = "gopher-broken" + diff --git a/icons/mecha/mecha_equipment_vr.dmi b/icons/mecha/mecha_equipment_vr.dmi index 52c17968c3..7bb519d706 100644 Binary files a/icons/mecha/mecha_equipment_vr.dmi and b/icons/mecha/mecha_equipment_vr.dmi differ diff --git a/icons/mecha/micro.dmi b/icons/mecha/micro.dmi new file mode 100644 index 0000000000..91984e132a Binary files /dev/null and b/icons/mecha/micro.dmi differ diff --git a/vorestation.dme b/vorestation.dme index f97086d22b..b4887f2124 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -725,6 +725,10 @@ #include "code\game\mecha\equipment\weapons\weapons.dm" #include "code\game\mecha\medical\medical.dm" #include "code\game\mecha\medical\odysseus.dm" +#include "code\game\mecha\micro\micro.dm" +#include "code\game\mecha\micro\micro_equipment.dm" +#include "code\game\mecha\micro\security.dm" +#include "code\game\mecha\micro\utility.dm" #include "code\game\mecha\working\hoverpod.dm" #include "code\game\mecha\working\ripley.dm" #include "code\game\mecha\working\working.dm"