diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 0da4f75e1bf..33d02d6e06e 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -77,4 +77,5 @@ #define ALIEN 4 #define ROBOT 8 #define SLIME 16 -#define DRONE 32 \ No newline at end of file +#define DRONE 32 +#define SWARMER 64 \ No newline at end of file diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 2ec7b4c407f..66ae50cf852 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -342,4 +342,10 @@ for(var/datum/D in L) if(D.vars.Find(varname)) if(D.vars[varname] == value) - return D \ No newline at end of file + return D + +//remove all nulls from a list +/proc/removeNullsFromList(list/L) + while(L.Remove(null)) + continue + return L \ No newline at end of file diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index fb209d087e7..d947bfa6553 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -197,6 +197,8 @@ var/datum/global_hud/global_hud = new() blob_hud() else if(isdrone(mymob)) drone_hud(ui_style) + else if(isswarmer(mymob)) + swarmer_hud() //Version denotes which style should be displayed. blank or 0 means "next version" diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 82a66b848e1..fbf9c5b26f3 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -235,10 +235,8 @@ return var/mob/living/simple_animal/M = user M.do_attack_animation(src) - if(M.melee_damage_upper <= 0) - return - attack_generic(M, M.melee_damage_upper) - + if(M.melee_damage_upper > 0 && (M.melee_damage_type == BRUTE || M.melee_damage_type == BURN)) + attack_generic(M, M.melee_damage_upper) /obj/machinery/door/window/attack_slime(mob/living/simple_animal/slime/user) user.do_attack_animation(src) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index f0a2c610a61..499198a49e3 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -311,7 +311,7 @@ /obj/machinery/porta_turret/attack_animal(mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) M.do_attack_animation(src) - if(M.melee_damage_upper == 0) + if(M.melee_damage_upper == 0 || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) return if(!(stat & BROKEN)) visible_message("[M] [M.attacktext] [src]!") diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index f1347bcd07e..65e2b67e0b3 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -45,8 +45,8 @@ new /obj/item/weapon/reagent_containers/pill/patch/silver_sulf(src) new /obj/item/weapon/reagent_containers/pill/patch/silver_sulf(src) new /obj/item/weapon/reagent_containers/pill/patch/silver_sulf(src) - new /obj/item/weapon/reagent_containers/pill/salicyclic(src) - new /obj/item/weapon/reagent_containers/pill/salicyclic(src) + new /obj/item/weapon/reagent_containers/pill/oxandrolone(src) + new /obj/item/weapon/reagent_containers/pill/oxandrolone(src) new /obj/item/weapon/reagent_containers/hypospray/medipen(src) new /obj/item/device/healthanalyzer(src) return diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index bb209cb9515..8fa1375a480 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -166,6 +166,7 @@ /obj/structure/closet/ex_act(severity, target) contents_explosion(severity, target) + new /obj/item/stack/sheet/metal(loc) dump_contents() qdel(src) ..() diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 355938166f5..e8775daf133 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -239,7 +239,7 @@ qdel(src) return if(3.0) - if (prob(15)) + if (prob(40)) var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) new remains(loc) qdel(src) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 488932acaa4..d6c56c34a34 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -79,7 +79,8 @@ /obj/structure/grille/attack_animal(var/mob/living/simple_animal/M) M.changeNext_move(CLICK_CD_MELEE) - if(M.melee_damage_upper == 0) return + if(M.melee_damage_upper == 0 || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) + return M.do_attack_animation(src) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) M.visible_message("[M] smashes against [src].", \ diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm index 696ed292eb9..b7862562752 100644 --- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm +++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm @@ -11,11 +11,13 @@ qdel(src) return if(2.0) - if (prob(50)) + if (prob(70)) + new /obj/item/stack/sheet/metal(loc) qdel(src) return if(3.0) - if (prob(5)) + if (prob(50)) + new /obj/item/stack/sheet/metal(loc) qdel(src) return return diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 6c02cd7e7d0..9dc8d6631e9 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -168,7 +168,7 @@ var/mob/living/simple_animal/M = user M.do_attack_animation(src) - if(M.melee_damage_upper <= 0) + if(M.melee_damage_upper <= 0 || (M.melee_damage_type != BRUTE && M.melee_damage_type != BURN)) return attack_generic(M, M.melee_damage_upper) diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index 9a55d77b4ad..f373fad4af6 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -7,7 +7,6 @@ /datum/round_event/brand_intelligence announceWhen = 21 endWhen = 1000 //Ends when all vending machines are subverted anyway. - var/list/obj/machinery/vending/vendingMachines = list() var/list/obj/machinery/vending/infectedMachines = list() var/obj/machinery/vending/originMachine @@ -28,11 +27,9 @@ for(var/obj/machinery/vending/V in machines) if(V.z != 1) continue vendingMachines.Add(V) - if(!vendingMachines.len) kill() return - originMachine = pick(vendingMachines) vendingMachines.Remove(originMachine) originMachine.shut_up = 0 @@ -48,7 +45,7 @@ originMachine.visible_message("[originMachine] beeps and seems lifeless.") kill() return - + vendingMachines = removeNullsFromList(vendingMachines) if(!vendingMachines.len) //if every machine is infected for(var/obj/machinery/vending/upriser in infectedMachines) if(prob(70) && !upriser.gc_destroyed) @@ -62,7 +59,6 @@ kill() return - if(IsMultiple(activeFor, 4)) var/obj/machinery/vending/rebel = pick(vendingMachines) vendingMachines.Remove(rebel) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index fd3fff64a4b..20577531b27 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -73,7 +73,19 @@ In all, this is a lot like the monkey code. /N /mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M) if(..()) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage) + switch(M.melee_damage_type) + if(BRUTE) + adjustBruteLoss(damage) + if(BURN) + adjustFireLoss(damage) + if(TOX) + adjustToxLoss(damage) + if(OXY) + adjustOxyLoss(damage) + if(CLONE) + adjustCloneLoss(damage) + if(STAMINA) + adjustStaminaLoss(damage) updatehealth() /mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 8fdb1c39ccf..283c745d796 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -74,9 +74,9 @@ . = ..() -/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0) +/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, override = 0) shock_damage *= siemens_coeff - if (shock_damage<1) + if(shock_damage<1 && !override) return 0 take_overall_damage(0,shock_damage) //src.burn_skin(shock_damage) @@ -95,7 +95,10 @@ jitteriness = max(jitteriness - 990, 10) //Still jittery, but vastly less Stun(3) Weaken(3) - return shock_damage + if(override) + return override + else + return shock_damage /mob/living/carbon/swap_hand() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index ec19362de9b..a6dbd65bfca 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -270,7 +270,7 @@ spreadFire(AM) //Added a safety check in case you want to shock a human mob directly through electrocute_act. -/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, safety = 0) +/mob/living/carbon/human/electrocute_act(shock_damage, obj/source, siemens_coeff = 1.0, safety = 0, override = 0) if(!safety) if(gloves) var/obj/item/clothing/gloves/G = gloves @@ -280,8 +280,7 @@ heart_attack = 0 if(stat == CONSCIOUS) src << "You feel your heart beating again!" - - . = ..(shock_damage,source,siemens_coeff) + . = ..(shock_damage,source,siemens_coeff,safety,override) if(.) electrocution_animation(40) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 7a39b9969fe..98a8c3b6eed 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -389,7 +389,7 @@ emp_act var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") var/obj/item/organ/limb/affecting = get_organ(ran_zone(dam_zone)) var/armor = run_armor_check(affecting, "melee") - apply_damage(damage, BRUTE, affecting, armor) + apply_damage(damage, M.melee_damage_type, affecting, armor) updatehealth() diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 5f721ecb512..bd9a1af5f52 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -155,7 +155,19 @@ /mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M) if(..()) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage) + switch(M.melee_damage_type) + if(BRUTE) + adjustBruteLoss(damage) + if(BURN) + adjustFireLoss(damage) + if(TOX) + adjustToxLoss(damage) + if(OXY) + adjustOxyLoss(damage) + if(CLONE) + adjustCloneLoss(damage) + if(STAMINA) + adjustStaminaLoss(damage) updatehealth() diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 83b20b450cb..1a42c2e82f2 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -381,7 +381,19 @@ /mob/living/silicon/attack_animal(mob/living/simple_animal/M) if(..()) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - adjustBruteLoss(damage) + switch(M.melee_damage_type) + if(BRUTE) + adjustBruteLoss(damage) + if(BURN) + adjustFireLoss(damage) + if(TOX) + adjustToxLoss(damage) + if(OXY) + adjustOxyLoss(damage) + if(CLONE) + adjustCloneLoss(damage) + if(STAMINA) + adjustStaminaLoss(damage) updatehealth() /mob/living/silicon/attack_paw(mob/living/user) diff --git a/code/modules/mob/living/simple_animal/bot_swarm/swarmer.dm b/code/modules/mob/living/simple_animal/bot_swarm/swarmer.dm new file mode 100644 index 00000000000..bbed56a6962 --- /dev/null +++ b/code/modules/mob/living/simple_animal/bot_swarm/swarmer.dm @@ -0,0 +1,513 @@ +////Deactivated swarmer shell//// +/obj/item/unactivated_swarmer + name = "unactivated swarmer" + desc = "A currently unactivated swarmer. Swarmers can self activate at any time, it would be wise to immediately dispose of this." + icon = 'icons/mob/swarmer.dmi' + icon_state = "swarmer_unactivated" + +/obj/item/unactivated_swarmer/attack_ghost(mob/user) + var/be_swarmer = alert("Become a swarmer? (Warning, You can no longer be cloned!)",,"Yes","No") + if(be_swarmer == "No" || qdeleted()) + return + var/mob/living/simple_animal/hostile/swarmer/S = new /mob/living/simple_animal/hostile/swarmer(get_turf(loc)) + S.key = user.key + qdel(src) + +////The Mob itself//// + +/mob/living/simple_animal/hostile/swarmer + name = "Swarmer" + unique_name = 1 + icon = 'icons/mob/swarmer.dmi' + desc = "A robot of unknown design, they seek only to consume materials and replicate themselves indefinitely." + speak_emote = list("tones") + health = 40 + maxHealth = 40 + status_flags = CANPUSH + icon_state = "swarmer" + icon_living = "swarmer" + icon_dead = "swarmer_unactivated" + icon_gib = null + wander = 0 + harm_intent_damage = 5 + minbodytemp = 0 + maxbodytemp = 500 + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + unsuitable_atmos_damage = 0 + melee_damage_lower = 15 + melee_damage_upper = 15 + melee_damage_type = STAMINA + ignored_damage_types = list(BRUTE = 0, BURN = 0, TOX = 1, CLONE = 1, STAMINA = 1, OXY = 1) + languages = SWARMER + environment_smash = 0 + attacktext = "shocks" + attack_sound = 'sound/effects/EMPulse.ogg' + friendly = "pinches" + speed = 0 + faction = list("swarmer") + AIStatus = AI_OFF + projectiletype = /obj/item/projectile/beam/disabler + pass_flags = PASSTABLE | PASSMOB + ventcrawler = 2 + ranged = 1 + projectiletype = /obj/item/projectile/beam/disabler + ranged_cooldown_cap = 2 + projectilesound = 'sound/weapons/taser2.ogg' + var/resources = 0 //Resource points, generated by consuming metal/glass + +/mob/living/simple_animal/hostile/swarmer/Login() + ..() + src << "You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate." + src << "Ctrl + Click provides most of your swarmer specific interactions, such as cannibalizing metal or glass, destroying the environment, or teleporting mobs away from you." + src << "Objectives:" + src << "1. Consume resources and replicate until there are no more resources left." + src << "2. Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable." + src << "3. Biological resources will be harvested at a later date, do not harm them." + +/mob/living/simple_animal/hostile/swarmer/New() + ..() + verbs -= /mob/living/verb/pulled + +/mob/living/simple_animal/hostile/swarmer/Stat() + ..() + if(statpanel("Status")) + stat("Resources:",resources) + +/mob/living/simple_animal/hostile/swarmer/death(gibbed) + ..(gibbed) + new /obj/effect/decal/cleanable/robot_debris(src.loc) + ghostize() + qdel(src) + +/mob/living/simple_animal/hostile/swarmer/emp_act() + if(health > 1) + health = 1 + ..() + health = 0 + +/mob/living/simple_animal/hostile/swarmer/CanPass(atom/movable/O) + if(istype(O, /obj/item/projectile/beam/disabler))//Allows for swarmers to fight as a group without wasting their shots hitting each other + return 1 + if(isswarmer(O)) + return 1 + ..() + +////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S//// +/mob/living/simple_animal/hostile/swarmer/CtrlClickOn(atom/A) + face_atom(A) + if(!isturf(loc)) + return + if(next_move > world.time) + return + if(!A.Adjacent(src)) + return + A.swarmer_act(src) + return + +/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + +/obj/item/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.Integrate(src) + +/obj/item/weapon/gun/swarmer_act()//Stops you from eating the entire armory + return + +/turf/simulated/floor/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor + return + +/obj/machinery/atmospherics/swarmer_act() + return + +/obj/structure/disposalpipe/swarmer_act() + return + +/obj/machinery/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DismantleMachine(src) + +/obj/machinery/light/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + +/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + +/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + deactivate(S, 0) + +/obj/machinery/particle_accelerator/control_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + +/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + +/obj/machinery/gravity_generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + +/obj/machinery/vending/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//It's more visually interesting than dismantling the machine + S.DisIntegrate(src) + +/obj/machinery/turretid/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisIntegrate(src) + +/obj/machinery/chem_dispenser/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "The volatile chemicals in this machine would destroy us. Aborting." + +/obj/machinery/nuclearbomb/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "This device's destruction would result in the extermination of everything in the area. Aborting." + +/obj/structure/reagent_dispensers/fueltank/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "Destroying this object would cause a chain reaction. Aborting." + +/obj/structure/cable/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "Disrupting the power grid would bring no benefit to us. Aborting." + +/obj/machinery/portable_atmospherics/canister/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "An inhospitable area may be created as a result of destroying this object. Aborting." + +/obj/machinery/power/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "Disrupting the power grid would bring no benefit to us. Aborting." + +/obj/machinery/gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "This bluespace source will be important to us later. Aborting." + +/turf/simulated/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + if(locate(/turf/space) in range(1, src)) + S << "Destroying this object has the potential to cause a hull breach. Aborting." + return + ..() + +/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + if(locate(/turf/space) in range(1, src)) + S << "Destroying this object has the potential to cause a hull breach. Aborting." + return + ..() + +/obj/item/stack/cable_coil/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//Wiring would be too effective as a resource + S << "This object does not contain enough materials to work with." + +/obj/machinery/porta_turret/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "Attempting to dismantle this machine would result in an immediate counterattack. Aborting." + +/mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S.DisperseTarget(src) + +/mob/living/simple_animal/slime/swarmer_act(mob/living/simple_animal/hostile/swarmer/S) + S << "This biological resource is somehow resisting our bluespace transceiver. Aborting." + + +////END CTRL CLICK FOR SWARMERS//// + +/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(var/atom/fabrication_object,var/fabrication_cost = 0) + if(!isturf(loc)) + src << "This is not a suitable location for fabrication. We need more space." + if(resources >= fabrication_cost) + resources -= fabrication_cost + else + src << "You do not have the necessary resources to fabricate this object." + return 0 + new fabrication_object(loc) + return 1 + +/mob/living/simple_animal/hostile/swarmer/proc/Integrate(var/obj/item/target) + if(resources >= 100) + src << "We cannot hold more materials!" + return + if((target.materials[MAT_METAL]) || (target.materials[MAT_GLASS])) + resources++ + do_attack_animation(target) + changeNext_move(CLICK_CD_MELEE) + if(istype(target, /obj/item/stack)) + var/obj/item/stack/S = target + S.use(1) + if(S.amount) + return + qdel(target) + else + src << "\the [target] is incompatible with our internal matter recycler." + return + +/mob/living/simple_animal/hostile/swarmer/proc/DisIntegrate(var/atom/movable/target) + new /obj/effect/effect/sparks(get_turf(target)) + do_attack_animation(target) + changeNext_move(CLICK_CD_MELEE) + target.ex_act(3) + return + +/mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(var/mob/living/target) + if(target != src) + src << "Attempting to remove this being from our presence." + if(src.z != ZLEVEL_STATION) + src << "Our bluespace transceiver cannot locate a viable bluespace link, our teleportation abilities are useless in this area." + return + if(do_mob(src, target, 30)) + var/cycle + for(cycle=0,cycle<100,cycle++) + var/random_location = locate(rand(37,202),rand(75,192),ZLEVEL_STATION)//Drunk dial a turf in the general ballpark of the station + if(istype(random_location, /turf/simulated/floor)) + var/turf/simulated/floor/F = random_location + if(F.air) + var/datum/gas_mixture/A = F.air + if(A.oxygen >= 16 && !A.toxins && A.carbon_dioxide < 10 && !A.trace_gases.len)//Can most things breathe in this location? + if((A.temperature > 270) && (A.temperature < 360))//Not too hot, not too cold + var/pressure = A.return_pressure() + if((pressure > 20) && (pressure < 550))//Account for crushing pressure or vaccuums + if(ishuman(target))//If we're getting rid of a human, slap some zipties on them to keep them away from us a little longer + var/obj/item/weapon/restraints/handcuffs/cable/zipties/Z = new /obj/item/weapon/restraints/handcuffs/cable/zipties(src) + var/mob/living/carbon/human/H = target + Z.apply_cuffs(H, src) + do_teleport(target, F, 0) + playsound(src,'sound/effects/sparks4.ogg',50,1) + break + return + +/mob/living/simple_animal/hostile/swarmer/proc/DismantleMachine(var/obj/machinery/target) + do_attack_animation(target) + src << "We begin to dismantle this machine. We will need to be uninterrupted." + new /obj/effect/effect/sparks(get_turf(target)) + if(do_mob(src, target, 100)) + src << "Dismantling complete." + var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(target.loc) + M.amount = 5 + for(var/obj/item/I in target.component_parts) + I.loc = M.loc + new /obj/effect/effect/sparks(get_turf(target)) + target.dropContents() + if(istype(target, /obj/machinery/computer)) + var/obj/machinery/computer/C = target + if(C.circuit) + C.circuit.loc = M.loc + qdel(target) + +/obj/effect/swarmer //Default destroyable object for swarmer constructions + name = "swarmer construction" + desc = "Debug swarmer item, this shouldn't be here. Yell at a coder." + gender = NEUTER + icon = 'icons/mob/swarmer.dmi' + icon_state = "ui_light" + luminosity = 1 + var/health = 30 + +/obj/effect/swarmer/proc/TakeDamage(damage) + health -= damage + if(health <= 0) + qdel(src) + +/obj/effect/swarmer/bullet_act(obj/item/projectile/Proj) + if(Proj.damage) + if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) + TakeDamage(Proj.damage) + ..() + +/obj/effect/swarmer/attackby(obj/item/weapon/I, mob/living/user, params) + if(istype(I, /obj/item/weapon)) + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + TakeDamage(I.force) + return + +/obj/effect/swarmer/ex_act() + qdel(src) + return + +/obj/effect/swarmer/blob_act() + qdel(src) + return + +/obj/effect/swarmer/attack_animal(mob/living/user) + if(isanimal(user)) + var/mob/living/simple_animal/S = user + S.do_attack_animation(src) + user.changeNext_move(CLICK_CD_MELEE) + if(S.melee_damage_type == BRUTE || S.melee_damage_type == BURN) + TakeDamage(rand(S.melee_damage_lower, S.melee_damage_upper)) + return + +/mob/living/simple_animal/hostile/swarmer/proc/CreateTrap() + set name = "Create trap" + set category = "Swarmer" + set desc = "Creates a simple trap that will non-lethally electrocute anything that steps on it. Costs 5 resources" + if(/obj/effect/swarmer/trap in loc) + src << "There is already a trap here. Aborting." + return + Fabricate(/obj/effect/swarmer/trap, 5) + return + +/obj/effect/swarmer/trap + name = "swarmer trap" + desc = "A quickly assembled electric trap. Will not retain its form if damaged enough." + icon_state = "trap" + luminosity = 1 + health = 10 + +/obj/effect/swarmer/trap/Crossed(var/atom/movable/AM) + if(isliving(AM)) + var/mob/living/L = AM + if(!istype(L, /mob/living/simple_animal/hostile/swarmer)) + L.electrocute_act(0, src, 1, 1) + qdel(src) + ..() + +/mob/living/simple_animal/hostile/swarmer/proc/CreateBarricade() + set name = "Create barricade" + set category = "Swarmer" + set desc = "Creates a barricade that will stop anything but swarmers and disabler beams from passing through." + if(/obj/effect/swarmer/blockade in loc) + src << "There is already a blockade here. Aborting." + return + Fabricate(/obj/effect/swarmer/blockade, 5) + return + +/obj/effect/swarmer/blockade + name = "swarmer blockade" + desc = "A quickly assembled energy blockade. Will not retain its form if damaged enough, but disabler beams and swarmers pass right through." + icon_state = "barricade" + luminosity = 1 + health = 50 + density = 1 + anchored = 1 + +/obj/effect/swarmer/blockade/CanPass(atom/movable/O) + if(isswarmer(O)) + return 1 + if(istype(O, /obj/item/projectile/beam/disabler)) + return 1 + +/mob/living/simple_animal/hostile/swarmer/proc/CreateSwarmer() + set name = "Replicate" + set category = "Swarmer" + set desc = "Creates a shell for a new swarmer. Swarmers will self activate." + src << "We are attempting to replicate ourselves. We will need to stand still until the process is complete." + if(resources < 50) + src << "We do not have the resources for this!" + return + if(!isturf(loc)) + src << "This is not a suitable location for replicating ourselves. We need more room." + return + if(do_mob(src, src, 100)) + if(Fabricate(/obj/item/unactivated_swarmer, 50)) + playsound(loc,'sound/items/poster_being_created.ogg',50, 1, -1) + +/mob/living/simple_animal/hostile/swarmer/proc/RepairSelf() + set name = "Self Repair" + set category = "Swarmer" + set desc = "Attempts to repair damage to our body. You will have to remain motionless until repairs are complete." + if(!isturf(loc)) + return + src << "Attempting to repair damage to our body, stand by..." + if(do_mob(src, src, 100)) + adjustBruteLoss(-100) + src << "We successfully repaired ourselves." + +/mob/living/simple_animal/hostile/swarmer/proc/ToggleLight() + if(!luminosity) + SetLuminosity(3) + else + SetLuminosity(0) + +/mob/living/simple_animal/hostile/swarmer/proc/ContactSwarmers() + var/message = input(src, "Announce to other swarmers", "Swarmer contact") + if(message) + for(var/mob/M in mob_list) + if(isswarmer(M) || (M in dead_mob_list)) + M << "Swarm communication - [M] states: [message]" + + + +////HUD NONSENSE//// +/obj/screen/swarmer + icon = 'icons/mob/swarmer.dmi' + +/obj/screen/swarmer/FabricateTrap + icon_state = "ui_trap" + name = "Create trap" + desc = "Creates a trap that will nonlethally shock any non-swarmer that attempts to cross it. (Costs 5 resources)" + +/obj/screen/swarmer/FabricateTrap/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.CreateTrap() + +/obj/screen/swarmer/Barricade + icon_state = "ui_barricade" + name = "Create barricade" + desc = "Creates a destructible barricade that will stop any non swarmer from passing it. Also allows disabler beams to pass through. (Costs 5 resources)" + +/obj/screen/swarmer/Barricade/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.CreateBarricade() + +/obj/screen/swarmer/Replicate + icon_state = "ui_replicate" + name = "Replicate" + desc = "Creates a another of our kind. (Costs 50 resources)" + +/obj/screen/swarmer/Replicate/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.CreateSwarmer() + +/obj/screen/swarmer/RepairSelf + icon_state = "ui_self_repair" + name = "Repair self" + desc = "Repairs damage to our body." + +/obj/screen/swarmer/RepairSelf/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.RepairSelf() + +/obj/screen/swarmer/ToggleLight + icon_state = "ui_light" + name = "Toggle light" + desc = "Toggles our inbuilt light on or off." + +/obj/screen/swarmer/ToggleLight/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.ToggleLight() + +/obj/screen/swarmer/ContactSwarmers + icon_state = "ui_contact_swarmers" + name = "Contact swarmers" + desc = "Sends a message to all other swarmers, should they exist." + +/obj/screen/swarmer/ContactSwarmers/Click() + if(isswarmer(usr)) + var/mob/living/simple_animal/hostile/swarmer/S = usr + S.ContactSwarmers() + +/datum/hud/proc/swarmer_hud(ui_style = 'icons/mob/screen_midnight.dmi') + adding = list() + + var/obj/screen/using + + using = new /obj/screen/swarmer/FabricateTrap() + using.screen_loc = ui_rhand + adding += using + + using = new /obj/screen/swarmer/Barricade() + using.screen_loc = ui_lhand + adding += using + + using = new /obj/screen/swarmer/Replicate() + using.screen_loc = ui_zonesel + adding += using + + using = new /obj/screen/swarmer/RepairSelf() + using.screen_loc = ui_storage1 + adding += using + + using = new /obj/screen/swarmer/ToggleLight() + using.screen_loc = ui_back + adding += using + + using = new /obj/screen/swarmer/ContactSwarmers() + using.screen_loc = ui_inventory + adding += using + + mymob.client.screen = list() + mymob.client.screen += mymob.client.void + mymob.client.screen += adding + diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index f3910d8af2d..f41c7847b90 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -41,6 +41,8 @@ //LETTING SIMPLE ANIMALS ATTACK? WHAT COULD GO WRONG. Defaults to zero so Ian can still be cuddly var/melee_damage_lower = 0 var/melee_damage_upper = 0 + var/melee_damage_type = BRUTE //Damage type of a simple mob's melee attack, should it do damage. + var/list/ignored_damage_types = list(BRUTE = 0, BURN = 0, TOX = 0, CLONE = 0, STAMINA = 1, OXY = 0) //Set 0 to receive that damage type, 1 to ignore var/attacktext = "attacks" var/attack_sound = null var/friendly = "nuzzles" //If the mob does no damage with it's attack @@ -253,7 +255,7 @@ /mob/living/simple_animal/attack_animal(mob/living/simple_animal/M) if(..()) var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) - attack_threshold_check(damage) + attack_threshold_check(damage,M.melee_damage_type) return 1 /mob/living/simple_animal/bullet_act(obj/item/projectile/Proj) @@ -263,8 +265,21 @@ Proj.on_hit(src) return 0 +/mob/living/simple_animal/adjustBruteLoss(amount) + if(!ignored_damage_types[BRUTE]) + ..() + /mob/living/simple_animal/adjustFireLoss(amount) - adjustBruteLoss(amount) + if(!ignored_damage_types[BURN]) + adjustBruteLoss(amount) + +/mob/living/simple_animal/adjustToxLoss(amount) + if(!ignored_damage_types[TOX]) + ..(amount) + +/mob/living/simple_animal/adjustCloneLoss(amount) + if(!ignored_damage_types[CLONE]) + ..(amount) /mob/living/simple_animal/adjustStaminaLoss(amount) return @@ -334,8 +349,8 @@ attack_threshold_check(damage) return 1 -/mob/living/simple_animal/proc/attack_threshold_check(damage) - if(damage <= force_threshold) +/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE) + if(damage <= force_threshold || ignored_damage_types[damagetype]) visible_message("[src] looks unharmed.") else adjustBruteLoss(damage) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 857b7f35181..c53fa9b1d3a 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -125,6 +125,11 @@ return 1 return 0 +/proc/isswarmer(A) + if(istype(A, /mob/living/simple_animal/hostile/swarmer)) + return 1 + return 0 + /proc/islimb(A) if(istype(A, /obj/item/organ/limb)) return 1 diff --git a/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm b/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm index a8999d8ddac..14213840918 100644 --- a/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents/Medicine-Reagents.dm @@ -173,13 +173,36 @@ if(method == INGEST) M.adjustToxLoss(0.5*reac_volume) if(show_message) - M << "You probably shouldn't have eaten that. Maybe you should of splashed it on, or applied a patch?" + M << "You probably shouldn't have eaten that. Maybe you should have splashed it on, or applied a patch?" ..() /datum/reagent/medicine/silver_sulfadiazine/on_mob_life(mob/living/M) M.adjustFireLoss(-2*REM) ..() +/datum/reagent/medicine/oxandrolone + name = "Oxandrolone" + id = "oxandrolone" + description = "Stimulates healing of severe burns. If you have more than 50 burn damage, it heals 2 units; otherwise, 0.5. If overdosed it will exacerbate existing burns, causing burn and brute damage." + reagent_state = LIQUID + color = "#f7ffa5" + metabolization_rate = 0.5 * REAGENTS_METABOLISM + overdose_threshold = 25 + +/datum/reagent/medicine/oxandrolone/on_mob_life(mob/living/M) + if(M.getFireLoss() > 50) + M.adjustFireLoss(-2*REM) + else + M.adjustFireLoss(-0.5*REM) + ..() + return + +/datum/reagent/medicine/oxandrolone/overdose_process(mob/living/M) + M.adjustFireLoss(2.5*REM) // it's going to be healing either 2 or 0.5 + M.adjustBruteLoss(0.5*REM) + ..() + return + /datum/reagent/medicine/styptic_powder name = "Styptic Powder" id = "styptic_powder" diff --git a/code/modules/reagents/Chemistry-Recipes/Medicine.dm b/code/modules/reagents/Chemistry-Recipes/Medicine.dm index 60e80923400..3ccc5753cc2 100644 --- a/code/modules/reagents/Chemistry-Recipes/Medicine.dm +++ b/code/modules/reagents/Chemistry-Recipes/Medicine.dm @@ -116,6 +116,12 @@ required_reagents = list("sodium" = 1, "phenol" = 1, "carbon" = 1, "oxygen" = 1, "sacid" = 1) result_amount = 5 +/datum/chemical_reaction/oxandrolone + name = "Oxandrolone" + id = "oxandrolone" + result = "oxandrolone" + required_reagents = list("carbon" = 3, "phenol" = 1, "hydrogen" = 1, "oxygen" = 1) + result_amount = 6 /datum/chemical_reaction/salbutamol name = "Salbutamol" diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm index 2a99e768c75..94ece6ee2c0 100644 --- a/code/modules/reagents/reagent_containers/pill.dm +++ b/code/modules/reagents/reagent_containers/pill.dm @@ -133,6 +133,12 @@ icon_state = "pill5" list_reagents = list("sal_acid" = 24) roundstart = 1 +/obj/item/weapon/reagent_containers/pill/oxandrolone + name = "oxandrolone pill" + desc = "Used to stimulate burn healing." + icon_state = "pill5" + list_reagents = list("oxandrolone" = 24) + roundstart = 1 /obj/item/weapon/reagent_containers/pill/insulin name = "insulin pill" diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index e57a3762319..acb72b88205 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -703,7 +703,8 @@ R.realProc = realProc R.revealed = TRUE dupes |= R - R.throw_at(pick(oview(7,get_turf(src))),10,1) + spawn() + R.throw_at(pick(oview(7,get_turf(src))),10,1) counter = 0 spawn(rand(10,100)) for(counter = 1; counter <= dupes.len; counter++) diff --git a/html/changelog.html b/html/changelog.html index 74b09bfbaa3..821377b3ad1 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -55,6 +55,13 @@ -->
+

28 August 2015

+

bgobandit updated:

+ +

19 August 2015

Joan updated: