mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 12:41:09 +01:00
Merge branch 'master' of https://github.com/tgstation/-tg-station into why_did_this_take_months
# Conflicts: # code/modules/client/preferences_savefile.dm
This commit is contained in:
@@ -266,6 +266,7 @@
|
||||
if(client)
|
||||
client.screen -= I
|
||||
I.layer = initial(I.layer)
|
||||
I.appearance_flags &= ~NO_CLIENT_COLOR
|
||||
I.forceMove(loc)
|
||||
I.dropped(src)
|
||||
return TRUE
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
if (notransform)
|
||||
return
|
||||
if(..())
|
||||
if(..()) //not dead
|
||||
// GROW!
|
||||
if(amount_grown < max_grown)
|
||||
amount_grown++
|
||||
|
||||
@@ -91,7 +91,7 @@ var/const/MAX_ACTIVE_TIME = 400
|
||||
return Attach(AM)
|
||||
return 0
|
||||
|
||||
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin)
|
||||
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0)
|
||||
if(!..())
|
||||
return
|
||||
if(stat == CONSCIOUS)
|
||||
|
||||
@@ -672,7 +672,8 @@
|
||||
if(B)
|
||||
B.damaged_brain = 0
|
||||
for(var/datum/disease/D in viruses)
|
||||
D.cure(0)
|
||||
if (D.severity != NONTHREAT)
|
||||
D.cure(0)
|
||||
if(admin_revive)
|
||||
regenerate_limbs()
|
||||
handcuffed = initial(handcuffed)
|
||||
|
||||
@@ -191,18 +191,26 @@
|
||||
for(var/obj/item/I in BP.embedded_objects)
|
||||
msg += "<B>[t_He] [t_has] \a \icon[I] [I] embedded in [t_his] [BP.name]!</B>\n"
|
||||
|
||||
//stores how many left limbs are missing
|
||||
//stores missing limbs
|
||||
var/l_limbs_missing = 0
|
||||
var/r_limbs_missing = 0
|
||||
for(var/t in missing)
|
||||
if(t=="head")
|
||||
msg += "<span class='deadsay'><B>[capitalize(t_his)] [parse_zone(t)] is missing!</B><span class='warning'>\n"
|
||||
continue
|
||||
if(t == "l_arm" || t == "l_leg")
|
||||
l_limbs_missing++
|
||||
else if(t == "r_arm" || t == "r_leg")
|
||||
r_limbs_missing++
|
||||
|
||||
msg += "<B>[capitalize(t_his)] [parse_zone(t)] is missing!</B>\n"
|
||||
|
||||
if(l_limbs_missing >= 2)
|
||||
if(l_limbs_missing >= 2 && r_limbs_missing == 0)
|
||||
msg += "[t_He] looks all right now.\n"
|
||||
else if(l_limbs_missing == 0 && r_limbs_missing >= 2)
|
||||
msg += "[t_He] really keeps to the left.\n"
|
||||
else if(l_limbs_missing >= 2 && r_limbs_missing >= 2)
|
||||
msg += "[t_He] doesn't seem all there.\n"
|
||||
|
||||
if(temp)
|
||||
if(temp < 30)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/has_gravity()
|
||||
/mob/living/carbon/human/mob_has_gravity()
|
||||
. = ..()
|
||||
if(!.)
|
||||
if(mob_negates_gravity())
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
if(slot_glasses)
|
||||
glasses = I
|
||||
var/obj/item/clothing/glasses/G = I
|
||||
if(G.glass_colour_type)
|
||||
update_glasses_color(G, 1)
|
||||
if(G.tint)
|
||||
update_tint()
|
||||
if(G.vision_correction)
|
||||
@@ -144,6 +146,8 @@
|
||||
else if(I == glasses)
|
||||
glasses = null
|
||||
var/obj/item/clothing/glasses/G = I
|
||||
if(G.glass_colour_type)
|
||||
update_glasses_color(G, 0)
|
||||
if(G.tint)
|
||||
update_tint()
|
||||
if(G.vision_correction)
|
||||
|
||||
@@ -29,20 +29,26 @@
|
||||
if (notransform)
|
||||
return
|
||||
|
||||
if(..())
|
||||
if(..()) //not dead
|
||||
for(var/datum/mutation/human/HM in dna.mutations)
|
||||
HM.on_life(src)
|
||||
|
||||
if(stat != DEAD)
|
||||
//heart attack stuff
|
||||
handle_heart()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Stuff jammed in your limbs hurts
|
||||
handle_embedded_objects()
|
||||
|
||||
//Update our name based on whether our face is obscured/disfigured
|
||||
name = get_visible_name()
|
||||
|
||||
dna.species.spec_life(src) // for mutantraces
|
||||
|
||||
if(stat != DEAD)
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
|
||||
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
|
||||
|
||||
@@ -172,6 +172,34 @@
|
||||
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
|
||||
specflags = list(NOBREATH,NOBLOOD,RADIMMUNE,VIRUSIMMUNE)
|
||||
dangerous_existence = 1
|
||||
var/datum/action/innate/shadow/darkvision/vision_toggle
|
||||
|
||||
/datum/action/innate/shadow/darkvision //Darkvision toggle so shadowpeople can actually see where darkness is
|
||||
name = "Toggle Darkvision"
|
||||
check_flags = AB_CHECK_CONSCIOUS
|
||||
background_icon_state = "bg_default"
|
||||
button_icon_state = "blind"
|
||||
|
||||
/datum/action/innate/shadow/darkvision/Activate()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.see_in_dark < 8)
|
||||
H.see_in_dark = 8
|
||||
H.see_invisible = SEE_INVISIBLE_MINIMUM
|
||||
H << "<span class='notice'>You adjust your vision to pierce the darkness.</span>"
|
||||
else
|
||||
H.see_in_dark = 2
|
||||
H.see_invisible = SEE_INVISIBLE_LIVING
|
||||
H << "<span class='notice'>You adjust your vision to recognize the shadows.</span>"
|
||||
|
||||
/datum/species/shadow/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
vision_toggle = new
|
||||
vision_toggle.Grant(C)
|
||||
|
||||
/datum/species/shadow/on_species_loss(mob/living/carbon/C)
|
||||
. = ..()
|
||||
if(vision_toggle)
|
||||
vision_toggle.Remove(C)
|
||||
|
||||
/datum/species/shadow/spec_life(mob/living/carbon/human/H)
|
||||
var/light_amount = 0
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
observe.client.screen -= I
|
||||
I.loc = src
|
||||
I.layer = ABOVE_HUD_LAYER
|
||||
I.appearance_flags |= NO_CLIENT_COLOR
|
||||
var/not_handled = FALSE
|
||||
switch(slot)
|
||||
if(slot_back)
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
damageoverlaytemp = 0
|
||||
update_damage_hud()
|
||||
|
||||
if(..())
|
||||
. = 1
|
||||
|
||||
if(..()) //not dead
|
||||
handle_blood()
|
||||
|
||||
if(stat != DEAD)
|
||||
for(var/X in internal_organs)
|
||||
var/obj/item/organ/O = X
|
||||
O.on_life()
|
||||
@@ -21,6 +20,9 @@
|
||||
//Updates the number of stored chemicals for powers
|
||||
handle_changeling()
|
||||
|
||||
if(stat != DEAD)
|
||||
return 1
|
||||
|
||||
///////////////
|
||||
// BREATHING //
|
||||
///////////////
|
||||
|
||||
@@ -11,10 +11,6 @@
|
||||
|
||||
/mob/living/carbon/monkey/punpun/New()
|
||||
Read_Memory()
|
||||
if(relic_hat)
|
||||
equip_to_slot_or_del(new relic_hat, slot_head)
|
||||
if(relic_mask)
|
||||
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
|
||||
if(ancestor_name)
|
||||
name = ancestor_name
|
||||
if(ancestor_chain > 1)
|
||||
@@ -27,6 +23,14 @@
|
||||
gender = pick(MALE, FEMALE)
|
||||
..()
|
||||
|
||||
//These have to be after the parent new to ensure that the monkey
|
||||
//bodyparts are actually created before we try to equip things to
|
||||
//those slots
|
||||
if(relic_hat)
|
||||
equip_to_slot_or_del(new relic_hat, slot_head)
|
||||
if(relic_mask)
|
||||
equip_to_slot_or_del(new relic_mask, slot_wear_mask)
|
||||
|
||||
/mob/living/carbon/monkey/punpun/Life()
|
||||
if(ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
Write_Memory(0)
|
||||
|
||||
@@ -24,3 +24,7 @@
|
||||
var/obj/item/organ/tongue/T = getorganslot("tongue")
|
||||
if(T)
|
||||
. |= T.get_spans()
|
||||
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I)
|
||||
. |= I.get_held_item_speechspans(src)
|
||||
|
||||
@@ -3,13 +3,9 @@
|
||||
if(stat != DEAD)
|
||||
death(1)
|
||||
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob(src,force=1) //to update alien nest overlay, forced because we don't exist anymore
|
||||
|
||||
if(!prev_lying)
|
||||
gib_animation()
|
||||
|
||||
|
||||
spill_organs(no_brain, no_organs, no_bodyparts)
|
||||
|
||||
if(!no_bodyparts)
|
||||
@@ -64,8 +60,6 @@
|
||||
living_mob_list -= src
|
||||
if(!gibbed)
|
||||
dead_mob_list += src
|
||||
else if(buckled)
|
||||
buckled.unbuckle_mob(src,force=1)
|
||||
paralysis = 0
|
||||
stunned = 0
|
||||
weakened = 0
|
||||
|
||||
@@ -19,21 +19,18 @@
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
if(stat != DEAD)
|
||||
|
||||
//Breathing, if applicable
|
||||
handle_breathing()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Mutations and radiation
|
||||
handle_mutations_and_radiation()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Chemicals in the body
|
||||
handle_chemicals_in_body()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Random events (vomiting etc)
|
||||
handle_random_events()
|
||||
|
||||
. = 1
|
||||
|
||||
//Handle temperature/pressure differences between body and environment
|
||||
if(environment)
|
||||
handle_environment(environment)
|
||||
@@ -43,16 +40,19 @@
|
||||
//stuff in the stomach
|
||||
handle_stomach()
|
||||
|
||||
update_gravity(has_gravity())
|
||||
update_gravity(mob_has_gravity())
|
||||
|
||||
if(machine)
|
||||
machine.check_eye(src)
|
||||
|
||||
|
||||
if(stat != DEAD)
|
||||
handle_disabilities() // eye, ear, brain damages
|
||||
if(stat != DEAD)
|
||||
handle_status_effects() //all special effects, stunned, weakened, jitteryness, hallucination, sleeping, etc
|
||||
|
||||
if(stat != DEAD)
|
||||
return 1
|
||||
|
||||
|
||||
/mob/living/proc/handle_breathing()
|
||||
return
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
/mob/living/Destroy()
|
||||
..()
|
||||
|
||||
if(buckled)
|
||||
buckled.unbuckle_mob(src,force=1)
|
||||
|
||||
for(var/mob/living/simple_animal/drone/D in player_list)
|
||||
for(var/image/I in staticOverlays)
|
||||
D.staticOverlays.Remove(I)
|
||||
|
||||
@@ -92,11 +92,12 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
|
||||
|
||||
if(message_mode != MODE_WHISPER) //whisper() calls treat_message(); double process results in "hisspering"
|
||||
message = treat_message(message)
|
||||
spans += get_spans()
|
||||
|
||||
if(!message)
|
||||
return
|
||||
|
||||
spans += get_spans()
|
||||
|
||||
//Log of what we've said, plain message, no spans or junk
|
||||
say_log += message
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
#define POWER_RESTORATION_APC_FOUND 3
|
||||
|
||||
/mob/living/silicon/ai/Life()
|
||||
if (src.stat == DEAD)
|
||||
if (stat == DEAD)
|
||||
return
|
||||
else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist
|
||||
//Being dead doesn't mean your temperature never changes
|
||||
|
||||
update_gravity(has_gravity())
|
||||
update_gravity(mob_has_gravity())
|
||||
|
||||
if(malfhack && malfhack.aidisabled)
|
||||
deltimer(malfhacking)
|
||||
|
||||
@@ -3,5 +3,4 @@
|
||||
ticker.mode.remove_cultist(mind, 0, 0)
|
||||
ticker.mode.remove_revolutionary(mind, 0)
|
||||
ticker.mode.remove_gangster(mind, remove_bosses=1)
|
||||
ticker.mode.remove_hog_follower(mind,0)
|
||||
..()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/mob/living/silicon/pai/Life()
|
||||
if (src.stat == DEAD)
|
||||
if(stat == DEAD)
|
||||
return
|
||||
if(src.cable)
|
||||
if(cable)
|
||||
if(get_dist(src, src.cable) > 1)
|
||||
var/turf/T = get_turf(src.loc)
|
||||
T.visible_message("<span class='warning'>[src.cable] rapidly retracts back into its spool.</span>", "<span class='italics'>You hear a click and the sound of wire spooling rapidly.</span>")
|
||||
|
||||
@@ -6,4 +6,3 @@
|
||||
if(mind)
|
||||
ticker.mode.remove_revolutionary(mind)
|
||||
ticker.mode.remove_gangster(mind,1,remove_bosses=1)
|
||||
ticker.mode.remove_hog_follower(mind, 0)
|
||||
|
||||
@@ -785,9 +785,8 @@
|
||||
if(isturf(tile))
|
||||
tile.clean_blood()
|
||||
for(var/A in tile)
|
||||
if(istype(A, /obj/effect))
|
||||
if(is_cleanable(A))
|
||||
qdel(A)
|
||||
if(is_cleanable(A))
|
||||
qdel(A)
|
||||
else if(istype(A, /obj/item))
|
||||
var/obj/item/cleaned_item = A
|
||||
cleaned_item.clean_blood()
|
||||
|
||||
@@ -402,4 +402,4 @@
|
||||
/datum/robot_energy_storage/medical
|
||||
max_energy = 2500
|
||||
recharge_rate = 250
|
||||
name = "Medical Synthesizer"
|
||||
name = "Medical Synthesizer"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/mob/living/silicon/robot/mob_negates_gravity()
|
||||
return magpulse
|
||||
|
||||
/mob/living/silicon/robot/has_gravity()
|
||||
/mob/living/silicon/robot/mob_has_gravity()
|
||||
return ..() || mob_negates_gravity()
|
||||
|
||||
/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
if(health < maxHealth)
|
||||
adjustHealth(-5)
|
||||
if(src != M)
|
||||
Beam(M,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=4)
|
||||
Beam(M,icon_state="sendbeam",time=4)
|
||||
M.visible_message("<span class='danger'>[M] repairs some of \the <b>[src]'s</b> dents.</span>", \
|
||||
"<span class='cult'>You repair some of <b>[src]'s</b> dents, leaving <b>[src]</b> at <b>[health]/[maxHealth]</b> health.</span>")
|
||||
else
|
||||
|
||||
@@ -53,4 +53,3 @@
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "xfloor1"
|
||||
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
|
||||
layer = ABOVE_OPEN_TURF_LAYER
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
staticOverlays = list()
|
||||
hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD)
|
||||
unique_name = TRUE
|
||||
faction = list("silicon")
|
||||
faction = list("neutral","silicon")
|
||||
dextrous = TRUE
|
||||
dextrous_hud_type = /datum/hud/dextrous/drone
|
||||
var/staticChoice = "static"
|
||||
@@ -245,7 +245,7 @@
|
||||
/mob/living/simple_animal/drone/mob_negates_gravity()
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/drone/has_gravity()
|
||||
/mob/living/simple_animal/drone/mob_has_gravity()
|
||||
return ..() || mob_negates_gravity()
|
||||
|
||||
/mob/living/simple_animal/drone/experience_pressure_difference(pressure_difference, direction)
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
var/datum/beam/C = pick(enemychains)
|
||||
qdel(C)
|
||||
enemychains -= C
|
||||
enemychains += Beam(target,"lightning[rand(1,12)]",'icons/effects/effects.dmi',70, 7,/obj/effect/ebeam/chain)
|
||||
enemychains += Beam(target, "lightning[rand(1,12)]", time=70, maxdistance=7, beam_type=/obj/effect/ebeam/chain)
|
||||
|
||||
/mob/living/simple_animal/hostile/guardian/beam/Destroy()
|
||||
removechains()
|
||||
@@ -39,7 +39,7 @@
|
||||
/mob/living/simple_animal/hostile/guardian/beam/Manifest()
|
||||
if(..())
|
||||
if(summoner)
|
||||
summonerchain = Beam(summoner,"lightning[rand(1,12)]",'icons/effects/effects.dmi',INFINITY, INFINITY,/obj/effect/ebeam/chain)
|
||||
summonerchain = Beam(summoner, "lightning[rand(1,12)]", time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain)
|
||||
while(loc != summoner)
|
||||
if(successfulshocks > 5)
|
||||
successfulshocks = 0
|
||||
@@ -57,7 +57,7 @@
|
||||
if(summonerchain && !qdeleted(summonerchain))
|
||||
. += chainshock(summonerchain)
|
||||
else
|
||||
summonerchain = Beam(summoner,"lightning[rand(1,12)]",'icons/effects/effects.dmi',INFINITY, INFINITY,/obj/effect/ebeam/chain)
|
||||
summonerchain = Beam(summoner, "lightning[rand(1,12)]", time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain)
|
||||
if(enemychains.len)
|
||||
for(var/chain in enemychains)
|
||||
if(!qdeleted(chain))
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
var/ranged_message = "fires" //Fluff text for ranged mobs
|
||||
var/ranged_cooldown = 0 //What the current cooldown on ranged attacks is, generally world.time + ranged_cooldown_time
|
||||
var/ranged_cooldown_time = 30 //How long, in deciseconds, the cooldown of ranged attacks is
|
||||
var/ranged_ignores_vision = FALSE //if it'll fire ranged attacks even if it lacks vision on its target, only works with environment smash
|
||||
var/check_friendly_fire = 0 // Should the ranged mob check for friendlies when shooting
|
||||
var/retreat_distance = null //If our mob runs from players when they're too close, set in tile distance. By default, mobs do not retreat.
|
||||
var/minimum_distance = 1 //Minimum approach distance, so ranged mobs chase targets down, but still keep their distance set in tiles to the target, set higher to make mobs keep distance
|
||||
@@ -53,6 +54,10 @@
|
||||
environment_target_typecache = typecacheof(environment_target_typecache)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/Destroy()
|
||||
targets_from = null
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/Life()
|
||||
. = ..()
|
||||
if(!.) //dead
|
||||
@@ -225,12 +230,14 @@
|
||||
else
|
||||
Goto(target,move_to_delay,minimum_distance)
|
||||
if(target)
|
||||
if(isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
|
||||
if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
|
||||
AttackingTarget()
|
||||
return 1
|
||||
return 0
|
||||
if(environment_smash)
|
||||
if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range) //We can't see our target, but he's in our vision range still
|
||||
if(ranged_ignores_vision && ranged_cooldown <= world.time) //we can't see our target... but we can fire at them!
|
||||
OpenFire(target)
|
||||
if(environment_smash >= 2) //If we're capable of smashing through walls, forget about vision completely after finding our target
|
||||
Goto(target,move_to_delay,minimum_distance)
|
||||
FindHidden()
|
||||
|
||||
@@ -9,15 +9,15 @@ Bubblegum's footsteps are heralded by shaking booms, proving its tremendous size
|
||||
|
||||
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
|
||||
|
||||
It often charges, dealing massive damage to anything unfortunate enough to be standing where it's aiming.
|
||||
Whenever it isn't chasing something down, it will sink into nearby blood pools (if possible) and springs out of the closest one to its target.
|
||||
To make this possible, it sprays streams of blood at random.
|
||||
From these blood pools Bubblegum may summon slaughterlings - weak, low-damage minions designed to impede the target's progress.
|
||||
It tries to strike at its target through any bloodpools under them; if it fails to do that, it will spray blood and then attempt to warp to a bloodpool near the target.
|
||||
If it fails to warp to a target, it may summon up to 6 slaughterlings from the blood around it.
|
||||
If it does not summon all 6 slaughterlings, it will instead charge at its target, dealing massive damage to anything it hits and spraying a stream of blood.
|
||||
At half health, it will either charge three times or warp, then charge, instead of doing a single charge.
|
||||
|
||||
When Bubblegum dies, it leaves behind a chest that can contain three things:
|
||||
1. A slaughter demon spawner
|
||||
2. A bottle that, when activated, drives everyone nearby into a frenzy
|
||||
3. A contract that marks for death the chosen target
|
||||
1. A bottle that, when activated, drives everyone nearby into a frenzy
|
||||
2. A contract that marks for death the chosen target
|
||||
3. A spellblade that can slice off limbs at range
|
||||
|
||||
Difficulty: Hard
|
||||
|
||||
@@ -45,6 +45,7 @@ Difficulty: Hard
|
||||
pixel_x = -32
|
||||
del_on_death = 1
|
||||
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
|
||||
blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
|
||||
var/charging = 0
|
||||
medal_type = MEDAL_PREFIX
|
||||
score_type = BUBBLEGUM_SCORE
|
||||
@@ -57,6 +58,12 @@ Difficulty: Hard
|
||||
desc = "You're not quite sure how a signal can be bloody."
|
||||
invisibility = 100
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/adjustBruteLoss(amount)
|
||||
if(amount > 0 && prob(33))
|
||||
var/obj/effect/decal/cleanable/blood/B = new /obj/effect/decal/cleanable/blood(loc)
|
||||
B.bloodiness = 20
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
|
||||
..()
|
||||
move_to_delay = Clamp(round((health/maxHealth) * 10), 5, 10)
|
||||
@@ -67,18 +74,21 @@ Difficulty: Hard
|
||||
return
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
|
||||
blood_warp()
|
||||
|
||||
if(prob(25))
|
||||
var/warped = FALSE
|
||||
if(!try_bloodattack())
|
||||
addtimer(src, "blood_spray", 0)
|
||||
warped = blood_warp()
|
||||
if(warped && prob(100 - anger_modifier))
|
||||
return
|
||||
|
||||
else if(prob(5+anger_modifier/2))
|
||||
slaughterlings()
|
||||
else
|
||||
if(health > maxHealth/2 && !client)
|
||||
if(prob(90 - anger_modifier) || slaughterlings())
|
||||
if(health > maxHealth * 0.5 || client)
|
||||
addtimer(src, "charge", 0)
|
||||
else
|
||||
addtimer(src, "triple_charge", 0)
|
||||
if(prob(70) || warped)
|
||||
addtimer(src, "triple_charge", 0)
|
||||
else
|
||||
addtimer(src, "warp_charge", 0)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/New()
|
||||
@@ -109,20 +119,22 @@ Difficulty: Hard
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
|
||||
if(!stat)
|
||||
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
|
||||
if(charging)
|
||||
PoolOrNew(/obj/effect/overlay/temp/decoy/fading, list(loc,src))
|
||||
DestroySurroundings()
|
||||
. = ..()
|
||||
if(!stat && .)
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
|
||||
if(charging)
|
||||
DestroySurroundings()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/warp_charge()
|
||||
blood_warp()
|
||||
charge()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/triple_charge()
|
||||
charge()
|
||||
sleep(10)
|
||||
charge()
|
||||
sleep(10)
|
||||
charge()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
|
||||
@@ -135,11 +147,11 @@ Difficulty: Hard
|
||||
walk(src, 0)
|
||||
setDir(get_dir(src, T))
|
||||
var/obj/effect/overlay/temp/decoy/D = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
|
||||
D.color = "#FF0000"
|
||||
animate(D, alpha = 0, color = initial(D.color), transform = matrix()*2, time = 5)
|
||||
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
|
||||
sleep(5)
|
||||
throw_at(T, get_dist(src, T), 1, src, 0)
|
||||
charging = 0
|
||||
try_bloodattack()
|
||||
Goto(target, move_to_delay, minimum_distance)
|
||||
|
||||
|
||||
@@ -167,17 +179,132 @@ Difficulty: Hard
|
||||
charging = 0
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_mobs_on_blood()
|
||||
var/list/targets = ListTargets()
|
||||
. = list()
|
||||
for(var/mob/living/L in targets)
|
||||
var/list/bloodpool = get_pools(get_turf(L), 0)
|
||||
if(bloodpool.len && !faction_check(L))
|
||||
. += L
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
|
||||
var/list/targets = get_mobs_on_blood()
|
||||
if(targets.len)
|
||||
addtimer(src, "bloodattack", 0, FALSE, targets)
|
||||
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodattack(list/targets)
|
||||
var/mob/living/target_one = pick_n_take(targets)
|
||||
var/turf/target_one_turf = get_turf(target_one)
|
||||
var/mob/living/target_two
|
||||
if(targets.len)
|
||||
target_two = pick_n_take(targets)
|
||||
var/turf/target_two_turf = get_turf(target_two)
|
||||
if(target_two.stat != CONSCIOUS || prob(10))
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, target_two_turf)
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, target_two_turf)
|
||||
bloodgrab(target_two_turf)
|
||||
else
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, target_two_turf)
|
||||
bloodsmack(target_two_turf)
|
||||
|
||||
var/list/pools = get_pools(get_turf(target_one), 0)
|
||||
if(pools.len)
|
||||
target_one_turf = get_turf(target_one)
|
||||
if(target_one.stat != CONSCIOUS || prob(10))
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftpaw, target_one_turf)
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftthumb, target_one_turf)
|
||||
bloodgrab(target_one_turf)
|
||||
else
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/leftsmack, target_one_turf)
|
||||
bloodsmack(target_one_turf)
|
||||
|
||||
if(!target_two && target_one)
|
||||
pools = get_pools(get_turf(target_one), 0)
|
||||
if(pools.len)
|
||||
target_one_turf = get_turf(target_one)
|
||||
if(target_one.stat != CONSCIOUS || prob(10))
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightpaw, target_one_turf)
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightthumb, target_one_turf)
|
||||
bloodgrab(target_one_turf)
|
||||
else
|
||||
PoolOrNew(/obj/effect/overlay/temp/bubblegum_hands/rightsmack, target_one_turf)
|
||||
bloodsmack(target_one_turf)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T)
|
||||
sleep(2.5)
|
||||
for(var/mob/living/L in T)
|
||||
if(!faction_check(L))
|
||||
L << "<span class='userdanger'>[src] rends you!</span>"
|
||||
playsound(T, attack_sound, 100, 1, -1)
|
||||
var/limb_to_hit = L.get_bodypart(pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg"))
|
||||
L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
|
||||
sleep(3)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T)
|
||||
sleep(6)
|
||||
for(var/mob/living/L in T)
|
||||
if(!faction_check(L))
|
||||
L << "<span class='userdanger'>[src] drags you through the blood!</span>"
|
||||
playsound(T, 'sound/magic/enter_blood.ogg', 100, 1, -1)
|
||||
var/turf/targetturf = get_step(src, dir)
|
||||
L.forceMove(targetturf)
|
||||
playsound(targetturf, 'sound/magic/exit_blood.ogg', 100, 1, -1)
|
||||
if(L.stat != CONSCIOUS)
|
||||
addtimer(src, "devour", 2, FALSE, L)
|
||||
sleep(1)
|
||||
|
||||
/obj/effect/overlay/temp/bubblegum_hands
|
||||
icon = 'icons/effects/bubblegum.dmi'
|
||||
duration = 9
|
||||
|
||||
/obj/effect/overlay/temp/bubblegum_hands/rightthumb
|
||||
icon_state = "rightthumbgrab"
|
||||
|
||||
/obj/effect/overlay/temp/bubblegum_hands/leftthumb
|
||||
icon_state = "leftthumbgrab"
|
||||
|
||||
/obj/effect/overlay/temp/bubblegum_hands/rightpaw
|
||||
icon_state = "rightpawgrab"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/bubblegum_hands/leftpaw
|
||||
icon_state = "leftpawgrab"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/overlay/temp/bubblegum_hands/rightsmack
|
||||
icon_state = "rightsmack"
|
||||
|
||||
/obj/effect/overlay/temp/bubblegum_hands/leftsmack
|
||||
icon_state = "leftsmack"
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp()
|
||||
if(Adjacent(target))
|
||||
return FALSE
|
||||
var/list/can_jaunt = get_pools(get_turf(src), 1)
|
||||
if(!can_jaunt.len)
|
||||
return FALSE
|
||||
|
||||
var/list/pools = get_pools(get_turf(target), 2)
|
||||
var/list/pools_to_remove = get_pools(get_turf(target), 1)
|
||||
pools -= pools_to_remove
|
||||
if(!pools.len)
|
||||
return FALSE
|
||||
|
||||
var/obj/effect/overlay/temp/decoy/DA = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
|
||||
DA.color = "#FF0000"
|
||||
var/oldtransform = DA.transform
|
||||
DA.transform = matrix()*2
|
||||
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 5)
|
||||
sleep(5)
|
||||
qdel(DA)
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/found_bloodpool
|
||||
var/list/pools = list()
|
||||
var/can_jaunt = FALSE
|
||||
for(var/obj/effect/decal/cleanable/blood/nearby in view(src,2))
|
||||
can_jaunt = TRUE
|
||||
break
|
||||
if(!can_jaunt)
|
||||
return
|
||||
for(var/obj/effect/decal/cleanable/blood/nearby in view(get_turf(target),2))
|
||||
pools += nearby
|
||||
pools = get_pools(get_turf(target), 2)
|
||||
pools_to_remove = get_pools(get_turf(target), 1)
|
||||
pools -= pools_to_remove
|
||||
if(pools.len)
|
||||
shuffle(pools)
|
||||
found_bloodpool = pick(pools)
|
||||
@@ -187,35 +314,56 @@ Difficulty: Hard
|
||||
forceMove(get_turf(found_bloodpool))
|
||||
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
|
||||
visible_message("<span class='danger'>And springs back out!</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
|
||||
. = list()
|
||||
for(var/obj/effect/decal/cleanable/blood/nearby in view(T, range))
|
||||
. += nearby
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray()
|
||||
visible_message("<span class='danger'>[src] sprays a stream of gore!</span>")
|
||||
var/turf/E = get_edge_target_turf(src, src.dir)
|
||||
var/range = 10
|
||||
var/range = 6 + round(anger_modifier * 0.4)
|
||||
var/turf/previousturf = get_turf(src)
|
||||
for(var/turf/J in getline(src,E))
|
||||
if(!range)
|
||||
var/turf/J = previousturf
|
||||
var/targetdir = get_dir(src, target)
|
||||
if(target.loc == loc)
|
||||
targetdir = dir
|
||||
face_atom(target)
|
||||
new /obj/effect/decal/cleanable/blood(J)
|
||||
for(var/i in 1 to range)
|
||||
J = get_step(previousturf, targetdir)
|
||||
PoolOrNew(/obj/effect/overlay/temp/dir_setting/bloodsplatter, list(previousturf, get_dir(previousturf, J)))
|
||||
playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
|
||||
if(!J || !previousturf.CanAtmosPass(J))
|
||||
break
|
||||
PoolOrNew(/obj/effect/overlay/temp/bloodsplatter, list(previousturf, get_dir(previousturf, J)))
|
||||
if(!previousturf.CanAtmosPass(J))
|
||||
break
|
||||
playsound(J,'sound/effects/splat.ogg', 100, 1, -1)
|
||||
new /obj/effect/decal/cleanable/blood(J)
|
||||
range--
|
||||
var/obj/effect/decal/cleanable/blood/B = new /obj/effect/decal/cleanable/blood(J)
|
||||
B.bloodiness = 0
|
||||
previousturf = J
|
||||
sleep(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/slaughterlings()
|
||||
visible_message("<span class='danger'>[src] summons a shoal of slaughterlings!</span>")
|
||||
for(var/obj/effect/decal/cleanable/blood/H in range(src, 10))
|
||||
if(prob(25))
|
||||
new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(H.loc)
|
||||
var/max_amount = 6
|
||||
for(var/H in get_pools(get_turf(src), 1))
|
||||
if(!max_amount)
|
||||
break
|
||||
max_amount--
|
||||
var/obj/effect/decal/cleanable/blood/B = H
|
||||
new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter(B.loc)
|
||||
return max_amount
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter
|
||||
name = "slaughterling"
|
||||
desc = "Though not yet strong enough to create a true physical form, it's nonetheless determined to murder you."
|
||||
faction = list("mining")
|
||||
density = 0
|
||||
faction = list("mining", "boss")
|
||||
weather_immunities = list("lava","ash")
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/slaughter/CanPass(atom/movable/mover, turf/target, height = 0)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
#undef MEDAL_PREFIX
|
||||
@@ -220,7 +220,8 @@ Difficulty: Very Hard
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/blast()
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 2)
|
||||
for(var/turf/turf in range(1, target))
|
||||
var/turf/T = get_turf(target)
|
||||
for(var/turf/turf in range(1, T))
|
||||
shoot_projectile(turf)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/proc/dir_shots(list/dirs)
|
||||
@@ -381,7 +382,7 @@ Difficulty: Very Hard
|
||||
var/activation_sound = 'sound/effects/break_stone.ogg'
|
||||
|
||||
/obj/machinery/anomalous_crystal/New()
|
||||
activation_method = pick("touch","laser","bullet","energy","magic","mob_bump","heat","weapon","speech")
|
||||
activation_method = pick("touch","laser","bullet","energy","bomb","mob_bump","heat","weapon","speech")
|
||||
..()
|
||||
|
||||
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
|
||||
@@ -423,8 +424,11 @@ Difficulty: Very Hard
|
||||
if(ismob(AM))
|
||||
ActivationReaction(AM,"mob_bump")
|
||||
|
||||
/obj/machinery/anomalous_crystal/ex_act()
|
||||
ActivationReaction(null,"bomb")
|
||||
|
||||
/obj/machinery/anomalous_crystal/random/New()//Just a random crysal spawner for loot
|
||||
var/random_crystal = pick(typesof(/obj/machinery/anomalous_crystal) - /obj/machinery/anomalous_crystal/random)
|
||||
var/random_crystal = pick(typesof(/obj/machinery/anomalous_crystal) - /obj/machinery/anomalous_crystal/random - /obj/machinery/anomalous_crystal)
|
||||
new random_crystal(loc)
|
||||
qdel(src)
|
||||
|
||||
@@ -472,13 +476,14 @@ Difficulty: Very Hard
|
||||
NewTerrainChairs = /obj/structure/chair/wood/normal
|
||||
NewTerrainTables = /obj/structure/table/glass
|
||||
NewFlora = list(/obj/structure/flora/grass/green, /obj/structure/flora/grass/brown, /obj/structure/flora/grass/both)
|
||||
if("jungle") //Beneficial due to actually having breathable air. Plus, monkeys.
|
||||
if("jungle") //Beneficial due to actually having breathable air. Plus, monkeys and bows and arrows.
|
||||
NewTerrainFloors = /turf/open/floor/grass
|
||||
NewTerrainWalls = /turf/closed/wall/mineral/sandstone
|
||||
NewTerrainChairs = /obj/structure/chair/wood
|
||||
NewTerrainTables = /obj/structure/table/wood
|
||||
NewFlora = list(/obj/structure/flora/ausbushes/sparsegrass, /obj/structure/flora/ausbushes/fernybush, /obj/structure/flora/ausbushes/leafybush,
|
||||
/obj/structure/flora/ausbushes/grassybush, /obj/structure/flora/ausbushes/sunnybush, /obj/structure/flora/tree/palm, /mob/living/carbon/monkey)
|
||||
/obj/structure/flora/ausbushes/grassybush, /obj/structure/flora/ausbushes/sunnybush, /obj/structure/flora/tree/palm, /mob/living/carbon/monkey,
|
||||
/obj/item/weapon/gun/projectile/bow, /obj/item/weapon/storage/backpack/quiver/full)
|
||||
florachance = 20
|
||||
if("ayy lmao") //Beneficial, turns stuff into alien alloy which is useful to cargo and research. Also repairs atmos.
|
||||
NewTerrainFloors = /turf/open/floor/plating/abductor
|
||||
@@ -523,8 +528,8 @@ Difficulty: Very Hard
|
||||
|
||||
/obj/machinery/anomalous_crystal/emitter/New()
|
||||
..()
|
||||
generated_projectile = pick(/obj/item/projectile/beam/emitter,/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
|
||||
/obj/item/projectile/energy/net, /obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray)
|
||||
generated_projectile = pick(/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
|
||||
/obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray, /obj/item/projectile/colossus)
|
||||
|
||||
/obj/machinery/anomalous_crystal/emitter/ActivationReaction(mob/user, method)
|
||||
if(..())
|
||||
@@ -545,17 +550,23 @@ Difficulty: Very Hard
|
||||
P.xo = 0
|
||||
P.fire()
|
||||
|
||||
/obj/machinery/anomalous_crystal/dark_reprise //Revives anyone nearby, but turns them into shadowpeople. Cannot revive shadowpeople, so this is a one time thing.
|
||||
/obj/machinery/anomalous_crystal/dark_reprise //Revives anyone nearby, but turns them into shadowpeople and renders them uncloneable, so the crystal is your only hope of getting up again if you go down.
|
||||
activation_method = "touch"
|
||||
activation_sound = 'sound/hallucinations/growl1.ogg'
|
||||
|
||||
/obj/machinery/anomalous_crystal/dark_reprise/ActivationReaction(mob/user, method)
|
||||
if(..())
|
||||
for(var/i in range(1, src))
|
||||
if(isturf(i))
|
||||
PoolOrNew(/obj/effect/overlay/temp/cult/sparks, i)
|
||||
continue
|
||||
if(ishuman(i))
|
||||
var/mob/living/carbon/human/H = i
|
||||
if(H.stat == DEAD && !isshadowperson(H))
|
||||
if(H.stat == DEAD)
|
||||
H.set_species(/datum/species/shadow, 1)
|
||||
H.revive(1,0)
|
||||
H.disabilities |= NOCLONE //Free revives, but significantly limits your options for reviving except via the crystal
|
||||
H.grab_ghost(force = TRUE)
|
||||
|
||||
/obj/machinery/anomalous_crystal/helpers //Lets ghost spawn as helpful creatures that can only heal people slightly. Incredibly fragile and they can't converse with humans
|
||||
activation_method = "touch"
|
||||
@@ -564,17 +575,23 @@ Difficulty: Very Hard
|
||||
/obj/machinery/anomalous_crystal/helpers/ActivationReaction(mob/user, method)
|
||||
if(..() && !ready_to_deploy)
|
||||
ready_to_deploy = 1
|
||||
notify_ghosts("An anomalous crystal has been activated in [get_area(src)]!", enter_link = "<a href=?src=\ref[src];ghostjoin=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK)
|
||||
notify_ghosts("An anomalous crystal has been activated in [get_area(src)]! This crystal can always be used by ghosts hereafter.", enter_link = "<a href=?src=\ref[src];ghostjoin=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK)
|
||||
|
||||
/obj/machinery/anomalous_crystal/helpers/attack_ghost(mob/dead/observer/user)
|
||||
..()
|
||||
if(ready_to_deploy)
|
||||
var/be_helper = alert("Become a Lightgeist? (Warning, You can no longer be cloned!)",,"Yes","No")
|
||||
if(!be_helper == "No")
|
||||
if(be_helper == "No")
|
||||
return
|
||||
var/mob/living/simple_animal/hostile/lightgeist/W = new /mob/living/simple_animal/hostile/lightgeist(get_turf(loc))
|
||||
W.key = user.key
|
||||
|
||||
/obj/machinery/anomalous_crystal/helpers/Topic(href, href_list)
|
||||
if(href_list["ghostjoin"])
|
||||
var/mob/dead/observer/ghost = usr
|
||||
if(istype(ghost))
|
||||
attack_ghost(ghost)
|
||||
|
||||
/mob/living/simple_animal/hostile/lightgeist
|
||||
name = "lightgeist"
|
||||
desc = "This small floating creature is a completely unknown form of life... being near it fills you with a sense of tranquility."
|
||||
@@ -603,19 +620,24 @@ Difficulty: Very Hard
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
luminosity = 4
|
||||
faction = list("neutral")
|
||||
languages_spoken = 0
|
||||
languages_spoken = SLIME
|
||||
languages_understood = ALL
|
||||
del_on_death = 1
|
||||
unsuitable_atmos_damage = 0
|
||||
flying = 1
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
environment_smash = 0
|
||||
AIStatus = AI_OFF
|
||||
stop_automated_movement = 1
|
||||
var/heal_power = 5
|
||||
|
||||
/mob/living/simple_animal/hostile/lightgeist/New()
|
||||
..()
|
||||
verbs -= /mob/living/verb/pulled
|
||||
verbs -= /mob/verb/me_verb
|
||||
var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
|
||||
medsensor.add_hud_to(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/lightgeist/AttackingTarget()
|
||||
..()
|
||||
@@ -625,29 +647,35 @@ Difficulty: Very Hard
|
||||
L.heal_overall_damage(heal_power, heal_power)
|
||||
PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(target), "#80F5FF"))
|
||||
|
||||
/mob/living/simple_animal/hostile/lightgeist/Life()
|
||||
if(!ckey)
|
||||
/mob/living/simple_animal/hostile/lightgeist/ghostize()
|
||||
if(..())
|
||||
death()
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/anomalous_crystal/refresher //Deletes and recreates a copy of the item, "refreshing" it. Only works once per item.
|
||||
/obj/machinery/anomalous_crystal/refresher //Deletes and recreates a copy of the item, "refreshing" it.
|
||||
activation_method = "touch"
|
||||
cooldown_add = 50
|
||||
activation_sound = 'sound/magic/TIMEPARADOX2.ogg'
|
||||
var/list/banned_items_typecache = list(/obj/item/weapon/storage, /obj/item/weapon/implant, /obj/item/weapon/implanter, /obj/item/weapon/disk/nuclear, /obj/item/projectile, /obj/item/weapon/spellbook)
|
||||
|
||||
/obj/machinery/anomalous_crystal/refresher/New()
|
||||
..()
|
||||
banned_items_typecache = typecacheof(banned_items_typecache)
|
||||
|
||||
|
||||
/obj/machinery/anomalous_crystal/refresher/ActivationReaction(mob/user, method)
|
||||
if(..())
|
||||
var/list/L
|
||||
var/list/L = list()
|
||||
var/turf/T = get_step(src, dir)
|
||||
PoolOrNew(/obj/effect/overlay/temp/emp/pulse,T)
|
||||
for(var/i in T)
|
||||
if(istype(i, /obj/item) && !istype(i, /obj/item/weapon/storage) && !(i in affected_targets) && !istype(i, /obj/item/weapon/implant) && !istype(i, /obj/item/weapon/implanter) && !istype(i, /obj/item/weapon/disk/nuclear))
|
||||
if(istype(i, /obj/item) && !is_type_in_typecache(i, banned_items_typecache))
|
||||
var/obj/item/W = i
|
||||
if(!W.admin_spawned)
|
||||
L += W
|
||||
var/obj/item/CHOSEN = pick(L)
|
||||
if(CHOSEN)
|
||||
var/A = new CHOSEN.type(T)
|
||||
affected_targets += A
|
||||
if(L.len)
|
||||
var/obj/item/CHOSEN = pick(L)
|
||||
new CHOSEN.type(T)
|
||||
qdel(CHOSEN)
|
||||
|
||||
/obj/machinery/anomalous_crystal/possessor //Allows you to bodyjack small animals, then exit them at your leisure, but you can only do this once per activation. Because they blow up. Also, if the bodyjacked animal dies, SO DO YOU.
|
||||
@@ -665,7 +693,7 @@ Difficulty: Very Hard
|
||||
mobcheck = 1
|
||||
break
|
||||
if(!mobcheck)
|
||||
new /mob/living/simple_animal/cockroach(loc) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it
|
||||
new /mob/living/simple_animal/cockroach(get_step(src,dir)) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it
|
||||
|
||||
/obj/structure/closet/stasis
|
||||
name = "quantum entanglement stasis warp field"
|
||||
@@ -673,17 +701,15 @@ Difficulty: Very Hard
|
||||
icon_state = null //This shouldn't even be visible, so if it DOES show up, at least nobody will notice
|
||||
density = 1
|
||||
anchored = 1
|
||||
health = 0
|
||||
health = 999
|
||||
var/mob/living/simple_animal/holder_animal
|
||||
|
||||
/obj/structure/closet/stasis/process()
|
||||
if(!isanimal(loc))
|
||||
dump_contents(1)
|
||||
return
|
||||
if(holder_animal)
|
||||
if(holder_animal.stat == DEAD)
|
||||
dump_contents(1)
|
||||
if(holder_animal.stat == DEAD && !qdeleted(holder_animal))
|
||||
dump_contents()
|
||||
holder_animal.gib()
|
||||
return
|
||||
|
||||
/obj/structure/closet/stasis/New()
|
||||
..()
|
||||
@@ -702,14 +728,15 @@ Difficulty: Very Hard
|
||||
holder_animal.mind.AddSpell(P)
|
||||
holder_animal.verbs -= /mob/living/verb/pulled
|
||||
|
||||
/obj/structure/closet/stasis/dump_contents(var/kill = 0)
|
||||
/obj/structure/closet/stasis/dump_contents(var/kill = 1)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
for(var/mob/living/L in src)
|
||||
L.disabilities &= ~MUTE
|
||||
L.status_flags &= ~GODMODE
|
||||
L.notransform = 0
|
||||
holder_animal.mind.transfer_to(L)
|
||||
L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
|
||||
if(holder_animal && !qdeleted(holder_animal))
|
||||
holder_animal.mind.transfer_to(L)
|
||||
L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
|
||||
if(kill || !isanimal(loc))
|
||||
L.death(0)
|
||||
..()
|
||||
@@ -717,6 +744,9 @@ Difficulty: Very Hard
|
||||
/obj/structure/closet/stasis/emp_act()
|
||||
return
|
||||
|
||||
/obj/structure/closet/stasis/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/exit_possession
|
||||
name = "Exit Possession"
|
||||
desc = "Exits the body you are possessing"
|
||||
@@ -737,7 +767,7 @@ Difficulty: Very Hard
|
||||
for(var/i in user)
|
||||
if(istype(i, /obj/structure/closet/stasis))
|
||||
var/obj/structure/closet/stasis/S = i
|
||||
S.dump_contents()
|
||||
S.dump_contents(0)
|
||||
qdel(S)
|
||||
break
|
||||
user.gib()
|
||||
|
||||
@@ -166,6 +166,7 @@ Difficulty: Medium
|
||||
addtimer(src, "fire_wall", 0, FALSE, d)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/proc/fire_wall(dir)
|
||||
var/list/hit_things = list(src)
|
||||
var/turf/E = get_edge_target_turf(src, dir)
|
||||
var/range = 10
|
||||
var/turf/previousturf = get_turf(src)
|
||||
@@ -175,10 +176,10 @@ Difficulty: Medium
|
||||
range--
|
||||
PoolOrNew(/obj/effect/hotspot,J)
|
||||
J.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/L in J)
|
||||
if(L != src)
|
||||
L.adjustFireLoss(20)
|
||||
L << "<span class='userdanger'>You're hit by the drake's fire breath!</span>"
|
||||
for(var/mob/living/L in J.contents - hit_things)
|
||||
L.adjustFireLoss(20)
|
||||
L << "<span class='userdanger'>You're hit by the drake's fire breath!</span>"
|
||||
hit_things += L
|
||||
previousturf = J
|
||||
sleep(1)
|
||||
|
||||
@@ -257,6 +258,7 @@ Difficulty: Medium
|
||||
name = "lesser ash drake"
|
||||
maxHealth = 300
|
||||
health = 300
|
||||
faction = list("neutral")
|
||||
melee_damage_upper = 30
|
||||
melee_damage_lower = 30
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
|
||||
|
||||
@@ -87,7 +87,7 @@ Difficulty: Hard
|
||||
did_reset = TRUE
|
||||
//visible_message("<span class='hierophant'>\"Vixyvrmrk xs fewi...\"</span>")
|
||||
blink(spawned_rune)
|
||||
adjustHealth(max((health - maxHealth) * 0.5, 25)) //heal for 50% of our missing health
|
||||
adjustHealth(min((health - maxHealth) * 0.5, -50)) //heal for 50% of our missing health
|
||||
wander = FALSE
|
||||
/*if(health > maxHealth * 0.9)
|
||||
visible_message("<span class='hierophant'>\"Vitemvw gsqtpixi. Stivexmrk ex qebmqyq ijjmgmirgc.\"</span>")
|
||||
@@ -279,6 +279,8 @@ Difficulty: Hard
|
||||
|
||||
/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)
|
||||
@@ -289,6 +291,8 @@ Difficulty: Hard
|
||||
|
||||
/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)
|
||||
@@ -299,6 +303,8 @@ Difficulty: Hard
|
||||
|
||||
/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)
|
||||
@@ -396,6 +402,7 @@ Difficulty: Hard
|
||||
/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
|
||||
@@ -415,7 +422,7 @@ Difficulty: Hard
|
||||
addtimer(src, "seek_target", 1)
|
||||
|
||||
/obj/effect/overlay/temp/hierophant/chaser/proc/get_target_dir()
|
||||
. = get_cardinal_dir(src, target)
|
||||
. = 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
|
||||
@@ -424,12 +431,13 @@ Difficulty: Hard
|
||||
/obj/effect/overlay/temp/hierophant/chaser/proc/seek_target()
|
||||
if(!currently_seeking)
|
||||
currently_seeking = TRUE
|
||||
while(target && src && !qdeleted(src) && currently_seeking && x && y && target.x && target.y) //can this target actually be sook out
|
||||
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, target)
|
||||
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
|
||||
@@ -446,6 +454,7 @@ Difficulty: Hard
|
||||
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))
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
weather_immunities = list("lava","ash")
|
||||
flying = 1
|
||||
robust_searching = 1
|
||||
ranged_ignores_vision = TRUE
|
||||
stat_attack = 2
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)
|
||||
|
||||
@@ -833,7 +833,7 @@
|
||||
desc = "[src] has become inert, it crackles no more and is useless for \
|
||||
healing injuries."
|
||||
|
||||
/obj/item/organ/hivelord_core/legion/preserved()
|
||||
/obj/item/organ/hivelord_core/legion/preserved(implanted = 0)
|
||||
..()
|
||||
desc = "[src] has been stabilized. It no longer crackles with power, but it's healing properties are preserved indefinitely."
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
loot = list(/obj/effect/decal/remains/human,
|
||||
/obj/item/clothing/suit/armor/riot/knight/templar,
|
||||
/obj/item/clothing/head/helmet/knight/templar,
|
||||
/obj/item/weapon/claymore/hog{name = "holy sword"})
|
||||
/obj/item/weapon/claymore/weak{name = "holy sword"})
|
||||
|
||||
/mob/living/simple_animal/hostile/skeleton/ice
|
||||
name = "ice skeleton"
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
anchors += locate(x+2,y-2,z)
|
||||
|
||||
for(var/turf/T in anchors)
|
||||
var/datum/beam/B = Beam(T,"vine",'icons/effects/spacevines.dmi',INFINITY, 5,/obj/effect/ebeam/vine)
|
||||
var/datum/beam/B = Beam(T, "vine", time=INFINITY, maxdistance=5, beam_type=/obj/effect/ebeam/vine)
|
||||
B.sleep_time = 10 //these shouldn't move, so let's slow down updates to 1 second (any slower and the deletion of the vines would be too slow)
|
||||
addtimer(src, "bear_fruit", growth_time)
|
||||
|
||||
@@ -98,15 +98,15 @@
|
||||
if(A.density && A != L)
|
||||
continue grasping
|
||||
if(prob(grasp_chance))
|
||||
L << "<span class='userdanger'>\the [src] has you entangled!</span>"
|
||||
grasping[L] = Beam(L,"vine",'icons/effects/spacevines.dmi',INFINITY, 5,/obj/effect/ebeam/vine)
|
||||
L << "<span class='userdanger'>\The [src] has you entangled!</span>"
|
||||
grasping[L] = Beam(L, "vine", time=INFINITY, maxdistance=5, beam_type=/obj/effect/ebeam/vine)
|
||||
|
||||
break //only take 1 new victim per cycle
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/venus_human_trap/OpenFire(atom/the_target)
|
||||
var/dist = get_dist(src,the_target)
|
||||
Beam(the_target,"vine",'icons/effects/spacevines.dmi',dist*2, dist+2,/obj/effect/ebeam/vine)
|
||||
Beam(the_target, "vine", time=dist*2, maxdistance=dist+2, beam_type=/obj/effect/ebeam/vine)
|
||||
the_target.attack_animal(src)
|
||||
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
if(istype(M, /mob/living/simple_animal/hostile/construct/builder))
|
||||
if(health < maxHealth)
|
||||
adjustHealth(-25)
|
||||
Beam(M,icon_state="sendbeam",icon='icons/effects/effects.dmi',time=4)
|
||||
Beam(M,icon_state="sendbeam",time=4)
|
||||
M.visible_message("<span class='danger'>[M] heals \the <b>[src]</b>.</span>", \
|
||||
"<span class='cult'>You heal <b>[src]</b>, leaving <b>[src]</b> at <b>[health]/[maxHealth]</b> health.</span>")
|
||||
else
|
||||
|
||||
@@ -104,10 +104,14 @@
|
||||
/mob/living/simple_animal/Life()
|
||||
if(..()) //alive
|
||||
if(!ckey)
|
||||
handle_automated_movement()
|
||||
handle_automated_action()
|
||||
handle_automated_speech()
|
||||
return 1
|
||||
if(stat != DEAD)
|
||||
handle_automated_movement()
|
||||
if(stat != DEAD)
|
||||
handle_automated_action()
|
||||
if(stat != DEAD)
|
||||
handle_automated_speech()
|
||||
if(stat != DEAD)
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/updatehealth()
|
||||
..()
|
||||
@@ -301,7 +305,11 @@
|
||||
if(del_on_death)
|
||||
ghostize()
|
||||
stat = DEAD
|
||||
//Prevent infinite loops if the mob Destroy() is overriden in such
|
||||
//a manner as to cause a call to death() again
|
||||
del_on_death = FALSE
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
health = 0
|
||||
icon_state = icon_dead
|
||||
|
||||
@@ -499,8 +499,8 @@ var/next_mob_id = 0
|
||||
return
|
||||
|
||||
var/mob/mob_eye = creatures[eye_name]
|
||||
|
||||
if(client && mob_eye)
|
||||
//Istype so we filter out points of interest that are not mobs
|
||||
if(client && mob_eye && istype(mob_eye))
|
||||
client.eye = mob_eye
|
||||
if(isobserver(src))
|
||||
src.client.screen = list()
|
||||
|
||||
@@ -465,3 +465,15 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
M << "There were no ghosts willing to take control."
|
||||
message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
|
||||
return FALSE
|
||||
|
||||
//toggles the talk wheel
|
||||
/mob/verb/toggle_talk_wheel()
|
||||
set name = "talk-wheel"
|
||||
set hidden = 1
|
||||
|
||||
if(isliving(src))
|
||||
var/mob/living/L = src
|
||||
if(L.hud_used)
|
||||
for(var/obj/screen/wheel/talk/TW in L.hud_used.wheels)
|
||||
TW.Click()
|
||||
|
||||
|
||||
@@ -236,14 +236,12 @@
|
||||
L.loc = locate(locx,locy,mobloc.z)
|
||||
var/limit = 2//For only two trailing shadows.
|
||||
for(var/turf/T in getline(mobloc, L.loc))
|
||||
spawn(0)
|
||||
anim(T,L,'icons/mob/mob.dmi',,"shadow",,L.dir)
|
||||
PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/shadow, list(T, L.dir))
|
||||
limit--
|
||||
if(limit<=0)
|
||||
break
|
||||
else
|
||||
spawn(0)
|
||||
anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,L.dir)
|
||||
PoolOrNew(/obj/effect/overlay/temp/dir_setting/ninja/shadow, list(mobloc, L.dir))
|
||||
L.loc = get_step(L, direct)
|
||||
L.setDir(direct)
|
||||
if(3) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
|
||||
@@ -303,6 +301,9 @@
|
||||
break
|
||||
. = dense_object_backup
|
||||
|
||||
/mob/proc/mob_has_gravity()
|
||||
return has_gravity()
|
||||
|
||||
/mob/proc/mob_negates_gravity()
|
||||
return 0
|
||||
|
||||
|
||||
@@ -332,6 +332,9 @@
|
||||
data_core.manifest_inject(humanc)
|
||||
AnnounceArrival(humanc, rank)
|
||||
AddEmploymentContract(humanc)
|
||||
if(highlander)
|
||||
humanc << "<span class='userdanger'><i>THERE CAN BE ONLY ONE!!!</i></span>"
|
||||
humanc.make_scottish()
|
||||
|
||||
joined_player_list += character.ckey
|
||||
|
||||
|
||||
@@ -41,14 +41,9 @@
|
||||
cut_overlays()
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
var/atom/movable/overlay/animation = new( loc )
|
||||
animation.icon_state = "blank"
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.master = src
|
||||
flick("h2monkey", animation)
|
||||
PoolOrNew(/obj/effect/overlay/temp/monkeyify, get_turf(src))
|
||||
sleep(22)
|
||||
var/mob/living/carbon/monkey/O = new /mob/living/carbon/monkey( loc )
|
||||
qdel(animation)
|
||||
|
||||
// hash the original name?
|
||||
if(tr_flags & TR_HASHNAME)
|
||||
@@ -188,16 +183,11 @@
|
||||
icon = null
|
||||
cut_overlays()
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
var/atom/movable/overlay/animation = new( loc )
|
||||
animation.icon_state = "blank"
|
||||
animation.icon = 'icons/mob/mob.dmi'
|
||||
animation.master = src
|
||||
flick("monkey2h", animation)
|
||||
PoolOrNew(/obj/effect/overlay/temp/monkeyify/humanify, get_turf(src))
|
||||
sleep(22)
|
||||
var/mob/living/carbon/human/O = new( loc )
|
||||
for(var/obj/item/C in O.loc)
|
||||
O.equip_to_appropriate_slot(C)
|
||||
qdel(animation)
|
||||
|
||||
dna.transfer_identity(O)
|
||||
O.updateappearance(mutcolor_update=1)
|
||||
@@ -496,23 +486,6 @@
|
||||
qdel(src)
|
||||
|
||||
|
||||
/mob/proc/become_god(var/side_colour)
|
||||
var/mob/camera/god/G = new /mob/camera/god(loc)
|
||||
G.side = side_colour
|
||||
if(mind)
|
||||
mind.transfer_to(G)
|
||||
else
|
||||
G.key = key
|
||||
|
||||
G.job = "Deity"
|
||||
G.rename_self("deity")
|
||||
G.update_icons()
|
||||
|
||||
. = G
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/corgize()
|
||||
if (notransform)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user