/obj/item/pneumatic_cannon name = "pneumatic cannon" desc = "A gas-powered cannon that can fire any object loaded into it." w_class = WEIGHT_CLASS_BULKY force = 8 //Very heavy attack_verb = list("bludgeoned", "smashed", "beaten") icon = 'icons/obj/pneumaticCannon.dmi' icon_state = "pneumaticCannon" item_state = "bulldog" lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi' righthand_file = 'icons/mob/inhands/guns_righthand.dmi' armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 60, ACID = 50) ///The max weight of items that can fit into the cannon var/max_weight_class = 20 ///The weight of items currently in the cannon var/loaded_weight_class = 0 ///The gas tank that is drawn from to fire things var/obj/item/tank/internals/tank = null ///If the cannon needs a tank at all var/requires_tank = TRUE ///How many moles of gas is drawn from a tank's pressure to fire var/gas_per_throw = 3 ///The items loaded into the cannon that will be fired out var/list/loaded_items = list() ///How powerful the cannon is - higher pressure = more gas but more powerful throws var/pressure_setting = 1 ///In case we want a really strong cannon var/max_pressure_setting = 3 /obj/item/pneumatic_cannon/Destroy() QDEL_NULL(tank) QDEL_LIST_CONTENTS(loaded_items) return ..() /obj/item/pneumatic_cannon/examine(mob/user) . = ..() if(!in_range(user, src)) . += "You'll need to get closer to see any more." else if(tank) . += "[bicon(tank)] It has [tank] mounted onto it." for(var/obj/item/I in loaded_items) . += "[bicon(I)] It has [I] loaded." /** * Arguments: * * I - item to load into the cannon * * user - the person loading the item in * Returns: * * True if item was loaded, false if it failed */ /obj/item/pneumatic_cannon/proc/load_item(obj/item/I, mob/user) if((loaded_weight_class + I.w_class) > max_weight_class) to_chat(user, "[I] won't fit into [src]!") return FALSE if(I.w_class > w_class) to_chat(user, "[I] is too large to fit into [src]!") return FALSE if(!user.unEquip(I) || I.flags & (ABSTRACT | NODROP | DROPDEL)) to_chat(user, "You can't put [I] into [src]!") return FALSE to_chat(user, "You load [I] into [src].") loaded_items.Add(I) loaded_weight_class += I.w_class I.forceMove(src) return TRUE /obj/item/pneumatic_cannon/wrench_act(mob/living/user, obj/item/I) adjust_setting(user) return TRUE /obj/item/pneumatic_cannon/proc/adjust_setting(mob/living/user) if(pressure_setting == max_pressure_setting) pressure_setting = 1 else pressure_setting++ to_chat(user, "You tweak [src]'s pressure output to [pressure_setting].") /obj/item/pneumatic_cannon/attackby(obj/item/W, mob/user, params) ..() if(istype(W, /obj/item/tank/internals) && !tank) if(istype(W, /obj/item/tank/internals/emergency_oxygen)) to_chat(user, "[W] is too small for [src].") return add_tank(W, user) return if(W.type == type) to_chat(user, "You're fairly certain that putting a pneumatic cannon inside another pneumatic cannon would cause a spacetime disruption.") return load_item(W, user) /obj/item/pneumatic_cannon/screwdriver_act(mob/living/user, obj/item/I) remove_tank(user) return TRUE /obj/item/pneumatic_cannon/afterattack(atom/target, mob/living/carbon/human/user, flag, params) if(isstorage(target)) //So you can store it in backpacks return ..() if(istype(target, /obj/structure/rack)) //So you can store it on racks return ..() if(!istype(user)) return ..() fire(user, target) /obj/item/pneumatic_cannon/proc/fire(mob/living/carbon/human/user, atom/target) if(!istype(user) && !target) return var/has_discharged = FALSE if(!loaded_items || !loaded_weight_class) to_chat(user, "[src] has nothing loaded.") return if(requires_tank) if(!tank) to_chat(user, "[src] can't fire without a source of gas.") return if(!tank.air_contents.boolean_remove(gas_per_throw * pressure_setting)) to_chat(user, "[src] lets out a weak hiss and doesn't react!") return if(user && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(75)) user.visible_message("[user] loses [user.p_their()] grip on [src], causing it to go off!", "[src] slips out of your hands and goes off!") user.drop_item() has_discharged = TRUE if(prob(10)) target = user else var/list/possible_targets = range(3,src) target = pick(possible_targets) if(!has_discharged) user.visible_message("[user] fires [src]!", \ "You fire [src]!") add_attack_logs(user, target, "Fired [src]") playsound(loc, 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE) for(var/obj/item/loaded_item in loaded_items) loaded_items.Remove(loaded_item) loaded_weight_class -= loaded_item.w_class loaded_item.throw_speed = pressure_setting * 2 loaded_item.forceMove(get_turf(src)) loaded_item.throw_at(target, pressure_setting * 5, pressure_setting * 2, user) if(pressure_setting >= 3 && user) user.visible_message("[user] is thrown down by the force of the cannon!", "[src] slams into your shoulder, knocking you down!") user.KnockDown(3 SECONDS) /obj/item/pneumatic_cannon/proc/add_tank(obj/item/tank/new_tank, mob/living/carbon/human/user) if(tank) to_chat(user, "[src] already has a tank.") return if(!user.unEquip(new_tank)) return to_chat(user, "You hook [new_tank] up to [src].") new_tank.forceMove(src) tank = new_tank update_icons() /obj/item/pneumatic_cannon/proc/remove_tank(mob/living/carbon/human/user) if(!tank) return FALSE to_chat(user, "You detach [tank] from [src].") user.put_in_hands(tank) tank = null update_icons() /obj/item/pneumatic_cannon/proc/update_icons() src.overlays.Cut() if(!tank) return src.overlays += image('icons/obj/pneumaticCannon.dmi', "[tank.icon_state]") src.update_icon() /obj/item/pneumatic_cannon/admin name = "admin pnuematic cannon" desc = "Infinite gas and infinite capacity, go crazy." requires_tank = FALSE max_weight_class = INFINITY /// Obtainable by improvised methods; more gas per use, less capacity, but smaller /obj/item/pneumatic_cannon/ghetto name = "improvised pneumatic cannon" desc = "A gas-powered, object-firing cannon made out of common parts." force = 5 w_class = WEIGHT_CLASS_NORMAL max_weight_class = 7 gas_per_throw = 5