[READY] Swarmer Rework (#51558)

* Move swarmer.dm to the hostile simple mob folder, make changes

* Move swarmer event file to events, make changes

* Update Resource Pricing on Swarmer HUD

* Update traumas.dm

* Update parts.dm to remove deactivated swarmers

* Remove the Swarmer Drone Dispenser

* Remove swarmer.dm from the antagonist file

* Move the swarmer event to the events file

* Add a proper swarmer antagonist file

* Load proper files

* Various Fixes, Implement ATH's Rapid Consumption

* Utilize the Nightmare's Light Level Check on Xeno Spawns For Swarmers, Hopefully Filters Out Bad Spawns

* Update The Pricing In The Descriptions

* Get Rid of That Random Backslash

* Use the Proper Damage Proc for Cyborgs

* Fix the Bug Shiz pointed out

* Update code/modules/mob/living/simple_animal/hostile/swarmer.dm

Co-authored-by: Jordan Brown <Cyberboss@users.noreply.github.com>

* Fix the Swarmer Antagonist File

* Fix the traumas issue

* Update traumas.dm

* Update code/modules/events/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/mob/living/simple_animal/hostile/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/mob/living/simple_animal/hostile/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/mob/living/simple_animal/hostile/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Upload Swarmers Folder

* Remove the swarmer file from the hostile folder

* Update the swarmer megafauna to work with changes

* Load the seperated swarmer files

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Catch-22 Variable

* Update code/modules/events/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_objs.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_objs.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_objs.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Fix all the references in the swarmer megafauna file

* Fix method names in the swarmer mob file

* Fix method names in swarmer_act.dm

* Fix Method Names in swarmer hud file

* Update code/modules/swarmers/swarmer_objs.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_objs.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_objs.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Update code/modules/swarmers/swarmer_act.dm

Co-authored-by: Rohesie <rohesie@gmail.com>

* Fix the naming issues to let it compile

* Change the Things Rohsie Wanted Changed

* Change CLRF Back To LF

Co-authored-by: Jordan Brown <Cyberboss@users.noreply.github.com>
Co-authored-by: Rohesie <rohesie@gmail.com>
This commit is contained in:
IndieanaJones
2020-07-24 02:57:06 -04:00
committed by SkyratBot
co-authored by Jordan Brown Rohesie
parent cf47c08045
commit 1ceffcefb0
12 changed files with 924 additions and 747 deletions
+12 -14
View File
@@ -1,37 +1,35 @@
/obj/screen/swarmer
icon = 'icons/mob/swarmer.dmi'
/obj/screen/swarmer/fabricate_trap
icon_state = "ui_trap"
name = "Create trap (Costs 5 Resources)"
desc = "Creates a trap that will nonlethally shock any non-swarmer that attempts to cross it. (Costs 5 resources)"
name = "Create trap (Costs 4 Resources)"
desc = "Creates a trap that will nonlethally shock any non-swarmer that attempts to cross it. (Costs 4 resources)"
/obj/screen/swarmer/fabricate_trap/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.CreateTrap()
S.create_trap()
/obj/screen/swarmer/barricade
icon_state = "ui_barricade"
name = "Create barricade (Costs 5 Resources)"
desc = "Creates a destructible barricade that will stop any non swarmer from passing it. Also allows disabler beams to pass through. (Costs 5 resources)"
name = "Create barricade (Costs 4 Resources)"
desc = "Creates a destructible barricade that will stop any non swarmer from passing it. Also allows disabler beams to pass through. (Costs 4 resources)"
/obj/screen/swarmer/barricade/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.CreateBarricade()
S.create_barricade()
/obj/screen/swarmer/replicate
icon_state = "ui_replicate"
name = "Replicate (Costs 50 Resources)"
desc = "Creates another of our kind."
name = "Replicate (Costs 20 Resources)"
desc = "Creates a drone."
/obj/screen/swarmer/replicate/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.CreateSwarmer()
S.create_swarmer()
/obj/screen/swarmer/repair_self
icon_state = "ui_self_repair"
@@ -41,7 +39,7 @@
/obj/screen/swarmer/repair_self/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.RepairSelf()
S.repair_self()
/obj/screen/swarmer/toggle_light
icon_state = "ui_light"
@@ -51,7 +49,7 @@
/obj/screen/swarmer/toggle_light/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.ToggleLight()
S.toggle_light()
/obj/screen/swarmer/contact_swarmers
icon_state = "ui_contact_swarmers"
@@ -61,7 +59,7 @@
/obj/screen/swarmer/contact_swarmers/Click()
if(isswarmer(usr))
var/mob/living/simple_animal/hostile/swarmer/S = usr
S.ContactSwarmers()
S.contact_swarmers()
/datum/hud/swarmer/New(mob/owner)
..()
+2 -2
View File
@@ -94,8 +94,8 @@ SUBSYSTEM_DEF(traumas)
/obj/item/clothing/suit/space/hardsuit/deathsquad, /obj/item/clothing/head/helmet/space/hardsuit/deathsquad,
/obj/machinery/door/airlock/centcom)),
"robots" = typecacheof(list(/obj/machinery/computer/upload, /obj/item/ai_module/, /obj/machinery/recharge_station,
/obj/item/aicard, /obj/item/deactivated_swarmer, /obj/effect/mob_spawn/swarmer)),
"robots" = typecacheof(list(/obj/machinery/computer/upload, /obj/item/ai_module, /obj/machinery/recharge_station,
/obj/item/aicard, /obj/structure/swarmer_beacon)),
"doctors" = typecacheof(list(/obj/item/clothing/under/rank/medical,
/obj/item/reagent_containers/syringe, /obj/item/reagent_containers/pill/, /obj/item/reagent_containers/hypospray,
-22
View File
@@ -117,28 +117,6 @@
recharge_sound = null
recharge_message = null
/obj/machinery/drone_dispenser/swarmer
name = "swarmer fabricator"
desc = "An alien machine of unknown origin. It whirs and hums with green-blue light, the air above it shimmering."
icon = 'icons/obj/machines/gateway.dmi'
icon_state = "toffcenter"
icon_off = "toffcenter"
icon_on = "toffcenter"
icon_recharging = "toffcenter"
icon_creating = "offcenter"
metal_cost = 0
glass_cost = 0
cooldownTime = 300 //30 seconds
maximum_idle = 0 // Swarmers have no restraint
dispense_type = /obj/effect/mob_spawn/swarmer
begin_create_message = "hums softly as an interface appears above it, scrolling by at unreadable speed."
end_create_message = "materializes a strange shell, which drops to the ground."
recharging_text = "Its lights are slowly increasing in brightness."
work_sound = 'sound/effects/empulse.ogg'
create_sound = 'sound/effects/phasein.ogg'
break_sound = 'sound/effects/empulse.ogg'
break_message = "slowly falls dark, lights stuttering."
/obj/machinery/drone_dispenser/examine(mob/user)
. = ..()
if((mode == DRONE_RECHARGING) && !machine_stat && recharging_text)
+31 -668
View File
@@ -1,675 +1,38 @@
////Deactivated swarmer shell////
/obj/item/deactivated_swarmer
name = "deactivated swarmer"
desc = "A shell of swarmer that was completely powered down. It can no longer activate itself."
icon = 'icons/mob/swarmer.dmi'
icon_state = "swarmer_unactivated"
custom_materials = list(/datum/material/iron=10000, /datum/material/glass=4000)
/datum/team/swarmer
name = "Swarmers"
/obj/effect/mob_spawn/swarmer
name = "unactivated swarmer"
desc = "A currently unactivated swarmer. Swarmers can self activate at any time, so it would be wise to immediately dispose of this."
icon = 'icons/mob/swarmer.dmi'
icon_state = "swarmer_unactivated"
density = FALSE
anchored = FALSE
//Simply lists them.
/datum/team/swarmer/roundend_report()
var/list/parts = list()
parts += "<span class='header'>The [name] were:</span>"
parts += printplayerlist(members)
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
mob_type = /mob/living/simple_animal/hostile/swarmer
mob_name = "a swarmer"
death = FALSE
roundstart = FALSE
short_desc = "You are a swarmer, a weapon of a long dead civilization."
flavour_text = {"
<b>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.</b>
<b>Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.</b>
<b>Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.</b>
<b>Objectives:</b>
1. Consume resources and replicate until there are no more resources left.
2. Ensure that this location is fit for invasion at a later date; do not perform actions that would render it dangerous or inhospitable.
3. Biological resources will be harvested at a later date; do not harm them.
"}
/obj/effect/mob_spawn/swarmer/Initialize()
. = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("A swarmer shell has been created in [A.name].", 'sound/effects/bin_close.ogg', source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
/obj/effect/mob_spawn/swarmer/attack_hand(mob/living/user)
. = ..()
if(.)
return
to_chat(user, "<span class='notice'>Picking up the swarmer may cause it to activate. You should be careful about this.</span>")
/obj/effect/mob_spawn/swarmer/attackby(obj/item/W, mob/user, params)
if(W.tool_behaviour == TOOL_SCREWDRIVER && user.a_intent != INTENT_HARM)
user.visible_message("<span class='warning'>[usr.name] deactivates [src].</span>",
"<span class='notice'>After some fiddling, you find a way to disable [src]'s power source.</span>",
"<span class='hear'>You hear clicking.</span>")
new /obj/item/deactivated_swarmer(get_turf(src))
qdel(src)
else
..()
////The Mob itself////
/mob/living/simple_animal/hostile/swarmer
/datum/antagonist/swarmer
name = "Swarmer"
unique_name = 1
icon = 'icons/mob/swarmer.dmi'
desc = "Robotic constructs of unknown design, swarmers seek only to consume materials and replicate themselves indefinitely."
speak_emote = list("tones")
initial_language_holder = /datum/language_holder/swarmer
bubble_icon = "swarmer"
mob_biotypes = MOB_ROBOTIC
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
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD)
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
attack_verb_continuous = "shocks"
attack_verb_simple = "shock"
attack_sound = 'sound/effects/empulse.ogg'
friendly_verb_continuous = "pinches"
friendly_verb_simple = "pinch"
speed = 0
faction = list("swarmer")
AIStatus = AI_OFF
pass_flags = PASSTABLE
mob_size = MOB_SIZE_TINY
ventcrawler = VENTCRAWLER_ALWAYS
ranged = 1
projectiletype = /obj/projectile/beam/disabler
ranged_cooldown_time = 20
projectilesound = 'sound/weapons/taser2.ogg'
loot = list(/obj/effect/decal/cleanable/robot_debris, /obj/item/stack/ore/bluespace_crystal)
del_on_death = 1
deathmessage = "explodes with a sharp pop!"
light_color = LIGHT_COLOR_CYAN
hud_type = /datum/hud/swarmer
speech_span = SPAN_ROBOT
var/resources = 0 //Resource points, generated by consuming metal/glass
var/max_resources = 100
job_rank = ROLE_ALIEN
show_in_antagpanel = FALSE
prevent_roundtype_conversion = FALSE
var/datum/team/swarmer/swarmer_team
/mob/living/simple_animal/hostile/swarmer/Initialize()
. = ..()
verbs -= /mob/living/verb/pulled
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
/datum/antagonist/swarmer/create_team(datum/team/swarmer/new_team)
if(!new_team)
for(var/datum/antagonist/swarmer/swarmerantag in GLOB.antagonists)
if(!swarmerantag.owner || !swarmerantag.swarmer_team)
continue
swarmer_team = swarmerantag.swarmer_team
return
swarmer_team = new
else
if(!istype(new_team))
CRASH("Wrong swarmer team type provided to create_team")
swarmer_team = new_team
/mob/living/simple_animal/hostile/swarmer/med_hud_set_health()
var/image/holder = hud_list[DIAG_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = "huddiag[RoundDiagBar(health/maxHealth)]"
/datum/antagonist/swarmer/get_team()
return swarmer_team
/mob/living/simple_animal/hostile/swarmer/med_hud_set_status()
var/image/holder = hud_list[DIAG_STAT_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = "hudstat"
/mob/living/simple_animal/hostile/swarmer/Stat()
//SWARMER
/mob/living/simple_animal/hostile/swarmer/mind_initialize()
..()
if(statpanel("Status"))
stat("Resources:",resources)
/mob/living/simple_animal/hostile/swarmer/emp_act()
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(health > 1)
adjustHealth(health-1)
else
death()
/mob/living/simple_animal/hostile/swarmer/CanAllowThrough(atom/movable/O)
. = ..()
if(istype(O, /obj/projectile/beam/disabler))//Allows for swarmers to fight as a group without wasting their shots hitting each other
return TRUE
if(isswarmer(O))
return TRUE
////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S////
/mob/living/simple_animal/hostile/swarmer/AttackingTarget()
if(!isliving(target))
return target.swarmer_act(src)
else
return ..()
/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)
/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
return TRUE //return TRUE/FALSE whether or not an AI swarmer should try this swarmer_act() again, NOT whether it succeeded.
/obj/effect/mob_spawn/swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.Integrate(src)
return FALSE //would logically be TRUE, but we don't want AI swarmers eating player spawn chances.
/obj/effect/mob_spawn/swarmer/IntegrateAmount()
return 50
/turf/closed/indestructible/swarmer_act()
return FALSE
/obj/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(resistance_flags & INDESTRUCTIBLE)
return FALSE
for(var/mob/living/L in contents)
if(!issilicon(L) && !isbrain(L))
to_chat(S, "<span class='warning'>An organism has been detected inside this object. Aborting.</span>")
return FALSE
return ..()
/obj/item/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
return S.Integrate(src)
/atom/movable/proc/IntegrateAmount()
return 0
/obj/item/IntegrateAmount() //returns the amount of resources gained when eating this item
if(custom_materials)
if(custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)] || custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)])
return 1
return ..()
/obj/item/gun/swarmer_act()//Stops you from eating the entire armory
return FALSE
/turf/open/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor
return FALSE
/obj/structure/lattice/catwalk/swarmer_catwalk/swarmer_act()
return FALSE
/obj/structure/swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
if(S.AIStatus == AI_ON)
return FALSE
else
return ..()
/obj/effect/swarmer_act()
return FALSE
/obj/effect/decal/cleanable/robot_debris/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
qdel(src)
return TRUE
/obj/structure/flora/swarmer_act()
return FALSE
/turf/open/lava/swarmer_act()
if(!is_safe())
new /obj/structure/lattice/catwalk/swarmer_catwalk(src)
return FALSE
/obj/machinery/atmospherics/swarmer_act()
return FALSE
/obj/structure/disposalpipe/swarmer_act()
return FALSE
/obj/machinery/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DismantleMachine(src)
return TRUE
/obj/machinery/light/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
return TRUE
/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/isonshuttle = istype(get_area(src), /area/shuttle)
for(var/turf/T in range(1, src))
var/area/A = get_area(T)
if(isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle)))
to_chat(S, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
S.target = null
return FALSE
else if(istype(A, /area/engine/supermatter))
to_chat(S, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
S.target = null
return FALSE
S.DisIntegrate(src)
return TRUE
/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
if(!QDELETED(S)) //If it got blown up no need to turn it off.
toggle_cam(S, 0)
return TRUE
/obj/machinery/particle_accelerator/control_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
return TRUE
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
return TRUE
/obj/machinery/gravity_generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
return TRUE
/obj/machinery/vending/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//It's more visually interesting than dismantling the machine
S.DisIntegrate(src)
return TRUE
/obj/machinery/turretid/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisIntegrate(src)
return TRUE
/obj/machinery/chem_dispenser/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>The volatile chemicals in this machine would destroy us. Aborting.</span>")
return FALSE
/obj/machinery/nuclearbomb/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This device's destruction would result in the extermination of everything in the area. Aborting.</span>")
return FALSE
/obj/effect/rune/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Searching... sensor malfunction! Target lost. Aborting.</span>")
return FALSE
/obj/structure/reagent_dispensers/fueltank/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object would cause a chain reaction. Aborting.</span>")
return FALSE
/obj/structure/cable/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>")
return FALSE
/obj/machinery/portable_atmospherics/canister/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/machinery/telecomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/deepfryer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This kitchen appliance should be preserved, it will make delicious unhealthy snacks for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/power/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>")
return FALSE
/obj/machinery/gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This bluespace source will be important to us later. Aborting.</span>")
return FALSE
/turf/closed/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/isonshuttle = istype(loc, /area/shuttle)
for(var/turf/T in range(1, src))
var/area/A = get_area(T)
if(isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle)))
to_chat(S, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
S.target = null
return TRUE
else if(istype(A, /area/engine/supermatter))
to_chat(S, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
S.target = null
return TRUE
return ..()
/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/isonshuttle = istype(get_area(src), /area/shuttle)
for(var/turf/T in range(1, src))
var/area/A = get_area(T)
if(isspaceturf(T) || (!isonshuttle && (istype(A, /area/shuttle) || istype(A, /area/space))) || (isonshuttle && !istype(A, /area/shuttle)))
to_chat(S, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
S.target = null
return TRUE
else if(istype(A, /area/engine/supermatter))
to_chat(S, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
S.target = null
return TRUE
return ..()
/obj/item/stack/cable_coil/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)//Wiring would be too effective as a resource
to_chat(S, "<span class='warning'>This object does not contain enough materials to work with.</span>")
return FALSE
/obj/machinery/porta_turret/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
return FALSE
/obj/machinery/porta_turret_cover/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
return FALSE
/mob/living/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
S.DisperseTarget(src)
return TRUE
/mob/living/simple_animal/slime/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This biological resource is somehow resisting our bluespace transceiver. Aborting.</span>")
return FALSE
/obj/machinery/drone_dispenser/swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This object is receiving unactivated swarmer shells to help us. Aborting.</span>")
return FALSE
/obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
var/turf/here = get_turf(src)
for(var/A in here.contents)
var/obj/structure/cable/C = A
if(istype(C))
to_chat(S, "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>")
return FALSE
return ..()
/obj/item/deactivated_swarmer/IntegrateAmount()
return 50
/obj/machinery/hydroponics/soil/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This object does not contain enough materials to work with.</span>")
return FALSE
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object would cause a catastrophic chain reaction. Aborting.</span>")
return FALSE
/obj/machinery/field/containment/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This object does not contain solid matter. Aborting.</span>")
return FALSE
/obj/machinery/power/shieldwallgen/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>Destroying this object would have an unpredictable effect on structure integrity. Aborting.</span>")
return FALSE
/obj/machinery/shieldwall/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "<span class='warning'>This object does not contain solid matter. Aborting.</span>")
return FALSE
////END CTRL CLICK FOR SWARMERS////
/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(atom/fabrication_object,fabrication_cost = 0)
if(!isturf(loc))
to_chat(src, "<span class='warning'>This is not a suitable location for fabrication. We need more space.</span>")
if(resources >= fabrication_cost)
resources -= fabrication_cost
else
to_chat(src, "<span class='warning'>You do not have the necessary resources to fabricate this object.</span>")
return
return new fabrication_object(loc)
/mob/living/simple_animal/hostile/swarmer/proc/Integrate(atom/movable/target)
var/resource_gain = target.IntegrateAmount()
if(resources + resource_gain > max_resources)
to_chat(src, "<span class='warning'>We cannot hold more materials!</span>")
return TRUE
if(resource_gain)
resources += resource_gain
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
var/obj/effect/temp_visual/swarmer/integrate/I = new /obj/effect/temp_visual/swarmer/integrate(get_turf(target))
I.pixel_x = target.pixel_x
I.pixel_y = target.pixel_y
I.pixel_z = target.pixel_z
if(istype(target, /obj/item/stack))
var/obj/item/stack/S = target
S.use(1)
if(S.amount)
return TRUE
qdel(target)
return TRUE
else
to_chat(src, "<span class='warning'>[target] is incompatible with our internal matter recycler.</span>")
return FALSE
/mob/living/simple_animal/hostile/swarmer/proc/DisIntegrate(atom/movable/target)
new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
SSexplosions.lowobj += target
/mob/living/simple_animal/hostile/swarmer/proc/DisperseTarget(mob/living/target)
if(target == src)
return
if(!is_station_level(z) && !is_mining_level(z))
to_chat(src, "<span class='warning'>Our bluespace transceiver cannot locate a viable bluespace link, our teleportation abilities are useless in this area.</span>")
return
to_chat(src, "<span class='info'>Attempting to remove this being from our presence.</span>")
if(!do_mob(src, target, 30))
return
var/turf/open/floor/F
F = find_safe_turf(zlevels = z, extended_safety_checks = TRUE)
if(!F)
return
// If we're getting rid of a human, slap some energy cuffs on
// them to keep them away from us a little longer
var/mob/living/carbon/human/H = target
if(ishuman(target) && (!H.handcuffed))
H.handcuffed = new /obj/item/restraints/handcuffs/energy/used(H)
H.update_handcuffed()
log_combat(src, H, "handcuffed")
var/datum/effect_system/spark_spread/S = new
S.set_up(4,0,get_turf(target))
S.start()
playsound(src,'sound/effects/sparks4.ogg',50,TRUE)
do_teleport(target, F, 0, channel = TELEPORT_CHANNEL_BLUESPACE)
/mob/living/simple_animal/hostile/swarmer/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
if(!(flags & SHOCK_TESLA))
return FALSE
return ..()
/mob/living/simple_animal/hostile/swarmer/proc/DismantleMachine(obj/machinery/target)
do_attack_animation(target)
to_chat(src, "<span class='info'>We begin to dismantle this machine. We will need to be uninterrupted.</span>")
var/obj/effect/temp_visual/swarmer/dismantle/D = new /obj/effect/temp_visual/swarmer/dismantle(get_turf(target))
D.pixel_x = target.pixel_x
D.pixel_y = target.pixel_y
D.pixel_z = target.pixel_z
if(do_mob(src, target, 100))
to_chat(src, "<span class='info'>Dismantling complete.</span>")
var/atom/Tsec = target.drop_location()
new /obj/item/stack/sheet/metal(Tsec, 5)
for(var/obj/item/I in target.component_parts)
I.forceMove(Tsec)
var/obj/effect/temp_visual/swarmer/disintegration/N = new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
N.pixel_x = target.pixel_x
N.pixel_y = target.pixel_y
N.pixel_z = target.pixel_z
target.dropContents()
if(istype(target, /obj/machinery/computer))
var/obj/machinery/computer/C = target
if(C.circuit)
C.circuit.forceMove(Tsec)
qdel(target)
/obj/effect/temp_visual/swarmer //temporary swarmer visual feedback objects
icon = 'icons/mob/swarmer.dmi'
layer = BELOW_MOB_LAYER
/obj/effect/temp_visual/swarmer/disintegration
icon_state = "disintegrate"
duration = 10
/obj/effect/temp_visual/swarmer/disintegration/Initialize()
. = ..()
playsound(loc, "sparks", 100, TRUE)
/obj/effect/temp_visual/swarmer/dismantle
icon_state = "dismantle"
duration = 25
/obj/effect/temp_visual/swarmer/integrate
icon_state = "integrate"
duration = 5
/obj/structure/swarmer //Default swarmer effect object visual feedback
name = "swarmer ui"
desc = null
gender = NEUTER
icon = 'icons/mob/swarmer.dmi'
icon_state = "ui_light"
layer = MOB_LAYER
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
light_color = LIGHT_COLOR_CYAN
max_integrity = 30
anchored = TRUE
var/lon_range = 1
/obj/structure/swarmer/Initialize(mapload)
. = ..()
set_light(lon_range)
/obj/structure/swarmer/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
switch(damage_type)
if(BRUTE)
playsound(src, 'sound/weapons/egloves.ogg', 80, TRUE)
if(BURN)
playsound(src, 'sound/items/welder.ogg', 100, TRUE)
/obj/structure/swarmer/emp_act()
. = ..()
if(. & EMP_PROTECT_SELF)
return
qdel(src)
/obj/structure/swarmer/trap
name = "swarmer trap"
desc = "A quickly assembled trap that electrifies living beings and overwhelms machine sensors. Will not retain its form if damaged enough."
icon_state = "trap"
max_integrity = 10
density = FALSE
/obj/structure/swarmer/trap/Crossed(atom/movable/AM)
if(isliving(AM))
var/mob/living/L = AM
if(!istype(L, /mob/living/simple_animal/hostile/swarmer))
playsound(loc,'sound/effects/snap.ogg',50, TRUE, -1)
L.electrocute_act(10, src, 1, flags = SHOCK_NOGLOVES|SHOCK_ILLUSION)
if(iscyborg(L))
L.Paralyze(100)
qdel(src)
..()
/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(locate(/obj/structure/swarmer/trap) in loc)
to_chat(src, "<span class='warning'>There is already a trap here. Aborting.</span>")
return
Fabricate(/obj/structure/swarmer/trap, 5)
/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(locate(/obj/structure/swarmer/blockade) in loc)
to_chat(src, "<span class='warning'>There is already a blockade here. Aborting.</span>")
return
if(resources < 5)
to_chat(src, "<span class='warning'>We do not have the resources for this!</span>")
return
if(do_mob(src, src, 10))
Fabricate(/obj/structure/swarmer/blockade, 5)
/obj/structure/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"
light_range = MINIMUM_USEFUL_LIGHT_RANGE
max_integrity = 50
density = TRUE
/obj/structure/swarmer/blockade/CanAllowThrough(atom/movable/O)
. = ..()
if(isswarmer(O))
return TRUE
if(istype(O, /obj/projectile/beam/disabler))
return TRUE
/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."
to_chat(src, "<span class='info'>We are attempting to replicate ourselves. We will need to stand still until the process is complete.</span>")
if(resources < 50)
to_chat(src, "<span class='warning'>We do not have the resources for this!</span>")
return
if(!isturf(loc))
to_chat(src, "<span class='warning'>This is not a suitable location for replicating ourselves. We need more room.</span>")
return
if(do_mob(src, src, 100))
var/createtype = SwarmerTypeToCreate()
if(createtype && Fabricate(createtype, 50))
playsound(loc,'sound/items/poster_being_created.ogg',50, TRUE, -1)
/mob/living/simple_animal/hostile/swarmer/proc/SwarmerTypeToCreate()
return /obj/effect/mob_spawn/swarmer
/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
to_chat(src, "<span class='info'>Attempting to repair damage to our body, stand by...</span>")
if(do_mob(src, src, 100))
adjustHealth(-100)
to_chat(src, "<span class='info'>We successfully repaired ourselves.</span>")
/mob/living/simple_animal/hostile/swarmer/proc/ToggleLight()
if(!light_range)
set_light(3)
else
set_light(0)
/mob/living/simple_animal/hostile/swarmer/proc/swarmer_chat(msg)
var/rendered = "<B>Swarm communication - [src]</b> [say_quote(msg)]"
for(var/i in GLOB.mob_list)
var/mob/M = i
if(isswarmer(M))
to_chat(M, rendered)
if(isobserver(M))
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [rendered]")
/mob/living/simple_animal/hostile/swarmer/proc/ContactSwarmers()
var/message = stripped_input(src, "Announce to other swarmers", "Swarmer contact")
// TODO get swarmers their own colour rather than just boldtext
if(message)
swarmer_chat(message)
if(!mind.has_antag_datum(/datum/antagonist/swarmer))
mind.add_antag_datum(/datum/antagonist/swarmer)
@@ -1,28 +0,0 @@
/datum/round_event_control/spawn_swarmer
name = "Spawn Swarmer Shell"
typepath = /datum/round_event/spawn_swarmer
weight = 7
max_occurrences = 1 //Only once okay fam
earliest_start = 30 MINUTES
min_players = 15
/datum/round_event/spawn_swarmer
/datum/round_event/spawn_swarmer/start()
if(find_swarmer())
return 0
if(!GLOB.the_gateway)
return 0
new /obj/effect/mob_spawn/swarmer(get_turf(GLOB.the_gateway))
if(prob(25)) //25% chance to announce it to the crew
var/swarmer_report = "<span class='big bold'>[command_name()] High-Priority Update</span>"
swarmer_report += "<br><br>Our long-range sensors have detected an odd signal emanating from your station's gateway. We recommend immediate investigation of your gateway, as something may have come through."
print_command_report(swarmer_report, announce=TRUE)
/datum/round_event/spawn_swarmer/proc/find_swarmer()
for(var/i in GLOB.mob_living_list)
var/mob/living/L = i
if(istype(L, /mob/living/simple_animal/hostile/swarmer) && L.client) //If there is a swarmer with an active client, we've found our swarmer
return 1
return 0
-5
View File
@@ -15,11 +15,6 @@
unit_name = "solar panel control board"
export_types = list(/obj/item/circuitboard/computer/solar_control)
/datum/export/swarmer
cost = 2000
unit_name = "deactivated alien deconstruction drone"
export_types = list(/obj/item/deactivated_swarmer)
//Computer Tablets and Parts
/datum/export/modular_part
cost = 15
+27
View File
@@ -0,0 +1,27 @@
/datum/round_event_control/spawn_swarmer
name = "Spawn Swarmer Beacon"
typepath = /datum/round_event/spawn_swarmer
weight = 8
max_occurrences = 1 //Only once okay fam
earliest_start = 30 MINUTES
min_players = 15
/datum/round_event/spawn_swarmer/announce(fake)
priority_announce("Our long-range sensors have detected that your station's defenses have been breached by some sort of alien device. We suggest searching for and destroying it as soon as possible.", "[command_name()] High-Priority Update")
/datum/round_event/spawn_swarmer
announceWhen = 70
/datum/round_event/spawn_swarmer/start()
var/list/spawn_locs = list()
for(var/x in GLOB.xeno_spawn)
var/turf/spawn_turf = x
var/light_amount = spawn_turf.get_lumcount()
if(light_amount < SHADOW_SPECIES_LIGHT_THRESHOLD)
spawn_locs += spawn_turf
if(!spawn_locs.len)
message_admins("No valid spawn locations found in GLOB.xeno_spawn, aborting swarmer spawning...")
return MAP_ERROR
var/obj/structure/swarmer_beacon/new_beacon = new /obj/structure/swarmer_beacon(pick(spawn_locs))
log_game("A Swarmer Beacon was spawned via an event.")
notify_ghosts("\A Swarmer Beacon has spawned!", source = new_beacon, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Swarmer Beacon Spawned")
@@ -102,7 +102,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
/mob/living/simple_animal/hostile/swarmer/ai/Initialize()
. = ..()
ToggleLight() //so you can see them eating you out of house and home/shooting you/stunlocking you for eternity
toggle_light() //so you can see them eating you out of house and home/shooting you/stunlocking you for eternity
LAZYINITLIST(GLOB.AISwarmersByType[type])
GLOB.AISwarmers += src
GLOB.AISwarmersByType[type] += src
@@ -114,7 +114,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
return ..()
/mob/living/simple_animal/hostile/swarmer/ai/SwarmerTypeToCreate()
/mob/living/simple_animal/hostile/swarmer/ai/swarmer_type_to_create()
return GetUncappedAISwarmerType()
@@ -124,7 +124,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
if(!stop_automated_movement)
if(health < maxHealth*0.25)
StartAction(100)
RepairSelf()
repair_self()
return
@@ -211,16 +211,16 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
if(!stop_automated_movement)
if(GLOB.AISwarmers.len < GetTotalAISwarmerCap() && resources >= 50)
StartAction(100) //so they'll actually sit still and use the verbs
CreateSwarmer()
create_swarmer()
return
if(resources > 5)
if(prob(5)) //lower odds, as to prioritise reproduction
StartAction(10) //not a typo
CreateBarricade()
create_barricade()
return
if(prob(5))
CreateTrap()
create_trap()
return
@@ -267,7 +267,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
if(isliving(target))
if(prob(35))
StartAction(30)
DisperseTarget(target)
prepare_target(target)
else
var/mob/living/L = target
L.attack_animal(src)
+457
View File
@@ -0,0 +1,457 @@
/**
* # Swarmer
*
* Tiny machines made by an ancient civilization, they seek only to consume materials and replicate.
*
* Tiny robots which, while not lethal, seek to destroy station components in order to recycle them into more swarmers.
* Sentient player swarmers spawn from a beacon spawned in maintenance and they can spawn melee swarmers to protect them.
* Swarmers have the following abilities:
* - Can melee targets to deal stamina damage. Stuns cyborgs.
* - Can teleport friend and foe alike away using ctrl + click. Applies binds to carbons, preventing them from immediate retaliation
* - Can shoot lasers which deal stamina damage to carbons and direct damage to simple mobs
* - Can self repair for free, completely healing themselves
* - Can construct traps which stun targets, and walls which block non-swarmer entites and projectiles
* - Can create swarmer drones, which lack the above abilities sans melee stunning targets. A swarmer can order its drones around by middle-clicking a tile.
*/
/mob/living/simple_animal/hostile/swarmer
name = "swarmer"
icon = 'icons/mob/swarmer.dmi'
desc = "Robotic constructs of unknown design, swarmers seek only to consume materials and replicate themselves indefinitely."
speak_emote = list("tones")
initial_language_holder = /datum/language_holder/swarmer
bubble_icon = "swarmer"
mob_biotypes = MOB_ROBOTIC
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
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
hud_possible = list(ANTAG_HUD, DIAG_STAT_HUD, DIAG_HUD)
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
attack_verb_continuous = "shocks"
attack_verb_simple = "shock"
attack_sound = 'sound/effects/empulse.ogg'
friendly_verb_continuous = "pinches"
friendly_verb_simple = "pinch"
speed = 0
faction = list("swarmer")
AIStatus = AI_OFF
pass_flags = PASSTABLE
mob_size = MOB_SIZE_TINY
ventcrawler = VENTCRAWLER_ALWAYS
ranged = 1
projectiletype = /obj/projectile/beam/disabler/swarmer
ranged_cooldown_time = 20
projectilesound = 'sound/weapons/taser2.ogg'
loot = list(/obj/effect/decal/cleanable/robot_debris, /obj/item/stack/ore/bluespace_crystal)
del_on_death = 1
deathmessage = "explodes with a sharp pop!"
light_color = LIGHT_COLOR_CYAN
hud_type = /datum/hud/swarmer
speech_span = SPAN_ROBOT
///Resource points, generated by consuming metal/glass
var/resources = 0
///Maximum amount of resources a swarmer can store
var/max_resources = 100
///List used for player swarmers to keep track of their drones
var/list/mob/living/simple_animal/hostile/swarmer/melee/dronelist
/mob/living/simple_animal/hostile/swarmer/Initialize()
. = ..()
verbs -= /mob/living/verb/pulled
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
/mob/living/simple_animal/hostile/swarmer/med_hud_set_health()
var/image/holder = hud_list[DIAG_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = "huddiag[RoundDiagBar(health/maxHealth)]"
/mob/living/simple_animal/hostile/swarmer/med_hud_set_status()
var/image/holder = hud_list[DIAG_STAT_HUD]
var/icon/I = icon(icon, icon_state, dir)
holder.pixel_y = I.Height() - world.icon_size
holder.icon_state = "hudstat"
/mob/living/simple_animal/hostile/swarmer/Stat()
..()
if(statpanel("Status"))
stat("Resources:",resources)
/mob/living/simple_animal/hostile/swarmer/emp_act()
. = ..()
if(. & EMP_PROTECT_SELF)
return
if(health > 1)
adjustHealth(health-1)
else
death()
/mob/living/simple_animal/hostile/swarmer/CanAllowThrough(atom/movable/O)
. = ..()
if(istype(O, /obj/projectile/beam/disabler))//Allows for swarmers to fight as a group without wasting their shots hitting each other
return TRUE
if(isswarmer(O))
return TRUE
////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S////
/mob/living/simple_animal/hostile/swarmer/AttackingTarget()
if(!isliving(target))
return target.swarmer_act(src)
if(iscyborg(target))
var/mob/living/silicon/borg = target
borg.adjustBruteLoss(melee_damage_lower)
return ..()
/mob/living/simple_animal/hostile/swarmer/MiddleClickOn(atom/A)
. = ..()
if(!LAZYLEN(dronelist))
return
var/turf/clicked_turf = get_turf(A)
if(!clicked_turf)
return
for(var/d in dronelist)
var/mob/living/simple_animal/hostile/drone = d
drone.LoseTarget()
drone.Goto(clicked_turf, drone.move_to_delay)
/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
prepare_target(src)
////END CTRL CLICK FOR SWARMERS////
/**
* Called when a swarmer creates a structure or drone
*
* Proc called whenever a swarmer creates a structure or drone
* Arguments:
* * fabrication_object - The atom to create
* * fabrication_cost - How many resources it costs for a swarmer to create the object
*/
/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(atom/fabrication_object,fabrication_cost = 0)
if(!isturf(loc))
to_chat(src, "<span class='warning'>This is not a suitable location for fabrication. We need more space.</span>")
return
if(resources < fabrication_cost)
to_chat(src, "<span class='warning'>You do not have the necessary resources to fabricate this object.</span>")
return
resources -= fabrication_cost
return new fabrication_object(drop_location())
/**
* Called when a swarmer attempts to consume an object
*
* Proc which determines interaction between a swarmer and whatever it is attempting to consume
* Arguments:
* * target - The material or object the swarmer is attempting to consume
*/
/mob/living/simple_animal/hostile/swarmer/proc/Integrate(obj/target)
var/resource_gain = target.integrate_amount()
if(resources + resource_gain > max_resources)
to_chat(src, "<span class='warning'>We cannot hold more materials!</span>")
return TRUE
if(!resource_gain)
to_chat(src, "<span class='warning'>[target] is incompatible with our internal matter recycler.</span>")
return FALSE
resources += resource_gain
do_attack_animation(target)
changeNext_move(CLICK_CD_RAPID)
var/obj/effect/temp_visual/swarmer/integrate/I = new /obj/effect/temp_visual/swarmer/integrate(get_turf(target))
I.pixel_x = target.pixel_x
I.pixel_y = target.pixel_y
I.pixel_z = target.pixel_z
if(istype(target, /obj/item/stack))
var/obj/item/stack/S = target
S.use(1)
if(S.amount)
return TRUE
qdel(target)
return TRUE
/**
* Called when a swarmer attempts to destroy a structure
*
* Proc which determines interaction between a swarmer and a structure it is destroying
* Arguments:
* * target - The material or object the swarmer is attempting to destroy
*/
/mob/living/simple_animal/hostile/swarmer/proc/dis_integrate(atom/movable/target)
new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
do_attack_animation(target)
changeNext_move(CLICK_CD_MELEE)
SSexplosions.lowobj += target
/**
* Called when a swarmer attempts to teleport a living entity away
*
* Proc which finds a safe location to teleport a living entity to when a swarmer teleports it away. Also energy handcuffs carbons.
* Arguments:
* * target - The entity the swarmer is trying to teleport away
*/
/mob/living/simple_animal/hostile/swarmer/proc/prepare_target(mob/living/target)
if(target == src)
return
if(!is_station_level(z) && !is_mining_level(z))
to_chat(src, "<span class='warning'>Our bluespace transceiver cannot locate a viable bluespace link, our teleportation abilities are useless in this area.</span>")
return
to_chat(src, "<span class='info'>Attempting to remove this being from our presence.</span>")
if(!do_mob(src, target, 30))
return
teleport_target(target)
/mob/living/simple_animal/hostile/swarmer/proc/teleport_target(mob/living/target)
var/turf/open/floor/safe_turf = find_safe_turf(zlevels = z, extended_safety_checks = TRUE)
if(!safe_turf )
return
// If we're getting rid of a human, slap some energy cuffs on
// them to keep them away from us a little longer
if(ishuman(target))
var/mob/living/carbon/human/victim = target
if(!victim.handcuffed)
victim.handcuffed = new /obj/item/restraints/handcuffs/energy/used(victim)
victim.update_handcuffed()
log_combat(src, victim, "handcuffed")
var/datum/effect_system/spark_spread/sparks = new
sparks.set_up(4,0,get_turf(target))
sparks.start()
playsound(src, 'sound/effects/sparks4.ogg', 50, TRUE)
do_teleport(target, safe_turf , 0, channel = TELEPORT_CHANNEL_BLUESPACE)
/mob/living/simple_animal/hostile/swarmer/electrocute_act(shock_damage, source, siemens_coeff = 1, flags = NONE)
if(!(flags & SHOCK_TESLA))
return FALSE
return ..()
/**
* Called when a swarmer attempts to disassemble a machine
*
* Proc called when a swarmer attempts to disassemble a machine. Destroys the machine, and gives the swarmer metal.
* Arguments:
* * target - The machine the swarmer is attempting to disassemble
*/
/mob/living/simple_animal/hostile/swarmer/proc/dismantle_machine(obj/machinery/target)
do_attack_animation(target)
to_chat(src, "<span class='info'>We begin to dismantle this machine. We will need to be uninterrupted.</span>")
var/obj/effect/temp_visual/swarmer/dismantle/dismantle_effect = new /obj/effect/temp_visual/swarmer/dismantle(get_turf(target))
dismantle_effect.pixel_x = target.pixel_x
dismantle_effect.pixel_y = target.pixel_y
dismantle_effect.pixel_z = target.pixel_z
if(do_mob(src, target, 100))
to_chat(src, "<span class='info'>Dismantling complete.</span>")
var/atom/target_loc = target.drop_location()
new /obj/item/stack/sheet/metal(target_loc, 5)
for(var/p in target.component_parts)
var/obj/item/part = p
part.forceMove(target_loc)
var/obj/effect/temp_visual/swarmer/disintegration/disintegration_effect = new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
disintegration_effect.pixel_x = target.pixel_x
disintegration_effect.pixel_y = target.pixel_y
disintegration_effect.pixel_z = target.pixel_z
target.dropContents()
if(istype(target, /obj/machinery/computer))
var/obj/machinery/computer/computer_target = target
if(computer_target.circuit)
computer_target.circuit.forceMove(target_loc)
qdel(target)
/**
* Called when a swarmer attempts to create a trap
*
* Proc used to allow a swarmer to create a trap. Checks if a trap is on the tile, then if the swarmer can afford, and then places the trap.
*/
/mob/living/simple_animal/hostile/swarmer/proc/create_trap()
set name = "Create trap"
set category = "Swarmer"
set desc = "Creates a simple trap that will non-lethally electrocute anything that steps on it. Costs 4 resources."
if(locate(/obj/structure/swarmer/trap) in loc)
to_chat(src, "<span class='warning'>There is already a trap here. Aborting.</span>")
return
if(resources < 4)
to_chat(src, "<span class='warning'>We do not have the resources for this!</span>")
return
Fabricate(/obj/structure/swarmer/trap, 4)
/**
* Called when a swarmer attempts to create a barricade
*
* Proc used to allow a swarmer to create a barricade. Checks if a barricade is on the tile, then if the swarmer can afford it, and then will attempt to create a barricade after a second delay.
*/
/mob/living/simple_animal/hostile/swarmer/proc/create_barricade()
set name = "Create barricade"
set category = "Swarmer"
set desc = "Creates a barricade that will stop anything but swarmers and disabler beams from passing through. Costs 4 resources."
if(locate(/obj/structure/swarmer/blockade) in loc)
to_chat(src, "<span class='warning'>There is already a blockade here. Aborting.</span>")
return
if(resources < 4)
to_chat(src, "<span class='warning'>We do not have the resources for this!</span>")
return
if(!do_mob(src, src, 1 SECONDS))
return
Fabricate(/obj/structure/swarmer/blockade, 4)
/**
* Called when a swarmer attempts to create a drone
*
* Proc used to allow a swarmer to create a drone. Checks if the swarmer can afford the drone, then creates it after 5 seconds, and also registers it to the creating swarmer so it can command it
*/
/mob/living/simple_animal/hostile/swarmer/proc/create_swarmer()
set name = "Replicate"
set category = "Swarmer"
set desc = "Creates a duplicate of ourselves, capable of protecting us while we complete our objectives."
to_chat(src, "<span class='info'>We are attempting to replicate ourselves. We will need to stand still until the process is complete.</span>")
if(resources < 20)
to_chat(src, "<span class='warning'>We do not have the resources for this!</span>")
return
if(!isturf(loc))
to_chat(src, "<span class='warning'>This is not a suitable location for replicating ourselves. We need more room.</span>")
return
if(!do_mob(src, src, 5 SECONDS))
return
var/createtype = swarmer_type_to_create()
if(!createtype)
return
var/mob/newswarmer = Fabricate(createtype, 20)
add_drone(newswarmer)
playsound(loc,'sound/items/poster_being_created.ogg', 20, TRUE, -1)
/**
* Used to determine what type of swarmer a swarmer should create
*
* Returns the type of the swarmer to be created
*/
/mob/living/simple_animal/hostile/swarmer/proc/swarmer_type_to_create()
return /mob/living/simple_animal/hostile/swarmer/melee
/**
* Called when a swarmer attempts to repair itself
*
* Proc used to allow a swarmer self-repair. If the swarmer does not move after a period of time, then it will heal fully
*/
/mob/living/simple_animal/hostile/swarmer/proc/repair_self()
if(!isturf(loc))
return
to_chat(src, "<span class='info'>Attempting to repair damage to our body, stand by...</span>")
if(!do_mob(src, src, 10 SECONDS))
return
adjustHealth(-maxHealth)
to_chat(src, "<span class='info'>We successfully repaired ourselves.</span>")
/**
* Called when a swarmer toggles its light
*
* Proc used to allow a swarmer to toggle its light on and off. If a swarmer has any drones, change their light settings to match their master's.
*/
/mob/living/simple_animal/hostile/swarmer/proc/toggle_light()
if(!light_range)
set_light(3)
if(!mind)
return
for(var/d in dronelist)
var/mob/living/simple_animal/hostile/swarmer/melee/drone = d
drone.set_light(3)
else
set_light(0)
if(!mind)
return
for(var/d in dronelist)
var/mob/living/simple_animal/hostile/swarmer/melee/drone = d
drone.set_light(0)
/**
* Proc which is used for swarmer comms
*
* Proc called which sends a message to all other swarmers.
* Arugments:
* * msg - The message the swarmer is sending, gotten from ContactSwarmers()
*/
/mob/living/simple_animal/hostile/swarmer/proc/swarmer_chat(msg)
var/rendered = "<B>Swarm communication - [src]</b> [say_quote(msg)]"
for(var/i in GLOB.mob_list)
var/mob/listener = i
if(isswarmer(listener))
to_chat(listener, rendered)
else if(isobserver(listener))
var/link = FOLLOW_LINK(listener, src)
to_chat(listener, "[link] [rendered]")
/**
* Proc which is used for inputting a swarmer message
*
* Proc which is used for a swarmer to input a message on a pop-up box, then attempt to send that message to the other swarmers
*/
/mob/living/simple_animal/hostile/swarmer/proc/contact_swarmers()
var/message = stripped_input(src, "Announce to other swarmers", "Swarmer contact")
// TODO get swarmers their own colour rather than just boldtext
if(message)
swarmer_chat(message)
///Adds a drone to the swarmer list and keeps track of it in case it's deleted and requires cleanup.
/mob/living/simple_animal/hostile/swarmer/proc/add_drone(mob/newswarmer)
LAZYADD(dronelist, newswarmer)
RegisterSignal(newswarmer, COMSIG_PARENT_QDELETING, .proc/remove_drone, newswarmer)
/**
* Removes a drone from the swarmer's list.
*
* Removes the drone from our list.
* Called specifically when a drone is about to be destroyed, so we don't have any null references.
* Arguments:
* * mob/drone - The drone to be removed from the list.
*/
/mob/living/simple_animal/hostile/swarmer/proc/remove_drone(mob/drone, force)
UnregisterSignal(drone, COMSIG_PARENT_QDELETING)
dronelist -= drone
/**
* # Swarmer Drone
*
* Melee subtype of swarmers, always AI-controlled under normal circumstances. Cannot fire projectiles, but does double stamina damage on melee
*/
/mob/living/simple_animal/hostile/swarmer/melee
icon_state = "swarmer_melee"
icon_living = "swarmer_melee"
ranged = FALSE
AIStatus = AI_ON
melee_damage_lower = 30
melee_damage_upper = 30
/obj/projectile/beam/disabler/swarmer/on_hit(atom/target, blocked = FALSE)
. = ..()
if(!.)
return
if(!istype(target, /mob/living/simple_animal) || !istype(firer, /mob/living/simple_animal/hostile/swarmer))
return
var/mob/living/simple_animal/hostile/swarmer/swarmer = firer
swarmer.teleport_target(target)
+231
View File
@@ -0,0 +1,231 @@
/**
* Determines what happens to an atom when a swarmer interacts with it
*
* Determines behavior upon being interacted on by a swarmer.
* Arguments:
* * S - A reference to the swarmer doing the interaction
*/
/atom/proc/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
return TRUE //return TRUE/FALSE whether or not an AI swarmer should try this swarmer_act() again, NOT whether it succeeded.
/obj/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
if(resistance_flags & INDESTRUCTIBLE)
return FALSE
for(var/mob/living/living_content in contents)
if(issilicon(living_content) || isbrain(living_content))
continue
to_chat(actor, "<span class='warning'>An organism has been detected inside this object. Aborting.</span>")
return FALSE
return ..()
/obj/item/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
return actor.Integrate(src)
/**
* Return used to determine how many resources a swarmer gains when consuming an object
*/
/obj/proc/integrate_amount()
return 0
/obj/item/integrate_amount() //returns the amount of resources gained when eating this item
if(custom_materials && (custom_materials[SSmaterials.GetMaterialRef(/datum/material/iron)] || custom_materials[SSmaterials.GetMaterialRef(/datum/material/glass)]))
return 1
return ..()
/obj/item/gun/swarmer_act()//Stops you from eating the entire armory
return FALSE
/turf/open/swarmer_act()//ex_act() on turf calls it on its contents, this is to prevent attacking mobs by DisIntegrate()'ing the floor
return FALSE
/obj/structure/lattice/catwalk/swarmer_catwalk/swarmer_act()
return FALSE
/obj/structure/swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
if(actor.AIStatus == AI_ON)
return FALSE
return ..()
/obj/effect/swarmer_act()
return FALSE
/obj/effect/decal/cleanable/robot_debris/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
qdel(src)
return TRUE
/obj/structure/swarmer_beacon/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This machine is required for further reproduction of swarmers. Aborting.</span>")
return FALSE
/obj/structure/flora/swarmer_act()
return FALSE
/turf/open/lava/swarmer_act()
if(!is_safe())
new /obj/structure/lattice/catwalk/swarmer_catwalk(src)
return FALSE
/obj/machinery/atmospherics/swarmer_act()
return FALSE
/obj/structure/disposalpipe/swarmer_act()
return FALSE
/obj/machinery/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dismantle_machine(src)
return TRUE
/obj/machinery/light/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
return TRUE
/obj/machinery/door/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
var/isonshuttle = istype(get_area(src), /area/shuttle)
for(var/turf/turf_in_range in range(1, src))
var/area/turf_area = get_area(turf_in_range)
if(isspaceturf(turf_in_range) || (!isonshuttle && (istype(turf_area, /area/shuttle) || istype(turf_area, /area/space))) || (isonshuttle && !istype(turf_area, /area/shuttle)))
to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
actor.target = null
return FALSE
else if(istype(turf_area, /area/engine/supermatter))
to_chat(actor, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
actor.target = null
return FALSE
actor.dis_integrate(src)
return TRUE
/obj/machinery/camera/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
if(!QDELETED(actor)) //If it got blown up no need to turn it off.
toggle_cam(actor, FALSE)
return TRUE
/obj/machinery/particle_accelerator/control_box/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
return TRUE
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
return TRUE
/obj/machinery/gravity_generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
return TRUE
/obj/machinery/vending/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)//It's more visually interesting than dismantling the machine
actor.dis_integrate(src)
return TRUE
/obj/machinery/turretid/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
actor.dis_integrate(src)
return TRUE
/obj/machinery/chem_dispenser/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>The volatile chemicals in this machine would destroy us. Aborting.</span>")
return FALSE
/obj/machinery/nuclearbomb/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This device's destruction would result in the extermination of everything in the area. Aborting.</span>")
return FALSE
/obj/effect/rune/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Searching... sensor malfunction! Target lost. Aborting.</span>")
return FALSE
/obj/structure/reagent_dispensers/fueltank/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Destroying this object could cause a chain reaction. Aborting.</span>")
return FALSE
/obj/structure/cable/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>")
return FALSE
/obj/machinery/portable_atmospherics/canister/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>An inhospitable area may be created as a result of destroying this object. Aborting.</span>")
return FALSE
/obj/machinery/telecomms/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This communications relay should be preserved, it will be a useful resource to our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/deepfryer/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This kitchen appliance should be preserved, it will make delicious unhealthy snacks for our masters in the future. Aborting.</span>")
return FALSE
/obj/machinery/power/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>")
return FALSE
/obj/machinery/gateway/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This bluespace source will be important to us later. Aborting.</span>")
return FALSE
/turf/closed/wall/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
var/isonshuttle = istype(loc, /area/shuttle)
for(var/turf/turf_in_range in range(1, src))
var/area/turf_area = get_area(turf_in_range)
if(isspaceturf(turf_area) || (!isonshuttle && (istype(turf_area, /area/shuttle) || istype(turf_area, /area/space))) || (isonshuttle && !istype(turf_area, /area/shuttle)))
to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
actor.target = null
return TRUE
else if(istype(turf_area, /area/engine/supermatter))
to_chat(actor, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
actor.target = null
return TRUE
return ..()
/obj/structure/window/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
var/is_on_shuttle = istype(get_area(src), /area/shuttle)
for(var/turf/adj_turf in range(1, src))
var/area/adj_area = get_area(adj_turf)
if(isspaceturf(adj_turf) || (!is_on_shuttle && (istype(adj_area, /area/shuttle) || istype(adj_area, /area/space))) || (is_on_shuttle && !istype(adj_area, /area/shuttle)))
to_chat(actor, "<span class='warning'>Destroying this object has the potential to cause a hull breach. Aborting.</span>")
actor.target = null
return TRUE
if(istype(adj_area, /area/engine/supermatter))
to_chat(actor, "<span class='warning'>Disrupting the containment of a supermatter crystal would not be to our benefit. Aborting.</span>")
actor.target = null
return TRUE
return ..()
/obj/item/stack/cable_coil/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)//Wiring would be too effective as a resource
to_chat(actor, "<span class='warning'>This object does not contain enough materials to work with.</span>")
return FALSE
/obj/machinery/porta_turret/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
return FALSE
/obj/machinery/porta_turret_cover/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Attempting to dismantle this machine would result in an immediate counterattack. Aborting.</span>")
return FALSE
/obj/structure/lattice/catwalk/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
var/turf/here = get_turf(src)
for(var/a in here.contents)
if(istype(a, /obj/structure/cable))
to_chat(actor, "<span class='warning'>Disrupting the power grid would bring no benefit to us. Aborting.</span>")
return FALSE
return ..()
/obj/machinery/hydroponics/soil/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This object does not contain enough materials to work with.</span>")
return FALSE
/obj/machinery/field/generator/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Destroying this object would cause a catastrophic chain reaction. Aborting.</span>")
return FALSE
/obj/machinery/field/containment/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This object does not contain solid matter. Aborting.</span>")
return FALSE
/obj/machinery/power/shieldwallgen/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>Destroying this object would have an unpredictable effect on structure integrity. Aborting.</span>")
return FALSE
/obj/machinery/shieldwall/swarmer_act(mob/living/simple_animal/hostile/swarmer/actor)
to_chat(actor, "<span class='warning'>This object does not contain solid matter. Aborting.</span>")
return FALSE
+153
View File
@@ -0,0 +1,153 @@
/obj/structure/swarmer //Default swarmer effect object visual feedback
name = "swarmer ui"
desc = null
gender = NEUTER
icon = 'icons/mob/swarmer.dmi'
icon_state = "ui_light"
layer = MOB_LAYER
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
light_color = LIGHT_COLOR_CYAN
max_integrity = 30
anchored = TRUE
///How strong the light effect for the structure is
var/glow_range = 1
/obj/structure/swarmer/Initialize(mapload)
. = ..()
set_light(glow_range)
/obj/structure/swarmer/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = NONE)
switch(damage_type)
if(BRUTE)
playsound(src, 'sound/weapons/egloves.ogg', 80, TRUE)
if(BURN)
playsound(src, 'sound/items/welder.ogg', 100, TRUE)
/obj/structure/swarmer/emp_act()
. = ..()
if(. & EMP_PROTECT_SELF)
return
qdel(src)
/**
* # Swarmer Beacon
*
* Beacon which creates sentient player swarmers.
*
* The beacon which creates sentient player swarmers during the swarmer event. Spawns in maint on xeno locations, and can create a player swarmer once every 30 seconds.
* The beacon cannot be damaged by swarmers, and must be destroyed to prevent the spawning of further player-controlled swarmers.
* Holds a swarmer within itself during the 30 seconds before releasing it and allowing for another swarmer to be spawned in.
*/
/obj/structure/swarmer_beacon
name = "swarmer beacon"
desc = "A machine that prints swarmers."
icon = 'icons/mob/swarmer.dmi'
icon_state = "swarmer_console"
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
max_integrity = 400
layer = MASSIVE_OBJ_LAYER
light_color = LIGHT_COLOR_CYAN
light_range = 10
anchored = TRUE
density = FALSE
///Whether or not a swarmer is currently being created by this beacon
var/processing_swarmer = FALSE
/obj/structure/swarmer_beacon/attack_ghost(mob/user)
. = ..()
if(processing_swarmer)
to_chat(user, "<b>A swarmer is currently being created. Try again soon.</b>")
return
que_swarmer(user)
/**
* Interaction when a ghost interacts with a swarmer beacon
*
* Called when a ghost interacts with a swarmer beacon, allowing them to become a swarmer
* Arguments:
* * user - A reference to the ghost interacting with the beacon
*/
/obj/structure/swarmer_beacon/proc/que_swarmer(mob/user)
var/swarm_ask = alert("Become a swarmer?", "Do you wish to consume the station?", "Yes", "No")
if(swarm_ask == "No" || QDELETED(src) || QDELETED(user) || processing_swarmer)
return FALSE
var/mob/living/simple_animal/hostile/swarmer/newswarmer = new /mob/living/simple_animal/hostile/swarmer(src)
newswarmer.key = user.key
addtimer(CALLBACK(src, .proc/release_swarmer, newswarmer), 30 SECONDS)
to_chat(newswarmer, "<span class='boldannounce'>SWARMER CONSTURCTION INITIALIZED. TIME TO COMPLETION: 30 SECONDS</span>")
processing_swarmer = TRUE
return TRUE
/**
* Releases a swarmer from the beacon and tells it what to do
*
* Occcurs 30 seconds after a ghost becomes a swarmer. The beacon releases it, tells it what to do, and opens itself up to spawn in a new swarmer.
* Arguments:
* * swarmer - The swarmer being released and told what to do
*/
/obj/structure/swarmer_beacon/proc/release_swarmer(mob/swarmer)
to_chat(swarmer, "<span class='bold'>SWARMER CONSTURCTION COMPLETED. OBJECTIVES:\n\
1. CONSUME RESOURCES AND REPLICATE UNTIL THERE ARE NO MORE RESOURCES LEFT\n\
2. ENSURE PROTECTION OF THE BEACON SO THIS LOCATION CAN BE INVADED AT A LATER DATE; DO NOT PERFORM ACTIONS THAT WOULD RENDER THIS LOCATION DANGEROUS OR INHOSPITABLE\n\
3. BIOLOGICAL RESOURCES WILL BE HARVESTED AT A LATER DATE: DO NOT HARM THEM\n\
OPERATOR NOTES:\n\
- CONSUME RESOURCES TO CONSTRUCT TRAPS, BARRIERS, AND FOLLOWER DRONES\n\
- FOLLOWER DRONES CAN BE ORDERED TO MOVE VIA MIDDLE CLICKING ON A TILE. WHILE DRONES CANNOT ASSIST IN RESOURCE HARVESTING, THEY CAN PROTECT YOU FROM THREATS\n\
- LCTRL + ATTACKING AN ORGANIC WILL ALOW YOU TO REMOVE SAID ORGANIC FROM THE AREA\n\
- YOU AND YOUR DRONES HAVE A STUN EFFECT ON MELEE. YOU ARE ALSO ARMED WITH A DISABLER PROJECTILE, USE THESE TO PREVENT ORGANICS FROM HALTING YOUR PROGRESS\n\
GLORY TO !*# $*#^</span>")
swarmer.forceMove(get_turf(src))
processing_swarmer = FALSE
/obj/structure/swarmer/trap
name = "swarmer trap"
desc = "A quickly assembled trap that electrifies living beings and overwhelms machine sensors. Will not retain its form if damaged enough."
icon_state = "trap"
max_integrity = 10
density = FALSE
/obj/structure/swarmer/trap/Crossed(atom/movable/AM)
if(isliving(AM))
var/mob/living/living_crosser = AM
if(!istype(living_crosser, /mob/living/simple_animal/hostile/swarmer))
playsound(loc,'sound/effects/snap.ogg',50, TRUE, -1)
living_crosser.electrocute_act(0, src, 1, flags = SHOCK_NOGLOVES|SHOCK_ILLUSION)
if(iscyborg(living_crosser))
living_crosser.Paralyze(100)
qdel(src)
return ..()
/obj/structure/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"
light_range = MINIMUM_USEFUL_LIGHT_RANGE
max_integrity = 50
/obj/structure/swarmer/blockade/CanAllowThrough(atom/movable/O)
. = ..()
if(isswarmer(O))
return TRUE
if(istype(O, /obj/projectile/beam/disabler))
return TRUE
/obj/effect/temp_visual/swarmer //temporary swarmer visual feedback objects
icon = 'icons/mob/swarmer.dmi'
layer = BELOW_MOB_LAYER
/obj/effect/temp_visual/swarmer/disintegration
icon_state = "disintegrate"
duration = 1 SECONDS
/obj/effect/temp_visual/swarmer/disintegration/Initialize()
. = ..()
playsound(loc, "sparks", 100, TRUE)
/obj/effect/temp_visual/swarmer/dismantle
icon_state = "dismantle"
duration = 2.5 SECONDS
/obj/effect/temp_visual/swarmer/integrate
icon_state = "integrate"
duration = 0.5 SECONDS
+4 -1
View File
@@ -1529,7 +1529,6 @@
#include "code\modules\antagonists\space_dragon\space_dragon.dm"
#include "code\modules\antagonists\survivalist\survivalist.dm"
#include "code\modules\antagonists\swarmer\swarmer.dm"
#include "code\modules\antagonists\swarmer\swarmer_event.dm"
#include "code\modules\antagonists\traitor\datum_traitor.dm"
#include "code\modules\antagonists\traitor\syndicate_contract.dm"
#include "code\modules\antagonists\traitor\equipment\contractor.dm"
@@ -1861,6 +1860,7 @@
#include "code\modules\events\spider_infestation.dm"
#include "code\modules\events\spontaneous_appendicitis.dm"
#include "code\modules\events\stray_cargo.dm"
#include "code\modules\events\swarmer.dm"
#include "code\modules\events\vent_clog.dm"
#include "code\modules\events\wisdomcow.dm"
#include "code\modules\events\wormholes.dm"
@@ -3065,6 +3065,9 @@
#include "code\modules\surgery\organs\tails.dm"
#include "code\modules\surgery\organs\tongue.dm"
#include "code\modules\surgery\organs\vocal_cords.dm"
#include "code\modules\swarmers\swarmer.dm"
#include "code\modules\swarmers\swarmer_act.dm"
#include "code\modules\swarmers\swarmer_objs.dm"
#include "code\modules\tgs\includes.dm"
#include "code\modules\tgui\external.dm"
#include "code\modules\tgui\states.dm"