Skip to content

Commit

Permalink
[MIRROR] Basic Constructs: Juggernaut [MDB IGNORE] (#24547)
Browse files Browse the repository at this point in the history
* Basic Constructs: Juggernaut (#79170)

## About The Pull Request

Converts juggernaut constructs to basic mobs. These guys are really
simple, so this is a pretty straightforward one.

The one notable thing about this PR is that I got annoyed that
projectile reflection code was copy-pasted in two different places (the
main one for things like the ablative trenchcoat, and right here on the
juggernaut). So, trenchcoat-style reflection is now a proc on
`/obj/projectile`, which is used in both places.

AI-controlled juggernauts are as simple as befits these big lugs, doing
nothing but slowly walking toward mobs and beating them to death with
their giant fists.
## Why It's Good For The Game

Removes another 5 simple animals.

Not too much else to say about this one, but it's easier to make
projectiles bounce off of things now if anyone wants to do that.
## Changelog
:cl:
refactor: Juggernaut constructs now use the basic mob framework. Please
report any bugs.
/:cl:

---------

Co-authored-by: san7890 <the@ san7890.com>

* Basic Constructs: Juggernaut

* Modular

* Map Reset

---------

Co-authored-by: lizardqueenlexi <[email protected]>
Co-authored-by: san7890 <the@ san7890.com>
Co-authored-by: Giz <[email protected]>
  • Loading branch information
4 people authored and FFMirrorBot committed Oct 24, 2023
1 parent 3dd52ac commit bd11f35
Show file tree
Hide file tree
Showing 17 changed files with 131 additions and 131 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@
/area/icemoon/underground/explored)
"mi" = (
/obj/effect/decal/remains/human,
/mob/living/simple_animal/hostile/construct/juggernaut/hostile{
/mob/living/basic/construct/juggernaut/hostile{
health = 450;
maxHealth = 450;
name = "Right Hand of the Elder"
Expand Down Expand Up @@ -360,7 +360,7 @@
"EF" = (
/obj/effect/decal/cleanable/blood/gibs/torso,
/obj/effect/decal/remains/human,
/mob/living/simple_animal/hostile/construct/juggernaut/hostile{
/mob/living/basic/construct/juggernaut/hostile{
health = 450;
maxHealth = 450;
name = "Left Hand of the Elder"
Expand Down
8 changes: 4 additions & 4 deletions _maps/RandomRuins/SpaceRuins/skyrat/port_tarkon/defcon2.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -1775,7 +1775,7 @@
/obj/effect/decal/cleanable/blood/tracks{
dir = 9
},
/mob/living/simple_animal/hostile/construct/juggernaut/hostile,
/mob/living/basic/construct/juggernaut/hostile,
/obj/effect/decal/cleanable/dirt,
/turf/open/floor/cult,
/area/ruin/space/has_grav/port_tarkon/cargo)
Expand Down Expand Up @@ -2048,7 +2048,7 @@
"lj" = (
/obj/effect/decal/cleanable/glass,
/obj/effect/decal/cleanable/blood,
/mob/living/simple_animal/hostile/construct/juggernaut/hostile{
/mob/living/basic/construct/juggernaut/hostile{
health = 275;
maxHealth = 275;
name = "Left hand of the veil"
Expand Down Expand Up @@ -4932,7 +4932,7 @@
"Cf" = (
/obj/effect/decal/cleanable/glass,
/obj/effect/decal/cleanable/blood,
/mob/living/simple_animal/hostile/construct/juggernaut/hostile{
/mob/living/basic/construct/juggernaut/hostile{
health = 275;
maxHealth = 275;
name = "Right hand of the veil"
Expand Down Expand Up @@ -5211,7 +5211,7 @@
"DE" = (
/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2,
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4,
/mob/living/simple_animal/hostile/construct/juggernaut/hostile{
/mob/living/basic/construct/juggernaut/hostile{
health = 200;
maxHealth = 200
},
Expand Down
2 changes: 1 addition & 1 deletion _maps/RandomRuins/SpaceRuins/the_outlet.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@
/obj/effect/decal/cleanable/blood{
icon_state = "gib2-old"
},
/mob/living/simple_animal/hostile/construct/juggernaut/hostile,
/mob/living/basic/construct/juggernaut/hostile,
/turf/open/floor/cult,
/area/ruin/space/has_grav/the_outlet/cultinfluence)
"MR" = (
Expand Down
2 changes: 1 addition & 1 deletion _maps/shuttles/emergency_narnar.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
/turf/open/floor/cult,
/area/shuttle/escape)
"C" = (
/mob/living/simple_animal/hostile/construct/juggernaut,
/mob/living/basic/construct/juggernaut,
/turf/open/floor/cult,
/area/shuttle/escape)
"D" = (
Expand Down
2 changes: 1 addition & 1 deletion _maps/shuttles/whiteship_obelisk.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@
/area/shuttle/abandoned)
"HU" = (
/obj/structure/cable,
/mob/living/simple_animal/hostile/construct/juggernaut/hostile,
/mob/living/basic/construct/juggernaut/hostile,
/obj/effect/decal/cleanable/crayon{
icon_state = "rune4";
paint_colour = "#DC143C"
Expand Down
8 changes: 4 additions & 4 deletions code/modules/antagonists/wizard/equipment/soulstone.dm
Original file line number Diff line number Diff line change
Expand Up @@ -462,15 +462,15 @@
switch(construct_class)
if(CONSTRUCT_JUGGERNAUT)
if(IS_CULTIST(creator))
makeNewConstruct(/mob/living/simple_animal/hostile/construct/juggernaut, target, creator, cultoverride, loc_override) // ignore themes, the actual giving of cult info is in the makeNewConstruct proc
makeNewConstruct(/mob/living/basic/construct/juggernaut, target, creator, cultoverride, loc_override) // ignore themes, the actual giving of cult info is in the makeNewConstruct proc
return
switch(theme)
if(THEME_WIZARD)
makeNewConstruct(/mob/living/simple_animal/hostile/construct/juggernaut/mystic, target, creator, cultoverride, loc_override)
makeNewConstruct(/mob/living/basic/construct/juggernaut/mystic, target, creator, cultoverride, loc_override)
if(THEME_HOLY)
makeNewConstruct(/mob/living/simple_animal/hostile/construct/juggernaut/angelic, target, creator, cultoverride, loc_override)
makeNewConstruct(/mob/living/basic/construct/juggernaut/angelic, target, creator, cultoverride, loc_override)
if(THEME_CULT)
makeNewConstruct(/mob/living/simple_animal/hostile/construct/juggernaut/noncult, target, creator, cultoverride, loc_override)
makeNewConstruct(/mob/living/basic/construct/juggernaut/noncult, target, creator, cultoverride, loc_override)
if(CONSTRUCT_WRAITH)
if(IS_CULTIST(creator))
makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith, target, creator, cultoverride, loc_override) // ignore themes, the actual giving of cult info is in the makeNewConstruct proc
Expand Down
6 changes: 4 additions & 2 deletions code/modules/events/portal_storm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@

/datum/round_event/portal_storm/portal_storm_narsie
boss_types = list(/mob/living/basic/construct/artificer/hostile = 6)
hostile_types = list(/mob/living/simple_animal/hostile/construct/juggernaut/hostile = 8,\
/mob/living/simple_animal/hostile/construct/wraith/hostile = 6)
hostile_types = list(
/mob/living/basic/construct/juggernaut/hostile = 8,
/mob/living/simple_animal/hostile/construct/wraith/hostile = 6,
)

/datum/round_event/portal_storm
start_when = 7
Expand Down
14 changes: 14 additions & 0 deletions code/modules/mob/living/basic/constructs/construct_ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,20 @@
/datum/ai_planning_subtree/flee_target/from_flee_key,
)

/// Juggernauts
/datum/ai_controller/basic_controller/juggernaut
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic,
BB_TARGET_MINIMUM_STAT = SOFT_CRIT,
)

ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree,
)

/// Targetting datum that will only allow mobs that constructs can heal.
/datum/targetting_datum/basic/same_faction/construct
target_wounded_key = BB_TARGET_WOUNDED_ONLY
Expand Down
62 changes: 62 additions & 0 deletions code/modules/mob/living/basic/constructs/juggernaut.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/mob/living/basic/construct/juggernaut
name = "Juggernaut"
real_name = "Juggernaut"
desc = "A massive, armored construct built to spearhead attacks and soak up enemy fire."
icon_state = "juggernaut"
icon_living = "juggernaut"
maxHealth = 150
health = 150
response_harm_continuous = "harmlessly punches"
response_harm_simple = "harmlessly punch"
obj_damage = 90
melee_damage_lower = 25
melee_damage_upper = 25
attack_verb_continuous = "smashes their armored gauntlet into"
attack_verb_simple = "smash your armored gauntlet into"
speed = 2.5
attack_sound = 'sound/weapons/punch3.ogg'
status_flags = NONE
mob_size = MOB_SIZE_LARGE
force_threshold = 10
construct_spells = list(
/datum/action/cooldown/spell/forcewall/cult,
/datum/action/cooldown/spell/basic_projectile/juggernaut,
/datum/action/innate/cult/create_rune/wall,
)
playstyle_string = span_bold("You are a Juggernaut. Though slow, your shell can withstand heavy punishment, create shield walls, rip apart enemies and walls alike, and even deflect energy weapons.")

smashes_walls = TRUE

/// Hostile NPC version. Pretty dumb, just attacks whoever is near.
/mob/living/basic/construct/juggernaut/hostile
ai_controller = /datum/ai_controller/basic_controller/juggernaut
smashes_walls = FALSE

/mob/living/basic/construct/juggernaut/bullet_act(obj/projectile/bullet)
if(!istype(bullet, /obj/projectile/energy) && !istype(bullet, /obj/projectile/beam))
return ..()
if(!prob(40 - round(bullet.damage / 3))) // reflect chance
return ..()

apply_damage(bullet.damage * 0.5, bullet.damage_type)
visible_message(
span_danger("The [bullet.name] is reflected by [src]'s armored shell!"),
span_userdanger("The [bullet.name] is reflected by your armored shell!"),
)

bullet.reflect(src)

return BULLET_ACT_FORCE_PIERCE // complete projectile permutation

// Alternate juggernaut themes
/mob/living/basic/construct/juggernaut/angelic
theme = THEME_HOLY

/mob/living/basic/construct/juggernaut/angelic/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_ANGELIC, INNATE_TRAIT)

/mob/living/basic/construct/juggernaut/mystic
theme = THEME_WIZARD

/mob/living/basic/construct/juggernaut/noncult
40 changes: 13 additions & 27 deletions code/modules/mob/living/carbon/human/human_defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,46 +44,32 @@
covering_part += C
return covering_part

/mob/living/carbon/human/bullet_act(obj/projectile/P, def_zone, piercing_hit = FALSE)
/mob/living/carbon/human/bullet_act(obj/projectile/bullet, def_zone, piercing_hit = FALSE)

if(P.firer == src && P.original == src) //can't block or reflect when shooting yourself
if(bullet.firer == src && bullet.original == src) //can't block or reflect when shooting yourself
return ..()

if(P.reflectable & REFLECT_NORMAL)
if(bullet.reflectable & REFLECT_NORMAL)
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
visible_message(
span_danger("The [P.name] gets reflected by [src]!"),
span_userdanger("The [P.name] gets reflected by [src]!"),
span_danger("The [bullet.name] gets reflected by [src]!"),
span_userdanger("The [bullet.name] gets reflected by [src]!"),
)
// Finds and plays the block_sound of item which reflected
for(var/obj/item/I in held_items)
if(I.IsReflect(def_zone))
playsound(src, I.block_sound, BLOCK_SOUND_VOLUME, TRUE)
for(var/obj/item/held_item in held_items)
if(held_item.IsReflect(def_zone))
playsound(src, held_item.block_sound, BLOCK_SOUND_VOLUME, TRUE)
// Find a turf near or on the original location to bounce to
if(!isturf(loc)) //Open canopy mech (ripley) check. if we're inside something and still got hit
P.force_hit = TRUE //The thing we're in passed the bullet to us. Pass it back, and tell it to take the damage.
loc.bullet_act(P, def_zone, piercing_hit)
bullet.force_hit = TRUE //The thing we're in passed the bullet to us. Pass it back, and tell it to take the damage.
loc.bullet_act(bullet, def_zone, piercing_hit)
return BULLET_ACT_HIT
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(src)

// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
var/new_angle_s = P.Angle + rand(120,240)
while(new_angle_s > 180) // Translate to regular projectile degrees
new_angle_s -= 360
P.set_angle(new_angle_s)
bullet.reflect(src)

return BULLET_ACT_FORCE_PIERCE // complete projectile permutation

if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration, P.damage_type))
P.on_hit(src, 100, def_zone, piercing_hit)
if(check_shields(bullet, bullet.damage, "the [bullet.name]", PROJECTILE_ATTACK, bullet.armour_penetration, bullet.damage_type))
bullet.on_hit(src, 100, def_zone, piercing_hit)
return BULLET_ACT_HIT

return ..()
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/living_defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@
else
switch(rand(1, 4))
if(1)
new /mob/living/simple_animal/hostile/construct/juggernaut/hostile(get_turf(src))
new /mob/living/basic/construct/juggernaut/hostile(get_turf(src))
if(2)
new /mob/living/simple_animal/hostile/construct/wraith/hostile(get_turf(src))
if(3)
Expand Down

This file was deleted.

19 changes: 19 additions & 0 deletions code/modules/projectiles/projectile.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,25 @@
/obj/projectile/proc/can_embed_into(atom/hit)
return embedding && shrapnel_type && iscarbon(hit) && !HAS_TRAIT(hit, TRAIT_PIERCEIMMUNE)

/// Reflects the projectile off of something
/obj/projectile/proc/reflect(atom/hit_atom)
if(!starting)
return
var/new_x = starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/current_tile = get_turf(hit_atom)

// redirect the projectile
original = locate(new_x, new_y, z)
starting = current_tile
firer = hit_atom
yo = new_y - current_tile.y
xo = new_x - current_tile.x
var/new_angle_s = Angle + rand(120,240)
while(new_angle_s > 180) // Translate to regular projectile degrees
new_angle_s -= 360
set_angle(new_angle_s)

#undef MOVES_HITSCAN
#undef MUZZLE_EFFECT_PIXEL_INCREMENT

Expand Down
6 changes: 3 additions & 3 deletions code/modules/spells/spell_types/shapeshift/shapechange.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
spell_requirements = SPELL_REQUIRES_NO_ANTIMAGIC

possible_shapes = list(
/mob/living/basic/carp/magic/chaos,
/mob/living/basic/construct/juggernaut/mystic,
/mob/living/basic/mouse,
/mob/living/basic/pet/dog/corgi,
/mob/living/basic/carp/magic/chaos,
/mob/living/simple_animal/bot/secbot/ed209,
/mob/living/basic/spider/giant/viper/wizard,
/mob/living/simple_animal/hostile/construct/juggernaut/mystic,
/mob/living/simple_animal/bot/secbot/ed209,
)
5 changes: 0 additions & 5 deletions code/modules/unit_tests/simple_animal_freeze.dm
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@
/mob/living/simple_animal/hostile/asteroid/polarbear/lesser,
/mob/living/simple_animal/hostile/asteroid/wolf,
/mob/living/simple_animal/hostile/construct,
/mob/living/simple_animal/hostile/construct/juggernaut,
/mob/living/simple_animal/hostile/construct/juggernaut/angelic,
/mob/living/simple_animal/hostile/construct/juggernaut/hostile,
/mob/living/simple_animal/hostile/construct/juggernaut/mystic,
/mob/living/simple_animal/hostile/construct/juggernaut/noncult,
/mob/living/simple_animal/hostile/construct/proteon,
/mob/living/simple_animal/hostile/construct/proteon/hostile,
/mob/living/simple_animal/hostile/construct/wraith,
Expand Down
Loading

0 comments on commit bd11f35

Please sign in to comment.