diff --git a/code/__DEFINES/xeno.dm b/code/__DEFINES/xeno.dm index 1bc925bb22fc..cbf2dab0a665 100644 --- a/code/__DEFINES/xeno.dm +++ b/code/__DEFINES/xeno.dm @@ -382,8 +382,11 @@ #define XENO_RESIN_NEST_COST 70 #define XENO_RESIN_STICKY_COST 30 #define XENO_RESIN_FAST_COST 10 +#define XENO_RESIN_HOLE_COST 150 #define XENO_RESIN_SPIKE_COST 100 +#define XENO_RESIN_SPIKE_BURROWER_COST 50 #define XENO_RESIN_ACID_PILLAR_COST 250 +#define XENO_RESIN_ACID_PILLAR_BURROWER_COST 150 #define XENO_RESIN_SHIELD_PILLAR_COST 250 #define XENO_RESIN_ACID_GRENADE_COST 500 diff --git a/code/_globalvars/global_lists.dm b/code/_globalvars/global_lists.dm index 4c81e788d2ce..2e0e7f3797c6 100644 --- a/code/_globalvars/global_lists.dm +++ b/code/_globalvars/global_lists.dm @@ -97,6 +97,16 @@ GLOBAL_LIST_INIT(resin_build_order_hivelord_whisperer, list( /datum/resin_construction/resin_obj/resin_node )) +GLOBAL_LIST_INIT(resin_build_order_burrower, list( + /datum/resin_construction/resin_obj/resin_hole, + /datum/resin_construction/resin_obj/acid_pillar/burrower, + /datum/resin_construction/resin_obj/resin_spike/burrower +)) + +GLOBAL_LIST_INIT(resin_build_order_carrier, list( + /datum/resin_construction/resin_obj/resin_hole, +)) + GLOBAL_LIST_INIT(resin_build_order_ovipositor, list( /datum/resin_construction/resin_turf/wall/queen, /datum/resin_construction/resin_turf/wall/reflective, diff --git a/code/modules/cm_aliens/structures/trap.dm b/code/modules/cm_aliens/structures/trap.dm index 5caf6f0ff713..b26159d730b8 100644 --- a/code/modules/cm_aliens/structures/trap.dm +++ b/code/modules/cm_aliens/structures/trap.dm @@ -15,19 +15,21 @@ var/hivenumber = XENO_HIVE_NORMAL //Hivenumber of the xeno that planted it OR the last Facehugger that was placed (essentially taking over the trap) var/trap_type = RESIN_TRAP_EMPTY var/armed = 0 - var/created_by // ckey + var/created_by //ckey var/list/notify_list = list() // list of xeno mobs to notify on trigger var/datum/effect_system/smoke_spread/smoke_system var/datum/cause_data/cause_data plane = FLOOR_PLANE -/obj/effect/alien/resin/trap/Initialize(mapload, mob/living/carbon/xenomorph/X) +/obj/effect/alien/resin/trap/Initialize(mapload, hive, mob/living/carbon/xenomorph/xeno) . = ..() - if(X) - created_by = X.ckey - hivenumber = X.hivenumber + if(hive) + hivenumber = hive - cause_data = create_cause_data("resin trap", X) + if(istype(xeno, /mob/living/carbon/xenomorph)) + created_by = xeno.ckey + + cause_data = create_cause_data("resin trap", xeno) set_hive_data(src, hivenumber) if(hivenumber == XENO_HIVE_NORMAL) RegisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING, PROC_REF(forsaken_handling)) @@ -61,8 +63,8 @@ UnregisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING) /obj/effect/alien/resin/trap/proc/facehugger_die() - var/obj/item/clothing/mask/facehugger/FH = new (loc) - FH.die() + var/obj/item/clothing/mask/facehugger/hugger = new (loc) + hugger.die() trap_type = RESIN_TRAP_EMPTY icon_state = "trap0" @@ -82,9 +84,9 @@ trigger_trap(TRUE) ..() -/obj/effect/alien/resin/trap/bullet_act(obj/projectile/P) - var/mob/living/carbon/xenomorph/X = P.firer - if(istype(X) && HIVE_ALLIED_TO_HIVE(X.hivenumber, hivenumber)) +/obj/effect/alien/resin/trap/bullet_act(obj/projectile/Proj) + var/mob/living/carbon/xenomorph/xeno = Proj.firer + if(istype(xeno) && HIVE_ALLIED_TO_HIVE(xeno.hivenumber, hivenumber)) return . = ..() @@ -135,12 +137,12 @@ icon_state = "trapgas" /obj/effect/alien/resin/trap/proc/burn_trap() - var/area/A = get_area(src) + var/area/area = get_area(src) facehugger_die() clear_tripwires() - for(var/mob/living/carbon/xenomorph/X in GLOB.living_xeno_list) - if(X.hivenumber == hivenumber) - to_chat(X, SPAN_XENOMINORWARNING("We sense one of our Hive's facehugger traps at [A.name] has been burnt!")) + for(var/mob/living/carbon/xenomorph/xeno in GLOB.living_xeno_list) + if(xeno.hivenumber == hivenumber) + to_chat(xeno, SPAN_XENOMINORWARNING("We sense one of our Hive's facehugger traps at [area.name] has been burnt!")) /obj/effect/alien/resin/trap/proc/get_spray_type(level) switch(level) @@ -155,21 +157,21 @@ /obj/effect/alien/resin/trap/proc/trigger_trap(destroyed = FALSE) set waitfor = 0 - var/area/A = get_area(src) + var/area/area = get_area(src) var/trap_type_name = "" switch(trap_type) if(RESIN_TRAP_EMPTY) trap_type_name = "empty" if(RESIN_TRAP_HUGGER) trap_type_name = "hugger" - var/obj/item/clothing/mask/facehugger/FH = new (loc) - FH.hivenumber = hivenumber - set_hive_data(FH, hivenumber) + var/obj/item/clothing/mask/facehugger/hugger = new (loc) + hugger.hivenumber = hivenumber + set_hive_data(hugger, hivenumber) set_state() - visible_message(SPAN_WARNING("[FH] gets out of [src]!")) + visible_message(SPAN_WARNING("[hugger] gets out of [src]!")) sleep(15) - if(FH.stat == CONSCIOUS && FH.loc) //Make sure we're conscious and not idle or dead. - FH.leap_at_nearest_target() + if(hugger.stat == CONSCIOUS && hugger.loc) //Make sure we're conscious and not idle or dead. + hugger.leap_at_nearest_target() if(RESIN_TRAP_GAS) trap_type_name = "gas" smoke_system.set_up(2, 0, src.loc) @@ -181,22 +183,22 @@ var/spray_type = get_spray_type(trap_type) new spray_type(loc, cause_data, hivenumber) - for(var/turf/T in range(1,loc)) - var/obj/effect/xenomorph/spray/SP = new spray_type(T, cause_data, hivenumber) - for(var/mob/living/carbon/H in T) - if(H.ally_of_hivenumber(hivenumber)) + for(var/turf/turf in range(1,loc)) + var/obj/effect/xenomorph/spray/acid_splash = new spray_type(turf, cause_data, hivenumber) + for(var/mob/living/carbon/human in turf) + if(human.ally_of_hivenumber(hivenumber)) continue - SP.apply_spray(H) + acid_splash.apply_spray(human) set_state() clear_tripwires() - if(!A) + if(!area) return - for(var/mob/living/carbon/xenomorph/X in GLOB.living_xeno_list) - if(X.hivenumber == hivenumber) + for(var/mob/living/carbon/xenomorph/xeno in GLOB.living_xeno_list) + if(xeno.hivenumber == hivenumber) if(destroyed) - to_chat(X, SPAN_XENOMINORWARNING("We sense one of our Hive's [trap_type_name] traps at [A.name] has been destroyed!")) + to_chat(xeno, SPAN_XENOMINORWARNING("We sense one of our Hive's [trap_type_name] traps at [area.name] has been destroyed!")) else - to_chat(X, SPAN_XENOMINORWARNING("We sense one of our Hive's [trap_type_name] traps at [A.name] has been triggered!")) + to_chat(xeno, SPAN_XENOMINORWARNING("We sense one of our Hive's [trap_type_name] traps at [area.name] has been triggered!")) /obj/effect/alien/resin/trap/proc/clear_tripwires() QDEL_NULL_LIST(tripwires) @@ -229,50 +231,50 @@ /obj/effect/alien/resin/trap/proc/setup_tripwires() clear_tripwires() - for(var/turf/T in orange(1,loc)) - if(T.density) + for(var/turf/turf in orange(1,loc)) + if(turf.density) continue - var/obj/effect/trap_tripwire/new_tripwire = new /obj/effect/trap_tripwire(T) + var/obj/effect/trap_tripwire/new_tripwire = new /obj/effect/trap_tripwire(turf) new_tripwire.linked_trap = src tripwires += new_tripwire -/obj/effect/alien/resin/trap/attackby(obj/item/W, mob/user) - if(!(istype(W, /obj/item/clothing/mask/facehugger) && isxeno(user))) +/obj/effect/alien/resin/trap/attackby(obj/item/weapon, mob/user) + if(!(istype(weapon, /obj/item/clothing/mask/facehugger) && isxeno(user))) return ..() if(trap_type != RESIN_TRAP_EMPTY) to_chat(user, SPAN_XENOWARNING("You can't put a hugger in this trap!")) return - var/obj/item/clothing/mask/facehugger/FH = W - if(FH.stat == DEAD) + var/obj/item/clothing/mask/facehugger/hugger = weapon + if(hugger.stat == DEAD) to_chat(user, SPAN_XENOWARNING("You can't put a dead facehugger in [src].")) else - var/mob/living/carbon/xenomorph/X = user - if (!istype(X)) + var/mob/living/carbon/xenomorph/xeno = user + if(!istype(xeno)) return - if (X.hivenumber != hivenumber) + if(xeno.hivenumber != hivenumber) to_chat(user, SPAN_XENOWARNING("This resin trap doesn't belong to your hive!")) return - if (FH.hivenumber != hivenumber) + if(hugger.hivenumber != hivenumber) to_chat(user, SPAN_XENOWARNING("This facehugger is tainted.")) return - if (!do_after(user, 3 SECONDS, INTERRUPT_ALL|INTERRUPT_DAZED, BUSY_ICON_HOSTILE)) + if(!do_after(user, 3 SECONDS, INTERRUPT_ALL|INTERRUPT_DAZED, BUSY_ICON_HOSTILE)) return set_state(RESIN_TRAP_HUGGER) to_chat(user, SPAN_XENONOTICE("You place a facehugger in [src].")) - qdel(FH) + qdel(hugger) /obj/effect/alien/resin/trap/healthcheck() if(trap_type != RESIN_TRAP_EMPTY && loc) trigger_trap() ..() -/obj/effect/alien/resin/trap/Crossed(atom/A) - if(ismob(A) || isVehicleMultitile(A)) - HasProximity(A) +/obj/effect/alien/resin/trap/Crossed(atom/atom) + if(ismob(atom) || isVehicleMultitile(atom)) + HasProximity(atom) /obj/effect/alien/resin/trap/Destroy() QDEL_NULL_LIST(tripwires) @@ -292,7 +294,7 @@ linked_trap = null . = ..() -/obj/effect/trap_tripwire/Crossed(atom/A) +/obj/effect/trap_tripwire/Crossed(atom/atom) if(!linked_trap) qdel(src) return @@ -301,5 +303,5 @@ qdel(src) return - if(ishuman(A) || isxeno(A) || isVehicleMultitile(A)) - linked_trap.HasProximity(A) + if(ishuman(atom) || isxeno(atom) || isVehicleMultitile(atom)) + linked_trap.HasProximity(atom) diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm index 0ea27be28d18..473b8d05a3cc 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/burrower/burrower_abilities.dm @@ -6,7 +6,7 @@ action_icon_state = "agility_on" macro_path = /datum/action/xeno_action/verb/verb_burrow action_type = XENO_ACTION_CLICK - ability_primacy = XENO_PRIMARY_ACTION_3 + ability_primacy = XENO_PRIMARY_ACTION_2 /datum/action/xeno_action/activable/burrow/use_ability(atom/A) var/mob/living/carbon/xenomorph/xenomorph = owner diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm index ed9ad321ce4b..8399c898ab66 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/carrier/carrier_abilities.dm @@ -3,7 +3,7 @@ action_icon_state = "throw_hugger" macro_path = /datum/action/xeno_action/verb/verb_throw_facehugger action_type = XENO_ACTION_CLICK - ability_primacy = XENO_PRIMARY_ACTION_3 + ability_primacy = XENO_PRIMARY_ACTION_4 /datum/action/xeno_action/activable/throw_hugger/action_cooldown_check() if(owner) @@ -16,7 +16,7 @@ action_icon_state = "retrieve_egg" macro_path = /datum/action/xeno_action/verb/verb_retrieve_egg action_type = XENO_ACTION_CLICK - ability_primacy = XENO_PRIMARY_ACTION_4 + ability_primacy = XENO_PRIMARY_ACTION_5 /datum/action/xeno_action/onclick/set_hugger_reserve name = "Set Hugger Reserve" diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm index f5814158d3e7..63157023e439 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_abilities.dm @@ -82,6 +82,9 @@ /datum/action/xeno_action/onclick/choose_resin/queen_macro //so it doesn't screw other macros up ability_primacy = XENO_PRIMARY_ACTION_4 //it's important that hivelord and drone have the same macros because their playstyle is similar, but it's not as important for queen since her playstyle is very different +/datum/action/xeno_action/onclick/choose_resin/burrower + ability_primacy = XENO_NOT_PRIMARY_ACTION + // Secrete Resin /datum/action/xeno_action/activable/secrete_resin name = "Secrete Resin" @@ -429,14 +432,6 @@ if(xeno.layer == XENO_HIDING_LAYER) button.icon_state = "template_active" -/datum/action/xeno_action/onclick/place_trap - name = "Place resin hole (200)" - action_icon_state = "place_trap" - plasma_cost = 200 - macro_path = /datum/action/xeno_action/verb/verb_resin_hole - action_type = XENO_ACTION_CLICK - ability_primacy = XENO_PRIMARY_ACTION_2 - /datum/action/xeno_action/activable/place_construction name = "Order Construction (400)" action_icon_state = "morph_resin" diff --git a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm index ce24257b472a..bb90c1d7bd42 100644 --- a/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm +++ b/code/modules/mob/living/carbon/xenomorph/abilities/general_powers.dm @@ -3,7 +3,7 @@ // and abilities files hold the object declarations for the abilities // Plant weeds -/datum/action/xeno_action/onclick/plant_weeds/use_ability(atom/A) +/datum/action/xeno_action/onclick/plant_weeds/use_ability(atom/atom) var/mob/living/carbon/xenomorph/xeno = owner if(!action_cooldown_check()) return @@ -131,41 +131,41 @@ return ..() // Shift spits -/datum/action/xeno_action/onclick/shift_spits/use_ability(atom/A) - var/mob/living/carbon/xenomorph/X = owner - if(!X.check_state()) - return - for(var/i in 1 to length(X.caste.spit_types)) - if(X.ammo == GLOB.ammo_list[X.caste.spit_types[i]]) - if(i == length(X.caste.spit_types)) - X.ammo = GLOB.ammo_list[X.caste.spit_types[1]] +/datum/action/xeno_action/onclick/shift_spits/use_ability(atom/atom) + var/mob/living/carbon/xenomorph/xeno = owner + if(!xeno.check_state()) + return + for(var/i in 1 to length(xeno.caste.spit_types)) + if(xeno.ammo == GLOB.ammo_list[xeno.caste.spit_types[i]]) + if(i == length(xeno.caste.spit_types)) + xeno.ammo = GLOB.ammo_list[xeno.caste.spit_types[1]] else - X.ammo = GLOB.ammo_list[X.caste.spit_types[i+1]] + xeno.ammo = GLOB.ammo_list[xeno.caste.spit_types[i+1]] break - to_chat(X, SPAN_NOTICE("We will now spit [X.ammo.name] ([X.ammo.spit_cost] plasma).")) + to_chat(xeno, SPAN_NOTICE("We will now spit [xeno.ammo.name] ([xeno.ammo.spit_cost] plasma).")) button.overlays.Cut() - button.overlays += image('icons/mob/hud/actions_xeno.dmi', button, "shift_spit_[X.ammo.icon_state]") + button.overlays += image('icons/mob/hud/actions_xeno.dmi', button, "shift_spit_[xeno.ammo.icon_state]") return ..() -/datum/action/xeno_action/onclick/release_haul/use_ability(atom/A) - var/mob/living/carbon/xenomorph/X = owner - if(!X.check_state()) +/datum/action/xeno_action/onclick/release_haul/use_ability(atom/atom) + var/mob/living/carbon/xenomorph/xeno = owner + if(!xeno.check_state()) return - if(!isturf(X.loc)) - to_chat(X, SPAN_WARNING("We cannot put them down here.")) + if(!isturf(xeno.loc)) + to_chat(xeno, SPAN_WARNING("We cannot put them down here.")) return - X.release_haul(TRUE) + xeno.release_haul(TRUE) return ..() -/datum/action/xeno_action/onclick/choose_resin/use_ability(atom/A) - var/mob/living/carbon/xenomorph/X = owner - if(!X.check_state()) +/datum/action/xeno_action/onclick/choose_resin/use_ability(atom/atom) + var/mob/living/carbon/xenomorph/xeno = owner + if(!xeno.check_state()) return - tgui_interact(X) + tgui_interact(xeno) return ..() /datum/action/xeno_action/onclick/choose_resin/ui_assets(mob/user) @@ -174,34 +174,34 @@ ) /datum/action/xeno_action/onclick/choose_resin/ui_static_data(mob/user) - var/mob/living/carbon/xenomorph/X = user - if(!istype(X)) + var/mob/living/carbon/xenomorph/xeno = user + if(!istype(xeno)) return . = list() var/list/constructions = list() - for(var/type in X.resin_build_order) + for(var/type in xeno.resin_build_order) var/list/entry = list() - var/datum/resin_construction/RC = GLOB.resin_constructions_list[type] + var/datum/resin_construction/resin_construct = GLOB.resin_constructions_list[type] - entry["name"] = RC.name - entry["desc"] = RC.desc - entry["image"] = replacetext(RC.construction_name, " ", "-") - entry["plasma_cost"] = RC.cost - entry["max_per_xeno"] = RC.max_per_xeno + entry["name"] = resin_construct.name + entry["desc"] = resin_construct.desc + entry["image"] = replacetext(resin_construct.construction_name, " ", "-") + entry["plasma_cost"] = resin_construct.cost + entry["max_per_xeno"] = resin_construct.max_per_xeno entry["id"] = "[type]" constructions += list(entry) .["constructions"] = constructions /datum/action/xeno_action/onclick/choose_resin/ui_data(mob/user) - var/mob/living/carbon/xenomorph/X = user - if(!istype(X)) + var/mob/living/carbon/xenomorph/xeno = user + if(!istype(xeno)) return . = list() - .["selected_resin"] = X.selected_resin + .["selected_resin"] = xeno.selected_resin /datum/action/xeno_action/onclick/choose_resin/tgui_interact(mob/user, datum/tgui/ui) @@ -223,18 +223,18 @@ if(.) return - var/mob/living/carbon/xenomorph/X = usr - if(!istype(X)) + var/mob/living/carbon/xenomorph/xeno = usr + if(!istype(xeno)) return switch(action) if("choose_resin") var/selected_type = text2path(params["type"]) - if(!(selected_type in X.resin_build_order)) + if(!(selected_type in xeno.resin_build_order)) return //update the button's overlay with new choice update_button_icon(selected_type, to_chat=TRUE) - X.selected_resin = selected_type + xeno.selected_resin = selected_type . = TRUE if("refresh_ui") . = TRUE @@ -277,7 +277,7 @@ // leader Marker -/datum/action/xeno_action/activable/info_marker/use_ability(atom/A, mods) +/datum/action/xeno_action/activable/info_marker/use_ability(atom/atom, mods) if(!..()) return FALSE @@ -287,50 +287,50 @@ if(!action_cooldown_check()) return - var/mob/living/carbon/xenomorph/X = owner - if(!X.check_state(TRUE)) + var/mob/living/carbon/xenomorph/xeno = owner + if(!xeno.check_state(TRUE)) return FALSE - if(ismob(A)) //anticheese : if they click a mob, it will cancel. - to_chat(X, SPAN_XENOWARNING("We can't place resin markers on living things!")) + if(ismob(atom)) //anticheese : if they click a mob, it will cancel. + to_chat(xeno, SPAN_XENOWARNING("We can't place resin markers on living things!")) return FALSE //this is because xenos have thermal vision and can see mobs through walls - which would negate not being able to place them through walls - if(isstorage(A.loc) || X.contains(A) || istype(A, /atom/movable/screen)) + if(isstorage(atom.loc) || xeno.contains(atom) || istype(atom, /atom/movable/screen)) return FALSE - var/turf/target_turf = get_turf(A) + var/turf/target_turf = get_turf(atom) - if(!SSmapping.same_z_map(X.loc.z, target_turf.loc.z)) - to_chat(X, SPAN_XENOWARNING("Our mind cannot reach that far.")) + if(!SSmapping.same_z_map(xeno.loc.z, target_turf.loc.z)) + to_chat(xeno, SPAN_XENOWARNING("Our mind cannot reach that far.")) return - if(!X.hive.living_xeno_queen || !SSmapping.same_z_map(X.hive.living_xeno_queen.z, X.z)) - to_chat(X, SPAN_XENOWARNING("Our psychic link is gone, the Queen is either dead or too far away!")) + if(!xeno.hive.living_xeno_queen || !SSmapping.same_z_map(xeno.hive.living_xeno_queen.z, xeno.z)) + to_chat(xeno, SPAN_XENOWARNING("Our psychic link is gone, the Queen is either dead or too far away!")) return var/tally = 0 - for(var/obj/effect/alien/resin/marker/MRK in X.hive.resin_marks) - if(MRK.createdby == X.nicknumber) + for(var/obj/effect/alien/resin/marker/hive_marker in xeno.hive.resin_marks) + if(hive_marker.createdby == xeno.nicknumber) tally++ if(tally >= max_markers) - to_chat(X, SPAN_XENOWARNING("We have reached the maximum number of resin marks.")) + to_chat(xeno, SPAN_XENOWARNING("We have reached the maximum number of resin marks.")) var/list/promptlist = list("Yes", "No") - var/obj/effect/alien/resin/marker/Goober = null + var/obj/effect/alien/resin/marker/goober = null var/promptuser = null - for(var/i=1, i<=length(X.hive.resin_marks)) - Goober = X.hive.resin_marks[i] - if(Goober.createdby == X.nicknumber) - promptuser = tgui_input_list(X, "Remove oldest placed mark: '[Goober.mark_meaning.name]!'?", "Mark limit reached.", promptlist, theme="hive_status") + for(var/i=1, i<=length(xeno.hive.resin_marks)) + goober = xeno.hive.resin_marks[i] + if(goober.createdby == xeno.nicknumber) + promptuser = tgui_input_list(xeno, "Remove oldest placed mark: '[goober.mark_meaning.name]!'?", "Mark limit reached.", promptlist, theme="hive_status") break i++ if(promptuser == "No") return else if(promptuser == "Yes") - qdel(Goober) - if(X.make_marker(target_turf)) + qdel(goober) + if(xeno.make_marker(target_turf)) apply_cooldown() return TRUE - else if(X.make_marker(target_turf)) + else if(xeno.make_marker(target_turf)) apply_cooldown() return TRUE @@ -457,8 +457,8 @@ playsound(loc, "alien_drool", 25) if(isqueen(src) && hive && length(hive.xeno_leader_list) && anchored) - for(var/mob/living/carbon/xenomorph/L in hive.xeno_leader_list) - L.handle_xeno_leader_pheromones() + for(var/mob/living/carbon/xenomorph/leader in hive.xeno_leader_list) + leader.handle_xeno_leader_pheromones() /datum/action/xeno_action/activable/pounce/use_ability(atom/target) var/mob/living/carbon/xenomorph/xeno = owner @@ -517,23 +517,23 @@ to_chat(xeno, SPAN_WARNING("You can't jump over an object in your path.")) return - if (!do_after(xeno, 0.5 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE)) + if(!do_after(xeno, 0.5 SECONDS, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE)) return if(target.z != xeno.z && xeno.mob_size >= MOB_SIZE_BIG) - if (!do_after(xeno, 2 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE)) + if(!do_after(xeno, 2 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE)) return apply_cooldown() - if (windup) + if(windup) xeno.set_face_dir(get_cardinal_dir(xeno, target)) - if (!windup_interruptable) + if(!windup_interruptable) ADD_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Pounce")) xeno.anchored = TRUE pre_windup_effects() - if (!do_after(xeno, windup_duration, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE)) + if(!do_after(xeno, windup_duration, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE)) to_chat(xeno, SPAN_XENODANGER("We cancel our [action_text]!")) if (!windup_interruptable) REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Pounce")) @@ -541,7 +541,7 @@ post_windup_effects(interrupted = TRUE) return - if (!windup_interruptable) + if(!windup_interruptable) REMOVE_TRAIT(xeno, TRAIT_IMMOBILIZED, TRAIT_SOURCE_ABILITY("Pounce")) xeno.anchored = FALSE post_windup_effects() @@ -562,32 +562,32 @@ return TRUE // Massive, customizable spray_acid -/datum/action/xeno_action/activable/spray_acid/use_ability(atom/A) - var/mob/living/carbon/xenomorph/X = owner +/datum/action/xeno_action/activable/spray_acid/use_ability(atom/atom) + var/mob/living/carbon/xenomorph/xeno = owner if(!action_cooldown_check()) return - if(!A) + if(!atom) return - if(A.layer >= FLY_LAYER) + if(atom.layer >= FLY_LAYER) return - if(!isturf(X.loc)) - to_chat(X, SPAN_XENOWARNING("We can't [action_text] from here!")) + if(!isturf(xeno.loc)) + to_chat(xeno, SPAN_XENOWARNING("We can't [action_text] from here!")) return - if(!X.check_state() || X.action_busy) + if(!xeno.check_state() || xeno.action_busy) return - if (activation_delay) - if(!do_after(X, activation_delay_length, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE)) - to_chat(X, SPAN_XENOWARNING("We decide to cancel our acid spray.")) + if(activation_delay) + if(!do_after(xeno, activation_delay_length, INTERRUPT_NO_NEEDHAND, BUSY_ICON_HOSTILE)) + to_chat(xeno, SPAN_XENOWARNING("We decide to cancel our acid spray.")) end_cooldown() return - if (!action_cooldown_check()) + if(!action_cooldown_check()) return apply_cooldown() @@ -595,17 +595,17 @@ if(!check_and_use_plasma_owner()) return - playsound(get_turf(X), 'sound/effects/refill.ogg', 25, 1) - X.visible_message(SPAN_XENOWARNING("[X] vomits a flood of acid!"), SPAN_XENOWARNING("We vomit a flood of acid!"), null, 5) + playsound(get_turf(xeno), 'sound/effects/refill.ogg', 25, 1) + xeno.visible_message(SPAN_XENOWARNING("[xeno] vomits a flood of acid!"), SPAN_XENOWARNING("We vomit a flood of acid!"), null, 5) apply_cooldown() // Build our list of target turfs based on - if (spray_type == ACID_SPRAY_LINE) - X.do_acid_spray_line(get_line(X, A, include_start_atom = FALSE), spray_effect_type, spray_distance) + if(spray_type == ACID_SPRAY_LINE) + xeno.do_acid_spray_line(get_line(xeno, atom, include_start_atom = FALSE), spray_effect_type, spray_distance) - else if (spray_type == ACID_SPRAY_CONE) - X.do_acid_spray_cone(get_turf(A), spray_effect_type, spray_distance) + else if(spray_type == ACID_SPRAY_CONE) + xeno.do_acid_spray_cone(get_turf(atom), spray_effect_type, spray_distance) return ..() @@ -636,55 +636,6 @@ if(!QDELETED(source) && (new_stat >= UNCONSCIOUS && old_stat <= UNCONSCIOUS)) post_attack() -/datum/action/xeno_action/onclick/place_trap/use_ability(atom/target) - var/mob/living/carbon/xenomorph/xeno = owner - if(!xeno.check_state()) - return - - if(HAS_TRAIT(xeno, TRAIT_ABILITY_BURROWED)) - return - - var/turf/turf = get_turf(xeno) - if(!istype(turf)) - to_chat(xeno, SPAN_XENOWARNING("We can't do that here.")) - return - - var/area/area = turf.loc - if(!area?.is_resin_allowed) - if(!area || area.flags_area & AREA_UNWEEDABLE) - to_chat(xeno, SPAN_XENOWARNING("We sense this is not a suitable area for creating a resin hole.")) - return - to_chat(xeno, SPAN_XENOWARNING("It's too early to spread the hive this far.")) - return - if(istype(area,/area/shuttle/drop1/lz1) || istype(area,/area/shuttle/drop2/lz2) || SSinterior.in_interior(owner)) - to_chat(xeno, SPAN_WARNING("We sense this is not a suitable area for creating a resin hole.")) - return - - var/obj/effect/alien/weeds/alien_weeds = turf.check_xeno_trap_placement(xeno) - if(!alien_weeds) - return - - if(istype(alien_weeds, /obj/effect/alien/weeds/node)) - to_chat(xeno, SPAN_NOTICE("We start uprooting the node so we can put the resin hole in its place...")) - if(!do_after(xeno, 1 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC, target, INTERRUPT_ALL)) - return - if(!turf.check_xeno_trap_placement(xeno)) - return - var/obj/effect/alien/weeds/the_replacer = new /obj/effect/alien/weeds(turf) - the_replacer.hivenumber = xeno.hivenumber - the_replacer.linked_hive = xeno.hive - set_hive_data(the_replacer, xeno.hivenumber) - qdel(alien_weeds) - - if(!xeno.check_plasma(plasma_cost)) - return - - xeno.use_plasma(plasma_cost) - playsound(xeno.loc, "alien_resin_build", 25) - new /obj/effect/alien/resin/trap(turf, xeno) - to_chat(xeno, SPAN_XENONOTICE("We place a resin hole on the weeds, it still needs a sister to fill it with acid.")) - return ..() - /turf/proc/check_xeno_trap_placement(mob/living/carbon/xenomorph/xeno) if(is_weedable < FULLY_WEEDABLE || !can_xeno_build(src)) to_chat(xeno, SPAN_XENOWARNING("We can't do that here.")) @@ -816,7 +767,6 @@ if(!spacecheck(xeno, target_turf, structure_template)) // spacecheck already cleans up the template return FALSE - if((choice == XENO_STRUCTURE_EGGMORPH) && locate(/obj/structure/flora/grass/tallgrass) in target_turf) to_chat(xeno, SPAN_WARNING("The tallgrass is preventing us from building the egg morpher!")) qdel(structure_template) @@ -882,25 +832,25 @@ // XSS Spacecheck -/datum/action/xeno_action/activable/place_construction/proc/spacecheck(mob/living/carbon/xenomorph/X, turf/T, datum/construction_template/xenomorph/tem) +/datum/action/xeno_action/activable/place_construction/proc/spacecheck(mob/living/carbon/xenomorph/xeno, turf/turf, datum/construction_template/xenomorph/tem) if(tem.block_range) - for(var/turf/TA in range(tem.block_range, T)) - if(!X.check_alien_construction(TA, FALSE, TRUE, ignore_nest = TRUE)) - to_chat(X, SPAN_WARNING("We need more open space to build here.")) + for(var/turf/turf_target in range(tem.block_range, turf)) + if(!xeno.check_alien_construction(turf_target, FALSE, TRUE, ignore_nest = TRUE)) + to_chat(xeno, SPAN_WARNING("We need more open space to build here.")) qdel(tem) return FALSE - if(!X.check_alien_construction(T, ignore_nest = TRUE)) - to_chat(X, SPAN_WARNING("We need more open space to build here.")) + if(!xeno.check_alien_construction(turf, ignore_nest = TRUE)) + to_chat(xeno, SPAN_WARNING("We need more open space to build here.")) qdel(tem) return FALSE - var/obj/effect/alien/weeds/alien_weeds = locate() in T - if(!alien_weeds || alien_weeds.weed_strength < WEED_LEVEL_HIVE || alien_weeds.linked_hive.hivenumber != X.hivenumber) - to_chat(X, SPAN_WARNING("We can only shape on [lowertext(GLOB.hive_datum[X.hivenumber].prefix)]hive weeds. We must find a hive node or core before we start building!")) + var/obj/effect/alien/weeds/alien_weeds = locate() in turf + if(!alien_weeds || alien_weeds.weed_strength < WEED_LEVEL_HIVE || alien_weeds.linked_hive.hivenumber != xeno.hivenumber) + to_chat(xeno, SPAN_WARNING("We can only shape on [lowertext(GLOB.hive_datum[xeno.hivenumber].prefix)]hive weeds. We must find a hive node or core before we start building!")) qdel(tem) return FALSE - if(T.density) + if(turf.density) qdel(tem) - to_chat(X, SPAN_WARNING("We need empty space to build this.")) + to_chat(xeno, SPAN_WARNING("We need empty space to build this.")) return FALSE return TRUE @@ -927,7 +877,7 @@ if(!current_turf) return - if (!check_plasma_owner()) + if(!check_plasma_owner()) return if(xeno.ammo.spit_windup) @@ -937,7 +887,7 @@ to_chat(xeno, SPAN_WARNING("We begin to prepare a large spit!")) xeno.visible_message(SPAN_WARNING("[xeno] prepares to spit a massive glob!"), SPAN_WARNING("We begin to spit [xeno.ammo.name]!")) - if (!do_after(xeno, xeno.ammo.spit_windup, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_HOSTILE)) + if(!do_after(xeno, xeno.ammo.spit_windup, INTERRUPT_ALL|BEHAVIOR_IMMOBILE, BUSY_ICON_HOSTILE)) to_chat(xeno, SPAN_XENODANGER("We decide to cancel our spit.")) spitting = FALSE return @@ -968,7 +918,7 @@ /datum/action/xeno_action/activable/bombard/use_ability(atom/atom) var/mob/living/carbon/xenomorph/xeno = owner - if (!istype(xeno) || !xeno.check_state() || !action_cooldown_check() || xeno.action_busy) + if(!istype(xeno) || !xeno.check_state() || !action_cooldown_check() || xeno.action_busy) return FALSE var/turf/turf = get_turf(atom) @@ -977,7 +927,7 @@ to_chat(xeno, SPAN_XENODANGER("We can't bombard that!")) return FALSE - if (!check_plasma_owner()) + if(!check_plasma_owner()) return FALSE if(turf.z != xeno.z) @@ -985,18 +935,18 @@ return FALSE var/atom/bombard_source = get_bombard_source() - if (!xeno.can_bombard_turf(turf, range, bombard_source)) + if(!xeno.can_bombard_turf(turf, range, bombard_source)) return FALSE xeno.visible_message(SPAN_XENODANGER("[xeno] digs itself into place!"), SPAN_XENODANGER("We dig ourself into place!")) - if (!do_after(xeno, activation_delay, interrupt_flags, BUSY_ICON_HOSTILE)) + if(!do_after(xeno, activation_delay, interrupt_flags, BUSY_ICON_HOSTILE)) to_chat(xeno, SPAN_XENODANGER("We decide to cancel our bombard.")) return FALSE - if (!xeno.can_bombard_turf(turf, range, bombard_source)) //Second check in case something changed during the do_after. + if(!xeno.can_bombard_turf(turf, range, bombard_source)) //Second check in case something changed during the do_after. return FALSE - if (!check_and_use_plasma_owner()) + if(!check_and_use_plasma_owner()) return FALSE apply_cooldown() @@ -1008,33 +958,32 @@ return ..() -/datum/action/xeno_action/activable/bombard/proc/recursive_spread(turf/T, dist_left, orig_depth) - if(!istype(T)) +/datum/action/xeno_action/activable/bombard/proc/recursive_spread(turf/turf, dist_left, orig_depth) + if(!istype(turf)) return else if(dist_left == 0) return - else if(istype(T, /turf/closed) || istype(T, /turf/open/space)) + else if(istype(turf, /turf/closed) || istype(turf, /turf/open/space)) return - else if(!T.can_bombard(owner)) + else if(!turf.can_bombard(owner)) return - addtimer(CALLBACK(src, PROC_REF(new_effect), T, owner), 2*(orig_depth - dist_left)) + addtimer(CALLBACK(src, PROC_REF(new_effect), turf, owner), 2*(orig_depth - dist_left)) - for(var/mob/living/L in T) - to_chat(L, SPAN_XENOHIGHDANGER("You see a massive ball of acid flying towards you!")) + for(var/mob/living/living in turf) + to_chat(living, SPAN_XENOHIGHDANGER("You see a massive ball of acid flying towards you!")) for(var/dirn in GLOB.alldirs) - recursive_spread(get_step(T, dirn), dist_left - 1, orig_depth) - + recursive_spread(get_step(turf, dirn), dist_left - 1, orig_depth) -/datum/action/xeno_action/activable/bombard/proc/new_effect(turf/T, mob/living/carbon/xenomorph/X) - if(!istype(T)) +/datum/action/xeno_action/activable/bombard/proc/new_effect(turf/turf, mob/living/carbon/xenomorph/xeno) + if(!istype(turf)) return - for(var/obj/effect/xenomorph/boiler_bombard/BB in T) + if(locate(/obj/effect/xenomorph/boiler_bombard) in turf) return - new effect_type(T, X) + new effect_type(turf, xeno) /datum/action/xeno_action/activable/bombard/proc/get_bombard_source() return owner @@ -1042,13 +991,13 @@ /turf/proc/can_bombard(mob/bombarder) if(!can_be_dissolved() && density) return FALSE - for(var/atom/A in src) - if(istype(A, /obj/structure/machinery)) + for(var/atom/atom in src) + if(istype(atom, /obj/structure/machinery)) continue // Machinery shouldn't block boiler gas (e.g. computers) - if(ismob(A)) + if(ismob(atom)) continue // Mobs shouldn't block boiler gas - if(A && A.unacidable && A.density && !(A.flags_atom & ON_BORDER)) + if(atom && atom.unacidable && atom.density && !(atom.flags_atom & ON_BORDER)) return FALSE return TRUE @@ -1060,7 +1009,7 @@ var/turf/current = bombard_source.loc var/turf/target_turf = get_turf(target) - if (get_dist_sqrd(current, target_turf) > (range*range)) + if(get_dist_sqrd(current, target_turf) > (range*range)) to_chat(src, SPAN_XENODANGER("That is too far away!")) return @@ -1073,8 +1022,8 @@ if(current.opacity) . = FALSE if(.) - for(var/atom/A in current) - if(A.opacity) + for(var/atom/atom in current) + if(atom.opacity) . = FALSE break if(!.) @@ -1103,7 +1052,7 @@ if(!action_cooldown_check()) return FALSE - if (world.time <= stabbing_xeno.next_move) + if(world.time <= stabbing_xeno.next_move) return FALSE if(stabbing_xeno.z != targetted_atom.z) @@ -1162,7 +1111,7 @@ return FALSE var/obj/limb/limb = target.get_limb(check_zone(stabbing_xeno.zone_selected)) - if (ishuman(target) && (!limb || (limb.status & LIMB_DESTROYED))) + if(ishuman(target) && (!limb || (limb.status & LIMB_DESTROYED))) to_chat(stabbing_xeno, (SPAN_WARNING("What [limb.display_name]?"))) return FALSE diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm b/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm index 6f2b4820387c..8b1058c56919 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Burrower.dm @@ -19,6 +19,7 @@ acid_level = 2 weed_level = WEED_LEVEL_STANDARD evolution_allowed = FALSE + max_build_dist = 1 behavior_delegate_type = /datum/behavior_delegate/burrower_base @@ -35,6 +36,11 @@ minimap_icon = "burrower" +/datum/caste_datum/burrower/New(mob/living/carbon/xenomorph/burrower) + . = ..() + + resin_build_order = GLOB.resin_build_order_burrower + /mob/living/carbon/xenomorph/burrower caste_type = XENO_CASTE_BURROWER name = XENO_CASTE_BURROWER @@ -43,6 +49,7 @@ icon_size = 64 icon_state = "Burrower Walking" layer = MOB_LAYER + claw_type = CLAW_TYPE_VERY_SHARP plasma_stored = 100 plasma_types = list(PLASMA_PURPLE) pixel_x = -12 @@ -60,11 +67,12 @@ /datum/action/xeno_action/activable/tail_stab, /datum/action/xeno_action/activable/corrosive_acid, /datum/action/xeno_action/activable/place_construction, - /datum/action/xeno_action/onclick/build_tunnel, /datum/action/xeno_action/onclick/plant_weeds, //first macro - /datum/action/xeno_action/onclick/place_trap, //second macro - /datum/action/xeno_action/activable/burrow, //third macro + /datum/action/xeno_action/activable/burrow, //second macro + /datum/action/xeno_action/onclick/choose_resin/burrower, + /datum/action/xeno_action/activable/secrete_resin, //third macro /datum/action/xeno_action/onclick/tremor, //fourth macro + /datum/action/xeno_action/onclick/build_tunnel, /datum/action/xeno_action/active_toggle/toggle_meson_vision, ) diff --git a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm index b17bf5c17337..f383855ceb9a 100644 --- a/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm +++ b/code/modules/mob/living/carbon/xenomorph/castes/Carrier.dm @@ -42,6 +42,11 @@ minimap_icon = "carrier" +/datum/caste_datum/carrier/New(mob/living/carbon/xenomorph/carrier) + . = ..() + + resin_build_order = GLOB.resin_build_order_carrier + /mob/living/carbon/xenomorph/carrier caste_type = XENO_CASTE_CARRIER name = XENO_CASTE_CARRIER @@ -68,9 +73,10 @@ /datum/action/xeno_action/activable/place_construction, /datum/action/xeno_action/onclick/emit_pheromones, /datum/action/xeno_action/onclick/plant_weeds, //1st macro - /datum/action/xeno_action/onclick/place_trap, //2nd macro - /datum/action/xeno_action/activable/throw_hugger, //3rd macro - /datum/action/xeno_action/activable/retrieve_egg, //4th macro + /datum/action/xeno_action/onclick/choose_resin, //2nd macro + /datum/action/xeno_action/activable/secrete_resin, //3rd macro + /datum/action/xeno_action/activable/throw_hugger, //4rd macro + /datum/action/xeno_action/activable/retrieve_egg, //5th macro /datum/action/xeno_action/onclick/set_hugger_reserve, ) diff --git a/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm b/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm index 418e66c10ef2..557ac998bf4c 100644 --- a/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm +++ b/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm @@ -14,79 +14,106 @@ var/build_path_thick var/max_per_xeno = RESIN_CONSTRUCTION_NO_MAX + var/is_trap = FALSE var/thick_hiveweed = FALSE // if this is set, the thick variants will only work on hiveweeds var/can_build_on_doors = TRUE // if it can be built on a tile with an open door or not /// Whether this construction gets more expensive the more saturated the area is var/scaling_cost = FALSE -/datum/resin_construction/proc/can_build_here(turf/T, mob/living/carbon/xenomorph/X) - var/mob/living/carbon/xenomorph/blocker = locate() in T - if(blocker && blocker != X && blocker.stat != DEAD) - to_chat(X, SPAN_WARNING("Can't do that with [blocker] in the way!")) +/datum/resin_construction/proc/can_build_here(turf/turf, mob/living/carbon/xenomorph/xeno) + var/mob/living/carbon/xenomorph/blocker = locate() in turf + if(blocker && blocker != xeno && blocker.stat != DEAD) + to_chat(xeno, SPAN_WARNING("Can't do that with [blocker] in the way!")) return FALSE - if(!istype(T)) + if(!istype(turf)) return FALSE - if(T.is_weedable < FULLY_WEEDABLE) + if(turf.is_weedable < FULLY_WEEDABLE) var/has_node = FALSE - for(var/obj/effect/alien/resin/design/node in T) + for(var/obj/effect/alien/resin/design/node in turf) has_node = TRUE break if(!has_node) - to_chat(X, SPAN_WARNING("You can't do that here without design nodes.")) + to_chat(xeno, SPAN_WARNING("You can't do that here without design nodes.")) return FALSE if(!check_for_wall_or_door()) - to_chat(X, SPAN_WARNING("This terrain is unsuitable for other resin secretions, only walls and doors can be built on this node.")) + to_chat(xeno, SPAN_WARNING("This terrain is unsuitable for other resin secretions, only walls and doors can be built on this node.")) return FALSE - var/area/AR = get_area(T) - if(isnull(AR) || !(AR.is_resin_allowed)) - if(!AR || AR.flags_area & AREA_UNWEEDABLE) - to_chat(X, SPAN_XENOWARNING("This area is unsuited to host the hive!")) + var/area/area = get_area(turf) + if(isnull(area) || !(area.is_resin_allowed)) + if(!area || area.flags_area & AREA_UNWEEDABLE) + to_chat(xeno, SPAN_XENOWARNING("This area is unsuited to host the hive!")) return - to_chat(X, SPAN_XENOWARNING("It's too early to spread the hive this far.")) + to_chat(xeno, SPAN_XENOWARNING("It's too early to spread the hive this far.")) return FALSE - if(!(AR.resin_construction_allowed)) //disable resin walls not weed, in special circumstances EG. Stairs and Dropship turfs - to_chat(X, SPAN_WARNING("You sense this is not a suitable area for expanding the hive.")) + if(!(area.resin_construction_allowed)) //disable resin walls not weed, in special circumstances EG. Stairs and Dropship turfs + to_chat(xeno, SPAN_WARNING("We sense this is not a suitable area for expanding the hive.")) return FALSE - var/obj/effect/alien/weeds/alien_weeds = locate() in T + var/obj/effect/alien/weeds/alien_weeds = locate() in turf if(!alien_weeds) - to_chat(X, SPAN_WARNING("You can only shape on weeds. Find some resin before you start building!")) + to_chat(xeno, SPAN_WARNING("You can only shape on weeds. Find some resin before you start building!")) return FALSE if(alien_weeds?.block_structures >= BLOCK_ALL_STRUCTURES) - to_chat(X, SPAN_WARNING("\The [alien_weeds] block the construction of any structures!")) + to_chat(xeno, SPAN_WARNING("[alien_weeds] block the construction of any structures!")) return FALSE - var/obj/vehicle/V = locate() in T - if(V) - to_chat(X, SPAN_WARNING("You cannot build under \the [V]!")) + var/obj/vehicle/vehicle = locate() in turf + if(vehicle) + to_chat(xeno, SPAN_WARNING("You cannot build under \the [vehicle]!")) return FALSE - if(alien_weeds.linked_hive.hivenumber != X.hivenumber) - to_chat(X, SPAN_WARNING("These weeds do not belong to your hive!")) + if(alien_weeds.linked_hive.hivenumber != xeno.hivenumber) + to_chat(xeno, SPAN_WARNING("These weeds do not belong to your hive!")) return FALSE - if(istype(T, /turf/closed/wall)) // Can't build in walls with no density - to_chat(X, SPAN_WARNING("This area is too unstable to support a construction.")) + if(istype(turf, /turf/closed/wall)) // Can't build in walls with no density + to_chat(xeno, SPAN_WARNING("This area is too unstable to support a construction")) return FALSE - if(!X.check_alien_construction(T, check_doors = !can_build_on_doors)) + if(!xeno.check_alien_construction(turf, check_doors = !can_build_on_doors)) return FALSE if(range_between_constructions) - for(var/i in long_range(range_between_constructions, T)) - var/atom/A = i - if(A.type == build_path) - to_chat(X, SPAN_WARNING("This is too close to another similar structure!")) + for(var/i in long_range(range_between_constructions, turf)) + var/atom/atom = i + if(atom.type == build_path) + to_chat(xeno, SPAN_WARNING("This is too close to another similar structure!")) return FALSE + if(is_trap) + if(istype(area,/area/shuttle/drop1/lz1) || istype(area,/area/shuttle/drop2/lz2) || SSinterior.in_interior(xeno)) + to_chat(xeno, SPAN_WARNING("We sense this is not a suitable area for creating a resin hole.")) + return + alien_weeds = turf.check_xeno_trap_placement(xeno) + if(!alien_weeds) + return + if(istype(alien_weeds, /obj/effect/alien/weeds/node)) + to_chat(xeno, SPAN_NOTICE("We start uprooting the node so we can put the resin hole in its place...")) + if(!do_after(xeno, 1 SECONDS, INTERRUPT_ALL, BUSY_ICON_GENERIC)) + return + if(!turf.check_xeno_trap_placement(xeno)) + return + var/obj/effect/alien/weeds/the_replacer = new /obj/effect/alien/weeds(turf) + the_replacer.hivenumber = xeno.hivenumber + the_replacer.linked_hive = xeno.hive + set_hive_data(the_replacer, xeno.hivenumber) + qdel(alien_weeds) + + if(!xeno.check_plasma(cost)) + return + xeno.use_plasma(cost) + playsound(xeno.loc, "alien_resin_build", 25) + new /obj/effect/alien/resin/trap(turf, xeno.hivenumber) + to_chat(xeno, SPAN_XENONOTICE("We place a resin hole on the weeds, it still needs a sister to fill it with acid.")) + return TRUE /datum/resin_construction/proc/check_for_wall_or_door() @@ -120,7 +147,7 @@ build_turf.place_on_top(path) var/turf/closed/wall/resin/resin_wall = build_turf - if (istype(resin_wall) && pass_hivenumber) + if(istype(resin_wall) && pass_hivenumber) resin_wall.hivenumber = hivenumber resin_wall.set_resin_builder(builder) set_hive_data(resin_wall, hivenumber) @@ -216,23 +243,23 @@ build_path = /obj/structure/mineral_door/resin build_animation_effect = /obj/effect/resin_construct/door -/datum/resin_construction/resin_obj/door/can_build_here(turf/T, mob/living/carbon/xenomorph/X) - if (!..()) +/datum/resin_construction/resin_obj/door/can_build_here(turf/turf, mob/living/carbon/xenomorph/xeno) + if(!..()) return FALSE var/wall_support = FALSE - for(var/D in GLOB.cardinals) - var/turf/CT = get_step(T, D) - if(CT) - if(CT.density) + for(var/dir in GLOB.cardinals) + var/turf/turf_target = get_step(turf, dir) + if(turf_target) + if(turf_target.density) wall_support = TRUE break - else if(locate(/obj/structure/mineral_door/resin) in CT) + else if(locate(/obj/structure/mineral_door/resin) in turf_target) wall_support = TRUE break if(!wall_support) - to_chat(X, SPAN_WARNING("Resin doors need a wall or resin door next to them to stand up.")) + to_chat(xeno, SPAN_WARNING("Resin doors need a wall or resin door next to them to stand up.")) return FALSE return TRUE @@ -291,6 +318,20 @@ build_path = /obj/effect/alien/resin/spike +/datum/resin_construction/resin_obj/resin_spike/burrower + cost = XENO_RESIN_SPIKE_BURROWER_COST + max_per_xeno = 30 + +/datum/resin_construction/resin_obj/resin_hole + name = "Resin Hole" + desc = "It looks like a hiding hole." + construction_name = "resin hole" + cost = XENO_RESIN_HOLE_COST + build_time = 1 SECONDS + is_trap = TRUE + + build_path = /obj/effect/alien/resin/trap + /datum/resin_construction/resin_obj/acid_pillar name = "Acid Pillar" desc = "A tall, green pillar that is capable of firing at multiple targets at once. Fires weak acid." @@ -305,6 +346,10 @@ range_between_constructions = 5 +/datum/resin_construction/resin_obj/acid_pillar/burrower + cost = XENO_RESIN_ACID_PILLAR_BURROWER_COST + range_between_constructions = 3 + /datum/resin_construction/resin_obj/shield_dispenser name = "Shield Pillar" desc = "A tall, strange pillar that gives shield to the interactor. Has a hefty cooldown." diff --git a/code/modules/mob/living/carbon/xenomorph/strains/castes/carrier/eggsac.dm b/code/modules/mob/living/carbon/xenomorph/strains/castes/carrier/eggsac.dm index c8a01d7f847b..b49c42b858fd 100644 --- a/code/modules/mob/living/carbon/xenomorph/strains/castes/carrier/eggsac.dm +++ b/code/modules/mob/living/carbon/xenomorph/strains/castes/carrier/eggsac.dm @@ -6,7 +6,8 @@ actions_to_remove = list( /datum/action/xeno_action/activable/throw_hugger, - /datum/action/xeno_action/onclick/place_trap, + /datum/action/xeno_action/onclick/choose_resin, + /datum/action/xeno_action/activable/secrete_resin, /datum/action/xeno_action/activable/retrieve_egg, // readding it so it gets at the end of the ability list /datum/action/xeno_action/onclick/set_hugger_reserve, ) @@ -122,7 +123,7 @@ xeno.eggs_cur++ to_chat(xeno, SPAN_XENONOTICE("We generate an egg. Now sheltering: [xeno.eggs_cur] / [xeno.eggs_max].")) xeno.update_icons() - + #undef EGGSAC_OFF_WEED_EGGCAP #undef EGGSAC_EGG_SUSTAIN_DISTANCE diff --git a/icons/mob/hud/actions_xeno.dmi b/icons/mob/hud/actions_xeno.dmi index 4409d45a1470..df6e20533c22 100644 Binary files a/icons/mob/hud/actions_xeno.dmi and b/icons/mob/hud/actions_xeno.dmi differ diff --git a/icons/mob/xenos/castes/tier_2/burrower.dmi b/icons/mob/xenos/castes/tier_2/burrower.dmi index 1a41dbbae908..2bae8822aedd 100644 Binary files a/icons/mob/xenos/castes/tier_2/burrower.dmi and b/icons/mob/xenos/castes/tier_2/burrower.dmi differ