diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 8e27f9315c3..ce46913c2d2 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -1,5 +1,25 @@ +// Atoms #define isatom(A) istype(A, /atom) #define ismovableatom(A) istype(A, /atom/movable) -#define isclient(A) istype(A, /client) +// Mobs +#define ismegafauna(A) (istype(A, /mob/living/simple_animal/hostile/megafauna)) + +//Turfs +#define issimulatedturf(A) (istype(A, /turf/simulated)) + +#define isspaceturf(A) (istype(A, /turf/space)) + +#define isfloorturf(A) (istype(A, /turf/simulated/floor)) + +#define isunsimulatedturf(A) (istype(A, /turf/unsimulated)) + +#define iswallturf(A) (istype(A, /turf/simulated/wall)) + +#define isreinforcedwallturf(A) (istype(A, /turf/simulated/wall/r_wall)) + +#define ismineralturf(A) (istype(A, /turf/simulated/mineral)) + +// Misc +#define isclient(A) istype(A, /client) #define isradio(A) istype(A, /obj/item/device/radio) \ No newline at end of file diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 3735f31caf8..b9ee580896c 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1814,4 +1814,22 @@ var/global/list/g_fancy_list_of_types = null namecounts[name] = 1 pois[name] = A - return pois \ No newline at end of file + return pois + +/proc/flash_color(mob_or_client, flash_color="#960000", flash_time=20) + var/client/C + if(istype(mob_or_client, /mob)) + var/mob/M = mob_or_client + if(M.client) + C = M.client + else + return + else if(istype(mob_or_client, /client)) + C = mob_or_client + + if(!istype(C)) + return + + C.color = flash_color + spawn(0) + animate(C, color = initial(C.color), time = flash_time) \ No newline at end of file diff --git a/code/datums/action.dm b/code/datums/action.dm index f1c197cdfe8..f1826c334c5 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -187,6 +187,40 @@ /datum/action/item_action/toggle_hardsuit_mode name = "Toggle Hardsuit Mode" + +/datum/action/item_action/toggle_unfriendly_fire + name = "Toggle Friendly Fire \[ON\]" + desc = "Toggles if the staff causes friendly fire." + button_icon_state = "vortex_ff_on" + +/datum/action/item_action/toggle_unfriendly_fire/Trigger() + if(..()) + UpdateButtonIcon() + +/datum/action/item_action/toggle_unfriendly_fire/UpdateButtonIcon() + if(istype(target, /obj/item/weapon/hierophant_staff)) + var/obj/item/weapon/hierophant_staff/H = target + if(H.friendly_fire_check) + button_icon_state = "vortex_ff_off" + name = "Toggle Friendly Fire \[OFF\]" + button.name = name + else + button_icon_state = "vortex_ff_on" + name = "Toggle Friendly Fire \[ON\]" + button.name = name + ..() + +/datum/action/item_action/vortex_recall + name = "Vortex Recall" + desc = "Recall yourself, and anyone nearby, to an attuned hierophant rune at any time.
If no such rune exists, will produce a rune at your location." + button_icon_state = "vortex_recall" + +/datum/action/item_action/vortex_recall/IsAvailable() + if(istype(target, /obj/item/weapon/hierophant_staff)) + var/obj/item/weapon/hierophant_staff/H = target + if(H.teleporting) + return 0 + return ..() /datum/action/item_action/toggle diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index 260da98d221..46f7b3fb469 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -144,7 +144,7 @@ var/global/list/datum/stack_recipe/sinew_recipes = list ( \ if(W.sharp) user.visible_message("[user] starts cutting hair off \the [src].", "You start cutting the hair off \the [src]...", "You hear the sound of a knife rubbing against flesh.") if(do_after(user,50, target = src)) - user << "You cut the hair from this [src.singular_name]." + to_chat(user, "You cut the hair from this [src.singular_name].") //Try locating an exisitng stack on the tile and add to there if possible for(var/obj/item/stack/sheet/hairlesshide/HS in usr.loc) if(HS.amount < 50) diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 8af2f5cd948..a64486b440c 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -1506,8 +1506,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that var/datum/map_template/ruin/template = landmark.ruin_template admin_forcemove(usr, get_turf(landmark)) - usr << "[template.name]" - usr << "[template.description]" + to_chat(usr, "[template.name]") + to_chat(usr, "[template.description]") log_admin("[key_name(usr)] jumped to ruin [ruinname]") if(!isobserver(usr)) diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm index 22d1e4cca8d..b5bd3f83f6b 100644 --- a/code/modules/mining/lavaland/ash_flora.dm +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -38,7 +38,7 @@ msg = harvest_message_low else if(rand_harvested == harvest_amount_high) msg = harvest_message_high - user << "[msg]" + to_chat(user, "[msg]") for(var/i in 1 to rand_harvested) new harvest(get_turf(src)) icon_state = "[base_icon]p" diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index c671763502d..6dfc5935b00 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -288,4 +288,252 @@ /obj/effect/overlay/temp/lavastaff icon_state = "lavastaff_warn" - duration = 50 \ No newline at end of file + duration = 50 + +// Legion + +/obj/item/weapon/staff/storm + name = "staff of storms" + desc = "An ancient staff retrieved from the remains of Legion. The wind stirs as you move it." + icon_state = "staffofstorms" + item_state = "staffofstorms" + icon = 'icons/obj/guns/magic.dmi' + slot_flags = SLOT_BACK + item_state = "staffofstorms" + w_class = 4 + force = 25 + damtype = BURN + hitsound = 'sound/weapons/sear.ogg' + var/storm_type = /datum/weather/ash_storm + var/storm_cooldown = 0 + +/obj/item/weapon/staff/storm/attack_self(mob/user) + if(storm_cooldown > world.time) + to_chat(user, "The staff is still recharging!") + return + + var/area/user_area = get_area(user) + var/datum/weather/A + var/z_level_name = space_manager.levels_by_name[user.z] + for(var/V in weather_master.existing_weather) + var/datum/weather/W = V + if(W.target_z == z_level_name && W.area_type == user_area.type) + A = W + break + if(A) + + if(A.stage != END_STAGE) + if(A.stage == WIND_DOWN_STAGE) + to_chat(user, "The storm is already ending! It would be a waste to use the staff now.") + return + user.visible_message("[user] holds [src] skywards as an orange beam travels into the sky!", \ + "You hold [src] skyward, dispelling the storm!") + playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) + A.wind_down() + return + else + A = new storm_type + A.name = "staff storm" + A.area_type = user_area.type + A.target_z = z_level_name + A.telegraph_duration = 100 + A.end_duration = 100 + + user.visible_message("[user] holds [src] skywards as red lightning crackles into the sky!", \ + "You hold [src] skyward, calling down a terrible storm!") + playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) + A.telegraph() + storm_cooldown = world.time + 200 + +// Hierophant + +//Hierophant + +/obj/item/weapon/hierophant_staff + name = "Hierophant's staff" + desc = "A large club with intense magic power infused into it." + icon_state = "hierophant_staff" + item_state = "hierophant_staff" + icon = 'icons/obj/guns/magic.dmi' + slot_flags = SLOT_BACK + w_class = 4 + force = 20 + hitsound = "swing_hit" + //hitsound = 'sound/weapons/sonic_jackhammer.ogg' + actions_types = list(/datum/action/item_action/vortex_recall, /datum/action/item_action/toggle_unfriendly_fire) + var/cooldown_time = 20 //how long the cooldown between non-melee ranged attacks is + var/chaser_cooldown = 101 //how long the cooldown between firing chasers at mobs is + var/chaser_timer = 0 //what our current chaser cooldown is + var/timer = 0 //what our current cooldown is + var/blast_range = 3 //how long the cardinal blast's walls are + var/obj/effect/hierophant/rune //the associated rune we teleport to + var/teleporting = FALSE //if we ARE teleporting + var/friendly_fire_check = FALSE //if the blasts we make will consider our faction against the faction of hit targets + +/obj/item/weapon/hierophant_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + ..() + var/turf/T = get_turf(target) + if(!T || timer > world.time) + return + timer = world.time + CLICK_CD_MELEE //by default, melee attacks only cause melee blasts, and have an accordingly short cooldown + if(proximity_flag) + spawn(0) + aoe_burst(T, user) + add_logs(user, target, "fired 3x3 blast at", src) + else + if(ismineralturf(target) && get_dist(user, target) < 6) //target is minerals, we can hit it(even if we can't see it) + spawn(0) + cardinal_blasts(T, user) + timer = world.time + cooldown_time + else if(target in view(5, get_turf(user))) //if the target is in view, hit it + timer = world.time + cooldown_time + if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one! + chaser_timer = world.time + chaser_cooldown + PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(get_turf(user), user, target, 1.5, friendly_fire_check)) + add_logs(user, target, "fired a chaser at", src) + else + spawn(0) + cardinal_blasts(T, user) //otherwise, just do cardinal blast + add_logs(user, target, "fired cardinal blast at", src) + else + to_chat(user, "That target is out of range!") //too far away + +/obj/item/weapon/hierophant_staff/ui_action_click(mob/user, actiontype) + if(actiontype == /datum/action/item_action/toggle_unfriendly_fire) //toggle friendly fire... + friendly_fire_check = !friendly_fire_check + to_chat(user, "You toggle friendly fire [friendly_fire_check ? "off":"on"]!") + return + if(user.get_active_hand() != src && user.get_inactive_hand() != src) //you need to hold the staff to teleport + to_chat(user, "You need to hold the staff in your hands to [rune ? "teleport with it" : "create a rune"]!") + return + if(!rune) + if(isturf(user.loc)) + user.visible_message("[user] holds [src] carefully in front of them, moving it in a strange pattern...", \ + "You start creating a hierophant rune to teleport to...") + timer = world.time + 51 + if(do_after(user, 50, target = user)) + var/turf/T = get_turf(user) + playsound(T,'sound/magic/Blind.ogg', 200, 1, -4) + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(T, user)) + var/obj/effect/hierophant/H = new/obj/effect/hierophant(T) + rune = H + user.update_action_buttons_icon() + user.visible_message("[user] creates a strange rune beneath them!", \ + "You create a hierophant rune, which you can teleport yourself and any allies to at any time!\n\ + You can remove the rune to place a new one by striking it with the staff.") + else + timer = world.time + else + to_chat(user, "You need to be on solid ground to produce a rune!") + return + if(get_dist(user, rune) <= 2) //rune too close abort + to_chat(user, "You are too close to the rune to teleport to it!") + return + if(is_blocked_turf(get_turf(rune))) + to_chat(user, "The rune is blocked by something, preventing teleportation!") + return + teleporting = TRUE //start channel + user.update_action_buttons_icon() + user.visible_message("[user] starts to glow faintly...") + timer = world.time + 50 + if(do_after(user, 40, target = user) && rune) + var/turf/T = get_turf(rune) + var/turf/source = get_turf(user) + if(is_blocked_turf(T)) + teleporting = FALSE + to_chat(user, "The rune is blocked by something, preventing teleportation!") + user.update_action_buttons_icon() + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, user)) + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(source, user)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/magic/Wand_Teleport.ogg', 200, 1) + playsound(source,'sound/magic/blink.ogg', 200, 1) + //playsound(source,'sound/machines/AirlockOpen.ogg', 200, 1) + if(!do_after(user, 3, target = user) || !rune) //no walking away shitlord + teleporting = FALSE + if(user) + user.update_action_buttons_icon() + return + if(is_blocked_turf(T)) + teleporting = FALSE + to_chat(user, "The rune is blocked by something, preventing teleportation!") + user.update_action_buttons_icon() + return + add_logs(user, rune, "teleported self from ([source.x],[source.y],[source.z]) to") + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(T, user)) + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(source, user)) + for(var/t in RANGE_TURFS(1, T)) + var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, user, TRUE)) //blasts produced will not hurt allies + B.damage = 30 + for(var/t in RANGE_TURFS(1, source)) + var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, user, TRUE)) //but absolutely will hurt enemies + B.damage = 30 + for(var/mob/living/L in range(1, source)) + spawn(0) + teleport_mob(source, L, T, user) //regardless, take all mobs near us along + sleep(6) //at this point the blasts detonate + else + timer = world.time + teleporting = FALSE + if(user) + user.update_action_buttons_icon() + +/obj/item/weapon/hierophant_staff/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user) + var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster + if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to)) + return + animate(M, alpha = 0, time = 2, easing = EASE_OUT) //fade out + sleep(1) + if(!M) + return + M.visible_message("[M] fades out!") + sleep(2) + if(!M) + return + M.forceMove(turf_to_teleport_to) + sleep(1) + if(!M) + return + animate(M, alpha = 255, time = 2, easing = EASE_IN) //fade IN + sleep(1) + if(!M) + return + M.visible_message("[M] fades in!") + if(user != M) + add_logs(user, M, "teleported", null, "from ([source.x],[source.y],[source.z])") + +/obj/item/weapon/hierophant_staff/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay + if(!T) + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/cardinal, list(T, user)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/effects/bin_close.ogg', 200, 1) + sleep(2) + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, user, friendly_fire_check)) + for(var/d in cardinal) + spawn(0) + blast_wall(T, d, user) + +/obj/item/weapon/hierophant_staff/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long + if(!T) + return + var/range = blast_range + var/turf/previousturf = T + var/turf/J = get_step(previousturf, dir) + for(var/i in 1 to range) + if(!J) + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(J, user, friendly_fire_check)) + previousturf = J + J = get_step(previousturf, dir) + +/obj/item/weapon/hierophant_staff/proc/aoe_burst(turf/T, mob/living/user) //make a 3x3 blast around a target + if(!T) + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, user)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/effects/bin_close.ogg', 200, 1) + sleep(2) + for(var/t in RANGE_TURFS(1, T)) + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, user, friendly_fire_check)) \ No newline at end of file diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 9e4f7289532..06e47411001 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -2,10 +2,16 @@ //this item is intended to give the effect of entering the mine, so that light gradually fades /obj/effect/light_emitter - name = "Light-emtter" + name = "Light emtter" anchored = 1 + invisibility = 101 unacidable = 1 - light_range = 8 + var/set_light = 8 + var/set_cap = 0 + +/obj/effect/light_emitter/New() + ..() + set_light(set_light, set_cap) /**********************Miner Lockers**************************/ diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 6c0b0430e57..62babcaa1bd 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -348,7 +348,7 @@ EscapeConfinement() for(var/dir in cardinal) var/turf/T = get_step(targets_from, dir) - if(istype(T, /turf/simulated/wall) || istype(T, /turf/simulated/mineral)) + if(iswallturf(T) || ismineralturf(T)) if(T.Adjacent(targets_from)) T.attack_animal(src) for(var/a in T) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm new file mode 100644 index 00000000000..88ef094d340 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -0,0 +1,611 @@ +#define MEDAL_PREFIX "Hierophant" +/* + +The Hierophant + +The Hierophant spawns in its arena, an area designed to make it harder to fight than it would otherwise be. + +The text this boss speaks is ROT4, use ROT22 to decode + +The Hierophant's attacks are as follows, and INTENSIFY at a random chance based on Hierophant's health; +- Creates a cardinal or diagonal blast(Cross Blast) under its target, exploding after a short time. + INTENSITY EFFECT: Creates one of the cross blast types under itself instead of under the target. + INTENSITY EFFECT: The created Cross Blast fires in all directions if below half health. +- If no chasers exist, creates a chaser that will seek its target, leaving a trail of blasts. + INTENSITY EFFECT: Creates a second, slower chaser. +- Creates an expanding AoE burst. +- INTENSE ATTACKS: + If target is at least 2 tiles away; Blinks to the target after a very brief delay, damaging everything near the start and end points. + As above, but does so multiple times if below half health. + Rapidly creates Cross Blasts under a target. + If chasers are off cooldown, creates four high-speed chasers. +- IF TARGET WAS STRUCK IN MELEE: Creates a 3x3 square of blasts under the target. + +Cross Blasts and the AoE burst gain additional range as the Hierophant loses health, while Chasers gain additional speed. + +When The Hierophant dies, it leaves behind its staff, which, while much weaker than when wielded by The Hierophant itself, is still quite effective. +- The staff can place a teleport rune, allowing the user to teleport themself and their allies to the rune. + +Difficulty: Hard + +*/ + +/mob/living/simple_animal/hostile/megafauna/hierophant + name = "Hierophant" + desc = "An ancient, powerful priest-like being wielding a mighty staff." + health = 2500 + maxHealth = 2500 + attacktext = "clubs" + //attack_sound = 'sound/weapons/sonic_jackhammer.ogg' + attack_sound = "swing_hit" + icon_state = "hierophant" + icon_living = "hierophant" + friendly = "stares down" + icon = 'icons/mob/lavaland/hierophant.dmi' + faction = list("boss") //asteroid mobs? get that shit out of my beautiful square house + speak_emote = list("preaches") + armour_penetration = 50 + melee_damage_lower = 10 + melee_damage_upper = 10 + speed = 1 + move_to_delay = 10 + ranged = 1 + pixel_x = -16 + ranged_cooldown_time = 40 + aggro_vision_range = 23 + loot = list(/obj/item/weapon/hierophant_staff) + wander = FALSE + var/burst_range = 3 //range on burst aoe + var/beam_range = 5 //range on cross blast beams + var/chaser_speed = 3 //how fast chasers are currently + var/chaser_cooldown = 101 //base cooldown/cooldown var between spawning chasers + var/major_attack_cooldown = 60 //base cooldown for major attacks + var/blinking = FALSE //if we're doing something that requires us to stand still and not attack + var/obj/effect/hierophant/spawned_rune //the rune we teleport back to + var/timeout_time = 15 //after this many Life() ticks with no target, we return to our rune + var/did_reset = TRUE //if we timed out, returned to our rune, and healed some + //var/list/kill_phrases = list("Wsyvgi sj irivkc xettih. Vitemvmrk...", "Irivkc wsyvgi jsyrh. Vitemvmrk...", "Jyip jsyrh. Egxmzexmrk vitemv gcgpiw...") + //var/list/target_phrases = list("Xevkix psgexih.", "Iriqc jsyrh.", "Eguymvih xevkix.") + medal_type = MEDAL_PREFIX + score_type = BIRD_SCORE + del_on_death = TRUE + death_sound = 'sound/magic/Repulse.ogg' + +/mob/living/simple_animal/hostile/megafauna/hierophant/New() + ..() + internal = new/obj/item/device/gps/internal/hierophant(src) + spawned_rune = new(loc) + +/mob/living/simple_animal/hostile/megafauna/hierophant/Life() + . = ..() + if(. && spawned_rune && !client) + if(target || loc == spawned_rune.loc) + timeout_time = initial(timeout_time) + else + timeout_time-- + if(timeout_time <= 0 && !did_reset) + did_reset = TRUE + //visible_message("\"Vixyvrmrk xs fewi...\"") + blink(spawned_rune) + adjustHealth(min((health - maxHealth) * 0.5, -50)) //heal for 50% of our missing health + wander = FALSE + /*if(health > maxHealth * 0.9) + visible_message("\"Vitemvw gsqtpixi. Stivexmrk ex qebmqyq ijjmgmirgc.\"") + else + visible_message("\"Vitemvw gsqtpixi. Stivexmsrep ijjmgmirgc gsqtvsqmwih.\"")*/ + +/mob/living/simple_animal/hostile/megafauna/hierophant/death() + if(health > 0 || stat == DEAD) + return + else + stat = DEAD + blinking = TRUE //we do a fancy animation, release a huge burst(), and leave our staff. + animate(src, alpha = 0, color = "660099", time = 20, easing = EASE_OUT) + burst_range = 10 + //visible_message("\"Mrmxmexmrk wipj-hiwxvygx wiuyirgi...\"") + visible_message("[src] disappears in a massive burst of magic, leaving only its staff.") + burst(get_turf(src)) + ..() + +/mob/living/simple_animal/hostile/megafauna/hierophant/Destroy() + qdel(spawned_rune) + . = ..() + +/mob/living/simple_animal/hostile/megafauna/hierophant/devour(mob/living/L) + for(var/obj/item/W in L) + if(!L.unEquip(W)) + qdel(W) + /*visible_message( + "\"[pick(kill_phrases)]\"\n[src] annihilates [L]!", + "You annihilate [L], restoring your health!")*/ + visible_message( + "\"Caw.\"\n[src] annihilates [L]!", + "You annihilate [L], restoring your health!") + adjustHealth(-L.maxHealth*0.5) + L.dust() + +/*/mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target) + var/targets_the_same = (new_target == target) + . = ..() + if(. && target && !targets_the_same) + visible_message("\"[pick(target_phrases)]\"")*/ + +/mob/living/simple_animal/hostile/megafauna/hierophant/adjustHealth(amount) + . = ..() + if(src && amount > 0 && !blinking) + wander = TRUE + did_reset = FALSE + +/mob/living/simple_animal/hostile/megafauna/hierophant/AttackingTarget() + if(!blinking) + if(target && isliving(target)) + spawn(0) + melee_blast(get_turf(target)) //melee attacks on living mobs produce a 3x3 blast + ..() + +/mob/living/simple_animal/hostile/megafauna/hierophant/DestroySurroundings() + if(!blinking) + ..() + +/mob/living/simple_animal/hostile/megafauna/hierophant/Move() + if(!blinking) + /*if(!stat) + playsound(loc, 'sound/mecha/mechmove04.ogg', 150, 1, -4)*/ + ..() + +/mob/living/simple_animal/hostile/megafauna/hierophant/Goto(target, delay, minimum_distance) + wander = TRUE + if(!blinking) + ..() + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/calculate_rage() //how angry we are overall + did_reset = FALSE //oh hey we're doing SOMETHING, clearly we might need to heal if we recall + anger_modifier = Clamp(((maxHealth - health) / 42),0,50) + burst_range = initial(burst_range) + round(anger_modifier * 0.08) + beam_range = initial(beam_range) + round(anger_modifier * 0.12) + +/mob/living/simple_animal/hostile/megafauna/hierophant/OpenFire() + calculate_rage() + var/target_is_slow = FALSE + if(isliving(target)) + var/mob/living/L = target + if(!blinking && L.stat == DEAD && get_dist(src, L) > 2) + blink(L) + return + if(L.movement_delay() > 1.5) + target_is_slow = TRUE + chaser_speed = max(1, (3 - anger_modifier * 0.04) + target_is_slow * 0.5) + if(blinking) + return + ranged_cooldown = world.time + max(5, ranged_cooldown_time - anger_modifier * 0.75) //scale cooldown lower with high anger. + + if(prob(anger_modifier * 0.75)) //major ranged attack + var/list/possibilities = list() + var/cross_counter = 1 + round(anger_modifier * 0.12) + if(cross_counter > 1) + possibilities += "cross_blast_spam" + if(get_dist(src, target) > 2) + possibilities += "blink_spam" + if(chaser_cooldown < world.time) + if(prob(anger_modifier * 2)) + possibilities = list("chaser_swarm") + else + possibilities += "chaser_swarm" + if(possibilities.len) + ranged_cooldown = world.time + max(5, major_attack_cooldown - anger_modifier * 0.75) //we didn't cancel out of an attack, use the higher cooldown + var/blink_counter = 1 + round(anger_modifier * 0.08) + switch(pick(possibilities)) + if("blink_spam") //blink either once or multiple times. + if(health < maxHealth * 0.5 && !target_is_slow && blink_counter > 1) + //visible_message("\"Mx ampp rsx iwgeti.\"") + animate(src, color = "#660099", time = 6) + while(health && target && blink_counter) + if(loc == target.loc || loc == target) //we're on the same tile as them after about a second we can stop now + break + blink_counter-- + blinking = FALSE + blink(target) + blinking = TRUE + sleep(5) + animate(src, color = initial(color), time = 8) + sleep(8) + blinking = FALSE + else + blink(target) + if("cross_blast_spam") //fire a lot of cross blasts at a target. + //visible_message("\"Piezi mx rsalivi xs vyr.\"") + blinking = TRUE + animate(src, color = "#660099", time = 6) + while(health && target && cross_counter) + cross_counter-- + var/delay = 6 + if(prob(60)) + spawn(0) + cardinal_blasts(target) + else + spawn(0) + diagonal_blasts(target) + delay = 5 //this one isn't so mean, so do the next one faster(if there is one) + sleep(delay) + animate(src, color = initial(color), time = 8) + sleep(8) + blinking = FALSE + if("chaser_swarm") //fire four fucking chasers at a target and their friends. + //visible_message("\"Mx gerrsx lmhi.\"") + blinking = TRUE + animate(src, color = "#660099", time = 10) + var/list/targets = ListTargets() + var/list/cardinal_copy = cardinal.Copy() + while(health && targets.len && cardinal_copy.len) + var/mob/living/pickedtarget = pick(targets) + if(targets.len > 4) + pickedtarget = pick_n_take(targets) + if(pickedtarget.stat == DEAD) + pickedtarget = target + var/obj/effect/overlay/temp/hierophant/chaser/C = PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(loc, src, pickedtarget, chaser_speed, FALSE)) + C.moving = 3 + C.moving_dir = pick_n_take(cardinal_copy) + sleep(10) + chaser_cooldown = world.time + initial(chaser_cooldown) + animate(src, color = initial(color), time = 8) + sleep(8) + blinking = FALSE + return + + if(prob(10 + (anger_modifier * 0.5)) && get_dist(src, target) > 2) + blink(target) + + else if(prob(70 - anger_modifier)) //a cross blast of some type + if(prob(anger_modifier)) //at us? + if(prob(anger_modifier * 2) && health < maxHealth * 0.5) //we're super angry do it at all dirs + spawn(0) + alldir_blasts(src) + else if(prob(60)) + spawn(0) + cardinal_blasts(src) + else + spawn(0) + diagonal_blasts(src) + else //at them? + if(prob(anger_modifier * 2) && health < maxHealth * 0.5 && !target_is_slow) //we're super angry do it at all dirs + spawn(0) + alldir_blasts(target) + else if(prob(60)) + spawn(0) + cardinal_blasts(target) + else + spawn(0) + diagonal_blasts(target) + else if(chaser_cooldown < world.time) //if chasers are off cooldown, fire some! + var/obj/effect/overlay/temp/hierophant/chaser/C = PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(loc, src, target, chaser_speed, FALSE)) + chaser_cooldown = world.time + initial(chaser_cooldown) + if((prob(anger_modifier) || target.Adjacent(src)) && target != src) + var/obj/effect/overlay/temp/hierophant/chaser/OC = PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(loc, src, target, max(1.5, 5 - anger_modifier * 0.07), FALSE)) + OC.moving = 4 + OC.moving_dir = pick(cardinal - C.moving_dir) + else //just release a burst of power + spawn(0) + burst(get_turf(src)) + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/diagonal_blasts(mob/victim) //fire diagonal cross blasts with a delay + var/turf/T = get_turf(victim) + if(!T) + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/diagonal, list(T, src)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/effects/bin_close.ogg', 200, 1) + sleep(2) + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE)) + for(var/d in diagonals) + spawn(0) + blast_wall(T, d) + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/cardinal_blasts(mob/victim) //fire cardinal cross blasts with a delay + var/turf/T = get_turf(victim) + if(!T) + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/cardinal, list(T, src)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/effects/bin_close.ogg', 200, 1) + sleep(2) + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE)) + for(var/d in cardinal) + spawn(0) + blast_wall(T, d) + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/alldir_blasts(mob/victim) //fire alldir cross blasts with a delay + var/turf/T = get_turf(victim) + if(!T) + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/effects/bin_close.ogg', 200, 1) + sleep(2) + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE)) + for(var/d in alldirs) + spawn(0) + blast_wall(T, d) + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/blast_wall(turf/T, dir) //make a wall of blasts beam_range tiles long + var/range = beam_range + var/turf/previousturf = T + var/turf/J = get_step(previousturf, dir) + for(var/i in 1 to range) + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(J, src, FALSE)) + previousturf = J + J = get_step(previousturf, dir) + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/blink(mob/victim) //blink to a target + if(blinking || !victim) + return + var/turf/T = get_turf(victim) + var/turf/source = get_turf(src) + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src)) + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(source, src)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/magic/Wand_Teleport.ogg', 200, 1) + playsound(source,'sound/magic/blink.ogg', 200, 1) + //playsound(source,'sound/machines/AirlockOpen.ogg', 200, 1) + blinking = TRUE + sleep(2) //short delay before we start... + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(T, src)) + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(source, src)) + for(var/t in RANGE_TURFS(1, T)) + var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, src, FALSE)) + B.damage = 30 + for(var/t in RANGE_TURFS(1, source)) + var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, src, FALSE)) + B.damage = 30 + animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out + sleep(1) + visible_message("[src] fades out!") + density = FALSE + sleep(2) + forceMove(T) + sleep(1) + animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN + sleep(1) + density = TRUE + visible_message("[src] fades in!") + sleep(1) //at this point the blasts we made detonate + blinking = FALSE + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/melee_blast(mob/victim) //make a 3x3 blast around a target + if(!victim) + return + var/turf/T = get_turf(victim) + if(!T) + return + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src)) + playsound(T,'sound/magic/blink.ogg', 200, 1) + //playsound(T,'sound/effects/bin_close.ogg', 200, 1) + sleep(2) + for(var/t in RANGE_TURFS(1, T)) + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, src, FALSE)) + +/mob/living/simple_animal/hostile/megafauna/hierophant/proc/burst(turf/original) //release a wave of blasts + playsound(original,'sound/magic/blink.ogg', 200, 1) + //playsound(original,'sound/machines/AirlockOpen.ogg', 200, 1) + var/last_dist = 0 + for(var/t in spiral_range_turfs(burst_range, original)) + var/turf/T = t + if(!T) + continue + var/dist = get_dist(original, T) + if(dist > last_dist) + last_dist = dist + sleep(1 + (burst_range - last_dist) * 0.5) //gets faster as it gets further out + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE)) + +/mob/living/simple_animal/hostile/megafauna/hierophant/AltClickOn(atom/A) //player control handler(don't give this to a player holy fuck) + if(!istype(A) || get_dist(A, src) <= 2) + return + blink(A) + +//Hierophant overlays +/obj/effect/overlay/temp/hierophant + layer = MOB_LAYER - 0.1 + var/mob/living/caster //who made this, anyway + +/obj/effect/overlay/temp/hierophant/New(loc, new_caster) + ..() + if(new_caster) + caster = new_caster + +/obj/effect/overlay/temp/hierophant/chaser //a hierophant's chaser. follows target around, moving and producing a blast every speed deciseconds. + duration = 98 + var/mob/living/target //what it's following + var/turf/targetturf //what turf the target is actually on + var/moving_dir //what dir it's moving in + var/previous_moving_dir //what dir it was moving in before that + var/more_previouser_moving_dir //what dir it was moving in before THAT + var/moving = 0 //how many steps to move before recalculating + var/standard_moving_before_recalc = 4 //how many times we step before recalculating normally + var/tiles_per_step = 1 //how many tiles we move each step + var/speed = 3 //how many deciseconds between each step + var/currently_seeking = FALSE + var/friendly_fire_check = FALSE //if blasts produced apply friendly fire + +/obj/effect/overlay/temp/hierophant/chaser/New(loc, new_caster, new_target, new_speed, is_friendly_fire) + ..() + target = new_target + friendly_fire_check = is_friendly_fire + if(new_speed) + speed = new_speed + spawn(0) + seek_target() + +/obj/effect/overlay/temp/hierophant/chaser/proc/get_target_dir() + . = get_cardinal_dir(src, targetturf) + if((. != previous_moving_dir && . == more_previouser_moving_dir) || . == 0) //we're alternating, recalculate + var/list/cardinal_copy = cardinal.Copy() + cardinal_copy -= more_previouser_moving_dir + . = pick(cardinal_copy) + +/obj/effect/overlay/temp/hierophant/chaser/proc/seek_target() + if(!currently_seeking) + currently_seeking = TRUE + targetturf = get_turf(target) + while(target && src && !qdeleted(src) && currently_seeking && x && y && targetturf) //can this target actually be sook out + if(!moving) //we're out of tiles to move, find more and where the target is! + more_previouser_moving_dir = previous_moving_dir + previous_moving_dir = moving_dir + moving_dir = get_target_dir() + var/standard_target_dir = get_cardinal_dir(src, targetturf) + if((standard_target_dir != previous_moving_dir && standard_target_dir == more_previouser_moving_dir) || standard_target_dir == 0) + moving = 1 //we would be repeating, only move a tile before checking + else + moving = standard_moving_before_recalc + if(moving) //move in the dir we're moving in right now + var/turf/T = get_turf(src) + for(var/i in 1 to tiles_per_step) + var/maybe_new_turf = get_step(T, moving_dir) + if(maybe_new_turf) + T = maybe_new_turf + else + break + forceMove(T) + make_blast() //make a blast, too + moving-- + sleep(speed) + targetturf = get_turf(target) + +/obj/effect/overlay/temp/hierophant/chaser/proc/make_blast() + PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(loc, caster, friendly_fire_check)) + +/obj/effect/overlay/temp/hierophant/telegraph + icon = 'icons/effects/96x96.dmi' + icon_state = "hierophant_telegraph" + pixel_x = -32 + pixel_y = -32 + duration = 3 + +/obj/effect/overlay/temp/hierophant/telegraph/diagonal + icon_state = "hierophant_telegraph_diagonal" + +/obj/effect/overlay/temp/hierophant/telegraph/cardinal + icon_state = "hierophant_telegraph_cardinal" + +/obj/effect/overlay/temp/hierophant/telegraph/teleport + icon_state = "hierophant_telegraph_teleport" + duration = 9 + +/obj/effect/overlay/temp/hierophant/blast + icon = 'icons/effects/effects.dmi' + icon_state = "hierophant_blast" + name = "vortex blast" + luminosity = 1 + desc = "Get out of the way!" + duration = 9 + var/damage = 10 //how much damage do we do? + var/list/hit_things = list() //we hit these already, ignore them + var/friendly_fire_check = FALSE + var/bursting = FALSE //if we're bursting and need to hit anyone crossing us + +/obj/effect/overlay/temp/hierophant/blast/New(loc, new_caster, friendly_fire) + ..() + friendly_fire_check = friendly_fire + if(new_caster) + hit_things += new_caster + if(ismineralturf(loc)) //drill mineral turfs + var/turf/simulated/mineral/M = loc + M.gets_drilled(caster) + spawn(0) + blast() + +/obj/effect/overlay/temp/hierophant/blast/proc/blast() + var/turf/T = get_turf(src) + if(!T) + return + playsound(T,'sound/magic/Blind.ogg', 125, 1, -5) //make a sound + sleep(6) //wait a little + bursting = TRUE + do_damage(T) //do damage and mark us as bursting + sleep(1.3) //slightly forgiving; the burst animation is 1.5 deciseconds + bursting = FALSE //we no longer damage crossers + +/obj/effect/overlay/temp/hierophant/blast/Crossed(atom/movable/AM) + ..() + if(bursting) + do_damage(get_turf(src)) + +/obj/effect/overlay/temp/hierophant/blast/proc/do_damage(turf/T) + for(var/mob/living/L in T.contents - hit_things) //find and damage mobs... + hit_things += L + if((friendly_fire_check && caster && caster.faction_check(L)) || L.stat == DEAD) + continue + if(L.client) + flash_color(L.client, "#660099", 1) + playsound(L,'sound/weapons/sear.ogg', 50, 1, -4) + to_chat(L, "You're struck by a [name]!") + var/limb_to_hit = pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg") + var/armor = L.run_armor_check(limb_to_hit, "melee", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!") + L.apply_damage(damage, BURN, limb_to_hit, armor) + if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid)) + L.adjustBruteLoss(damage) + add_logs(caster, L, "struck with a [name]") + for(var/obj/mecha/M in T.contents - hit_things) //and mechs. + hit_things += M + if(M.occupant) + if(friendly_fire_check && caster && caster.faction_check(M.occupant)) + continue + to_chat(M.occupant, "Your [M.name] is struck by a [name]!") + playsound(M,'sound/weapons/sear.ogg', 50, 1, -4) + M.take_damage(damage, BURN, 0, 0) + +/obj/effect/hierophant + name = "hierophant rune" + desc = "A powerful magic mark allowing whomever attunes themself to it to return to it at will." + icon = 'icons/obj/rune.dmi' + icon_state = "hierophant" + layer = 2.5 + anchored = TRUE + color = "#CC00FF" + +/obj/effect/hierophant/attackby(obj/item/I, mob/user, params) + if(istype(I, /obj/item/weapon/hierophant_staff)) + var/obj/item/weapon/hierophant_staff/H = I + if(H.rune == src) + to_chat(user, "You start removing your hierophant rune...") + H.timer = world.time + 51 + if(do_after(user, 50, target = src)) + playsound(src,'sound/magic/Blind.ogg', 200, 1, -4) + PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(get_turf(src), user)) + to_chat(user, "You touch the rune with the staff, dispelling it!") + H.rune = null + user.update_action_buttons_icon() + qdel(src) + else + H.timer = world.time + else + to_chat(user, "You touch the rune with the staff, but nothing happens.") + + else + ..() + +/obj/item/device/gps/internal/hierophant + icon_state = null + gpstag = "Zealous Signal" + desc = "Heed its words." + invisibility = 100 + +/turf/simulated/indestructible/hierophant + icon_state = "hierophant1" + oxygen = 14 + nitrogen = 23 + temperature = 300 + desc = "A floor with a square pattern. It's faintly cool to the touch." + +/turf/simulated/indestructible/hierophant/New() + ..() + if(prob(50)) + icon_state = "hierophant2" + +/turf/unsimulated/indestructible/riveted/hierophant + name = "wall" + desc = "A wall made out of smooth, cold stone." + icon = 'icons/turf/walls/hierophant_wall.dmi' + icon_state = "hierophant" + smooth = SMOOTH_TRUE + +#undef MEDAL_PREFIX \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index 975f7f0b93c..89119952f60 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -79,7 +79,8 @@ Difficulty: Medium minimum_distance = 0 speed = 0 charging = 1 - addtimer(src, "reset_charge", 50) + spawn(50) + reset_charge() /mob/living/simple_animal/hostile/megafauna/legion/proc/reset_charge() ranged = 1 @@ -138,60 +139,4 @@ Difficulty: Medium desc = "The message repeats." invisibility = 100 - -//Loot - -/obj/item/weapon/staff/storm - name = "staff of storms" - desc = "An ancient staff retrieved from the remains of Legion. The wind stirs as you move it." - icon_state = "staffofstorms" - item_state = "staffofstorms" - icon = 'icons/obj/guns/magic.dmi' - slot_flags = SLOT_BACK - item_state = "staffofstorms" - w_class = 4 - force = 25 - damtype = BURN - hitsound = 'sound/weapons/sear.ogg' - var/storm_type = /datum/weather/ash_storm - var/storm_cooldown = 0 - -/obj/item/weapon/staff/storm/attack_self(mob/user) - if(storm_cooldown > world.time) - to_chat(user, "The staff is still recharging!") - return - - var/area/user_area = get_area(user) - var/datum/weather/A - var/z_level_name = space_manager.levels_by_name[user.z] - for(var/V in weather_master.existing_weather) - var/datum/weather/W = V - if(W.target_z == z_level_name && W.area_type == user_area.type) - A = W - break - if(A) - - if(A.stage != END_STAGE) - if(A.stage == WIND_DOWN_STAGE) - to_chat(user, "The storm is already ending! It would be a waste to use the staff now.") - return - user.visible_message("[user] holds [src] skywards as an orange beam travels into the sky!", \ - "You hold [src] skyward, dispelling the storm!") - playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) - A.wind_down() - return - else - A = new storm_type - A.name = "staff storm" - A.area_type = user_area.type - A.target_z = z_level_name - A.telegraph_duration = 100 - A.end_duration = 100 - - user.visible_message("[user] holds [src] skywards as red lightning crackles into the sky!", \ - "You hold [src] skyward, calling down a terrible storm!") - playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0) - A.telegraph() - storm_cooldown = world.time + 200 - #undef MEDAL_PREFIX \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index c7dd1a24f33..c29a6e8a4f8 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -1,7 +1,7 @@ #define MEDAL_PREFIX "Boss" /mob/living/simple_animal/hostile/megafauna - name = "boss of this gym" + name = "megafauna" desc = "Attack the weak point for massive damage." health = 1000 maxHealth = 1000 diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index 4f12bb92270..c50e2dd2944 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -99,17 +99,17 @@ if(proximity_flag && ishuman(target)) var/mob/living/carbon/human/H = target if(inert) - user << "[src] has become inert, its healing properties are no more." + to_chat(user, "[src] has become inert, its healing properties are no more.") return else if(H.stat == DEAD) - user << "[src] are useless on the dead." + to_chat(user, "[src] are useless on the dead.") return if(H != user) H.visible_message("[user] forces [H] to apply [src]... They quickly regenerate all injuries!") feedback_add_details("hivelord_core","[src.type]|used|other") else - user << "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments." + to_chat(user, "You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.") feedback_add_details("hivelord_core","[src.type]|used|self") playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1) H.revive() diff --git a/goon/browserassets/css/browserOutput.css b/goon/browserassets/css/browserOutput.css index dad1ab1a340..8d00fca2d54 100644 --- a/goon/browserassets/css/browserOutput.css +++ b/goon/browserassets/css/browserOutput.css @@ -362,3 +362,8 @@ h1.alert, h2.alert {color: #000000;} /* HELPER CLASSES */ .text-normal {font-weight: normal; font-style: normal;} .hidden {display: none; visibility: hidden;} + +/* MEGAFAUNA */ +.colossus {color: #7F282A; font-size: 5;} +.hierophant {color: #660099; font-weight: bold; font-size: 4;} +.hierophant_warning {color: #660099; font-weight: bold; font-style: italic;} \ No newline at end of file diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 725d97ce21b..6f8eb8a6f71 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi index b13c88015cc..9da31cf8814 100644 Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi index 4c7a3707efd..721f739ac96 100644 Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index fd5deb0da2c..72636e0a000 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 5ff67d8002f..2cc920010f8 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/obj/rune.dmi b/icons/obj/rune.dmi index 901b7466d57..5df6a842ad5 100644 Binary files a/icons/obj/rune.dmi and b/icons/obj/rune.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index 7b67484616a..661db4f09bb 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/icons/turf/walls/hierophant_wall.dmi b/icons/turf/walls/hierophant_wall.dmi new file mode 100644 index 00000000000..8482970eaf0 Binary files /dev/null and b/icons/turf/walls/hierophant_wall.dmi differ diff --git a/paradise.dme b/paradise.dme index b094b194f01..c55cff9a6d9 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1656,6 +1656,7 @@ #include "code\modules\mob\living\simple_animal\hostile\tree.dm" #include "code\modules\mob\living\simple_animal\hostile\winter_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\dragon.dm" +#include "code\modules\mob\living\simple_animal\hostile\megafauna\hierophant.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\legion.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\megafauna.dm" #include "code\modules\mob\living\simple_animal\hostile\mining\hivelord.dm"