Astral Collective Part 1. (#12361)

This commit is contained in:
FluffMedic
2026-02-09 00:01:24 +01:00
committed by GitHub
parent d06091f5cb
commit 639dde2caa
29 changed files with 2264 additions and 6090 deletions
@@ -11,6 +11,7 @@
shock_resist = -0.2
deflect_chance = 0
movement_cooldown = 10
damage_fatigue_mult = 0
status_flags = null
special_attack_min_range = 0
special_attack_max_range = 14
@@ -812,7 +812,7 @@
return
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/eclipse))
if(istype(entry, /mob/living/simple_mob/mechanical/mecha/eclipse))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
@@ -860,7 +860,7 @@
return
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/eclipse))
if(istype(entry, /mob/living/simple_mob/mechanical/mecha/eclipse))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
@@ -1,421 +1,57 @@
//Most mechas have a strange defense mechanism
//This one however, is the simplest one, more meant as an intro
/mob/living/simple_mob/mechanical/mecha/eclipse/antipersonal_unit //Melts folks with lasers
name = "Eclipse Expirmental Anti-Infantary Unit"
health = 400
maxHealth = 400
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorge
armor = list(melee = 60, bullet = 60, laser = 60, energy = 60, bomb = 90, bio = 100, rad = 100)
icon_state = "orb"
wreckage = /obj/structure/loot_pile/mecha/odd_gygax
/mob/living/simple_mob/mechanical/mecha/eclipse/antipersonal_unit/do_special_attack(atom/A)
switch(a_intent)
if(I_DISARM) //phase3
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 20, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
Beam(A, icon_state = "solar_beam", time = 2 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, rng_cycle), 2 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_HURT) //phase1
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 8, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
Beam(A, icon_state = "solar_beam", time = 2 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, rng_cycle), 2 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_GRAB) // Phase 2
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 12, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
Beam(A, icon_state = "solar_beam", time = 1.5 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, rng_cycle), 1 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
//Nigh unbreakable defenses except during certian attack phases.
/mob/living/simple_mob/mechanical/mecha/eclipse/mining_guard //Explosive death
name = "Eclipse Expirmental Mining Mecha"
desc = "You mecha guarded by a powerful shield. Perhaps it will drop at some point."
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorgealien
armor = list(melee = 99, bullet = 99, laser = 99, energy = 99, bomb = 90, bio = 100, rad = 100)
icon_state = "shielded_mining_mecha"
shock_resist = 1
wreckage = /obj/structure/loot_pile/mecha/odd_ripley
attackcycle = 1
/mob/living/simple_mob/mechanical/mecha/eclipse/mining_guard/do_special_attack(atom/A)
switch(a_intent)
if(I_DISARM) //phase3
if(attackcycle == 1)
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorgealien
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 12, 2, 10), 1 SECOND, TIMER_DELETE_ME)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
icon_state = "mining_mecha"
attackcycle = 0
else if(attackcycle == 2)
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorgealien
addtimer(CALLBACK(src, PROC_REF(hole_in_wall), A, 3, 15), 0.5 SECONDS, TIMER_DELETE_ME)
armor = list(melee = 99, bullet = 99, laser = 99, energy = 99, bomb = 90, bio = 100, rad = 100)
icon_state = "shielded_mining_mecha"
attackcycle = 0
else if(attackcycle == 3)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(chain_burst), A, 1, 15), 0.5 SECONDS, TIMER_DELETE_ME)
armor = list(melee = 99, bullet = 99, laser = 99, energy = 99, bomb = 90, bio = 100, rad = 100)
icon_state = "shielded_mining_mecha"
attackcycle = 0
if(I_HURT) //phase1
if(attackcycle == 1)
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorgealien
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 6, 2, 10), 1 SECOND, TIMER_DELETE_ME)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
icon_state = "mining_mecha"
attackcycle = 0
else if(attackcycle == 2)
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorgealien
addtimer(CALLBACK(src, PROC_REF(hole_in_wall), A, 3, 20), 0.5 SECONDS, TIMER_DELETE_ME)
armor = list(melee = 99, bullet = 99, laser = 99, energy = 99, bomb = 90, bio = 100, rad = 100)
icon_state = "shielded_mining_mecha"
attackcycle = 0
else if(attackcycle == 3)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(chain_burst), A, 1, 20), 0.5 SECONDS, TIMER_DELETE_ME)
armor = list(melee = 99, bullet = 99, laser = 99, energy = 99, bomb = 90, bio = 100, rad = 100)
icon_state = "shielded_mining_mecha"
attackcycle = 0
if(I_GRAB) // Phase 2
if(attackcycle == 1)
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorgealien
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 8, 2, 10), 1 SECOND, TIMER_DELETE_ME)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
icon_state = "mining_mecha"
attackcycle = 0
else if(attackcycle == 2)
specialattackprojectile = /obj/item/projectile/energy/eclipse/lorgealien
addtimer(CALLBACK(src, PROC_REF(hole_in_wall), A, 3, 15), 0.5 SECONDS, TIMER_DELETE_ME)
armor = list(melee = 99, bullet = 99, laser = 99, energy = 99, bomb = 90, bio = 100, rad = 100)
icon_state = "shielded_mining_mecha"
attackcycle = 0
else if(attackcycle == 3)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(chain_burst), A, 1, 15), 0.5 SECONDS, TIMER_DELETE_ME)
armor = list(melee = 99, bullet = 99, laser = 99, energy = 99, bomb = 90, bio = 100, rad = 100)
icon_state = "shielded_mining_mecha"
attackcycle = 0
//radidation gimmick go brrrr
/mob/living/simple_mob/mechanical/mecha/eclipse/engimecha
name = "Eclipse Expirmental Enginering Mecha"
health = 300
maxHealth = 300
desc = "A mecha made for enginering purposes, with several alterations to be an odd ball combat unit."
specialattackprojectile = /obj/item/projectile/energy/excavate/weak
armor = list(melee = 30, bullet = 30, laser = 30, energy = 40, bomb = 90, bio = 100, rad = 100)
icon_state = "engi_spider"
shock_resist = 1
projectiletype = /obj/item/projectile/beam/chain_lightning
reload_max = 1
reload_time = 0.5 SECONDS
ranged_attack_delay = 2 SECONDS
glow_color = "#14ff20"
light_color = "#14ff20"
glow_range = 5
glow_intensity = 3
special_attack_cooldown = 60
pilot_type = /mob/living/simple_mob/humanoid/eclipse/head/engineer
var/rads = 5
/mob/living/simple_mob/mechanical/mecha/eclipse/engimecha/do_special_attack(atom/A)
rads += 15
/mob/living/simple_mob/mechanical/mecha/eclipse/engimecha/handle_special()
if(stat != DEAD)
irradiate()
..()
/mob/living/simple_mob/mechanical/mecha/eclipse/engimecha/proc/irradiate()
SSradiation.radiate(src, rads)
/mob/living/simple_mob/mechanical/mecha/eclipse/engimecha/ranged_pre_animation(atom/A)
Beam(get_turf(A), icon_state = "sniper_beam", time = 2 SECONDS, maxdistance = 15)
. = ..()
/mob/living/simple_mob/mechanical/mecha/eclipse/engimecha/shoot_target(atom/A)
set waitfor = FALSE
if(!istype(A) || QDELETED(A))
return
setClickCooldown(get_attack_speed())
face_atom(A)
var/atom/orig_targ = A
if(ranged_attack_delay)
A = get_turf(orig_targ)
ranged_pre_animation(A)
handle_attack_delay(A, ranged_attack_delay) // This will sleep this proc for a bit, which is why waitfor is false.
if(needs_reload)
if(reload_count >= reload_max)
try_reload()
return FALSE
/*
* CHOMP Addition: This section here is (duplicated) special snowflake code because sniper does not call parent. Basically, this is a non-stupid version of the above intended for ranged mobs.
* ranged_attack_delay is stupid because it sleeps the entire mob.
* This new ranged_cooldown_time is smarter in the sense that it is an internalized timer. Try not to confuse the names.
*/
if(ranged_cooldown_time) //If you have a non-zero number in a mob's variables, this pattern begins.
if(ranged_cooldown <= world.time) //Further down, a timer keeps adding to the ranged_cooldown variable automatically.
visible_message(span_bolddanger("\The [src]") + " fires at \the [A]!") //Leave notice of shooting.
shoot(A) //Perform the shoot action
if(casingtype) //If the mob is designated to leave casings...
new casingtype(loc) //... leave the casing.
ranged_cooldown = world.time + ranged_cooldown_time + ((injury_level / 2) SECONDS) //Special addition here. This is a timer. Keeping updating the time after shooting. Add that ranged cooldown time specified in the mob to the world time.
return TRUE //End these commands here.
// CHOMPAddition End
visible_message(span_bolddanger("\The [src]") + " fires at \the [orig_targ]!")
shoot(A)
if(casingtype)
new casingtype(loc)
if(ranged_attack_delay)
ranged_post_animation(A)
return TRUE
//High overall defense, swaps between Burn and brute defense based off what was just used.
/mob/living/simple_mob/mechanical/mecha/eclipse/darkmatter_assualt/armored //The final boss
name = "Eclipse Expirmental Janus"
desc = "A powerful looking mecha, it's shield appears to swap to protect itself against the most rescent damage type."
armor = list(melee = 60, bullet = 60, laser = 60, energy = 60, bomb = 80, bio = 100, rad = 100)
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
pilot_type =/mob/living/simple_mob/mechanical/mecha/eclipse/darkmatter_assualt/phasetwo
wreckage = /obj/item/prop/tyrlore/monodisc
icon_state = "eclipse_janus"
attackcycle = 1
/mob/living/simple_mob/mechanical/mecha/eclipse/darkmatter_assualt/armored/bullet_act(obj/item/projectile/P)
.= ..()
if(istype(P, /obj/item/projectile/bullet))
armor = list(melee = 90, bullet = 90, laser = 30, energy = 30, bomb = 80, bio = 100, rad = 100)
icon_state = "eclipse_janus_red"
visible_message(span_cult("[P] has been adapted too!."))
else
armor = list(melee = 30, bullet = 30, laser = 80, energy = 80, bomb = 80, bio = 100, rad = 100)
icon_state = "eclipse_janus_orange"
visible_message(span_cult("[P] has been adapted too!."))
/mob/living/simple_mob/mechanical/mecha/eclipse/darkmatter_assualt/armored/do_special_attack(atom/A)
switch(a_intent)
if(I_DISARM) //phase3
if(attackcycle == 1)
rng_cycle = rand(1,4)
addtimer(CALLBACK(src, PROC_REF(teleport_attack), A, rng_cycle, 2), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(dual_burst), A, rng_cycle), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 8, rng_cycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 4)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(chain_burst), A, rng_cycle), 1 SECOND, TIMER_DELETE_ME)
attackcycle = 0
if(I_HURT) //phase1 simple projectiles
if(attackcycle == 1)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 8, rng_cycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
Beam(A, icon_state = "solar_beam", time = 2 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, rng_cycle), 2 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 4)
rng_cycle = rand(1,4)
addtimer(CALLBACK(src, PROC_REF(teleport_attack), A, rng_cycle, 3), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_GRAB) // Phase 2
if(attackcycle == 1)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 8, rng_cycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, rng_cycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,4)
addtimer(CALLBACK(src, PROC_REF(teleport_attack), A, rng_cycle, 2), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 4)
rng_cycle = rand(1,4)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(checker_board), A, rng_cycle), 1 SECOND, TIMER_DELETE_ME)
attackcycle = 0
/mob/living/simple_mob/mechanical/mecha/eclipse/darkmatter_assualt/phasetwo //we ain't done yet
name = "Collapsing Janus"
armor = list(melee = 30, bullet = 30, laser = 30, energy = 30, bomb = 80, bio = 100, rad = 100) //our shielding is gone
health = 400
maxHealth = 400
desc = "The mecha is smoking, it's drone and shield is broken, but it's pilot is pushing it further."
specialattackprojectile = /obj/item/projectile/energy/eclipse/janusjavelin
wreckage = /obj/item/prop/tyrlore/neonjanus
pilot_type = /mob/living/simple_mob/mechanical/mecha/eclipse/sniper
has_repair_droid = FALSE //broken mecha
icon_state = "eclipse_janus"
/mob/living/simple_mob/mechanical/mecha/eclipse/darkmatter_assualt/phasetwo/do_special_attack(atom/A)
if(attackcycle == 1)
attackcycle = rand(4,6)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 14, attackcycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
else if(attackcycle == 2)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, attackcycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = rand(4,6)
else if(attackcycle == 3)
addtimer(CALLBACK(src, PROC_REF(hole_in_wall), A, attackcycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = rand(4,6)
else if(attackcycle == 4)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, rng_cycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 5)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 7, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 6)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(teleport_attack), A, rng_cycle, 5), 3 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
/mob/living/simple_mob/mechanical/mecha/eclipse/sniper //one last stand
name = "Eclipse Lead Pilot"
icon_state = "captian"
icon_living = "captian"
health = 200
maxHealth = 200
ai_holder_type = /datum/ai_holder/simple_mob/intentional/three_phases
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 50, bio = 100, rad = 100)
specialattackprojectile = /obj/item/projectile/arc/explosive_rocket
wreckage = /obj/item/prop/tyrlore/truegoal
has_repair_droid = FALSE
/mob/living/simple_mob/mechanical/mecha/eclipse/sniper/do_special_attack(atom/A)
. = TRUE
if(attackcycle == 1)
addtimer(CALLBACK(src, PROC_REF(teleport_attack), A, 2, 4), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
specialattackprojectile = /obj/item/projectile/beam/heavylaser/cannon
Beam(A, icon_state = "solar_beam", time = 0.75 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, 1), 1 SECOND, TIMER_DELETE_ME)
attackcycle = 0
/mob/living/simple_mob/mechanical/mecha/eclipse/battle_top
name = "eclipse cryo top"
name = "astral collective cryo top"
icon_state = "mecha_top"
icon_living = "mecha_top"
health = 3000
maxHealth = 3000
wreckage = /obj/item/melee/energy/sword/top_shield
specialattackprojectile = /obj/item/projectile/energy/eclipse/chillingwind
desc = "It appears to be spinning at rapid speeds; enough to deflect projectiles. The air around it feels frigid.."
desc = "It appears to be spinning at rapid speeds; enough to deflect projectiles. The air around it feels frigid."
specialattackprojectile = /obj/item/projectile/energy/eclipse_boss/chillingwind
projectiletype = /obj/item/projectile/energy/eclipse_boss/chillingwind
pilot_type = /mob/living/simple_mob/humanoid/astral_collective/purity
/mob/living/simple_mob/mechanical/mecha/eclipse/battle_top/do_special_attack(atom/A)
var/rng_cycle
rng_cycle = rand(1,3)
switch(a_intent)
if(I_DISARM) //phase3
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 20, rng_cycle, 20), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(bomb_chaos), A, rng_cycle), 2.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_HURT) //phase1
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 20, rng_cycle, 20), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(bomb_lines), A, rng_cycle), 2.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_GRAB) // Phase 2
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 20, rng_cycle, 25), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(bomb_lines), A, rng_cycle), 2.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
switch(attackcycle)
if(1)
specialattackprojectile = /obj/item/projectile/energy/eclipse_boss/chillingwind
addtimer(CALLBACK(src, PROC_REF(rising_star), A, rng_cycle, 7), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(2)
specialattackprojectile = /obj/item/projectile/energy/eclipse_boss/chillingwind
addtimer(CALLBACK(src, PROC_REF(hole_in_wall), A, rng_cycle, 18), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(3)
addtimer(CALLBACK(src, PROC_REF(summon_puddles), A, rng_cycle, /datum/modifier/mmo_drop/eclipse_iceball), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_GRAB) //phase2
switch(attackcycle)
if(1)
specialattackprojectile = /obj/item/projectile/energy/eclipse_boss/chillingwind
addtimer(CALLBACK(src, PROC_REF(bullet_blossom), A, 3, 8), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(2)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(chain_burst), A, rng_cycle, 6), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(3)
addtimer(CALLBACK(src, PROC_REF(summon_puddles), A, rng_cycle, /datum/modifier/mmo_drop/eclipse_iceball), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_DISARM) //phase3
switch(attackcycle)
if(1)
addtimer(CALLBACK(src, PROC_REF(summon_puddles), A, rng_cycle, /datum/modifier/mmo_drop/eclipse_iceball), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(2)
specialattackprojectile = /obj/item/projectile/arc/blue_energy/precusor
addtimer(CALLBACK(src, PROC_REF(checker_board), A, rng_cycle), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(3)
projectiletype = /obj/item/projectile/energy/eclipse_boss/chillingwind
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, rng_cycle, 8), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
/mob/living/simple_mob/mechanical/mecha/eclipse/battle_top/handle_special()
@@ -428,72 +64,117 @@
if(!IIsAlly(L))
L.add_modifier(/datum/modifier/chilled, 3, src)
/mob/living/simple_mob/mechanical/mecha/eclipse/excavate_head
name = "Xenoarch Lead"
desc = "A unathi wearing what appears to be a modified breacher suit. Something seems off though"
icon_state = "cursor_guard"
icon_living = "cursor_guard"
armor = list(melee = 80, bullet = 80, laser = 80, energy = 80, bomb = 80, bio = 100, rad = 100)
wreckage = /obj/item/prop/tyrlore/stolenbreacher
specialattackprojectile = /obj/item/projectile/energy/eclipse/mining
desc = "A being wearing what appears to be a modified breacher outfit."
projectiletype = /obj/item/projectile/arc/explosive_rocket
ranged_cooldown = 50
/mob/living/simple_mob/mechanical/mecha/eclipse/tankyboss/crystal_boss/ufo
name = "astral collective deflection saucer"
icon_state = "UPshield_mecha"
icon_living = "UPshield_mecha"
desc = "A metallic flying saucer, a reflective barrier around it."
faction = FACTION_ECLIPSE
icon = 'modular_chomp/icons/mob/eclipse.dmi'
health = 1500
maxHealth = 1500
specialattackprojectile = /obj/item/projectile/energy/eclipse_boss/metalsphere
projectiletype = /obj/item/projectile/energy/eclipse_boss/metalsphere
wreckage = /obj/item/prop/deconstructable/gigacell
pilot_type = /mob/living/simple_mob/humanoid/astral_collective/purity
/mob/living/simple_mob/mechanical/mecha/eclipse/excavate_head/updatehealth()
. = ..()
if(health < maxHealth*0.3)
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
else if(health < maxHealth*0.6)
armor = list(melee = 30, bullet = 30, laser = 30, energy = 30, bomb = 30, bio = 100, rad = 100)
else if (health < maxHealth*0.9)
armor = list(melee = 60, bullet = 60, laser = 60, energy = 50, bomb = 60, bio = 100, rad = 100)
/mob/living/simple_mob/mechanical/mecha/eclipse/excavate_head/do_special_attack(atom/A)
var/rng_cycle
/mob/living/simple_mob/mechanical/mecha/eclipse/tankyboss/crystal_boss/ufo/do_special_attack(atom/A)
switch(a_intent)
if(I_DISARM) //phase3
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 20, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
Beam(A, icon_state = "solar_beam", time = 2 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, rng_cycle), 2 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_HURT) //phase1
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 8, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
Beam(A, icon_state = "solar_beam", time = 2 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, rng_cycle), 2 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_GRAB) // Phase 2
if(attackcycle == 1)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 12, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 2)
rng_cycle = rand(1,3)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 10), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
else if(attackcycle == 3)
rng_cycle = rand(1,3)
Beam(A, icon_state = "solar_beam", time = 1.5 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(singleproj), A, rng_cycle), 1 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
switch(attackcycle)
if(1)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, 2, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
parry_chance = 100
icon_state = "UPshield_mecha"
if(2)
addtimer(CALLBACK(src, PROC_REF(rising_star), A, 3, 7), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
parry_chance = 100
icon_state = "UPshield_mecha"
if(3)
addtimer(CALLBACK(src, PROC_REF(random_firing), A, 10, 1, 7), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
icon_state = "shield_mecha"
if(I_GRAB) //phase2
switch(attackcycle)
if(1)
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, 2, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
parry_chance = 100
icon_state = "UPshield_mecha"
if(2)
addtimer(CALLBACK(src, PROC_REF(bullet_blossom), A, 3, 8), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
parry_chance = 100
icon_state = "UPshield_mecha"
if(3)
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 10, 1, 7), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
icon_state = "shield_mecha"
if(I_DISARM) //phase3
switch(attackcycle)
if(1)
addtimer(CALLBACK(src, PROC_REF(dual_spin), A, 2, 4), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
parry_chance = 100
icon_state = "UPshield_mecha"
if(2)
addtimer(CALLBACK(src, PROC_REF(hole_in_wall), A, 3, 15), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
parry_chance = 100
icon_state = "UPshield_mecha"
if(3)
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 10, 1, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
parry_chance = 0
icon_state = "shield_mecha"
/mob/living/simple_mob/mechanical/mecha/eclipse/janus
name = "astral collective janus"
icon_state = "astral_janus"
icon_living = "astral_janus"
desc = "A janus made from stolen tech."
health = 4500
maxHealth = 4500
specialattackprojectile = /obj/item/projectile/energy/eclipse_boss/energyjavelin
projectiletype = /obj/item/projectile/energy/eclipse_boss/energyjavelin
wreckage = /obj/item/prop/deconstructable/gigacell
pilot_type = /mob/living/simple_mob/humanoid/astral_collective/purity
/mob/living/simple_mob/mechanical/mecha/eclipse/janus/do_special_attack(atom/A)
rng_cycle = rand(1,3)
switch(a_intent)
if(I_HURT) //phase1
switch(attackcycle)
if(1)
addtimer(CALLBACK(src, PROC_REF(gattlingfire), A, rng_cycle, 4, 7), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(2)
addtimer(CALLBACK(src, PROC_REF(rising_star), A, rng_cycle, 7), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(3)
addtimer(CALLBACK(src, PROC_REF(quad_random_firing), A, 4, rng_cycle, 5), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_GRAB) //phase2
switch(attackcycle)
if(1)
addtimer(CALLBACK(src, PROC_REF(death_wall), A, rng_cycle, 9), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(2)
addtimer(CALLBACK(src, PROC_REF(bomb_chaos), A, rng_cycle), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(3)
addtimer(CALLBACK(src, PROC_REF(bullet_blossom), A, rng_cycle, 7), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(I_DISARM) //phase3
switch(attackcycle)
if(1)
addtimer(CALLBACK(src, PROC_REF(summon_puddles), A, rng_cycle, /datum/modifier/mmo_drop/blade_boss_short), 2.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(2)
addtimer(CALLBACK(src, PROC_REF(hole_in_wall), A, 3, 12), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
if(3)
addtimer(CALLBACK(src, PROC_REF(cross_spin), A, rng_cycle, 3), 0.5 SECONDS, TIMER_DELETE_ME)
attackcycle = 0
@@ -58,6 +58,7 @@
size_multiplier = 2
maxHealth = 600
health = 600
projectiletype = /obj/item/projectile/energy/wallbreaker/boss
wreckage = /obj/structure/loot_pile/surface/alien/engineering
ai_holder_type = /datum/ai_holder/simple_mob/intentional/three_phases/no_movement
anchored = 1
@@ -42,6 +42,51 @@
s2.start()
attackcycle = next_cycle
/obj/effect/artillery_attack
anchored = TRUE
density = FALSE
unacidable = TRUE
mouse_opacity = 0
icon = 'icons/effects/effects.dmi'
icon_state = "drop_marker"
var/ammmotype = /obj/effect/falling_effect/callstrike_bomb
/obj/effect/artillery_attack/Initialize(mapload)
..()
return INITIALIZE_HINT_LATELOAD
/obj/effect/artillery_attack/LateInitialize()
var/delay = rand(25, 30)
addtimer(CALLBACK(src, PROC_REF(spawner)), delay, TIMER_DELETE_ME)
/obj/effect/artillery_attack/proc/spawner()
new ammmotype(src.loc)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src), 0.7 SECONDS, TIMER_DELETE_ME)
/obj/effect/falling_effect/callstrike_bomb
falling_type = /obj/effect/callstrike
crushing = FALSE
/obj/effect/callstrike
anchored = TRUE
density = FALSE
mouse_opacity = 0
icon ='modular_chomp/icons/obj/guns/precursor/tyr.dmi'
/obj/effect/callstrike/Initialize(mapload)
.=..()
icon_state = "arti"
/obj/effect/callstrike/end_fall(var/crushing = FALSE)
for(var/mob/living/L in loc)
var/target_zone = ran_zone()
var/blocked = L.run_armor_check(target_zone, "laser")
if(!L.apply_damage(70, BURN, target_zone, blocked))
break
playsound(src, 'sound/effects/clang2.ogg', 50, 1)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src), 0.25 SECONDS, TIMER_DELETE_ME)
/mob/living/simple_mob/mechanical/mecha/eclipse/proc/gravity_surge(atom/target, var/next_cycle, var/pull_radius, var/pull_strength)
if(!target)
return
@@ -68,6 +68,7 @@
/obj/item/projectile/bullet/incendiary/dragonflame/occult
range = 4
speed = 4
damage = 10
/obj/item/grenade/shooter/auto_explode/occult_fireball
spread_range = 2
@@ -75,3 +76,10 @@
/datum/modifier/mmo_drop/occult_fireball
puddleitem = /obj/item/grenade/shooter/auto_explode/occult_fireball
/obj/item/grenade/shooter/auto_explode/eclipse_iceball
spread_range = 2
projectile_types = list(/obj/item/projectile/energy/eclipse_boss/chillingwind)
/datum/modifier/mmo_drop/eclipse_iceball
puddleitem = /obj/item/grenade/shooter/auto_explode/eclipse_iceball
@@ -52,6 +52,7 @@
icon_living = "poison_boss"
wreckage = /obj/item/prop/tyrlore/acid_boss
specialattackprojectile = /obj/item/projectile/energy/neurotoxin/toxic/tyr_flora
projectiletype = /obj/item/projectile/energy/neurotoxin/toxic/tyr_flora
var/regeneration_strength = -20
/mob/living/simple_mob/mechanical/mecha/eclipse/tankyboss/acid_boss/load_default_bellies()
@@ -94,7 +95,7 @@
/mob/living/simple_mob/mechanical/mecha/eclipse/tankyboss/sonic_boss
name = "experiment 10"
desc = "A strange furball, the air vibrating around it."
specialattackprojectile = /obj/item/projectile/knockback/slow
specialattackprojectile = /obj/item/projectile/energy/eclipse/tyrjavelin
icon_state = "sonic_boss"
icon_living = "sonic_boss"
projectiletype = /obj/item/projectile/knockback/slow
@@ -204,7 +205,26 @@
melee_attack_delay = 2.5 SECONDS
movement_cooldown = 4
special_attack_cooldown = 8 SECONDS
evasion = 200 //forced to fight in melee lol
var/parry_chance = 100
/mob/living/simple_mob/mechanical/mecha/eclipse/tankyboss/crystal_boss/bullet_act(obj/item/projectile/P)
if(prob(parry_chance))
visible_message(span_danger("The [P.name] gets reflected by [src]'s armor!"), \
span_userdanger("The [P.name] gets reflected by [src]'s armor!"))
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/new_y = P.starting.y + pick(0, 0, -1, 1, -2, 2, -2, 2, -2, 2, -3, 3, -3, 3)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.redirect(new_x, new_y, curloc, src)
P.reflected = 1
return -1 // complete projectile permutation
return (..(P))
/mob/living/simple_mob/mechanical/mecha/eclipse/tankyboss/crystal_boss/do_special_attack(atom/A)
addtimer(CALLBACK(src, PROC_REF(bomb_chaos), A, 4), 1.5 SECONDS, TIMER_DELETE_ME)
@@ -286,8 +306,8 @@
/mob/living/simple_mob/mechanical/mecha/eclipse/tankyboss/swarm_ai
name = "swarm controler"
desc = "A massive hivebot that has shifting bits of metal upon it's body."
health = 700
maxHealth = 700
health = 400
maxHealth = 400
icon_state = "bright_green"
icon_living = "bright_green"
icon = 'modular_chomp/icons/mob/hivebot.dmi'
@@ -363,16 +383,3 @@
adjustToxLoss(-1000)
adjustOxyLoss(-1000)
adjustCloneLoss(-1000)
/*
/mob/living/simple_mob/mechanical/hivebot/tyr/heart
name = "barrier unit"
icon = 'modular_chomp/icons/mob/tyr.dmi'
icon_state = "guardian"
icon_living = "guardian"
maxHealth = 1.5 LASERS_TO_KILL // 60 hp
health = 1.5 LASERS_TO_KILL
melee_damage_lower = 10
melee_damage_upper = 10
attack_armor_pen = 80
movement_cooldown = 4
*/
@@ -0,0 +1,441 @@
/mob/living/simple_mob/humanoid/astral_collective
name = "Astral Collective Unit"
tt_desc = "E Homo sapiens"
desc = "You shouldn't be seeing this."
icon = 'modular_chomp/icons/mob/eclipse.dmi'
icon_state = "medi"
icon_living = "medi"
icon_dead = "medi"
taser_kill = 0
faction = FACTION_ECLIPSE
movement_cooldown = 0
status_flags = 0
response_help = "pokes"
response_disarm = "shoves"
response_harm = "hits"
health = 100
maxHealth = 100
harm_intent_damage = 0
melee_damage_lower = 25
melee_damage_upper = 25
melee_attack_delay = 0.75 SECONDS
evasion = 20
attack_sharp = 1
attack_edge = 1
attacktext = list("slashed", "stabbed")
projectile_dispersion = 0
armor = list(melee = 30, bullet = 30, laser = 30, energy = 60, bomb = 20, bio = 100, rad = 100) // Simple mob immunuties plus minour armor
can_be_drop_prey = FALSE
can_be_drop_pred = TRUE
pass_flags = PASSTABLE //mostly for the melee mobs.
softfall = TRUE //highly advanced spacesuit stuff
min_oxy = 0
max_oxy = 0
min_tox = 0
max_tox = 0
min_co2 = 0
max_co2 = 0
min_n2 = 0
max_n2 = 0
minbodytemp = 0
heat_damage_per_tick = 0
projectilesound = 'sound/weapons/Gunshot_light.ogg'
ai_holder_type = /datum/ai_holder/simple_mob/ranged/astral_collective
special_attack_cooldown = 15 SECONDS
special_attack_min_range = 0
special_attack_max_range = 14
swallowTime = 3 SECONDS
vore_active = 1
vore_capacity = 1
vore_bump_chance = 10
vore_stomach_name = "Stomach"
vore_default_item_mode = IM_DIGEST
vore_pounce_chance = 50
vore_pounce_cooldown = 10
vore_pounce_successrate = 75
vore_pounce_falloff = 0
vore_pounce_maxhealth = 100
vore_standing_too = TRUE
unacidable = TRUE
movement_cooldown = 0
loot_list = list(/obj/item/slime_extract/sepia = 75,
/obj/item/bone/skull = 100,
/obj/item/seeds/random = 60,
/obj/random/powercell = 20,
/obj/random/medical/pillbottle = 7,
/obj/random/firstaid = 3,
/obj/random/grenade/box = 5,
/obj/random/tool/power = 30,
/obj/random/tool/alien = 20,
/obj/random/tech_supply/component/nofail = 40,
/obj/random/medical = 12,
/obj/random/cash/big = 25,
/obj/random/material = 60,
/obj/random/material/refined = 50,
/obj/random/material/precious = 40,
/obj/random/janusmodule = 3,
/obj/item/dnainjector/random_verybad = 10,
/obj/item/stock_parts/scanning_module/omni = 10,
/obj/item/stock_parts/micro_laser/omni = 10,
/obj/item/stock_parts/capacitor/omni = 10,
/obj/item/stock_parts/manipulator/omni = 10,
/obj/item/stock_parts/matter_bin/omni = 10,
/obj/item/stock_parts/scanning_module/hyper = 25,
/obj/item/stock_parts/micro_laser/hyper = 25,
/obj/item/stock_parts/capacitor/hyper = 25,
/obj/item/stock_parts/manipulator/hyper = 25,
/obj/item/stock_parts/matter_bin/hyper = 25,
/obj/item/assembly/signaler/anomaly/flux = 7,
/obj/item/assembly/signaler/anomaly/bluespace = 7,
/obj/item/assembly/signaler/anomaly/grav = 7,
/obj/item/assembly/signaler/anomaly/dimensional = 7,
/obj/item/assembly/signaler/anomaly/bioscrambler = 7,
/obj/item/assembly/signaler/anomaly/hallucination = 7,
/obj/item/assembly/signaler/anomaly/pyro = 7,
/obj/item/assembly/signaler/anomaly/weather = 7,
)
var/expirmental
/mob/living/simple_mob/humanoid/astral_collective/Initialize(mapload)
. = ..()
expirmental = rand(1,7)
expirmentresult()
/datum/modifier/astralcollect_swift
slowdown = -0.5
evasion = 20
/datum/modifier/astralcollect_regen
mob_overlay_state = "poisoned"
/datum/modifier/astralcollect_regen/tick()
holder.adjustBruteLoss(-8)
holder.adjustFireLoss(-8)
holder.adjustToxLoss(-8)
holder.adjustOxyLoss(-8)
holder.adjustCloneLoss(-8)
/datum/modifier/astralcollect_titan
max_health_percent = 1.8
/datum/modifier/astralcollect_armour
incoming_damage_percent = 0.65
/datum/modifier/astralcollect_mistake
mob_overlay_state = "poisoned"
incoming_damage_percent = 1.35
slowdown = 1
max_health_percent = 0.75
/datum/modifier/astralcollect_solar
mob_overlay_state = "red_electricity_constant"
incoming_brute_damage_percent = 2
incoming_fire_damage_percent = 0.3
/datum/modifier/astralcollect_lunar
mob_overlay_state = "blue_electricity_constant"
incoming_brute_damage_percent = 0.3
incoming_fire_damage_percent = 2
/mob/living/simple_mob/humanoid/astral_collective/proc/expirmentresult()
switch(expirmental)
if(1)
add_modifier(/datum/modifier/astralcollect_swift, null, src)
size_multiplier -= 0.3
if(2)
add_modifier(/datum/modifier/astralcollect_regen, null, src)
if(3)
add_modifier(/datum/modifier/astralcollect_titan, null, src)
size_multiplier += 0.6
if(4)
add_modifier(/datum/modifier/astralcollect_armour, null, src)
size_multiplier += 0.3
if(5)
add_modifier(/datum/modifier/astralcollect_mistake, null, src)
if(6)
add_modifier(/datum/modifier/astralcollect_solar, null, src)
if(7)
add_modifier(/datum/modifier/astralcollect_lunar, null, src)
if(8)
ai_holder_type = /datum/ai_holder/hostile/ranged/robust
if(9)
ai_holder_type = /datum/ai_holder/simple_mob/intentional/adv_dark_gygax
if(10)
projectile_dispersion = 10
/datum/ai_holder/simple_mob/ranged/astral_collective
pointblank = TRUE
can_breakthrough = TRUE
violent_breakthrough = TRUE
unconscious_vore = TRUE
handle_corpse = TRUE
hostile = TRUE
mauling = TRUE
destructive = TRUE
/datum/ai_holder/simple_mob/ranged/astral_collective/pre_ranged_attack(atom/A)
holder.IMove(get_step(holder, pick(GLOB.alldirs)))
holder.face_atom(A)
/datum/ai_holder/simple_mob/ranged/astral_collective/post_ranged_attack(atom/A)
holder.IMove(get_step(holder, pick(GLOB.alldirs)))
holder.face_atom(A)
/datum/ai_holder/simple_mob/ranged/astral_collective/post_melee_attack(atom/A)
holder.IMove(get_step_away(holder, A))
holder.face_atom(A)
/datum/ai_holder/simple_mob/melee/evasive/astral_collective
/datum/ai_holder/simple_mob/melee/evasive/astral_collective/pre_special_attack(atom/A)
holder.IMove(get_step(holder, pick(GLOB.alldirs)))
holder.face_atom(A)
/datum/ai_holder/simple_mob/melee/evasive/astral_collective/post_special_attack(atom/A)
holder.IMove(get_step(holder, pick(GLOB.alldirs)))
holder.face_atom(A)
/mob/living/simple_mob/humanoid/astral_collective/purity
name = "Astral Collective Purity"
desc = "A strange living bioweapon"
icon_state = "purity"
icon_living = "purity"
ai_holder_type = /datum/ai_holder/simple_mob/melee/evasive/astral_collective
melee_damage_lower = 32 //25ish with explo voidsuit
melee_damage_upper = 32
attack_armor_pen = 20
melee_attack_delay = 1.5 SECONDS
health = 200
maxHealth = 200
special_attack_cooldown = 3 SECONDS
special_attack_min_range = 0
special_attack_max_range = 14
/mob/living/simple_mob/humanoid/astral_collective/purity/do_special_attack(atom/A)
adjustBruteLoss(-3)
adjustFireLoss(-3)
adjustToxLoss(-3)
adjustOxyLoss(-3)
adjustCloneLoss(-3)
//the ranged mobs
/mob/living/simple_mob/humanoid/astral_collective/ranged
name = "Astral Collective Unit"
projectile_accuracy = 10
needs_reload = TRUE
special_attack_cooldown = 7 SECONDS
reload_max = 7
reload_time = 1.5 SECONDS
ranged_cooldown = 65
//snake creature
/mob/living/simple_mob/humanoid/astral_collective/ranged/noodle
desc = "A naga wrapped up in strange glowing armour."
icon_state = "noodle"
icon_living = "noodle"
projectiletype = /obj/item/projectile/energy/astral_collective/anti_mecha
/mob/living/simple_mob/humanoid/astral_collective/ranged/noodle/do_special_attack(atom/A)
if((health / maxHealth) <= 0.5)
alpha = 180
teleport_self(A)
//taur creature
/mob/living/simple_mob/humanoid/astral_collective/ranged/taur
desc = "A quadrapel creature with expirmental gear."
icon_state = "taur"
icon_living = "taur"
projectiletype = /obj/item/projectile/energy/astral_collective/armour_breaker
health = 125
maxHealth = 125
/mob/living/simple_mob/humanoid/astral_collective/ranged/taur/do_special_attack(atom/A)
expirmental = rand(1,5)
switch(expirmental)
if(1)
teleport_attack(A)
if(2)
gravity_surge(A)
if(3)
air_strike(A)
if(4)
repair_self(A)
if(5)
teleport_self(A)
//teshari
/mob/living/simple_mob/humanoid/astral_collective/ranged/tesh
desc = "A teshari contained within prototype equipment."
icon_state = "tesh"
icon_living = "tesh"
projectiletype = /obj/item/projectile/energy/astral_collective/particle
health = 75
maxHealth = 75
/mob/living/simple_mob/humanoid/astral_collective/ranged/tesh/do_special_attack(atom/A)
if((health / maxHealth) <= 0.5)
selfexplode_attack(A)
else
teleport_attack(A)
//cannine
/mob/living/simple_mob/humanoid/astral_collective/ranged/wolf
desc = "A humanoid armored cannine folk."
icon_state = "wolf"
icon_living = "wolf"
projectiletype = /obj/item/projectile/energy/astral_collective/green
/mob/living/simple_mob/humanoid/astral_collective/ranged/wolf/do_special_attack(atom/A)
gravity_surge(A)
//lizard
/mob/living/simple_mob/humanoid/astral_collective/ranged/lizard
desc = "A humanoid heavily armoured lizardfolk."
icon_state = "breacher"
icon_living = "breacher"
projectiletype = /obj/item/projectile/energy/astral_collective/searing
health = 150
maxHealth = 150
/mob/living/simple_mob/humanoid/astral_collective/ranged/lizard/do_special_attack(atom/A)
if((health / maxHealth) <= 0.5)
repair_self(A)
air_strike(A)
//zaddat
/mob/living/simple_mob/humanoid/astral_collective/ranged/zaddat
desc = "An armoured zaddat."
icon_state = "zaddat"
icon_living = "zaddat"
special_attack_cooldown = 1 SECOND
/mob/living/simple_mob/humanoid/astral_collective/ranged/zaddat/do_special_attack(atom/A)
projectiletype = pick(/obj/item/projectile/energy/astral_collective/anti_mecha, /obj/item/projectile/energy/astral_collective/armour_breaker, /obj/item/projectile/energy/astral_collective/searing, /obj/item/projectile/energy/astral_collective/green, /obj/item/projectile/energy/astral_collective/particle)
/mob/living/simple_mob/humanoid/astral_collective/ranged/zaddat/bullet_act(var/obj/item/projectile/Proj)
if(!Proj)
return
if(prob(60))
visible_message(span_bolddanger("[Proj] is blocked by the shield."))
if(Proj.firer)
ai_holder.react_to_attack(Proj.firer)
return
else
..()
/mob/living/simple_mob/humanoid/astral_collective/proc/teleport_attack(atom/target)
// Teleport attack.
if(!target)
to_chat(src, span_warning("There's nothing to teleport to."))
return FALSE
var/list/nearby_things = range(2, src)
var/list/valid_turfs = list()
// All this work to just go to a non-dense tile.
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
if(!(valid_turfs.len))
to_chat(src, span_warning("There wasn't an unoccupied spot to teleport to."))
return FALSE
var/turf/target_turf = pick(valid_turfs)
do_teleport(target, target_turf, channel = TELEPORT_CHANNEL_QUANTUM)
/mob/living/simple_mob/humanoid/astral_collective/proc/selfexplode_attack(atom/target)
if(!target)
return FALSE
explosion(src.loc, 2, 3, 4, 5)
/mob/living/simple_mob/humanoid/astral_collective/proc/gravity_surge(atom/target)
if(!target)
return FALSE
playsound(src, 'sound/weapons/wave.ogg', 75, 1)
for(target in range(7, src))
target.singularity_pull(src, 3)
/mob/living/simple_mob/humanoid/astral_collective/proc/air_strike(atom/target)
if(!target)
return FALSE
for(var/mob/living/L in orange(src, 14))
if(L.stat != DEAD && !IIsAlly(L))
L.add_modifier(/datum/modifier/mmo_drop/blade_boss_short, 3, src)
/mob/living/simple_mob/humanoid/astral_collective/proc/repair_self(atom/target)
if(!target)
return FALSE
adjustBruteLoss(-70)
adjustFireLoss(-70)
adjustToxLoss(-70)
adjustOxyLoss(-70)
adjustCloneLoss(-70)
/mob/living/simple_mob/humanoid/astral_collective/proc/teleport_self(atom/A)
// Teleport attack.
if(!A)
to_chat(src, span_warning("There's nothing to teleport to."))
return FALSE
var/list/nearby_things = range(4, A)
var/list/valid_turfs = list()
// All this work to just go to a non-dense tile.
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
if(!(valid_turfs.len))
to_chat(src, span_warning("There wasn't an unoccupied spot to teleport to."))
return FALSE
var/turf/target_turf = pick(valid_turfs)
var/turf/T = get_turf(src)
var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread
s1.set_up(5, 1, T)
var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread
s2.set_up(5, 1, target_turf)
T.visible_message(span_warning("\The [src] vanishes!"))
s1.start()
forceMove(target_turf)
playsound(target_turf, 'sound/effects/phasein.ogg', 50, 1)
to_chat(src, span_notice("You teleport to \the [target_turf]."))
target_turf.visible_message(span_warning("\The [src] appears!"))
s2.start()
@@ -1,668 +0,0 @@
/mob/living/simple_mob/humanoid/eclipse/head
name = "Eclipse Head"
desc = "You shouldn't be seeing this. This is going to be rough"
health = 315
maxHealth = 315 //A 20 damage shot will need to land 35 times
projectile_dispersion = 8
projectile_accuracy = 0
ranged_cooldown = 5
grab_resist = 100
damage_fatigue_mult = 0
armor = list(melee = 34, bullet = 34, laser = 34, energy = 34, bomb = 100, bio = 100, rad = 100)
has_heal_droid = TRUE
/mob/living/simple_mob/humanoid/eclipse/head/security
name = "Eclipse Head Of Security"
icon_state = "fleetsec"
projectiletype = /obj/item/projectile/energy/flamecrystal
special_attack_cooldown = 10 SECONDS
special_attack_min_range = 1
special_attack_max_range = 8
has_heal_droid = TRUE
specialattackprojectile = /obj/item/projectile/bullet/dragon
loot_list = list(/obj/item/gun/energy/flamegun = 100,
/obj/item/prop/tyrlore/neonsec = 100,
/obj/item/bone/skull = 100
)
/mob/living/simple_mob/humanoid/eclipse/head/security/do_special_attack(atom/A)
if(vore_fullness > 3)
bomb_chaos(A)
else if(vore_fullness > 0)
visible_message(span_warning("\The [src]'s maw glows!"))
Beam(A, icon_state = "sat_beam", time = 2.5 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(special_projectile), A), 3 SECONDS, TIMER_DELETE_ME)
else
if(prob(50))
visible_message(span_warning("\The [src] throws out a chain!"))
Beam(A, icon_state = "chain", time = 3 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(gravity_pull), A), 3 SECOND, TIMER_DELETE_ME)
else
visible_message(span_warning("\The [src] throws out a chain!"))
Beam(A, icon_state = "chain", time = 3 SECONDS, maxdistance = INFINITY)
addtimer(CALLBACK(src, PROC_REF(itemyoink), A), 3 SECOND, TIMER_DELETE_ME)
/obj/item/projectile/energy/flamecrystal
name = "Flame Crystal"
icon = 'modular_chomp/icons/mob/eclipse.dmi' //commiting sin
icon_state = "firecrystal"
damage = 15
armor_penetration = 40 //Large pointy crystal
damage_type = BRUTE
check_armour = "bullet"
range = 12
hud_state = "laser_sniper"
/obj/item/projectile/energy/flamecrystal/on_hit(atom/target, blocked = 0, def_zone)
. = ..()
if(isliving(target))
var/mob/living/L = target
L.adjust_fire_stacks(5)
L.ignite_mob()
/obj/item/projectile/bullet/flamegun
use_submunitions = 1
only_submunitions = 1
range = 0
embed_chance = 0
submunition_spread_max = 800
submunition_spread_min = 200
submunitions = list(/obj/item/projectile/energy/flamecrystal = 3)
hud_state = "laser_heat"
/obj/item/projectile/bullet/flamegun/on_range()
qdel(src)
/mob/living/simple_mob/humanoid/eclipse/head/scientist
name = "Eclipse Lead Researcher"
icon_state = "fleetsci"
maxHealth = 60
health = 60
special_attack_cooldown = 5 SECONDS
special_attack_min_range = 1
special_attack_max_range = 10
projectiletype = /obj/item/projectile/bullet/pistol/ap
loot_list = list(/obj/item/circuitboard/mecha/imperion/targeting = 60,
/obj/item/circuitboard/mecha/gygax/peripherals = 60,
/obj/item/prop/alien/phasecoil = 60,
/obj/item/circuitboard/mecha/durand/peripherals = 60,
/obj/item/bluespace_harpoon = 10,
/obj/item/bone/skull = 100,
/obj/item/prop/tyrlore/neonsci = 100
)
var/obj/item/shield_projector/shield1 = null
var/obj/item/shield_projector/shield2 = null
var/obj/item/shield_projector/shield3 = null
/mob/living/simple_mob/humanoid/eclipse/head/scientist/Initialize(mapload)
shield1 = new /obj/item/shield_projector/rectangle/automatic/eclipse(src)
shield2 = new /obj/item/shield_projector/rectangle/automatic/eclipse/medium(src)
shield3 = new /obj/item/shield_projector/rectangle/automatic/eclipse/big(src)
return ..()
/obj/item/shield_projector/rectangle/automatic/eclipse
name = "cult shield stone"
icon = 'icons/obj/device.dmi'
icon_state = "implant_melted"
shield_health = 100
max_shield_health = 100
shield_regen_delay = 120 SECONDS
shield_regen_amount = 100
size_x = 1
size_y = 1
color = "#FF6600"
high_color = "#0099CC"
low_color = "#660066"
/obj/item/shield_projector/rectangle/automatic/eclipse/medium
size_x = 2
size_y = 2
/obj/item/shield_projector/rectangle/automatic/eclipse/big
size_x = 3
size_y = 3
/mob/living/simple_mob/mechanical/hivebot/swarm/eclipse
faction = FACTION_ECLIPSE
/mob/living/simple_mob/mechanical/combat_drone/artillery
faction = FACTION_ECLIPSE
projectiletype = /obj/item/projectile/arc/blue_energy
/mob/living/simple_mob/humanoid/eclipse/head/captain
name = "Eclipse Expedition Leader"
icon_state = "captain"
/mob/living/simple_mob/humanoid/eclipse/head/tyrlead
name = "Eclipse Precursor Overseer"
icon_state = "overseer_shield"
icon_living = "overseer_shield"
special_attack_cooldown = 4 SECONDS
special_attack_min_range = 1
special_attack_max_range = 8
projectiletype = /obj/item/projectile/energy/homing_bolt
ai_holder_type = /datum/ai_holder/simple_mob/intentional/adv_dark_gygax
loot_list = list(/obj/item/prop/tyrlore/baseneon = 100,
/obj/item/disposable_teleporter = 100,
/obj/item/hand_tele = 10,
/obj/item/bone/skull = 100
)
var/fullshield = 140
var/shieldrage = 3
/mob/living/simple_mob/humanoid/eclipse/head/tyrlead/bullet_act(obj/item/projectile/P) //Projectiles will be absorbed by the shield. Note to self do funky sprite. 4 hits to remove
if(fullshield > 0)
fullshield -= P.damage
if(P == /obj/item/projectile/ion)
fullshield = 0
visible_message(span_boldwarning(span_orange("[P] breaks the shield!!.")))
icon_state = "overseer"
if(fullshield > 0)
visible_message(span_boldwarning(span_orange("[P] is absorbed by the shield!.")))
else
visible_message(span_boldwarning(span_orange("[P] breaks the shield!!.")))
icon_state = "overseer"
else
..()
shieldrage--
if(shieldrage == 0)
shieldrage = 3
fullshield = 140
visible_message(span_boldwarning(span_orange("The shield reactivates!!.")))
icon_state = "overseer_shield"
/mob/living/simple_mob/humanoid/eclipse/head/tyrlead/do_special_attack(atom/A)
var/deathdir = rand(1,3)
switch(deathdir)
if(1)
teleport(A)
if(2)
bomb_chaos(A)
if(3)
bomb_lines(A)
/mob/living/simple_mob/humanoid/eclipse/head/engineer //teshari
name = "Eclipse Chief Engineer"
icon_state = "engi"
icon_living = "engi"
health = 50
maxHealth = 50
melee_damage_lower = 60 //Durasteel fireaxe
melee_damage_upper = 60
projectiletype = null
loot_list = list(/obj/item/stock_parts/matter_bin/omni = 60,
/obj/item/material/twohanded/fireaxe = 60,
/obj/item/storage/toolbox/syndicate/powertools = 60,
/obj/item/rig/ce = 60,
/obj/item/rig_module/teleporter = 5,
/obj/item/prop/tyrlore/neonengi = 100
)
/mob/living/simple_mob/humanoid/eclipse/head/engineer/Initialize(mapload)
add_modifier(/datum/modifier/technomancer/haste, null, src) // tesh goes nyooooom
return ..()
/mob/living/simple_mob/humanoid/eclipse/head/medical
name = "Eclipse Chief Medical Officer"
icon_state = "medi"
icon_living = "medi"
health = 150
maxHealth = 150
special_attack_cooldown = 5 SECONDS
special_attack_min_range = 0
special_attack_max_range = 7
melee_damage_lower = 15 //Durasteel fireaxe
melee_damage_upper = 15
attack_armor_pen = 60
projectiletype = null
loot_list = list(/obj/item/rig_module/atmos_shield = 60,
/obj/item/rig_module/rad_shield/advanced = 60,
/obj/item/rig/baymed = 60,
/obj/item/ammo_casing/microbattery/medical/brute3 = 15,
/obj/item/ammo_casing/microbattery/medical/burn3 = 15,
/obj/item/ammo_casing/microbattery/medical/toxin3 = 15,
/obj/item/prop/tyrlore/neonmedi = 100,
/obj/item/ammo_casing/microbattery/medical/omni3 = 5
)
var/cloaked_alpha = 45 // Lower = Harder to see.
var/cloak_cooldown = 5 SECONDS // Amount of time needed to re-cloak after losing it.
var/last_uncloak = 0 // world.time
var/poison_type = REAGENT_ID_STOXIN
var/poison_per_bite = 8
var/poison_chance = 80
/mob/living/simple_mob/humanoid/eclipse/head/medical/apply_melee_effects(var/atom/A)
if(isliving(A))
var/mob/living/L = A
if(L.reagents)
var/target_zone = pick(BP_TORSO,BP_TORSO,BP_TORSO,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_HEAD)
if(L.can_inject(src, null, target_zone))
inject_poison(L, target_zone)
/mob/living/simple_mob/humanoid/eclipse/head/medical/proc/inject_poison(mob/living/L, target_zone)
if(prob(poison_chance))
to_chat(L, span_warning("You feel a tiny prick."))
L.reagents.add_reagent(poison_type, poison_per_bite)
/mob/living/simple_mob/humanoid/eclipse/head/medical/cloak()
if(cloaked)
return
animate(src, alpha = cloaked_alpha, time = 1 SECOND)
cloaked = TRUE
/mob/living/simple_mob/humanoid/eclipse/head/medical/uncloak()
last_uncloak = world.time // This is assigned even if it isn't cloaked already, to 'reset' the timer if the spider is continously getting attacked.
if(!cloaked)
return
animate(src, alpha = initial(alpha), time = 1 SECOND)
cloaked = FALSE
// Check if cloaking if possible.
/mob/living/simple_mob/humanoid/eclipse/head/medical/proc/can_cloak()
if(stat)
return FALSE
if(last_uncloak + cloak_cooldown > world.time)
return FALSE
return TRUE
// Called by things that break cloaks, like Technomancer wards.
/mob/living/simple_mob/humanoid/eclipse/head/medical/break_cloak()
uncloak()
/mob/living/simple_mob/humanoid/eclipse/head/medical/is_cloaked()
return cloaked
// Cloaks the spider automatically, if possible.
/mob/living/simple_mob/humanoid/eclipse/head/medical/handle_special()
if(!cloaked && can_cloak())
cloak()
//special attack things
/mob/living/simple_mob/humanoid/eclipse/head/scientist/do_special_attack(atom/A)
addtimer(CALLBACK(src, PROC_REF(summon_drones), A, 3, 0.5 SECONDS), 0.5 SECONDS, TIMER_DELETE_ME)
/mob/living/simple_mob/humanoid/eclipse/proc/summon_drones(atom/target, var/amount, var/fire_delay)
if(!target)
return
var/deathdir = rand(1,3)
switch(deathdir)
if(1)
new /mob/living/simple_mob/mechanical/mining_drone/scavenger/eclipse(src.loc)
if(2)
new /mob/living/simple_mob/mechanical/hivebot/swarm/eclipse(src.loc)
if(3)
new /mob/living/simple_mob/mechanical/combat_drone/artillery(src.loc)
amount--
if(amount > 0)
addtimer(CALLBACK(src, PROC_REF(summon_drones), target, amount, fire_delay), fire_delay, TIMER_DELETE_ME)
/mob/living/simple_mob/humanoid/eclipse/head/medical/do_special_attack(atom/A)
if(!cloaked)
teleport(A)
/mob/living/simple_mob/humanoid/eclipse/proc/teleport(atom/A)
// Teleport attack.
if(!A)
to_chat(src, span_warning("There's nothing to teleport to."))
return FALSE
var/list/nearby_things = range(4, A)
var/list/valid_turfs = list()
// All this work to just go to a non-dense tile.
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
if(!(valid_turfs.len))
to_chat(src, span_warning("There wasn't an unoccupied spot to teleport to."))
return FALSE
var/turf/target_turf = pick(valid_turfs)
var/turf/T = get_turf(src)
var/datum/effect/effect/system/spark_spread/s1 = new /datum/effect/effect/system/spark_spread
s1.set_up(5, 1, T)
var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/spark_spread
s2.set_up(5, 1, target_turf)
T.visible_message(span_warning("\The [src] vanishes!"))
s1.start()
forceMove(target_turf)
playsound(target_turf, 'sound/effects/phasein.ogg', 50, 1)
to_chat(src, span_notice("You teleport to \the [target_turf]."))
target_turf.visible_message(span_warning("\The [src] appears!"))
s2.start()
/mob/living/simple_mob/humanoid/eclipse/head/cargomaster //Naga
name = "Eclipse Cargo Master"
/mob/living/simple_mob/humanoid/eclipse/proc/bomb_lines(atom/A)
if(!A)
return
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/eclipse))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
for(var/i = 0, i < iteration, i++)
if(!(potential_targets.len))
break
var/mob/target = pick(potential_targets)
potential_targets -= target
spawn_lines(target)
/mob/living/simple_mob/humanoid/eclipse/proc/spawn_lines(atom/target)
var/alignment = rand(1,2) // 1 for vertical, 2 for horizontal
var/list/line_range = list()
var/turf/T = get_turf(target)
line_range += T
for(var/i = 1, i <= 7, i++)
switch(alignment)
if(1)
if(T.x-i > 0)
line_range += locate(T.x-i, T.y-i, T.z)
if(T.x+i <= world.maxx)
line_range += locate(T.x+i, T.y+i, T.z)
if(T.y-i > 0)
line_range += locate(T.x+i, T.y-i, T.z)
if(T.y+i <= world.maxy)
line_range += locate(T.x-i, T.y+i, T.z)
if(2)
if(T.x-i > 0)
line_range += locate(T.x-i, T.y, T.z)
if(T.x+i <= world.maxx)
line_range += locate(T.x+i, T.y, T.z)
if(T.y-i > 0)
line_range += locate(T.x, T.y-i, T.z)
if(T.y+i <= world.maxy)
line_range += locate(T.x, T.y+i, T.z)
for(var/turf/dropspot in line_range)
new artidrop(dropspot)
/mob/living/simple_mob/humanoid/eclipse/proc/bomb_chaos(atom/A)
if(!A)
return
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/eclipse))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
for(var/i = 0, i < iteration, i++)
if(!(potential_targets.len))
break
var/mob/target = pick(potential_targets)
potential_targets -= target
chaos_lines(target)
/mob/living/simple_mob/humanoid/eclipse/proc/chaos_lines(atom/target)
var/alignment = rand(1,2)
var/list/line_range = list()
var/turf/T = get_turf(target)
line_range += T
for(var/i = 1, i <= 7, i++)
switch(alignment)
if(1)
if(T.x-i > 0)
var/zed = rand(1,3)
line_range += locate(T.x+zed, T.y-i, T.z)
if(T.x+i <= world.maxx)
var/zed = rand(1,3)
line_range += locate(T.x+zed, T.y+i, T.z)
if(T.y-i > 0)
var/zed = rand(1,3)
line_range += locate(T.x+i, T.y+zed, T.z)
if(T.y+i <= world.maxy)
var/zed = rand(1,3)
line_range += locate(T.x-i, T.y+zed, T.z)
if(2)
if(T.x-i > 0)
var/zed = rand(1,3)
line_range += locate(T.x-i, T.y-zed, T.z)
if(T.x+i <= world.maxx)
var/zed = rand(1,3)
line_range += locate(T.x+i, T.y-zed, T.z)
if(T.y-i > 0)
var/zed = rand(1,3)
line_range += locate(T.x-zed, T.y-i, T.z)
if(T.y+i <= world.maxy)
var/zed = rand(1,3)
line_range += locate(T.x-zed, T.y+i, T.z)
for(var/turf/dropspot in line_range)
new artidrop(dropspot)
/obj/effect/artillery_attack
anchored = TRUE
density = FALSE
unacidable = TRUE
mouse_opacity = 0
icon = 'icons/effects/effects.dmi'
icon_state = "drop_marker"
var/ammmotype = /obj/effect/falling_effect/callstrike_bomb
/obj/effect/artillery_attack/Initialize(mapload)
..()
return INITIALIZE_HINT_LATELOAD
/obj/effect/artillery_attack/LateInitialize()
var/delay = rand(25, 30)
addtimer(CALLBACK(src, PROC_REF(spawner)), delay, TIMER_DELETE_ME)
/obj/effect/artillery_attack/proc/spawner()
new ammmotype(src.loc)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src), 0.7 SECONDS, TIMER_DELETE_ME)
/obj/effect/falling_effect/callstrike_bomb
falling_type = /obj/effect/callstrike
crushing = FALSE
/obj/effect/callstrike
anchored = TRUE
density = FALSE
mouse_opacity = 0
icon ='modular_chomp/icons/obj/guns/precursor/tyr.dmi'
/obj/effect/callstrike/Initialize(mapload)
.=..()
icon_state = "arti"
/obj/effect/callstrike/end_fall(var/crushing = FALSE)
for(var/mob/living/L in loc)
var/target_zone = ran_zone()
var/blocked = L.run_armor_check(target_zone, "laser")
if(!L.apply_damage(70, BURN, target_zone, blocked))
break
playsound(src, 'sound/effects/clang2.ogg', 50, 1)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src), 0.25 SECONDS, TIMER_DELETE_ME)
//Spacing
/obj/effect/falling_effect/callstrike_slime
falling_type = /obj/effect/callstrike_slime
crushing = FALSE
/obj/effect/callstrike_slime
anchored = TRUE
density = FALSE
mouse_opacity = 0
icon ='modular_chomp/icons/obj/guns/precursor/tyr.dmi'
/obj/effect/callstrike_slime/Initialize(mapload)
.=..()
icon_state = "squish"
/obj/effect/callstrike_slime/end_fall(var/crushing = FALSE)
for(var/mob/living/L in loc)
var/target_zone = ran_zone()
var/blocked = L.run_armor_check(target_zone, "energy")
if(!L.apply_damage(50, BURN, target_zone, blocked))
break
playsound(src, 'sound/effects/squelch1.ogg', 50, 1)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src), 0.25 SECONDS, TIMER_DELETE_ME)
/obj/effect/artillery_attack/goop
ammmotype = /obj/effect/falling_effect/callstrike_slime
/obj/effect/falling_effect/callstrike_slimezone
falling_type = /obj/effect/slimeattack
crushing = FALSE
/obj/effect/slimeattack
name = "slime goop"
desc = "A pool of acidic slime"
icon_state = "pool"
icon ='modular_chomp/icons/obj/guns/precursor/tyr.dmi'
var/health = 5
var/modifiertype = /datum/modifier/poisoned/weak
/obj/effect/slimeattack/Crossed(atom/movable/source)
if(source.is_incorporeal())
return
Bumped(source)
/obj/effect/slimeattack/attackby(var/obj/item/W, var/mob/user)
user.setClickCooldown(user.get_attack_speed(W))
if(LAZYLEN(W.attack_verb))
visible_message(span_warning("\The [src] has been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]"))
else
visible_message(span_warning("\The [src] has been attacked with \the [W][(user ? " by [user]." : ".")]"))
var/damage = W.force / 4.0
health -= damage
healthcheck()
/obj/effect/slimeattack/bullet_act(var/obj/item/projectile/Proj)
..()
health -= Proj.get_structure_damage()
healthcheck()
/obj/effect/slimeattack/proc/die()
qdel(src)
/obj/effect/slimeattack/proc/healthcheck()
if(health <= 0)
die()
/obj/effect/slimeattack/Bumped(mob/M as mob|obj)
if(istype(M, /obj/mecha))
return
if(istype(M, /mob/living/))
var/mob/living/mob = M
if(!mob.hovering || !mob.flying)
attack_mob(M)
/obj/effect/slimeattack/proc/attack_mob(mob/living/L)
var/target_zone = pick(BP_ALL)
var/amount_blocked = L.run_armor_check(target_zone, "bio")
var/damage = rand(5,5)
if(amount_blocked >= 40)
return
L.apply_damage(damage, BURN, target_zone, amount_blocked, used_weapon = "slime")
L.add_modifier(modifiertype, 5 SECONDS)
/mob/living/simple_mob/humanoid/eclipse/minion
name = "Eclipse Expirment"
desc = "A being in an armored spacesuit"
/mob/living/simple_mob/humanoid/eclipse/minion/squish_sphere
name = "Eclipse Bio-Sphere"
desc = "A floating orb of slime"
health = 7
maxHealth = 7
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 100)
icon_state = "squishblob"
icon_living = "squishblob"
ai_holder_type = /datum/ai_holder/simple_mob/intentional/adv_dark_gygax
melee_damage_lower = 1
melee_damage_upper = 1
attack_armor_pen = 100 //90% sure we need damage for the application of mods to proc
/mob/living/simple_mob/humanoid/eclipse/minion/squish_sphere/apply_melee_effects(var/atom/A) //bring curea, a synth or gamble hard enough.
if(isliving(A))
var/mob/living/L = A
L.add_modifier(/datum/modifier/poisoned, 120 SECONDS)
/mob/living/simple_mob/humanoid/eclipse/head/stargazer //starhunter boss replacement
name = "Eclipse Stargazer"
desc = "A being in an armored spacesuit"
icon_state = "medi" //place holdery
icon_living = "medi" //place holdery
health = 600
maxHealth = 600
glow_toggle = TRUE
glow_override = TRUE
glow_color = "#FFA723"
glow_range = 16
armor = list(melee = 49, bullet = 49, laser = 49, energy = 49, bomb = 100, bio = 100, rad = 100)
projectiletype = /obj/item/projectile/energy/homing_bolt
ai_holder_type = /datum/ai_holder/simple_mob/intentional/adv_dark_gygax
loot_list = list(/obj/item/slime_extract/sepia = 25,
/obj/item/slime_extract/ruby = 25,
/obj/item/slime_extract/bluespace = 25,
/obj/item/slime_extract/light_pink = 25,
/obj/item/slime_extract/yellow = 25,
/obj/item/slime_extract/oil = 25,
)
/mob/living/simple_mob/humanoid/eclipse/head/stargazer/bullet_act(obj/item/projectile/P)
..()
for(var/i =1 to 3)
new /mob/living/simple_mob/humanoid/eclipse/minion/squish_sphere
/mob/living/simple_mob/humanoid/eclipse/head/stargazer/attackby(var/obj/item/O as obj, var/mob/user as mob)
..()
new /mob/living/simple_mob/humanoid/eclipse/minion/squish_sphere
/mob/living/simple_mob/humanoid/eclipse/head/stargazer/do_special_attack(atom/A)
if(prob(50))
artidrop = /obj/effect/artillery_attack/goop
if(prob(50))
bomb_lines(A)
else
chaos_lines(A)
else
artidrop = /obj/effect/falling_effect/callstrike_slime
if(prob(50))
bomb_lines(A)
else
chaos_lines(A)
@@ -1,153 +0,0 @@
/datum/category_item/catalogue/fauna/eclipse
name = "The Eclipse"
desc = "Life on the Frontier is hard, and unregulated. Unlike life in \
more 'civlized' areas of the Galaxy, violence and piracy remain common \
this far out. The Eclipse cares naught for this, rather their attention \
shifting to the fallen kingdoms and empires of the past. \
Salavaging secerts and materials long forgotton and stiching them \
togther in new, strange creations."
value = CATALOGUER_REWARD_TRIVIAL
unlocked_by_any = list(/datum/category_item/catalogue/fauna/eclipse)
/datum/category_item/catalogue/fauna/eclipse/teslanoodle
name = "The Tesla Armor"
desc = "The tesla's units armor crackles with eletrical current. \
Manifestation of such energy seeming to be summoned at will or at \
random. This creation seems to be in a prototype phase."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/firemoff
name = "Eclipse Shielding"
desc = "Eclipse armor and uniform is unlike most others, seeming wide \
and varied, but in reality is simplified to two diffrent types. \
One of the Eclipse's first studies was a mix of precursor ablative and \
bullet proof technolgy. They have gotten an understanding of it, they \
are able to fuse it with many diffrent uniforms, allowing for a more \
diverse apperance."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/snipertesh
name = "Cult-like rituals"
desc = "The Eclipse started off as a strange mixutre of a friendly \
band, and lower tier orginization. as their technolgy has evolved, so did \
their behaviors. Some sects begining to worship and heavly praise the fallen \
precusor empires. Some going as far to try and revivive them, always to \
mixed results, rarely resulting in in-fighting."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/radiation
name = "Nuclear Failures"
desc = "Failure is not an option for the Eclipse. More so, failure \
is just another opportunity to learn. Their radiation units coming\
from serveral failures of nuclear power soruces alongside failures amongst, \
nuclear weaponry. Eventually creating quality weapons, and refitting their \
power sources to radiation field generators."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/silvernoodle
name = "Failed Selling"
desc = "While one would think the Eclipse would become rather wealthy and \
fame from their line of work, they are instead rather average due to most \
of their products having a high chance of failure. For every working weapon, \
armor, tool, there are at least 10 failures. Resleeving and high quality \
medication are one of the few reasons they have not wiped themselves out."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/shotgunner
name = "Specialized Arms"
desc = "The Eclipse's focus on utilizing precursor tech leads them down \
strange weaponry. Even with firearms, they are always modified slightly \
just to fufill having some form of what they see as future tech. \
Although this leads to weapon failures, or creation accidents."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/bulletstorm
name = "Open Joining"
desc = "The Eclipse has many varying memebers, of all diffrent shapes, \
sizes, and heritages. This is due to a varity of factors, which includes \
high mortality rates, mutations, and body modification expermintation."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/ravanger
name = "Resleeving Failures"
desc = "The Eclipse has precourdered many bits of resleeving equipment \
but like most of that comes into their grasp it has become more dangerous \
and expirmental. Corruption and malformed bodies have become common place, \
minds becoming lost. But failure is non-exsistant, instead being repurosed \
such as shaping them into ravanger units."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/hellhound
name = "Hellhound Units"
desc = "Equiped with specialized armor, the systems of the suit pairing \
with their nervous system in an attempt to allow for better hunting. \
Venom is found within their claws and fangs, the chemical compound being, \
akin to soporific, The hellhound units are both useful for single target \
hunting, and frontal assualt."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/wheel
name = "Armadillo"
desc = "With several strange creatures among their ranks, the Eclipse \
has attempted strange and usual armors and tatics. With several being able \
to curl up into a ball shape, the wheel armor was created, trying to turn \
a rolling motion into an offensive force."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/guardian
name = "Slime Pits"
desc = "Another potential of failed resleeves are the slime pits, \
the failed body being merged with one of their many slimes, creating something \
akin to a promethean but having a mind more akin to a drone. Some of the \
slime creations the similiar abilties to their slime counter parts, or \
renamants of the donator's DNA."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/pummler
name = "Hunter Unit - Pummler"
desc = "Another drone like creation, meld with alien sea life, and traces \
renamants of solar grubs. Was orginally meant for assualting mecha pilots, \
and tearing them free from the mechas, but prooved to be too variable with \
results. Instead their desgin changing to that of hunting down single \
targets across any and all terrains."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/aeroblaster
name = "Eclipse Drones"
desc = "Sometimes, the failed resleeves only leave the fragments of a mind \
behind. But even that is useful, latching onto the renamants of loyalty and \
the brain's remaining procressing power to create special circuits for, \
their drones."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/miner
name = "Bio-tech Unit"
desc = "One benefit of the slime units is they're able to easily interface \
with the drone units. Cooperation is keenly unquie between the slime and \
drone units. This is espically helpful within hazardous mining conditions \
both being able to flee or alter plans as soon as either noitces."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/froststalker
name = "Mindless Ice"
desc = "Cryogel expermination has been one of the most active fronts, but \
with it, countless failures. Whilst not on purpose, many of their number\
have had their bodies freeze over, transforming into sentient creatures, \
of ice. Their minds sometimes lost alongside their orginal form."
value = CATALOGUER_REWARD_MEDIUM
/datum/category_item/catalogue/fauna/eclipse/cryomancer
name = "Cryomancers"
desc = "One of the few success in the Pluto Intitative, but one that \
yields great results. Highly resistant to cold, and heat, more so then it's \
contemparies, all the while wielding expirmental frost weaponry to deadly \
effecieny. Rare and vaulable pieces in the Eclipse's army, they are rarely seen \
but when utilized, that area is of high priority. "
value = CATALOGUER_REWARD_MEDIUM
@@ -1,149 +0,0 @@
/mob/living/simple_mob/humanoid/eclipse
vore_active = 1
vore_capacity = 2
vore_max_size = RESIZE_HUGE
vore_min_size = RESIZE_SMALL
vore_pounce_chance = 30
vore_icons = null
can_be_drop_prey = FALSE
can_be_drop_pred = TRUE
/mob/living/simple_mob/humanoid/eclipse/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
add_verb(src,/mob/living/simple_mob/proc/animal_mount) //CHOMPEdit TGPanel
add_verb(src,/mob/living/proc/toggle_rider_reins) //CHOMPEdit TGPanel
movement_cooldown = 3
/mob/living/simple_mob/humanoid/eclipse/MouseDrop_T(mob/living/M, mob/living/user)
return
/mob/living/simple_mob/humanoid/eclipse/load_default_bellies()
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The fearsome preadtor gets a firm grip upon you, before dunking you into it's maw, then with a powerful swift gulp you're sent tumbling into it's stomach.."
B.emote_lists[DM_HOLD] = list(
"Your surroundings are momentarily filled with tour predator's pleased rumbling, its hands stroking over the taut swell you make in its belly.",)
B.emote_lists[DM_DIGEST] = list(
"Every clench of the predator's stomach grinds powerful digestive fluids into your body, forcibly churning away your strength!",)
//This is placeholder code. Going to add special vorny for each of them slowly but surely.
/mob/living/simple_mob/humanoid/eclipse/head/scientist
vore_active = 1
vore_capacity = 6
vore_max_size = RESIZE_HUGE
vore_min_size = RESIZE_SMALL
vore_pounce_chance = 0 // Beat them into crit before eating.
can_be_drop_prey = FALSE //CHOMP Add
digestable = 0
devourable = 0
/mob/living/simple_mob/humanoid/eclipse/head/scientist/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
add_verb(src,/mob/living/simple_mob/proc/animal_mount) //CHOMPEdit TGPanel
add_verb(src,/mob/living/proc/toggle_rider_reins) //CHOMPEdit TGPanel
movement_cooldown = 1
/mob/living/simple_mob/humanoid/eclipse/head/scientist/MouseDrop_T(mob/living/M, mob/living/user)
return
/mob/living/simple_mob/humanoid/eclipse/head/scientist/load_default_bellies()
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The fearsome preadtor gets a firm grip upon you, before dunking you into it's maw, then with a powerful swift gulp you're sent tumbling into it's stomach.."
B.emote_lists[DM_HOLD] = list(
"Your surroundings are momentarily filled with tour predator's pleased rumbling, its hands stroking over the taut swell you make in its belly.",
"Your surrondings glow with a neon red, dashes and spirals of pitch black flowing through the red gummy flesh as if it were a strange sky.",
"Your satsified predator sways their bloated gullet happily, their warm rumbling vibrarting the stomach, and by extension you.",)
B.emote_lists[DM_DIGEST] = list(
"Every clench of the predator's stomach grinds powerful digestive fluids into your body, forcibly churning away your strength!",
"The caustic red acid splashes, and washes over your frame, your sense of smell being overwhelmed by acid and sulfur as you're turned to nutrion.",
"Every swift swap of the predator's hips sends you slamming against the glowing red sides, your vision blurring further as you contunie to weaken." ,)
/mob/living/simple_mob/humanoid/eclipse/head/security
vore_active = 1
vore_capacity = 6
vore_max_size = RESIZE_HUGE
vore_min_size = RESIZE_SMALL
vore_pounce_chance = 0 // Beat them into crit before eating.
can_be_drop_prey = FALSE //CHOMP Add
digestable = 0
devourable = 0
/mob/living/simple_mob/humanoid/eclipse/head/security/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
add_verb(src,/mob/living/simple_mob/proc/animal_mount) //CHOMPEdit TGPanel
add_verb(src,/mob/living/proc/toggle_rider_reins) //CHOMPEdit TGPanel
movement_cooldown = 1
/mob/living/simple_mob/humanoid/eclipse/head/security/MouseDrop_T(mob/living/M, mob/living/user)
return
/mob/living/simple_mob/humanoid/eclipse/head/security/load_default_bellies()
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The fearsome preadtor gets a firm grip upon you, before dunking you into it's maw, then with a powerful swift gulp you're sent tumbling into it's stomach.."
B.emote_lists[DM_HOLD] = list(
"Your surroundings are momentarily filled with tour predator's pleased rumbling, its hands stroking over the taut swell you make in its belly.",
"Your surrondings glow with a neon red, dashes and spirals of pitch black flowing through the red gummy flesh as if it were a strange sky.",
"Your satsified predator sways their bloated gullet happily, their warm rumbling vibrarting the stomach, and by extension you.",)
B.emote_lists[DM_DIGEST] = list(
"Every clench of the predator's stomach grinds powerful digestive fluids into your body, forcibly churning away your strength!",
"The caustic red acid splashes, and washes over your frame, your sense of smell being overwhelmed by acid and sulfur as you're turned to nutrion.",
"Every swift swap of the predator's hips sends you slamming against the glowing red sides, your vision blurring further as you contunie to weaken." ,)
/mob/living/simple_mob/humanoid/eclipse/head/captain
vore_active = 1
vore_capacity = 6
vore_max_size = RESIZE_HUGE
vore_min_size = RESIZE_SMALL
vore_pounce_chance = 0 // Beat them into crit before eating.
can_be_drop_prey = FALSE //CHOMP Add
digestable = 0
devourable = 0
/mob/living/simple_mob/humanoid/eclipse/head/captain/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
add_verb(src,/mob/living/simple_mob/proc/animal_mount) //CHOMPEdit TGPanel
add_verb(src,/mob/living/proc/toggle_rider_reins) //CHOMPEdit TGPanel
movement_cooldown = 1
/mob/living/simple_mob/humanoid/eclipse/head/captain/MouseDrop_T(mob/living/M, mob/living/user)
return
/mob/living/simple_mob/humanoid/eclipse/head/captain/load_default_bellies()
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The fearsome preadtor gets a firm grip upon you, before dunking you into it's maw, then with a powerful swift gulp you're sent tumbling into it's stomach.."
B.emote_lists[DM_HOLD] = list(
"Your surroundings are momentarily filled with tour predator's pleased rumbling, its hands stroking over the taut swell you make in its belly.",
"Your surrondings glow with a neon red, dashes and spirals of pitch black flowing through the red gummy flesh as if it were a strange sky.",
"Your satsified predator sways their bloated gullet happily, their warm rumbling vibrarting the stomach, and by extension you.",)
B.emote_lists[DM_DIGEST] = list(
"Every clench of the predator's stomach grinds powerful digestive fluids into your body, forcibly churning away your strength!",
"The caustic red acid splashes, and washes over your frame, your sense of smell being overwhelmed by acid and sulfur as you're turned to nutrion.",
"Every swift swap of the predator's hips sends you slamming against the glowing red sides, your vision blurring further as you contunie to weaken." ,)
@@ -1,219 +0,0 @@
/mob/living/simple_mob/humanoid/starhunter/hunter/clone
name = "Avatar Of The Serpent"
icon_state = "avatar"
health = 15
maxHealth = 15
ai_holder_type = /datum/ai_holder/simple_mob/ranged/aggressive/starhunter
projectiletype = /obj/item/projectile/energy/ninjastar
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar
name = "Avatar Of The Serpent"
icon_state = "avatar"
health = 1000 //50 hits from 20 damage
maxHealth = 1000 //50 hits from 20 damage
damage_fatigue_mult = 0
ai_holder_type = /datum/ai_holder/simple_mob/ranged/aggressive/starhunter
special_attack_cooldown = 20 SECONDS
special_attack_min_range = 1
special_attack_max_range = 7
projectiletype = /obj/item/projectile/energy/ninjastar
digestable = 0
devourable = 0
//note to self, expand the loot list later
loot_list = list(/obj/item/storage/belt/holding = 60,
/obj/item/clothing/glasses/omni = 60,
/obj/item/kinetic_crusher/glaive = 60,
/obj/item/slime_extract/sepia = 60,
/obj/item/circuitboard/defenseonelisk = 60,
/obj/item/circuitboard/paradoxrift = 60,
/obj/item/capture_crystal = 60
)
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/updatehealth()
. = ..()
if(health < maxHealth*0.25)
special_attack_cooldown = 5 SECONDS
projectiletype = /obj/item/projectile/bullet/ninjaburst
else if(health < maxHealth*0.5)
special_attack_cooldown = 10 SECONDS
projectiletype = /obj/item/projectile/energy/kunai
else if (health < maxHealth*0.75)
special_attack_cooldown = 15 SECONDS
projectiletype = /obj/item/projectile/energy/chakaram
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/do_special_attack(atom/A)
if(health < maxHealth*0.4)
if(prob(20))
lightingstorm(A)
if(prob(20))
lightingline(A)
if(prob(20))
lightpillar(A)
if(prob(20))
clones(A)
else
rapidfire_windup(A)
else if(health < maxHealth*0.7)
if(prob(25))
lightingstorm(A)
if(prob(25))
lightingline(A)
if(prob(25))
lightpillar(A)
else
rapidfire_windup(A)
else
if(prob(50))
lightingstrike(A)
else
lightpillar(A)
/obj/item/projectile/energy/kunai //chip damage
name = "Energy Kunai"
icon = 'modular_chomp/icons/mob/starhunters.dmi' //commiting sin
icon_state = "kunai"
damage = 5
armor_penetration = 65 //Gets into the gaps
speed = 2
damage_type = BURN
check_armour = "laser"
/obj/item/projectile/energy/chakaram //slower but hits harder
name = "Energy Chakaram"
icon = 'modular_chomp/icons/mob/starhunters.dmi' //commiting sin
icon_state = "chakaram"
damage = 25
armor_penetration = 25 //Gets into the gaps
speed = 5
damage_type = BURN
check_armour = "laser"
/obj/item/projectile/bullet/ninjaburst
use_submunitions = 1
only_submunitions = 1
range = 0
embed_chance = 0
submunition_spread_max = 2600
submunition_spread_min = 150
submunitions = list(/obj/item/projectile/energy/kunai = 3, /obj/item/projectile/energy/chakaram = 1, /obj/item/projectile/energy/ninjastar = 3)
/datum/ai_holder/simple_mob/ranged/aggressive/starhunter
vision_range = 14
closest_distance = 5
returns_home = TRUE // Stay close to the base...
wander = TRUE // ... but "patrol" a little.
intelligence_level = AI_SMART // Also knows not to walk while confused if it risks death.
mauling = TRUE
call_distance = 0 //Trying to disable this for the mobs
retaliate = TRUE
hostile = FALSE
violent_breakthrough = TRUE
respect_alpha = FALSE
pointblank = TRUE
/obj/effect/calldown_attack_lighting
anchored = TRUE
density = FALSE
unacidable = TRUE
mouse_opacity = 0
icon = 'icons/effects/effects.dmi'
icon_state = "drop_marker"
/obj/effect/calldown_attack_lighting/Initialize(mapload)
..()
return INITIALIZE_HINT_LATELOAD
/obj/effect/calldown_attack_fire/LateInitialize()
var/delay = rand(25, 30)
spawn(delay-7)
lightning_strike(src.loc)
spawn(delay)
qdel(src)
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/proc/lightingstorm(atom/A)
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/starhunter/hunter))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
for(var/i = 0, i < iteration, i++)
if(!(potential_targets.len))
break
var/mob/target = pick(potential_targets)
potential_targets -= target
lightingstormfollow(target)
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/proc/lightingstormfollow(atom/target)
var/list/bomb_range = block(locate(target.x-6, target.y-6, target.z), locate(target.x+6, target.y+6, target.z))
new /obj/effect/calldown_attack(get_turf(target))
bomb_range -= get_turf(target)
for(var/i = 0, i < 4, i++)
var/turf/T = pick(bomb_range)
new /obj/effect/calldown_attack_lighting(T)
bomb_range -= T
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/proc/lightingline(atom/A)
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/starhunter/hunter))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
for(var/i = 0, i < iteration, i++)
if(!(potential_targets.len))
break
var/mob/target = pick(potential_targets)
potential_targets -= target
lightinglinefollow(target)
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/proc/lightinglinefollow(atom/target)
var/alignment = rand(1,2) // 1 for vertical, 2 for horizontal
var/list/line_range = list()
var/turf/T = get_turf(target)
line_range += T
for(var/i = 1, i <= 7, i++)
switch(alignment)
if(1)
if(T.x-i > 0)
line_range += locate(T.x-i, T.y, T.z)
if(T.x+i <= world.maxx)
line_range += locate(T.x+i, T.y, T.z)
if(2)
if(T.y-i > 0)
line_range += locate(T.x, T.y-i, T.z)
if(T.y+i <= world.maxy)
line_range += locate(T.x, T.y+i, T.z)
for(var/turf/dropspot in line_range)
new /obj/effect/calldown_attack_lighting(dropspot)
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/proc/clones(atom/A)
new /mob/living/simple_mob/humanoid/starhunter/hunter/clone (src.loc)
new /mob/living/simple_mob/humanoid/starhunter/hunter/clone (src.loc)
new /mob/living/simple_mob/humanoid/starhunter/hunter/clone (src.loc)
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/proc/lightingstrike(atom/A)
var/list/nearby_things = range(1, A)
var/list/valid_turfs = list()
// All this work to just go to a non-dense tile.
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
if(!(valid_turfs.len))
to_chat(src, span_warning("There wasn't an unoccupied spot to teleport to."))
return FALSE
var/turf/target_turf = pick(valid_turfs)
new/obj/effect/calldown_attack_lighting(target_turf)
@@ -1,156 +0,0 @@
/mob/living/simple_mob/humanoid/starhunter
name = "Starhunter Initiate"
desc = "A strange critter cladded in strange armor."
icon = 'modular_chomp/icons/mob/starhunters.dmi'
icon_state = "sun"
icon_living = "sun"
icon_dead = "statisgem"
icon_gib = "syndicate_gib"
taser_kill = 0
faction = "starhunter"
movement_cooldown = 0
status_flags = 0
response_help = "pokes"
response_disarm = "shoves"
response_harm = "hits"
health = 120 //This may be high, but intend for the combative ones to be on their own.
maxHealth = 120
harm_intent_damage = 5
melee_damage_lower = 17 //machette
melee_damage_upper = 17 //beg knife go brrr
attack_sharp = 1
attack_edge = 1
attacktext = list("slashed", "stabbed")
projectile_dispersion = 8
projectile_accuracy = -20
armor = list(melee = 40, bullet = 70, laser = 10, energy = 0, bomb = 50, bio = 100, rad = 100) // Critters are more ortiented torwards melee and bullet
ranged_cooldown = 5
ai_holder_type = /datum/ai_holder/simple_mob/starhunter
can_be_drop_prey = FALSE
pass_flags = PASSTABLE
softfall = TRUE
//spaceproofing things
minbodytemp = 0 // Minimum "okay" temperature in kelvin
maxbodytemp = 600 // Maximum of above
min_oxy = 0 // Oxygen in moles, minimum, 0 is 'no minimum'
max_oxy = 0 // Oxygen in moles, maximum, 0 is 'no maximum'
min_tox = 0 // Phoron min
max_tox = 0 // Phoron max
min_co2 = 0 // CO2 min
max_co2 = 0 // CO2 max
min_n2 = 0 // N2 min
max_n2 = 0
/datum/ai_holder/simple_mob/starhunter
returns_home = TRUE // Stay close to the base...
wander = TRUE // ... but "patrol" a little.
intelligence_level = AI_SMART // Also knows not to walk while confused if it risks death.
can_flee = TRUE // If they're even allowed to flee.
flee_when_dying = TRUE // If they should flee when low on health.
dying_threshold = 0.2 // How low on health the holder needs to be before fleeing. Defaults to 30% or lower health.
mauling = TRUE
call_distance = 0 //Trying to disable this for the mobs
vision_range = 10
retaliate = TRUE
hostile = FALSE
violent_breakthrough = TRUE
respect_alpha = FALSE
pointblank = TRUE
/datum/ai_holder/simple_mob/starhunter/aggro
hostile = TRUE
//basic aggro stahunters
/mob/living/simple_mob/humanoid/starhunter/hunter
ai_holder_type = /datum/ai_holder/simple_mob/starhunter/aggro
special_attack_cooldown = 30 SECONDS
special_attack_min_range = 1
special_attack_max_range = 7
/mob/living/simple_mob/humanoid/starhunter/hunter/harvester
icon_state = "snekdruid"
icon_state = "snekdruid"
melee_damage_lower = 25
melee_damage_upper = 25
melee_attack_delay = 2.5 SECOND
/mob/living/simple_mob/humanoid/starhunter/hunter/harvester/handle_special() //wierd movement
if(prob(20))
step(src, pick(GLOB.cardinal))
..()
/mob/living/simple_mob/humanoid/starhunter/hunter/ninja
icon_state = "suneswift"
icon_living = "suneswift"
movement_cooldown = -3
melee_damage_lower = 15
melee_damage_upper = 15
melee_attack_delay = 1.5 SECOND
/mob/living/simple_mob/humanoid/starhunter/hunter/ninja/do_special_attack(atom/target)
if(prob(50))
teleportnompf(target)
else
smokebomb(target)
//Special attack procs
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/teleportnompf(atom/target)
var/list/nearby_things = range(1, target)
var/list/valid_turfs = list()
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
if(!(valid_turfs.len))
to_chat(src, span_warning("There wasn't an unoccupied spot to teleport to."))
return FALSE
var/turf/target_turf = pick(valid_turfs)
forceMove(target_turf)
var/mob/living/L = target
var/obj/belly/belly_dest
if(L.can_be_drop_prey && L.devourable)
L.forceMove(belly_dest)
to_chat(target, span_danger("[src] materializes around you, as you end up in their [belly_dest]!"))
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/smokebomb(atom/target)
var/list/nearby_things = range(1, target)
var/list/valid_turfs = list()
// All this work to just go to a non-dense tile.
for(var/turf/potential_turf in nearby_things)
var/valid_turf = TRUE
if(potential_turf.density)
continue
for(var/atom/movable/AM in potential_turf)
if(AM.density)
valid_turf = FALSE
if(valid_turf)
valid_turfs.Add(potential_turf)
if(!(valid_turfs.len))
to_chat(src, span_warning("There wasn't an unoccupied spot to teleport to."))
return FALSE
var/turf/target_turf = pick(valid_turfs)
var/datum/effect/effect/system/spark_spread/s2 = new /datum/effect/effect/system/smoke_spread
s2.set_up(5, 1, target_turf)
@@ -1,108 +0,0 @@
/mob/living/simple_mob/humanoid/starhunter/hunter/druid
vore_active = 1
vore_capacity = 6
vore_max_size = RESIZE_HUGE
vore_min_size = RESIZE_SMALL
vore_pounce_chance = 0 // Beat them into crit before eating.
can_be_drop_prey = FALSE //CHOMP Add
/mob/living/simple_mob/humanoid/starhunter/hunter/druid/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
add_verb(src,/mob/living/simple_mob/proc/animal_mount) //CHOMPEdit TGPanel
add_verb(src,/mob/living/proc/toggle_rider_reins) //CHOMPEdit TGPanel
movement_cooldown = 1
/mob/living/simple_mob/humanoid/starhunter/hunter/druid/MouseDrop_T(mob/living/M, mob/living/user)
return
/mob/living/simple_mob/humanoid/starhunter/hunter/druid/load_default_bellies()
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The fearsome preadtor gets a firm grip upon you, before dunking you into it's maw, then with a powerful swift gulp you're sent tumbling into it's stomach.."
B.emote_lists[DM_HOLD] = list(
"Your surroundings are momentarily filled with tour predator's pleased rumbling, its hands stroking over the taut swell you make in its belly.",
"Your surrondings glow with a neon red, dashes and spirals of pitch black flowing through the red gummy flesh as if it were a strange sky.",
"Your satsified predator sways their bloated gullet happily, their warm rumbling vibrarting the stomach, and by extension you.",)
B.emote_lists[DM_DIGEST] = list(
"Every clench of the predator's stomach grinds powerful digestive fluids into your body, forcibly churning away your strength!",
"The caustic red acid splashes, and washes over your frame, your sense of smell being overwhelmed by acid and sulfur as you're turned to nutrion.",
"Every swift swap of the predator's hips sends you slamming against the glowing red sides, your vision blurring further as you contunie to weaken." ,)
/mob/living/simple_mob/humanoid/starhunter/hunter/champion
vore_active = 1
vore_capacity = 6
vore_max_size = RESIZE_HUGE
vore_min_size = RESIZE_SMALL
vore_pounce_chance = 0 // Beat them into crit before eating.
can_be_drop_prey = FALSE //CHOMP Add
/mob/living/simple_mob/humanoid/starhunter/hunter/champion/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
add_verb(src,/mob/living/simple_mob/proc/animal_mount) //CHOMPEdit TGPanel
add_verb(src,/mob/living/proc/toggle_rider_reins) //CHOMPEdit TGPanel
movement_cooldown = 1
/mob/living/simple_mob/humanoid/starhunter/hunter/champion/MouseDrop_T(mob/living/M, mob/living/user)
return
/mob/living/simple_mob/humanoid/starhunter/hunter/champion/load_default_bellies()
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The fearsome preadtor gets a firm grip upon you, before dunking you into it's maw, then with a powerful swift gulp you're sent tumbling into it's stomach.."
B.emote_lists[DM_HOLD] = list(
"Your surroundings are momentarily filled with tour predator's pleased rumbling, its hands stroking over the taut swell you make in its belly.",
"Your surrondings glow with a neon red, dashes and spirals of pitch black flowing through the red gummy flesh as if it were a strange sky.",
"Your satsified predator sways their bloated gullet happily, their warm rumbling vibrarting the stomach, and by extension you.",)
B.emote_lists[DM_DIGEST] = list(
"Every clench of the predator's stomach grinds powerful digestive fluids into your body, forcibly churning away your strength!",
"The caustic red acid splashes, and washes over your frame, your sense of smell being overwhelmed by acid and sulfur as you're turned to nutrion.",
"Every swift swap of the predator's hips sends you slamming against the glowing red sides, your vision blurring further as you contunie to weaken." ,)
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar
vore_active = 1
vore_capacity = 6
vore_max_size = RESIZE_HUGE
vore_min_size = RESIZE_SMALL
vore_pounce_chance = 0 // Beat them into crit before eating.
vore_icons = SA_ICON_LIVING
can_be_drop_prey = FALSE //CHOMP Add
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/Login()
. = ..()
if(!riding_datum)
riding_datum = new /datum/riding/simple_mob(src)
add_verb(src,/mob/living/simple_mob/proc/animal_mount) //CHOMPEdit TGPanel
add_verb(src,/mob/living/proc/toggle_rider_reins) //CHOMPEdit TGPanel
movement_cooldown = 1
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/MouseDrop_T(mob/living/M, mob/living/user)
return
/mob/living/simple_mob/humanoid/starhunter/hunter/avatar/load_default_bellies()
. = ..()
var/obj/belly/B = vore_selected
B.name = "stomach"
B.desc = "The fearsome preadtor gets a firm grip upon you, before dunking you into it's maw, then with a powerful swift gulp you're sent tumbling into it's stomach.."
B.emote_lists[DM_HOLD] = list(
"Your surroundings are momentarily filled with tour predator's pleased rumbling, its hands stroking over the taut swell you make in its belly.",
"Your surrondings glow with a neon red, dashes and spirals of pitch black flowing through the red gummy flesh as if it were a strange sky.",
"Your satsified predator sways their bloated gullet happily, their warm rumbling vibrarting the stomach, and by extension you.",)
B.emote_lists[DM_DIGEST] = list(
"Every clench of the predator's stomach grinds powerful digestive fluids into your body, forcibly churning away your strength!",
"The caustic red acid splashes, and washes over your frame, your sense of smell being overwhelmed by acid and sulfur as you're turned to nutrion.",
"Every swift swap of the predator's hips sends you slamming against the glowing red sides, your vision blurring further as you contunie to weaken." ,)
@@ -1,242 +0,0 @@
//beg critters
//kitsune is bullet hell esque in a traditonal sense
//naga does a bunch of spawning and CoC
//This are both training for the bigger dude I'll make later
/mob/living/simple_mob/humanoid/starhunter/hunter/druid
name = "Starhunter Druid"
health = 200 //20 hits from 20 damage
maxHealth = 200 //20 hits from 20 damage
damage_fatigue_mult = 0
icon_state = "snekdruid"
icon_living = "snekdruid"
/mob/living/simple_mob/humanoid/starhunter/hunter/druid/do_special_attack(atom/A)
if(prob(50))
lightpillar(A)
else
fire_lines(A)
/mob/living/simple_mob/humanoid/starhunter/hunter/bullet_act(obj/item/projectile/P)
if(istype(P, /obj/item/projectile/energy/lightpillar))
visible_message(span_bolddanger(span_orange("[P] seems ineffective!."))) //immune to their own attack
else
..()
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/lightpillar(atom/A)
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/starhunter/hunter))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
for(var/i = 0, i < iteration, i++)
if(!(potential_targets.len))
break
var/mob/target = pick(potential_targets)
potential_targets -= target
spawn_lightpillar(target)
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/spawn_lightpillar(atom/target)
var/list/bomb_range = block(locate(target.x-4, target.y-4, target.z), locate(target.x+4, target.y+4, target.z))
new /obj/effect/calldown_attack(get_turf(target))
bomb_range -= get_turf(target)
for(var/i = 0, i < 4, i++)
var/turf/T = pick(bomb_range)
new /mob/living/simple_mob/humanoid/starhunter/hunter/prop(T)
bomb_range -= T
/mob/living/simple_mob/humanoid/starhunter/hunter/prop //This ain't a mob to spawn, but something apart of other mobs attacks and self deletes
health = 1000
maxHealth = 1000
projectile_dispersion = 0
projectile_accuracy = 100
armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 100, bio = 100, rad = 100)
projectiletype = /obj/item/projectile/energy/lightpillar
ranged_attack_delay = 1.5 SECONDS
icon_state = "prism"
icon_living = "prism"
/mob/living/simple_mob/humanoid/starhunter/hunter/prop/ranged_pre_animation(atom/A)
Beam(get_turf(A), icon_state = "sniper_beam", time = 2 SECONDS, maxdistance = 10)
. = ..()
/mob/living/simple_mob/humanoid/starhunter/hunter/prop/shoot_target(atom/A)
set waitfor = FALSE
if(!istype(A) || QDELETED(A))
return
setClickCooldown(get_attack_speed())
face_atom(A)
var/atom/orig_targ = A
if(ranged_attack_delay)
A = get_turf(orig_targ)
ranged_pre_animation(A)
handle_attack_delay(A, ranged_attack_delay) // This will sleep this proc for a bit, which is why waitfor is false.
if(needs_reload)
if(reload_count >= reload_max)
try_reload()
return FALSE
/*
* CHOMP Addition: This section here is (duplicated) special snowflake code because sniper does not call parent. Basically, this is a non-stupid version of the above intended for ranged mobs.
* ranged_attack_delay is stupid because it sleeps the entire mob.
* This new ranged_cooldown_time is smarter in the sense that it is an internalized timer. Try not to confuse the names.
*/
if(ranged_cooldown_time) //If you have a non-zero number in a mob's variables, this pattern begins.
if(ranged_cooldown <= world.time) //Further down, a timer keeps adding to the ranged_cooldown variable automatically.
visible_message(span_danger(span_bold("\The [src]") + " fires at \the [A]!")) //Leave notice of shooting.
shoot(A) //Perform the shoot action
if(casingtype) //If the mob is designated to leave casings...
new casingtype(loc) //... leave the casing.
ranged_cooldown = world.time + ranged_cooldown_time + ((injury_level / 2) SECONDS) //Special addition here. This is a timer. Keeping updating the time after shooting. Add that ranged cooldown time specified in the mob to the world time.
qdel(src)
return TRUE //End these commands here.
// CHOMPAddition End
visible_message(span_danger(span_bold("\The [src]") + " fires at \the [orig_targ]!"))
shoot(A)
if(casingtype)
new casingtype(loc)
if(ranged_attack_delay)
ranged_post_animation(A)
return TRUE
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/fire_lines(atom/A)
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/starhunter/hunter))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
for(var/i = 0, i < iteration, i++)
if(!(potential_targets.len))
break
var/mob/target = pick(potential_targets)
potential_targets -= target
spawn_fire(target)
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/spawn_fire(atom/target)
var/alignment = rand(1,2) // 1 for vertical, 2 for horizontal
var/list/line_range = list()
var/turf/T = get_turf(target)
line_range += T
for(var/i = 1, i <= 7, i++)
switch(alignment)
if(1)
if(T.x-i > 0)
line_range += locate(T.x-i, T.y, T.z)
if(T.x+i <= world.maxx)
line_range += locate(T.x+i, T.y, T.z)
if(2)
if(T.y-i > 0)
line_range += locate(T.x, T.y-i, T.z)
if(T.y+i <= world.maxy)
line_range += locate(T.x, T.y+i, T.z)
for(var/turf/dropspot in line_range)
new /obj/effect/calldown_attack_fire(dropspot)
/obj/effect/calldown_attack_fire
anchored = TRUE
density = FALSE
unacidable = TRUE
mouse_opacity = 0
icon = 'icons/effects/effects.dmi'
icon_state = "drop_marker"
/obj/effect/calldown_attack_fire/Initialize(mapload)
..()
return INITIALIZE_HINT_LATELOAD
/obj/effect/calldown_attack_fire/LateInitialize()
var/delay = rand(25, 30)
spawn(delay-7)
new /obj/fire(src.loc)
spawn(delay)
qdel(src)
//Kitsune Stuff
/mob/living/simple_mob/humanoid/starhunter/hunter/champion
name = "Starhunter Starweilder"
health = 200 //10 hits from 20 damage
maxHealth = 200
damage_fatigue_mult = 0
projectiletype = /obj/item/projectile/energy/ninjastar
icon_state = "suneswift"
icon_living = "suneswift"
/mob/living/simple_mob/humanoid/starhunter/hunter/champion/do_special_attack(atom/A)
if(prob(50))
bullethell(A)
else
rapidfire_windup(A)
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/bullethell(atom/A)
set waitfor = FALSE
var/sd = dir2angle(dir)
var/list/offsets = list(45, 45, 20, 10)
for(var/i = 0, i<4, i++)
for(var/j = 0, j <4, j++)
var/obj/item/projectile/energy/slow_orb/shot = new(get_turf(src))
shot.firer = src
shot.fire(sd)
sd += 90
sd += pick(offsets)
sleep(20)
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/rapidfire_windup(atom/A)
var/list/potential_targets = ai_holder.list_targets()
for(var/atom/entry in potential_targets)
if(istype(entry, /mob/living/simple_mob/humanoid/starhunter/hunter))
potential_targets -= entry
if(potential_targets.len)
var/iteration = clamp(potential_targets.len, 1, 3)
for(var/i = 0, i < iteration, i++)
if(!(potential_targets.len))
break
var/mob/target = pick(potential_targets)
potential_targets -= target
rapidfire(target)
/mob/living/simple_mob/humanoid/starhunter/hunter/proc/rapidfire(atom/target)
var/list/bomb_range = block(locate(target.x-4, target.y-4, target.z), locate(target.x+4, target.y+4, target.z))
var/obj/item/projectile/P = new /obj/item/projectile/energy/ninjastar(get_turf(src))
bomb_range -= get_turf(target)
for(var/i = 0, i < 4, i++)
var/turf/T = pick(bomb_range)
P.launch_projectile(target, BP_TORSO, src)
bomb_range -= T
/obj/item/projectile/energy/lightpillar
name = "Light Pillar"
icon = 'modular_chomp/icons/mob/starhunters.dmi' //commiting sin
icon_state = "lightpillar"
damage = 30 //DIVINE JUDGMENT
armor_penetration = 50 //DIVINE JUDGMENT
light_range = 5
light_power = 5
damage_type = BURN
check_armour = "laser"
light_color = "#FF6600"
range = 7
speed = 13
/obj/item/projectile/energy/ninjastar
name = "Energy Star"
icon = 'modular_chomp/icons/mob/starhunters.dmi' //commiting sin
icon_state = "ninjastar"
damage = 15
armor_penetration = 25 //Gets into the gaps
damage_type = BURN
check_armour = "laser"
@@ -1,128 +0,0 @@
/mob/living/simple_mob/humanoid/starhunter/trader/weaponsmith
name = "Starhunter Weapon Smith"
icon_state = "sunetrader"
icon_living = "sunetrader"
products = list(/obj/item/gun/energy/sickshot = 5,
/obj/item/material/twohanded/fireaxe/scythe = 3,
/obj/item/material/twohanded/spear/lance = 3,
/obj/item/beartrap = 12,
/obj/item/material/barbedwire = 12,
/obj/item/material/sword/battleaxe = 3
) // For each, use the following pattern:
premium = list(/obj/item/gun/energy/maghowitzer) //This may be a mistake
prices = list(/obj/item/gun/energy/maghowitzer = 8000,
/obj/item/gun/energy/sickshot = 800,
/obj/item/material/twohanded/fireaxe/scythe = 400,
/obj/item/material/twohanded/spear/lance = 400,
/obj/item/beartrap = 80,
/obj/item/material/barbedwire = 80,
/obj/item/material/sword/battleaxe = 400
)
/mob/living/simple_mob/humanoid/starhunter/trader/reliccollecter
name = "Starhunter Relic Collector"
icon_state = "snektrader"
icon_living = "snektrader"
products = list(/obj/item/clothing/head/helmet/combat/crusader = 3,
/obj/item/clothing/suit/armor/combat/crusader = 3,
/obj/item/clothing/head/culthood = 3,
/obj/item/clothing/suit/cultrobes = 3,
/obj/item/clothing/head/helmet/space/cult = 3,
/obj/item/clothing/suit/space/cult = 3,
/obj/item/soulstone = 8,
/obj/item/clothing/glasses/monocoole = 3,
/obj/item/storage/belt/holding = 1,
/obj/item/clothing/gloves/regen = 1
) // For each, use the following pattern:
premium = list(/obj/item/clothing/glasses/omni) //I am unsure why but this feels right
prices = list(/obj/item/clothing/head/helmet/combat/crusader = 600,
/obj/item/clothing/suit/armor/combat/crusader = 600,
/obj/item/clothing/head/culthood = 600,
/obj/item/clothing/suit/cultrobes = 600,
/obj/item/clothing/head/helmet/space/cult = 600,
/obj/item/clothing/suit/space/cult = 600,
/obj/item/soulstone = 80,
/obj/item/clothing/glasses/monocoole = 1200,
/obj/item/storage/belt/holding = 1800,
/obj/item/clothing/gloves/regen = 1800,
/obj/item/clothing/glasses/omni = 2600
)
/mob/living/simple_mob/humanoid/starhunter/trader/miner
name = "Starhunter Miner"
icon_state = "snektrader"
icon_living = "snektrader"
products = list(/obj/item/kinetic_crusher/glaive = 5,
/obj/item/kinetic_crusher = 3,
/obj/item/gun/energy/mininglaser = 3,
/obj/item/melee/shock_maul = 3,
/obj/item/stack/material/phoron = 50,
/obj/item/stack/material/uranium = 50,
/obj/item/stack/material/tritium = 50,
/obj/item/stack/material/deuterium = 50,
/obj/item/stack/material/bronze = 50,
/obj/item/circuitboard/paradoxrift = 3
) // For each, use the following pattern:
premium = list(/obj/item/circuitboard/defenseonelisk) // No specified amount = only one in stock
prices = list(/obj/item/kinetic_crusher/glaive = 600,
/obj/item/kinetic_crusher = 600,
/obj/item/gun/energy/mininglaser = 800,
/obj/item/melee/shock_maul = 600,
/obj/item/stack/material/phoron = 12,
/obj/item/stack/material/uranium = 12,
/obj/item/stack/material/tritium = 12,
/obj/item/stack/material/deuterium = 12,
/obj/item/stack/material/bronze = 12,
/obj/item/circuitboard/paradoxrift = 2400,
/obj/item/circuitboard/defenseonelisk = 5000
)
/mob/living/simple_mob/humanoid/starhunter/trader/farmer
name = "Starhunter Farmer"
icon_state = "sunetrader"
icon_living = "sunetrader"
products = list(/obj/item/slime_extract/sepia =3,
/obj/item/slime_extract/ruby = 3,
/obj/item/slime_extract/bluespace = 3,
/obj/item/slime_extract/oil = 3,
/obj/item/slime_extract/sapphire = 3,
/obj/item/slime_extract/emerald = 3,
/obj/item/seeds/shrinkshroom = 12,
/obj/item/seeds/megashroom = 12,
/obj/item/seeds/pitcherseed = 6,
/obj/item/seeds/deathberryseed = 6,
/obj/item/seeds/ambrosiainfernusseed = 6,
/obj/item/seeds/thaadra = 6,
/obj/item/seeds/icepepperseed = 6,
/obj/item/seeds/jurlmah = 6,
/obj/item/seeds/amauri = 6,
/obj/item/seeds/gelthi = 6,
/obj/item/seeds/vale = 6
) // For each, use the following pattern:
premium = list() // No specified amount = only one in stock
prices = list(/obj/item/slime_extract/sepia = 2500,
/obj/item/slime_extract/ruby = 2250,
/obj/item/slime_extract/bluespace = 2250,
/obj/item/slime_extract/oil = 2250,
/obj/item/slime_extract/sapphire = 2250,
/obj/item/slime_extract/emerald = 2250,
/obj/item/seeds/shrinkshroom = 50,
/obj/item/seeds/megashroom = 50,
/obj/item/seeds/pitcherseed = 125,
/obj/item/seeds/deathberryseed = 125,
/obj/item/seeds/ambrosiainfernusseed = 125,
/obj/item/seeds/thaadra = 125,
/obj/item/seeds/icepepperseed = 125,
/obj/item/seeds/jurlmah = 125,
/obj/item/seeds/amauri = 125,
/obj/item/seeds/gelthi = 125,
/obj/item/seeds/vale = 125)
@@ -1,392 +0,0 @@
/mob/living/simple_mob/humanoid/starhunter/trader
var/vend_ready = 1 //Are we ready to vend?? Is it time??
var/vend_delay = 10 //How long does it take to vend?
var/categories = CAT_NORMAL // Bitmask of cats we're currently showing
var/datum/stored_item/vending_product/currently_vending = null // What we're requesting payment for right now
var/vending_sound = "machines/vending/vending_drop.ogg"
/*
Variables used to initialize the product list
These are used for initialization only, and so are optional if
product_records is specified
*/
var/list/products = list() // For each, use the following pattern:
var/list/contraband = list() // list(/type/path = amount,/type/path2 = amount2)
var/list/premium = list() // No specified amount = only one in stock
/// Set automatically, allows coin use
var/has_premium = FALSE
var/list/prices = list() // Prices for each item, list(/type/path = price), items not in the list don't have a price.
/// Set automatically, enables pricing
var/has_prices = FALSE
// This one is used for refill cartridge use.
var/list/refill = list() // For each, use the following pattern:
// Enables refilling with appropriate cartridges
var/refillable = TRUE
var/obj/item/coin/coin
var/list/log = list()
var/has_logs = 0
var/list/product_records = list()
/mob/living/simple_mob/humanoid/starhunter/trader/Initialize(mapload)
. = ..()
build_inventory()
/mob/living/simple_mob/humanoid/starhunter/trader/proc/build_inventory()
var/list/all_products = list(
list(products, CAT_NORMAL),
list(contraband, CAT_HIDDEN),
list(premium, CAT_COIN))
for(var/current_list in all_products)
var/category = current_list[2]
for(var/entry in current_list[1])
var/datum/stored_item/vending_product/product = new/datum/stored_item/vending_product(src, entry)
product.price = (entry in prices) ? prices[entry] : 0
product.amount = (current_list[1][entry]) ? current_list[1][entry] : 1
product.category = category
GLOB.vending_products[entry] = 1
if(LAZYLEN(prices))
has_prices = TRUE
if(LAZYLEN(premium))
has_premium = TRUE
LAZYCLEARLIST(products)
LAZYCLEARLIST(contraband)
LAZYCLEARLIST(premium)
LAZYCLEARLIST(prices)
all_products.Cut()
/mob/living/simple_mob/humanoid/starhunter/trader/attackby(obj/item/W as obj, mob/user as mob)
var/obj/item/card/id/I = W.GetID()
if(I || istype(W, /obj/item/spacecash))
attack_hand(user)
return
else if(istype(W, /obj/item/coin) && has_premium)
user.drop_item()
W.forceMove(src)
coin = W
categories |= CAT_COIN
to_chat(user, span_notice("You insert \the [W] into \the [src]."))
SStgui.update_uis(src)
return
else
for(var/datum/stored_item/vending_product/R in product_records)
if(istype(W, R.item_path) && (W.name == R.item_name))
stock(W, R, user)
return
..()
/mob/living/simple_mob/humanoid/starhunter/trader/proc/pay_with_cash(var/obj/item/spacecash/cashmoney, mob/user)
if(currently_vending.price > cashmoney.worth)
// This is not a status display message, since it's something the character
// themselves is meant to see BEFORE putting the money in
to_chat(usr, "[icon2html(cashmoney,user.client)] " + span_warning("That is not enough money."))
return 0
if(istype(cashmoney, /obj/item/spacecash))
visible_message(span_info("\The [usr] inserts some cash into \the [src]."))
cashmoney.worth -= currently_vending.price
if(cashmoney.worth <= 0)
usr.drop_from_inventory(cashmoney)
qdel(cashmoney)
else
cashmoney.update_icon()
// Vending machines have no idea who paid with cash
credit_purchase("(cash)")
return 1
/mob/living/simple_mob/humanoid/starhunter/trader/proc/credit_purchase(var/target as text)
GLOB.vendor_account.money += currently_vending.price
var/datum/transaction/T = new()
T.target_name = target
T.purpose = "Purchase of [currently_vending.item_name]"
T.amount = "[currently_vending.price]"
T.source_terminal = name
T.date = GLOB.current_date_string
T.time = stationtime2text()
GLOB.vendor_account.transaction_log.Add(T)
/mob/living/simple_mob/humanoid/starhunter/trader/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Vending", name)
ui.open()
/mob/living/simple_mob/humanoid/starhunter/trader/tgui_data(mob/user)
var/list/data = list()
var/list/listed_products = list()
data["chargesMoney"] = has_prices ? TRUE : FALSE
data["products"] = listed_products
if(coin)
data["coin"] = coin.name
else
data["coin"] = FALSE
if(currently_vending)
data["actively_vending"] = currently_vending.item_name
else
data["actively_vending"] = null
var/mob/living/carbon/human/H
var/obj/item/card/id/C
data["guestNotice"] = "Please present cash.";
data["userMoney"] = 0
data["user"] = null
if(ishuman(user))
H = user
C = H.GetIdCard()
var/obj/item/spacecash/S = H.get_active_hand()
if(istype(S))
data["userMoney"] = S.worth
data["guestNotice"] = "Accepting [S.initial_name]. You have: [S.worth]₮."
else if(istype(C))
var/datum/money_account/A = get_account(C.associated_account_number)
if(istype(A))
data["user"] = list()
data["user"]["name"] = A.owner_name
data["userMoney"] = A.money
data["user"]["job"] = (istype(C) && C.rank) ? C.rank : "No Job"
else
data["guestNotice"] = "Unlinked ID detected. Present cash to pay.";
return data
/mob/living/simple_mob/humanoid/starhunter/trader/tgui_act(action, params)
if(usr.stat || usr.restrained())
return
if(..())
return TRUE
. = TRUE
switch(action)
if("remove_coin")
if(issilicon(usr))
return FALSE
if(!coin)
to_chat(usr, span_filter_notice("There is no coin in this machine."))
return
coin.forceMove(src.loc)
if(!usr.get_active_hand())
usr.put_in_hands(coin)
to_chat(usr, span_notice("You remove \the [coin] from \the [src]."))
coin = null
categories &= ~CAT_COIN
return TRUE
if("vend")
if(!vend_ready)
to_chat(usr, span_warning("[src] is busy!"))
return
var/key = text2num(params["vend"])
var/datum/stored_item/vending_product/R = product_records[key]
// This should not happen unless the request from NanoUI was bad
if(!(R.category & categories))
return
if(!can_buy(R, usr))
return
if(R.price <= 0)
vend(R, usr)
add_fingerprint(usr)
return TRUE
if(issilicon(usr)) //If the item is not free, provide feedback if a synth is trying to buy something.
to_chat(usr, span_danger("Lawed unit recognized. Lawed units cannot complete this transaction. Purchase canceled."))
return
if(!ishuman(usr))
return
vend_ready = FALSE // From this point onwards, vendor is locked to performing this transaction only, until it is resolved.
var/mob/living/carbon/human/H = usr
var/obj/item/card/id/C = H.GetIdCard()
if(!GLOB.vendor_account || GLOB.vendor_account.suspended)
to_chat(usr, span_filter_notice("Vendor account offline. Unable to process transaction."))
flick("[icon_state]-deny",src)
vend_ready = TRUE
return
currently_vending = R
var/paid = FALSE
if(istype(usr.get_active_hand(), /obj/item/spacecash))
var/obj/item/spacecash/cash = usr.get_active_hand()
paid = pay_with_cash(cash, usr)
else if(istype(usr.get_active_hand(), /obj/item/spacecash/ewallet))
var/obj/item/spacecash/ewallet/wallet = usr.get_active_hand()
paid = pay_with_ewallet(wallet)
else if(istype(C, /obj/item/card))
paid = pay_with_card(C, usr)
/*else if(usr.can_advanced_admin_interact())
to_chat(usr, span_notice("Vending object due to admin interaction."))
paid = TRUE*/
else
to_chat(usr, span_warning("Payment failure: you have no ID or other method of payment."))
vend_ready = TRUE
flick("[icon_state]-deny",src)
return TRUE // we set this because they shouldn't even be able to get this far, and we want the UI to update.
if(paid)
vend(currently_vending, usr) // vend will handle vend_ready
. = TRUE
else
to_chat(usr, span_warning("Payment failure: unable to process payment."))
vend_ready = TRUE
/mob/living/simple_mob/humanoid/starhunter/trader/proc/vend(datum/stored_item/vending_product/R, mob/user)
if(!can_buy(R, user))
return
if(!R.amount)
to_chat(user, span_warning("[src] has ran out of that product."))
vend_ready = TRUE
return
vend_ready = FALSE //One thing at a time!!
SStgui.update_uis(src)
if(R.category & CAT_COIN)
if(!coin)
to_chat(user, span_notice("You need to insert a coin to get this item."))
return
else
qdel(coin)
coin = null
categories &= ~CAT_COIN
flick("[icon_state]-vend",src)
addtimer(CALLBACK(src, PROC_REF(delayed_vend), R, user), vend_delay)
/mob/living/simple_mob/humanoid/starhunter/trader/proc/delayed_vend(datum/stored_item/vending_product/R, mob/user)
R.get_product(get_turf(src))
playsound(src, "sound/[vending_sound]", 100, 1, 1)
GLOB.items_sold_shift_roundstat++
vend_ready = 1
currently_vending = null
SStgui.update_uis(src)
/mob/living/simple_mob/humanoid/starhunter/trader/proc/stock(obj/item/W, var/datum/stored_item/vending_product/R, var/mob/user)
if(!user.unEquip(W))
return
to_chat(user, span_notice("You insert \the [W] in the product receptor."))
R.add_product(W)
if(has_logs)
do_logging(R, user)
SStgui.update_uis(src)
/mob/living/simple_mob/humanoid/starhunter/trader/proc/pay_with_ewallet(var/obj/item/spacecash/ewallet/wallet)
visible_message(span_info("\The [usr] swipes \the [wallet] through \the [src]."))
playsound(src, 'sound/machines/id_swipe.ogg', 50, 1)
if(currently_vending.price > wallet.worth)
to_chat(usr, span_warning("Insufficient funds on chargecard."))
return 0
else
wallet.worth -= currently_vending.price
credit_purchase("[wallet.owner_name] (chargecard)")
return 1
/**
* Scan a card and attempt to transfer payment from associated account.
*
* Takes payment for whatever is the currently_vending item. Returns 1 if
* successful, 0 if failed
*/
/mob/living/simple_mob/humanoid/starhunter/trader/proc/pay_with_card(obj/item/card/id/I, mob/M)
visible_message(span_info("[M] swipes a card through [src]."))
playsound(src, 'sound/machines/id_swipe.ogg', 50, 1)
var/datum/money_account/customer_account = get_account(I.associated_account_number)
if(!customer_account)
to_chat(M, span_warning("Error: Unable to access account. Please contact technical support if problem persists."))
return FALSE
if(customer_account.suspended)
to_chat(M, span_warning("Unable to access account: account suspended."))
return FALSE
// Have the customer punch in the PIN before checking if there's enough money. Prevents people from figuring out acct is
// empty at high security levels
if(customer_account.security_level != 0) //If card requires pin authentication (ie seclevel 1 or 2)
var/attempt_pin = tgui_input_number(usr, "Enter pin code", "Vendor transaction")
customer_account = attempt_account_access(I.associated_account_number, attempt_pin, 2)
if(!customer_account)
to_chat(M, span_warning("Unable to access account: incorrect credentials."))
return FALSE
if(currently_vending.price > customer_account.money)
to_chat(M, span_warning("Insufficient funds in account."))
return FALSE
// Okay to move the money at this point
// debit money from the purchaser's account
customer_account.money -= currently_vending.price
// create entry in the purchaser's account log
var/datum/transaction/T = new()
T.target_name = "[GLOB.vendor_account.owner_name] (via [name])"
T.purpose = "Purchase of [currently_vending.item_name]"
if(currently_vending.price > 0)
T.amount = "([currently_vending.price])"
else
T.amount = "[currently_vending.price]"
T.source_terminal = name
T.date = GLOB.current_date_string
T.time = stationtime2text()
customer_account.transaction_log.Add(T)
// Give the vendor the money. We use the account owner name, which means
// that purchases made with stolen/borrowed card will look like the card
// owner made them
credit_purchase(customer_account.owner_name)
return 1
/mob/living/simple_mob/humanoid/starhunter/trader/proc/do_logging(datum/stored_item/vending_product/R, mob/user, var/vending = 0)
if(user.GetIdCard())
var/obj/item/card/id/tempid = user.GetIdCard()
var/list/list_item = list()
if(vending)
list_item += "vend"
else
list_item += "stock"
list_item += tempid.registered_name
list_item += stationtime2text()
list_item += R.item_name
log[++log.len] = list_item
/mob/living/simple_mob/humanoid/starhunter/trader/proc/can_buy(datum/stored_item/vending_product/R, mob/user)
return TRUE
@@ -27,37 +27,52 @@
list(mode_name="shotgun", fire_delay=15, projectile_type=/obj/item/projectile/bullet/frostshotgun, charge_cost = 240),
)
/obj/item/gun/energy/flamegun
name = "Flame Crystal Projector"
desc = "A strange gun pulsing with energy, it's touch warming you up."
icon = 'modular_chomp/icons/obj/guns/precursor/eclipse.dmi'
icon_state = "flamegun"
item_state = "flamegun"
wielded_item_state = "flame-wielded"
/obj/item/grenade/chem_grenade/frost
name = "frost grenade"
desc = "Currently in the testing phase, pratical purposes are unknown."
icon_state = "foam"
path = 1
stage = 2
sealed = TRUE
w_class = ITEMSIZE_LARGE
/obj/item/grenade/chem_grenade/frost/Initialize(mapload)
. = ..()
var/obj/item/reagent_containers/glass/beaker/bluespace/B1 = new(src)
var/obj/item/reagent_containers/glass/beaker/bluespace/B2 = new(src)
accept_cell_type = /obj/item/cell/device
cell_type = /obj/item/cell/device/weapon
projectile_type = /obj/item/projectile/energy/flamecrystal
B1.reagents.add_reagent(REAGENT_ID_CRYOSLURRY, 150)
B1.reagents.add_reagent(REAGENT_ID_POTASSIUM, 150)
B2.reagents.add_reagent(REAGENT_ID_PHOSPHORUS, 150)
B2.reagents.add_reagent(REAGENT_ID_SUGAR, 150)
matter = list(MAT_DURASTEEL = 1000, MAT_MORPHIUM = 500)
origin_tech = list(TECH_COMBAT = 6, TECH_POWER = 5, TECH_PRECURSOR = 3)
detonator = new/obj/item/assembly_holder/timer_igniter(src)
recoil_mode = 0
charge_meter = 1
beakers += B1
move_delay = 0
/obj/item/projectile/bullet/frostshotgun
use_submunitions = 1
only_submunitions = 1
range = 0
embed_chance = 0
submunition_spread_max = 1200
submunition_spread_min = 500
submunitions = list(/obj/item/projectile/energy/frostsphere = 4)
charge_cost = 80
hud_state = "plasma_sphere"
reload_time = 10
/obj/item/projectile/bullet/frostshotgun/on_range()
qdel(src)
firemodes = list(
list(mode_name="normal", fire_delay=5, projectile_type=/obj/item/projectile/energy/flamecrystal, charge_cost = 80),
list(mode_name="shotgun", fire_delay=15, projectile_type=/obj/item/projectile/bullet/flamegun, charge_cost = 240),
list(mode_name="explosive", fire_delay=10, projectile_type=/obj/item/projectile/energy/fireball, charge_cost = 160),
)
/obj/item/projectile/energy/frostsphere
name = "frost sphere"
icon_state = "ice_2"
fire_sound = 'sound/weapons/pulse3.ogg'
damage = 20
modifier_type_to_apply = /datum/modifier/cryogelled
modifier_duration = 0.25 MINUTE
speed = 2.5
range = 12
hud_state = "water"
/obj/item/projectile/energy/mechahack
name = "remote hack"
@@ -95,72 +110,68 @@
else
target_mob.electrocute_act(power, src, 0.75, BP_TORSO)
/obj/item/projectile/bullet/crystaline
name = "crystal bullet"
icon = 'modular_chomp/icons/obj/guns/precursor/eclipse.dmi'
icon_state = "crystal"
damage = 30
armor_penetration = 20
embed_chance = 0
speed = 2
/obj/item/projectile/energy/eclipse
/obj/item/projectile/energy/eclipse_boss
name = "experimental laser"
icon = 'modular_chomp/icons/obj/guns/precursor/eclipse.dmi'
icon_state = "laser"
check_armour = "laser"
damage = 30
armor_penetration = 20
penetrating = 2
speed = 2
speed = 10
crawl_destroy = TRUE
//The normal laser respects more armor, but deals more damage if you don't have it.precursor will thwack folks equally.
/obj/item/projectile/energy/eclipse/lorge
damage = 60
armor_penetration = 30
icon_state = "mega_laser"
speed = 10
/obj/item/projectile/energy/eclipse/lorgealien
damage = 20
armor_penetration = 60
icon_state = "mega_laser_p"
speed = 10
/obj/item/projectile/bullet/crystalineburst
use_submunitions = 1
range = 0
embed_chance = 0
spread_submunition_damage = FALSE
submunition_spread_max = 120
submunition_spread_min = 60
submunitions = list(/obj/item/projectile/bullet/crystaline = 5)
/obj/item/projectile/energy/eclipse/janusjavelin //This will end you
name = "energy javelin"
icon_state = "javelin"
damage_type = SEARING
check_armour = "bullet"
damage = 45
armor_penetration = 95
speed = 10
/obj/item/projectile/energy/eclipse/chillingwind
/obj/item/projectile/energy/eclipse_boss/chillingwind
name = "ice winds"
icon_state = "ice_wind"
damage = 15
armor_penetration = 70
speed = 10
modifier_type_to_apply = /datum/modifier/cryogelled
modifier_duration = 0.25 MINUTE
/obj/item/projectile/energy/eclipse/mining
name = "drill"
icon_state = "drill"
/obj/item/projectile/energy/eclipse_boss/metalsphere
name = "metal sphere"
icon_state = "metal_sphere"
damage_type = BRUTE
check_armour = "bullet"
damage = 20
agony = 10
armor_penetration = 50
/obj/item/projectile/energy/eclipse_boss/energyjavelin
name = "searing javelin"
icon_state = "javelin"
damage_type = SEARING
damage = 40
armor_penetration = 30
speed = 10
excavation_amount = 100
//projectiles
/obj/item/projectile/energy/astral_collective
name = "abnormal energy"
speed = 2
damage = 28 //roughly 25 with intended armour
damage_type = BURN //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS, ELECTROCUTE, BIOACID, SEARING are the only things that should be in here
check_armour = "laser" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb //Cael - bio and rad are also valid
/obj/item/projectile/energy/astral_collective/anti_mecha
damage_type = BIOACID
icon_state = "declone"
/obj/item/projectile/energy/astral_collective/armour_breaker
damage = 10
dephasing = TRUE
hits_phased = TRUE
icon_state = "fuel-deuterium"
penetrating = 10
armor_penetration = 100
/obj/item/projectile/energy/astral_collective/searing
damage_type = SEARING
icon_state = "bolter"
/obj/item/projectile/energy/astral_collective/green
icon_state = "energy"
irradiate = 40
/obj/item/projectile/energy/astral_collective/particle
icon_state = "particle"
damage_type = ELECTROMAG
incendiary = 1
flammability = 1