diff --git a/aurora.dme b/aurora.dme index 858cb0a4..d823f29d 100644 --- a/aurora.dme +++ b/aurora.dme @@ -1275,6 +1275,7 @@ #include "code\modules\projectiles\guns\projectile\bow.dm" #include "code\modules\projectiles\guns\projectile\pistol.dm" #include "code\modules\projectiles\guns\projectile\pneumatic.dm" +#include "code\modules\projectiles\guns\projectile\reloadlaser.dm" #include "code\modules\projectiles\guns\projectile\revolver.dm" #include "code\modules\projectiles\guns\projectile\rocket.dm" #include "code\modules\projectiles\guns\projectile\shotgun.dm" @@ -1441,6 +1442,9 @@ #include "code\modules\telesci\gps.dm" #include "code\modules\telesci\telepad.dm" #include "code\modules\telesci\telesci_computer.dm" +#include "code\modules\vehicles\cargo_train.dm" +#include "code\modules\vehicles\train.dm" +#include "code\modules\vehicles\vehicle.dm" #include "code\modules\virus2\analyser.dm" #include "code\modules\virus2\antibodies.dm" #include "code\modules\virus2\centrifuge.dm" diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index f09a659a..6616fda5 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -251,6 +251,22 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "MULEbot Crate" group = "Operations" +/datum/supply_packs/cargotrain + name = "Cargo Train Tug" + contains = list(/obj/vehicle/train/cargo/engine) + cost = 30 + containertype = /obj/structure/largecrate + containername = "Cargo Train Tug Crate" + group = "Operations" + +/datum/supply_packs/cargotrailer + name = "Cargo Train Trolley" + contains = list(/obj/vehicle/train/cargo/trolley) + cost = 20 + containertype = /obj/structure/largecrate + containername = "Cargo Train Trolley Crate" + group = "Operations" + /datum/supply_packs/lisa name = "Corgi Crate" contains = list() diff --git a/code/game/objects/items/devices/suit_cooling.dm b/code/game/objects/items/devices/suit_cooling.dm index 6355fd26..0da99369 100644 --- a/code/game/objects/items/devices/suit_cooling.dm +++ b/code/game/objects/items/devices/suit_cooling.dm @@ -5,57 +5,57 @@ icon = 'icons/obj/device.dmi' icon_state = "suitcooler0" slot_flags = SLOT_BACK //you can carry it on your back if you want, but it won't do anything unless attached to suit storage - + //copied from tank.dm flags = FPRINT | TABLEPASS | CONDUCT force = 5.0 throwforce = 10.0 throw_speed = 1 throw_range = 4 - + origin_tech = "magnets=2;materials=2" - + var/on = 0 //is it turned on? var/cover_open = 0 //is the cover open? var/obj/item/weapon/cell/cell var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here - var/charge_consumption = 16.6 //charge per second at max_cooling + var/charge_consumption = 2 //16.6 //charge per second at max_cooling //16.6 is the original value. It eats batteries too fast. var/thermostat = T20C - + //TODO: make it heat up the surroundings when not in space /obj/item/device/suit_cooling_unit/New() processing_objects |= src - + cell = new/obj/item/weapon/cell() //comes with the crappy default power cell - high-capacity ones shouldn't be hard to find cell.loc = src /obj/item/device/suit_cooling_unit/process() - if (!on || !cell) + if (!on || !cell) return - + if (!ismob(loc)) return - + if (!attached_to_suit(loc)) //make sure they have a suit and we are attached to it return - + var/mob/living/carbon/human/H = loc - + var/efficiency = 1 - H.get_pressure_weakness() //you need to have a good seal for effective cooling var/env_temp = get_environment_temperature() //wont save you from a fire var/temp_adj = min(H.bodytemperature - max(thermostat, env_temp), max_cooling) - + if (temp_adj < 0.5) //only cools, doesn't heat, also we don't need extreme precision return - + var/charge_usage = (temp_adj/max_cooling)*charge_consumption - + H.bodytemperature -= temp_adj*efficiency - + cell.use(charge_usage) - - if(cell.charge <= 0) + + if(cell.charge <= charge_usage) turn_off() /obj/item/device/suit_cooling_unit/proc/get_environment_temperature() @@ -70,22 +70,22 @@ var/turf/T = get_turf(src) if(istype(T, /turf/space)) return 0 //space has no temperature, this just makes sure the cooling unit works in space - + var/datum/gas_mixture/environment = T.return_air() if (!environment) return 0 - + return environment.temperature /obj/item/device/suit_cooling_unit/proc/attached_to_suit(mob/M) - if (!ishuman(M)) + if (!ishuman(M)) return 0 - + var/mob/living/carbon/human/H = M - + if (!H.wear_suit || H.s_store != src) return 0 - + return 1 /obj/item/device/suit_cooling_unit/proc/turn_on() @@ -93,7 +93,7 @@ return if(cell.charge <= 0) return - + on = 1 updateicon() @@ -149,7 +149,7 @@ user << "You insert the [cell]." updateicon() return - + return ..() /obj/item/device/suit_cooling_unit/proc/updateicon() @@ -163,9 +163,9 @@ /obj/item/device/suit_cooling_unit/examine() set src in view(1) - + ..() - + if (on) if (attached_to_suit(src.loc)) usr << "It's switched on and running." @@ -173,13 +173,13 @@ usr << "It's switched on, but not attached to anything." else usr << "It is switched off." - + if (cover_open) if(cell) usr << "The panel is open, exposing the [cell]." else usr << "The panel is open." - + if (cell) usr << "The charge meter reads [round(cell.percent())]%." else diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 931edd3d..71b1629f 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -100,7 +100,8 @@ /obj/machinery/bot, /obj/machinery/door, /obj/machinery/telecomms, - /obj/machinery/mecha_part_fabricator + /obj/machinery/mecha_part_fabricator, + /obj/vehicle ) @@ -200,7 +201,7 @@ access = list(access_maint_tunnels, access_syndicate, access_external_airlocks) origin_tech = "syndicate=3" var/registered_user=null - + /obj/item/weapon/card/id/syndicate/New(mob/user as mob) ..() if(!isnull(user)) // Runtime prevention on laggy starts or where users log out because of lag at round start. @@ -208,7 +209,7 @@ else registered_name = "Agent Card" assignment = "Agent" - name = "[registered_name]'s ID Card ([assignment])" + name = "[registered_name]'s ID Card ([assignment])" /obj/item/weapon/card/id/syndicate/afterattack(var/obj/item/weapon/O as obj, mob/user as mob, proximity) if(!proximity) return @@ -239,7 +240,7 @@ registered_user = user else if(!registered_user || registered_user == user) - if(!registered_user) registered_user = user // + if(!registered_user) registered_user = user // switch(alert("Would you like to display the ID, or retitle it?","Choose.","Rename","Show")) if("Rename") diff --git a/code/modules/aurora/bluespacetech.dm b/code/modules/aurora/bluespacetech.dm index 0de534d1..024a96e5 100644 --- a/code/modules/aurora/bluespacetech.dm +++ b/code/modules/aurora/bluespacetech.dm @@ -256,6 +256,20 @@ var/verb = "says in a subdued tone" ..(message, verb) + verb/bstwalk() + set name = "Ruin Everything" + set desc = "Uses bluespace technology to phase through solid matter and also move fast." + set category = "BST" + set popup_menu = 0 + + if(!src.incorporeal_move) + src.incorporeal_move = 2 + src << "\blue You will now phase through solid matter." + else + src.incorporeal_move = 0 + src << "\blue You will no-longer phase through solid matter." + return + //Equipment. All should have canremove set to 0 //All items with a /bst need the attack_hand() proc overrided to stop people getting overpowered items. diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index b56c078d..3bd9bff6 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -335,7 +335,7 @@ BLIND // can't see anything permeability_coefficient = 0.02 flags = FPRINT | TABLEPASS | STOPSPRESSUREDMAGE | THICKMATERIAL body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit) slowdown = 3 armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 50) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index c729c4a4..32ff5a09 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -22,7 +22,7 @@ allowed = list(/obj/item/weapon/tank/emergency_oxygen, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_magazine, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs) slowdown = 1.5 armor = list(melee = 65, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50) - flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL + flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAIL cold_protection = UPPER_TORSO | LOWER_TORSO | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_COLD_PROTECTION_TEMPERATURE siemens_coefficient = 0.7 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 6d81acee..49f0c755 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -478,10 +478,9 @@ var/obj/machinery/bot/mulebot/MB = AM MB.RunOver(src) -/* if(istype(AM, /obj/vehicle)) + if(istype(AM, /obj/vehicle)) var/obj/vehicle/V = AM V.RunOver(src) -*/ //gets assignment from ID or ID inside PDA or PDA itself //Useful when player do something with computers diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index ca8015e6..3e58626b 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -203,7 +203,8 @@ if(!mob.canmove) - return + if (mob.buckled && (istype(mob.buckled, /obj/structure/stool/bed/chair/wheelchair) || istype(mob.buckled, /obj/vehicle))) // Exception for wheelchairs + else return //if(istype(mob.loc, /turf/space) || (mob.flags & NOGRAV)) // if(!mob.Process_Spacemove(0)) return 0 @@ -257,6 +258,9 @@ if(mob.machine.relaymove(mob,direct)) return + if(istype(mob.buckled, /obj/vehicle)) + return mob.buckled.relaymove(mob,direct) + if(mob.pulledby || mob.buckled) // Wheelchair driving! if(istype(mob.loc, /turf/space)) return // No wheelchair driving in space diff --git a/code/modules/organs/organ_external.dm b/code/modules/organs/organ_external.dm index 66081658..ce0577ef 100644 --- a/code/modules/organs/organ_external.dm +++ b/code/modules/organs/organ_external.dm @@ -816,7 +816,7 @@ Note that amputating the affected organ does in fact remove the infection from t return ((status & ORGAN_BROKEN) && !(status & ORGAN_SPLINTED)) /datum/organ/external/proc/is_malfunctioning() - return ((status & ORGAN_ROBOT) && prob(brute_dam + burn_dam)) + return ((status & ORGAN_ROBOT) && prob(brute_dam + burn_dam - 11)) //for arms and hands /datum/organ/external/proc/process_grasp(var/obj/item/c_hand, var/hand_name) diff --git a/code/modules/projectiles/guns/energy/erifles.dm b/code/modules/projectiles/guns/energy/erifles.dm index 96eadadf..4d12c857 100644 --- a/code/modules/projectiles/guns/energy/erifles.dm +++ b/code/modules/projectiles/guns/energy/erifles.dm @@ -52,7 +52,7 @@ ///////////LASER RIFLE////////////// /obj/item/weapon/gun/energy/rifle/laser name = "laser rifle" - desc = "a basic weapon designed kill with concentrated energy bolts" + desc = "a basic weapon designed to kill with concentrated energy bolts" icon_state = "laser" item_state = "laser" fire_sound = 'sound/weapons/Laser.ogg' diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index a9b5b86c..e912275a 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -1,6 +1,6 @@ /obj/item/weapon/gun/energy/laser name = "laser rifle" - desc = "a basic weapon designed kill with concentrated energy bolts" + desc = "a basic weapon designed to kill with concentrated energy bolts" icon_state = "laser" item_state = "laser" fire_sound = 'sound/weapons/Laser.ogg' diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 2ce69211..7172382e 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -38,12 +38,14 @@ loaded -= AC //Remove casing from loaded list. if(isnull(AC) || !istype(AC)) return 0 - AC.loc = get_turf(src) //Eject casing onto ground. + if(ejectshell == 1) + AC.loc = get_turf(src) //Eject casing onto ground. If 0, casings stay in the gun. Totally a good idea trust me okay. if(AC.BB) AC.desc += " This one is spent." //descriptions are magic - only when there's a projectile in the casing in_chamber = AC.BB //Load projectile into chamber. AC.BB.loc = src //Set projectile loc to gun. return 1 + return 0 diff --git a/code/modules/projectiles/guns/projectile/reloadlaser.dm b/code/modules/projectiles/guns/projectile/reloadlaser.dm new file mode 100644 index 00000000..39da20cd --- /dev/null +++ b/code/modules/projectiles/guns/projectile/reloadlaser.dm @@ -0,0 +1,179 @@ +/obj/item/weapon/gun/projectile/laser //butts + desc = "a basic weapon designed to kill with concentrated energy bolts." + name = "laser rifle" + caliber = "laser" + w_class = 3.0 + recoil = 0 + ammo_type = "/obj/item/ammo_casing/laser" + max_shells = 100 + load_method = 2 //0 = Single shells or quick loader, 1 = box, 2 = magazine + fire_delay = 6 + ejectshell = 0 + slot_flags = SLOT_BACK + var/modded = 0 + var/obj/item/weapon/reloadlasermodkit/mod + + //placeholders// + icon_state = "laser" + item_state = "laser" + fire_sound = 'sound/weapons/Laser.ogg' + //placeholders// Well, okay, not the sound. + + New() + for(var/i = 1, i <= 30, i++) + loaded += new ammo_type(src) + update_icon() + + empty_mag = new /obj/item/ammo_magazine/laser/empty(src) + update_icon() + return + + + + +/obj/item/ammo_magazine/laser/empty + max_ammo = 0 + +/obj/item/ammo_magazine/laser + name = "charge cell (laser)" + desc = "A standard 30-shot cell." + icon_state = "12mm" + origin_tech = "combat=2" + ammo_type = "/obj/item/ammo_casing/laser" + max_ammo = 30 +// multiple_sprites = 1 + +/obj/item/ammo_magazine/laser/pulse + name = "charge cell (pulse)" + desc = "A heavy-duty 15-shot pulse cell." + ammo_type = "/obj/item/ammo_casing/laser/pulse" + max_ammo = 15 + +/obj/item/ammo_magazine/laser/heavy + name = "charge cell (heavy)" + desc = "A 15-shot cell designed to overload your projectiles with an extremely heavy charge." + ammo_type = "/obj/item/ammo_casing/laser/heavy" + max_ammo = 15 + +/obj/item/ammo_magazine/laser/practice + name = "charge cell (practice)" + desc = "A hundred-shot cell keyed in to a harmless wavelength for practice shooting." + ammo_type = "/obj/item/ammo_casing/laser/practice" + max_ammo = 100 + +/obj/item/ammo_magazine/laser/light + name = "charge cell (light)" + desc = "A 60-shot cell designed with capacity in mind. The lasers are weaker, though." + ammo_type = "/obj/item/ammo_casing/laser/light" + max_ammo = 60 + +/obj/item/ammo_magazine/laser/stun + name = "charge cell (stun)" + desc = "A 20-shot cell that fires lethal incapacitating bolts. Not standard issue." + ammo_type = "/obj/item/ammo_casing/laser/stun" + max_ammo = 20 + +//////////////////////////// +//Shells for the magazines// +//////////////////////////// + +//don't spawn these you butts// + +/obj/item/ammo_casing/laser + desc = "A LASER SHELL. You shouldn't be seeing this." + caliber = "laser" + projectile_type = "/obj/item/projectile/beam" + +/obj/item/ammo_casing/laser/pulse + desc = "A PULSE SHELL. You shouldn't be seeing this." + caliber = "laser" + projectile_type = "/obj/item/projectile/beam/pulse" + +/obj/item/ammo_casing/laser/heavy + desc = "A LASER CANNON SHELL. You shouldn't be seeing this." + caliber = "laser" + projectile_type = "/obj/item/projectile/beam/heavylaser" + +/obj/item/ammo_casing/laser/practice + desc = "A PRACTICE BLANK FAKE LASER SHELL. You shouldn't be seeing this." + caliber = "laser" + projectile_type = "/obj/item/projectile/beam/practice" + +/obj/item/ammo_casing/laser/light + desc = "A LIGHT LASER XRAY SHELL. You shouldn't be seeing this." + caliber = "laser" + projectile_type = "/obj/item/projectile/beam/xray/burst" + +/obj/item/ammo_casing/laser/stun + desc = "A STUN LASER SHELL. You shouldn't be seeing this." + caliber = "laser" + projectile_type = "/obj/item/projectile/beam/stun" + + +//////////////////////////////// +//////////////mods////////////// +//////////////////////////////// + +/obj/item/weapon/reloadlasermodkit + desc = "A cheap, disposable modkit designed to rapidly and permanently augment NT-standard laser rifles." + name = "rifle nanokit" + var/modtype = 0 + var/uses = 1 + var/emagged + icon = 'icons/obj/assemblies.dmi' + icon_state = "posibrain" //the placeholders are real + +/* Not sure about this yet. +/obj/item/device/megaphone/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/card/emag) && !emagged) + user << "\red You sneakily unlock the highly illegal military-grade burstfire augment." + emagged = 1 + return + return +*/ +/obj/item/weapon/reloadlasermodkit/attack_self(var/mob/user as mob) + + if (!emagged) + if (modtype == 0) + user << "Size modification selected." + modtype = 1 + else if (modtype == 1) + user << "Rapid-fire modification selected." + modtype = 2 + else if (modtype == 2) + user << "Silencer modification selected." + modtype = 0 + else if (emagged) //We'll see. Burst is ridiculous, especially on a full-power laser. + user << "Burstfire modification selected." + modtype = 3 + +/obj/item/weapon/gun/projectile/laser/attackby(obj/item/I as obj, mob/user as mob) + if(istype(I, /obj/item/weapon/reloadlasermodkit)) + if(user.l_hand != src && user.r_hand != src) //if we're not in his hands + user << "You'll need [src] in your hands to do that." + return + if(src.modded == 1) + user << "The frame can only handle one mod." + return + user.drop_item() + user << "You activate the modkit and watch the nanites swarm over [src]." + I.loc = src.mod + src.mod = I + src.modded = 1 + if (mod.modtype == 0) + user << "[src]'s firerate has been increased." + src.fire_delay = 4 + else if (mod.modtype == 1) + user << "[src]'s shape changes rapidly, becoming smaller and more economical." + src.w_class = 3 + else if (mod.modtype == 2) + user << "[src] sprouts wave-cancelling emitters. Its shots are now silenced." + src.silenced = 1 + else if (mod.modtype == 3) + user << "[src] rapidly reshapes its firing mechanism. It now fires in bursts." + src.fire_delay = 0 + src.projectiles_per_shot = 3 + src.fire_cooldown = 1 + fire_sound = 'sound/weapons/Gunshot_smg.ogg' + return + ..() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index e57d13e6..439bce57 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -87,7 +87,7 @@ return 0// nope.avi var/distance = get_dist(starting,loc) - var/miss_modifier = -30 + var/miss_modifier = -60 if (istype(shot_from,/obj/item/weapon/gun)) //If you aim at someone beforehead, it'll hit more often. var/obj/item/weapon/gun/daddy = shot_from //Kinda balanced by fact you need like 2 seconds to aim diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 236517f3..063cbc7b 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -99,12 +99,13 @@ var/list/beam_master = list() name = "xray beam" icon_state = "xray" damage = 30 +// forcedodge = -1 /obj/item/projectile/beam/xray/burst name = "xray beam" icon_state = "xray" // damage = 15 this makes rapidlasers kill almost exactly as fast as the rifle, but since they do a tripleburst, armor is much more effective. plus. rng miss. - damage = 20 //hence 20 damage. slight advantage over regular lasers. half-capacity for damage. use for coolness. use laser cannons for powergame. + damage = 25 //hence 25 damage. slight advantage over regular lasers. half-capacity for damage. use for coolness. use laser cannons for powergame. /obj/item/projectile/beam/pulse name = "pulse" @@ -122,10 +123,10 @@ var/list/beam_master = list() icon_state = "emitter" damage = 30 -/obj/item/projectile/beam/stunrevolver +/obj/item/projectile/beam/stun name = "stun beam" icon_state = "stun" - damage = 10 + damage = 20 agony = 45 /obj/item/projectile/beam/lastertag/blue diff --git a/code/modules/projectiles/projectile/energy.dm b/code/modules/projectiles/projectile/energy.dm index a9175887..d30d0217 100644 --- a/code/modules/projectiles/projectile/energy.dm +++ b/code/modules/projectiles/projectile/energy.dm @@ -88,3 +88,30 @@ */ agony = 70 damage_type = HALLOSS + + +/obj/item/projectile/energy/mining //not in the game. i'll play with it later probably. + name = "electrode" + icon_state = "spark" + damage = 5 + kill_count = 3 + var/life = 5 + + Bump(atom/A) + A.bullet_act(src, def_zone) + src.life -= 1 + if(life <= 0) + del(src) + return + +/turf/simulated/mineral/bullet_act(var/obj/item/projectile/Proj) + if(istype(Proj ,/obj/item/projectile/energy/mining)) + src.GetDrilled() + ..() + return 0 + +/obj/structure/boulder/bullet_act(var/obj/item/projectile/Proj) + if(istype(Proj ,/obj/item/projectile/energy/mining)) + del(src) + ..() + return 0 \ No newline at end of file diff --git a/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm b/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm index 05e6d02d..48ac8785 100644 --- a/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm +++ b/code/modules/research/xenoarchaeology/tools/anomaly_suit.dm @@ -20,7 +20,7 @@ icon_state = "cespace_suit" item_state = "cespace_suit" armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 100, rad = 100) - allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank) + allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank, /obj/item/device/suit_cooling_unit) /obj/item/clothing/head/helmet/space/anomaly name = "Excavation hood" diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm new file mode 100644 index 00000000..cc416aa3 --- /dev/null +++ b/code/modules/vehicles/cargo_train.dm @@ -0,0 +1,303 @@ +/obj/vehicle/train/cargo/engine + name = "cargo train tug" + desc = "A ridable electric car designed for pulling cargo trolleys." + icon = 'icons/obj/vehicles.dmi' + icon_state = "cargo_engine" + on = 0 + powered = 1 + locked = 0 + + load_item_visible = 1 + load_offset_x = 0 + mob_offset_y = 7 + + var/car_limit = 3 //how many cars an engine can pull before performance degrades + active_engines = 1 + var/obj/item/weapon/key/cargo_train/key + +/obj/item/weapon/key/cargo_train + name = "key" + desc = "A keyring with a small steel key, and a yellow fob reading \"Choo Choo!\"." + icon = 'icons/obj/vehicles.dmi' + icon_state = "train_keys" + w_class = 1 + +/obj/vehicle/train/cargo/trolley + name = "cargo train trolley" + icon = 'icons/obj/vehicles.dmi' + icon_state = "cargo_trailer" + anchored = 0 + passenger_allowed = 0 + locked = 0 + + load_item_visible = 1 + load_offset_x = 0 + load_offset_y = 4 + mob_offset_y = 8 + +//------------------------------------------- +// Standard procs +//------------------------------------------- +/obj/vehicle/train/cargo/engine/New() + ..() + cell = new /obj/item/weapon/cell/high + verbs -= /atom/movable/verb/pull + key = new() + var/image/I = new(icon = 'icons/obj/vehicles.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs + overlays += I + turn_off() //so engine verbs are correctly set + +/obj/vehicle/train/cargo/engine/Move() + if(on && cell.charge < charge_use) + turn_off() + update_stats() + if(load && is_train_head()) + load << "The drive motor briefly whines, then drones to a stop." + + if(is_train_head() && !on) + return 0 + + return ..() + +/obj/vehicle/train/cargo/trolley/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(open && istype(W, /obj/item/weapon/wirecutters)) + passenger_allowed = !passenger_allowed + user.visible_message("[user] [passenger_allowed ? "cuts" : "mends"] a cable in [src].","You [passenger_allowed ? "cut" : "mend"] the load limiter cable.") + else + ..() + +/obj/vehicle/train/cargo/engine/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/key/cargo_train)) + if(!key) + user.drop_item() + W.forceMove(src) + key = W + verbs += /obj/vehicle/train/cargo/engine/verb/remove_key + return + ..() + +/obj/vehicle/train/cargo/update_icon() + if(open) + icon_state = initial(icon_state) + "_open" + else + icon_state = initial(icon_state) + +/obj/vehicle/train/cargo/trolley/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + return + +/obj/vehicle/train/cargo/engine/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + ..() + update_stats() + +/obj/vehicle/train/cargo/engine/remove_cell(var/mob/living/carbon/human/H) + ..() + update_stats() + +/obj/vehicle/train/cargo/engine/Bump(atom/Obstacle) + var/obj/machinery/door/D = Obstacle + var/mob/living/carbon/human/H = load + if(istype(D) && istype(H)) + D.Bumped(H) //a little hacky, but hey, it works, and respects access rights + + ..() + +/obj/vehicle/train/cargo/trolley/Bump(atom/Obstacle) + if(!lead) + return //so people can't knock others over by pushing a trolley around + ..() + +//------------------------------------------- +// Train procs +//------------------------------------------- +/obj/vehicle/train/cargo/engine/turn_on() + if(!key) + return + else + ..() + update_stats() + + verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine + verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine + + if(on) + verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine + else + verbs += /obj/vehicle/train/cargo/engine/verb/start_engine + +/obj/vehicle/train/cargo/engine/turn_off() + ..() + + verbs -= /obj/vehicle/train/cargo/engine/verb/stop_engine + verbs -= /obj/vehicle/train/cargo/engine/verb/start_engine + + if(!on) + verbs += /obj/vehicle/train/cargo/engine/verb/start_engine + else + verbs += /obj/vehicle/train/cargo/engine/verb/stop_engine + +/obj/vehicle/train/cargo/RunOver(var/mob/living/carbon/human/H) + var/list/parts = list("head", "chest", "l_leg", "r_leg", "l_arm", "r_arm") + + H.apply_effects(5, 5) + for(var/i = 0, i < rand(1,3), i++) + H.apply_damage(rand(1,5), BRUTE, pick(parts)) + +/obj/vehicle/train/cargo/trolley/RunOver(var/mob/living/carbon/human/H) + ..() + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + +/obj/vehicle/train/cargo/engine/RunOver(var/mob/living/carbon/human/H) + ..() + + if(is_train_head() && istype(load, /mob/living/carbon/human)) + var/mob/living/carbon/human/D = load + D << "\red \b You ran over [H]!" + visible_message("\red \The [src] ran over [H]!") + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey]), driven by [D.name] ([D.ckey])") + msg_admin_attack("[D.name] ([D.ckey]) ran over [H.name] ([H.ckey]). (JMP)") + else + attack_log += text("\[[time_stamp()]\] ran over [H.name] ([H.ckey])") + + +//------------------------------------------- +// Interaction procs +//------------------------------------------- +/obj/vehicle/train/cargo/engine/relaymove(mob/user, direction) + if(user != load) + return 0 + + if(is_train_head()) + if(direction == reverse_direction(dir) && tow) + return 0 + if(Move(get_step(src, direction))) + return 1 + return 0 + else + return ..() + +/obj/vehicle/train/cargo/engine/examine() + ..() + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(get_dist(usr,src) <= 1) + usr << "The power light is [on ? "on" : "off"].\nThere are[key ? "" : " no"] keys in the ignition." + usr << "The charge meter reads [cell? round(cell.percent(), 0.01) : 0]%" + +/obj/vehicle/train/cargo/engine/verb/start_engine() + set name = "Start engine" + set category = "Object" + set src in view(1) + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(on) + usr << "The engine is already running." + return + + turn_on() + if (on) + usr << "You start [src]'s engine." + else + if(cell.charge < charge_use) + usr << "[src] is out of power." + else + usr << "[src]'s engine won't start." + +/obj/vehicle/train/cargo/engine/verb/stop_engine() + set name = "Stop engine" + set category = "Object" + set src in view(1) + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(!on) + usr << "The engine is already stopped." + return + + turn_off() + if (!on) + usr << "You stop [src]'s engine." + +/obj/vehicle/train/cargo/engine/verb/remove_key() + set name = "Remove key" + set category = "Object" + set src in view(1) + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(!key || (load && load != usr)) + return + + if(on) + turn_off() + + key.loc = usr.loc + if(!usr.get_active_hand()) + usr.put_in_hands(key) + key = null + + verbs -= /obj/vehicle/train/cargo/engine/verb/remove_key + +//------------------------------------------- +// Loading/unloading procs +//------------------------------------------- +/obj/vehicle/train/cargo/trolley/load(var/atom/movable/C) + if(ismob(C) && !passenger_allowed) + return 0 + if(!istype(C,/obj/machinery) && !istype(C,/obj/structure/closet) && !istype(C,/obj/structure/largecrate) && !istype(C,/obj/structure/reagent_dispensers) && !istype(C,/obj/structure/ore_box) && !istype(C, /mob/living/carbon/human)) + return 0 + + ..() + + if(load) + return 1 + +/obj/vehicle/train/cargo/engine/load(var/atom/movable/C) + if(!istype(C, /mob/living/carbon/human)) + return 0 + + return ..() + + +//------------------------------------------------------- +// Stat update procs +// +// Update the trains stats for speed calculations. +// The longer the train, the slower it will go. car_limit +// sets the max number of cars one engine can pull at +// full speed. Adding more cars beyond this will slow the +// train proportionate to the length of the train. Adding +// more engines increases this limit by car_limit per +// engine. +//------------------------------------------------------- +/obj/vehicle/train/cargo/engine/update_car(var/train_length, var/active_engines) + src.train_length = train_length + src.active_engines = active_engines + + //Update move delay + if(!is_train_head() || !on) + move_delay = initial(move_delay) //so that engines that have been turned off don't lag behind + else + move_delay = max(0, (-car_limit * active_engines) + train_length - active_engines) //limits base overweight so you cant overspeed trains + move_delay *= (1 / max(1, active_engines)) * 2 //overweight penalty (scaled by the number of engines) + move_delay += config.run_speed //base reference speed + move_delay *= 1.1 //makes cargo trains 10% slower than running when not overweight + +/obj/vehicle/train/cargo/trolley/update_car(var/train_length, var/active_engines) + src.train_length = train_length + src.active_engines = active_engines + + if(!lead && !tow) + anchored = 0 + if(verbs.Find(/atom/movable/verb/pull)) + return + else + verbs += /atom/movable/verb/pull + else + anchored = 1 + verbs -= /atom/movable/verb/pull diff --git a/code/modules/vehicles/train.dm b/code/modules/vehicles/train.dm new file mode 100644 index 00000000..c5ca6329 --- /dev/null +++ b/code/modules/vehicles/train.dm @@ -0,0 +1,229 @@ +/obj/vehicle/train + name = "train" + dir = 4 + + move_delay = 1 + + health = 100 + maxhealth = 100 + fire_dam_coeff = 0.7 + brute_dam_coeff = 0.5 + + var/passenger_allowed = 1 + + var/active_engines = 0 + var/train_length = 0 + + var/obj/vehicle/train/lead + var/obj/vehicle/train/tow + + +//------------------------------------------- +// Standard procs +//------------------------------------------- +/obj/vehicle/train/initialize() + for(var/obj/vehicle/train/T in orange(1, src)) + latch(T) + +/obj/vehicle/train/Move() + var/old_loc = get_turf(src) + if(..()) + if(tow) + tow.Move(old_loc) + return 1 + else + if(lead) + unattach() + return 0 + +/obj/vehicle/train/Bump(atom/Obstacle) + if(!istype(Obstacle, /atom/movable)) + return + var/atom/movable/A = Obstacle + + if(!A.anchored) + var/turf/T = get_step(A, dir) + if(isturf(T)) + A.Move(T) //bump things away when hit + + if(emagged) + if(istype(A, /mob/living)) + var/mob/living/M = A + visible_message("\red [src] knocks over [M]!") + M.apply_effects(5, 5) //knock people down if you hit them + M.apply_damages(22 / move_delay) // and do damage according to how fast the train is going + if(istype(load, /mob/living/carbon/human)) + var/mob/living/D = load + D << "\red You hit [M]!" + msg_admin_attack("[D.name] ([D.ckey]) hit [M.name] ([M.ckey]) with [src]. (JMP)") + + +//------------------------------------------- +// Vehicle procs +//------------------------------------------- +/obj/vehicle/train/explode() + if (tow) + tow.unattach() + unattach() + ..() + + +//------------------------------------------- +// Interaction procs +//------------------------------------------- +/obj/vehicle/train/relaymove(mob/user, direction) + var/turf/T = get_step_to(src, get_step(src, direction)) + if(!T) + user << "You can't find a clear area to step onto." + return 0 + + if(user != load) + if(user in src) //for handling players stuck in src - this shouldn't happen - but just in case it does + user.forceMove(T) + return 1 + return 0 + + unload(user, direction) + + user << "\blue You climb down from [src]." + + return 1 + +/obj/vehicle/train/MouseDrop_T(var/atom/movable/C, mob/user as mob) + if(user.buckled || user.stat || user.restrained() || !Adjacent(user) || !user.Adjacent(C) || !istype(C) || (user == C && !user.canmove)) + return + if(istype(C,/obj/vehicle/train)) + latch(C, user) + else + if(!load(C)) + user << "\red You were unable to load [C] on [src]." + +/obj/vehicle/train/attack_hand(mob/user as mob) + if(user.stat || user.restrained() || !Adjacent(user)) + return 0 + + if(user != load && (user in src)) + user.forceMove(loc) //for handling players stuck in src + else if(load) + unload(user) //unload if loaded + else if(!load && !user.buckled) + load(user) //else try climbing on board + else + return 0 + +/obj/vehicle/train/verb/unlatch_v() + set name = "Unlatch" + set desc = "Unhitches this train from the one in front of it." + set category = "Object" + set src in view(1) + + if(!istype(usr, /mob/living/carbon/human)) + return + + if(!usr.canmove || usr.stat || usr.restrained() || !Adjacent(usr)) + return + + unattach(usr) + + +//------------------------------------------- +// Latching/unlatching procs +//------------------------------------------- + +//attempts to attach src as a follower of the train T +/obj/vehicle/train/proc/attach_to(obj/vehicle/train/T, mob/user) + if (get_dist(src, T) > 1) + user << "\red [src] is too far away from [T] to hitch them together." + return + + if (lead) + user << "\red [src] is already hitched to something." + return + + if (T.tow) + user << "\red [T] is already towing something." + return + + //check for cycles. + var/obj/vehicle/train/next_car = T + while (next_car) + if (next_car == src) + user << "\red That seems very silly." + return + next_car = next_car.lead + + //latch with src as the follower + lead = T + T.tow = src + dir = lead.dir + + if(user) + user << "\blue You hitch [src] to [T]." + + update_stats() + + +//detaches the train from whatever is towing it +/obj/vehicle/train/proc/unattach(mob/user) + if (!lead) + user << "\red [src] is not hitched to anything." + return + + lead.tow = null + lead.update_stats() + + user << "\blue You unhitch [src] from [lead]." + lead = null + + update_stats() + +/obj/vehicle/train/proc/latch(obj/vehicle/train/T, mob/user) + if(!istype(T) || !Adjacent(T)) + return 0 + + var/T_dir = get_dir(src, T) //figure out where T is wrt src + + if(dir == T_dir) //if car is ahead + src.attach_to(T, user) + else if(reverse_direction(dir) == T_dir) //else if car is behind + T.attach_to(src, user) + +//returns 1 if this is the lead car of the train +/obj/vehicle/train/proc/is_train_head() + if (lead) + return 0 + return 1 + +//------------------------------------------------------- +// Stat update procs +// +// Used for updating the stats for how long the train is. +// These are useful for calculating speed based on the +// size of the train, to limit super long trains. +//------------------------------------------------------- +/obj/vehicle/train/update_stats() + //first, seek to the end of the train + var/obj/vehicle/train/T = src + while(T.tow) + //check for cyclic train. + if (T.tow == src) + lead.tow = null + lead.update_stats() + + lead = null + update_stats() + return + T = T.tow + + //now walk back to the front. + var/active_engines = 0 + var/train_length = 0 + while(T) + train_length++ + if (powered && on) + active_engines++ + T.update_car(train_length, active_engines) + T = T.lead + +/obj/vehicle/train/proc/update_car(var/train_length, var/active_engines) + return diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm new file mode 100644 index 00000000..76fd7d89 --- /dev/null +++ b/code/modules/vehicles/vehicle.dm @@ -0,0 +1,358 @@ +/obj/vehicle + name = "vehicle" + icon = 'icons/obj/vehicles.dmi' + layer = MOB_LAYER + 0.1 //so it sits above objects including mobs + density = 1 + anchored = 1 + animate_movement=1 + luminosity = 3 + + var/attack_log = null + var/on = 0 + var/health = 0 //do not forget to set health for your vehicle! + var/maxhealth = 0 + var/fire_dam_coeff = 1.0 + var/brute_dam_coeff = 1.0 + var/open = 0 //Maint panel + var/locked = 1 + var/stat = 0 + var/emagged = 0 + var/powered = 0 //set if vehicle is powered and should use fuel when moving + var/move_delay = 1 //set this to limit the speed of the vehicle + var/movable = 1 + + var/obj/item/weapon/cell/cell + var/charge_use = 5 //set this to adjust the amount of power the vehicle uses per move + + var/atom/movable/load //all vehicles can take a load, since they should all be a least drivable + var/load_item_visible = 1 //set if the loaded item should be overlayed on the vehicle sprite + var/load_offset_x = 0 //pixel_x offset for item overlay + var/load_offset_y = 0 //pixel_y offset for item overlay + var/mob_offset_y = 0 //pixel_y offset for mob overlay + +//------------------------------------------- +// Standard procs +//------------------------------------------- +/obj/vehicle/New() + ..() + //spawn the cell you want in each vehicle + +/obj/vehicle/Move() + if(world.time > l_move_time + move_delay) + if(on && powered && cell.charge < charge_use) + turn_off() + + var/init_anc = anchored + anchored = 0 + if(!..()) + anchored = init_anc + return 0 + + anchored = init_anc + + if(on && powered) + cell.use(charge_use) + + if(load) + load.forceMove(loc)// = loc + load.dir = dir + + return 1 + else + return 0 + +/obj/vehicle/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/hand_labeler)) + return + if(istype(W, /obj/item/weapon/screwdriver)) + if(!locked) + open = !open + update_icon() + user << "Maintenance panel is now [open ? "opened" : "closed"]." + else if(istype(W, /obj/item/weapon/crowbar) && cell && open) + remove_cell(user) + + else if(istype(W, /obj/item/weapon/cell) && !cell && open) + insert_cell(W, user) + else if(istype(W, /obj/item/weapon/weldingtool)) + var/obj/item/weapon/weldingtool/T = W + if(T.welding) + if(health < maxhealth) + if(open) + health = min(maxhealth, health+10) + user.visible_message("\red [user] repairs [src]!","\blue You repair [src]!") + else + user << "Unable to repair with the maintenance panel closed." + else + user << "[src] does not need a repair." + else + user << "Unable to repair while [src] is off." + else if(istype(W, /obj/item/weapon/card/emag) && !emagged) + Emag(user) + else if(hasvar(W,"force") && hasvar(W,"damtype")) + switch(W.damtype) + if("fire") + health -= W.force * fire_dam_coeff + if("brute") + health -= W.force * brute_dam_coeff + ..() + healthcheck() + else + ..() + +/obj/vehicle/attack_animal(var/mob/living/simple_animal/M as mob) + if(M.melee_damage_upper == 0) return + health -= M.melee_damage_upper + src.visible_message("\red [M] has [M.attacktext] [src]!") + M.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + if(prob(10)) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + healthcheck() + +/obj/vehicle/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + healthcheck() + +/obj/vehicle/meteorhit() + explode() + return + +/obj/vehicle/blob_act() + src.health -= rand(20,40)*fire_dam_coeff + healthcheck() + return + +/obj/vehicle/ex_act(severity) + switch(severity) + if(1.0) + explode() + return + if(2.0) + health -= rand(5,10)*fire_dam_coeff + health -= rand(10,20)*brute_dam_coeff + healthcheck() + return + if(3.0) + if (prob(50)) + health -= rand(1,5)*fire_dam_coeff + health -= rand(1,5)*brute_dam_coeff + healthcheck() + return + return + +/obj/vehicle/emp_act(severity) + var/was_on = on + stat |= EMPED + var/obj/effect/overlay/pulse2 = new/obj/effect/overlay ( src.loc ) + pulse2.icon = 'icons/effects/effects.dmi' + pulse2.icon_state = "empdisable" + pulse2.name = "emp sparks" + pulse2.anchored = 1 + pulse2.dir = pick(cardinal) + + spawn(10) + pulse2.delete() + if(on) + turn_off() + spawn(severity*300) + stat &= ~EMPED + if(was_on) + turn_on() + +/obj/vehicle/attack_ai(mob/user as mob) + return + +/obj/vehicle/proc/handle_rotation() + return + +//------------------------------------------- +// Vehicle procs +//------------------------------------------- +/obj/vehicle/proc/turn_on() + if(stat) + return 0 + if(powered && cell.charge < charge_use) + return 0 + on = 1 + luminosity = initial(luminosity) + update_icon() + return 1 + +/obj/vehicle/proc/turn_off() + on = 0 + luminosity = 0 + update_icon() + +/obj/vehicle/proc/Emag(mob/user as mob) + emagged = 1 + + if(locked) + locked = 0 + user << "You bypass [src]'s controls." + +/obj/vehicle/proc/explode() + src.visible_message("\red [src] blows apart!", 1) + var/turf/Tsec = get_turf(src) + + new /obj/item/stack/rods(Tsec) + new /obj/item/stack/rods(Tsec) +// new /obj/item/stack/cable_coil/cut(Tsec) THIS DOESN'T WORK SO I'M GETTING RID OF IT. + + if(cell) + cell.forceMove(Tsec) + cell.update_icon() + cell = null + + //stuns people who are thrown off a train that has been blown up + if(istype(load, /mob/living)) + var/mob/living/M = load + M.apply_effects(5, 5) + + unload() + + new /obj/effect/gibspawner/robot(Tsec) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + + del(src) + +/obj/vehicle/proc/healthcheck() + if(health <= 0) + explode() + +/obj/vehicle/proc/powercheck() + if(!cell && !powered) + return + + if(!cell && powered) + turn_off() + return + + if(cell.charge < charge_use) + turn_off() + return + + if(cell && powered) + turn_on() + return + +/obj/vehicle/proc/insert_cell(var/obj/item/weapon/cell/C, var/mob/living/carbon/human/H) + if(cell) + return + if(!istype(C)) + return + + H.drop_from_inventory(C) + C.forceMove(src) + cell = C + powercheck() + usr << "You install [C] in [src]." + +/obj/vehicle/proc/remove_cell(var/mob/living/carbon/human/H) + if(!cell) + return + + usr << "You remove [cell] from [src]." + cell.forceMove(get_turf(H)) + H.put_in_hands(cell) + cell = null + powercheck() + +/obj/vehicle/proc/RunOver(var/mob/living/carbon/human/H) + return //write specifics for different vehicles + +//------------------------------------------- +// Loading/unloading procs +// +// Set specific item restriction checks in +// the vehicle load() definition before +// calling this parent proc. +//------------------------------------------- +/obj/vehicle/proc/load(var/atom/movable/C) + //define allowed items for loading in specific vehicle definitions + + if(!isturf(C.loc)) //To prevent loading things from someone's inventory, which wouldn't get handled properly. + return 0 + if(load || C.anchored) + return 0 + + // if a create/closet, close before loading + var/obj/structure/closet/crate = C + if(istype(crate)) + crate.close() + + C.forceMove(loc) + C.dir = dir + C.anchored = 1 + + load = C + + if(load_item_visible) + C.pixel_x += load_offset_x + if(ismob(C)) + C.pixel_y += mob_offset_y + else + C.pixel_y += load_offset_y + C.layer = layer + 0.1 //so it sits above the vehicle + + if(ismob(C)) + var/mob/M = C + M.buckled = src + M.update_canmove() + + return 1 + + +/obj/vehicle/proc/unload(var/mob/user, var/direction) + if(!load) + return + + var/turf/dest = null + + //find a turf to unload to + if(direction) //if direction specified, unload in that direction + dest = get_step(src, direction) + else if(user) //if a user has unloaded the vehicle, unload at their feet + dest = get_turf(user) + + if(!dest) + dest = get_step_to(src, get_step(src, turn(dir, 90))) //try unloading to the side of the vehicle first if neither of the above are present + + //if these all result in the same turf as the vehicle or nullspace, pick a new turf with open space + if(!dest || dest == get_turf(src)) + var/list/options = new() + for(var/test_dir in alldirs) + var/new_dir = get_step_to(src, get_step(src, test_dir)) + if(new_dir && load.Adjacent(new_dir)) + options += new_dir + if(options.len) + dest = pick(options) + else + dest = get_turf(src) //otherwise just dump it on the same turf as the vehicle + + if(!isturf(dest)) //if there still is nowhere to unload, cancel out since the vehicle is probably in nullspace + return 0 + + load.forceMove(dest) + load.dir = get_dir(loc, dest) + load.anchored = initial(load.anchored) + load.pixel_x = initial(load.pixel_x) + load.pixel_y = initial(load.pixel_y) + load.layer = initial(load.layer) + + if(ismob(load)) + var/mob/M = load + M.buckled = null + M.anchored = initial(M.anchored) + M.update_canmove() + + load = null + + return 1 + + +//------------------------------------------------------- +// Stat update procs +//------------------------------------------------------- +/obj/vehicle/proc/update_stats() + return \ No newline at end of file diff --git a/data/investigate/gravity.html b/data/investigate/gravity.html index 4864ca62..df50bfda 100644 --- a/data/investigate/gravity.html +++ b/data/investigate/gravity.html @@ -1,2 +1,6 @@ -00:14 [0x20077d3] (92,152,1) || the gravitational generator has regained power.
-00:14 [0x20077d3] (92,152,1) || the gravitational generator is now charging.
+00:42 [0x20078ca] (92,152,1) || the gravitational generator has regained power.
+00:42 [0x20078ca] (92,152,1) || the gravitational generator is now charging.
+00:43 [0x20078ca] (92,152,1) || the gravitational generator has regained power.
+00:43 [0x20078ca] (92,152,1) || the gravitational generator is now charging.
+00:43 [0x20078ca] (92,152,1) || the gravitational generator has regained power.
+00:43 [0x20078ca] (92,152,1) || the gravitational generator is now charging.
diff --git a/icons/obj/vehicles.dmi b/icons/obj/vehicles.dmi index fd6daee8..e7027559 100644 Binary files a/icons/obj/vehicles.dmi and b/icons/obj/vehicles.dmi differ