Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into cultthings

# Conflicts:
#	paradise.dme
This commit is contained in:
Mark van Alphen
2019-06-09 23:28:41 +02:00
795 changed files with 101167 additions and 8028 deletions
+29 -19
View File
@@ -1,23 +1,33 @@
/mob/dead/Login()
. = ..()
var/turf/T = get_turf(src)
if (isturf(T))
update_z(T.z)
/mob/dead/Logout()
update_z(null)
return ..()
/mob/dead/forceMove(atom/destination)
// Overriden from code/game/atoms_movable.dm#141 to prevent things like mice squeaking when ghosts walk on them.
// Same as parent, except that it does not include Uncrossed or Crossed calls.
var/turf/old_loc = loc
var/turf/old_turf = get_turf(src)
var/turf/new_turf = get_turf(destination)
if (old_turf?.z != new_turf?.z)
onTransitZ(old_turf?.z, new_turf?.z)
var/oldloc = loc
loc = destination
Moved(oldloc, NONE, TRUE)
if(old_loc)
old_loc.Exited(src, destination)
/mob/dead/onTransitZ(old_z,new_z)
..()
update_z(new_z)
if(destination)
destination.Entered(src)
if(isturf(destination) && opacity)
var/turf/new_loc = destination
new_loc.reconsider_lights()
if(isturf(old_loc) && opacity)
old_loc.reconsider_lights()
for(var/datum/light_source/L in light_sources)
L.source_atom.update_light()
return 1
/mob/dead/proc/update_z(new_z) // 1+ to register, null to unregister
if (registered_z != new_z)
if (registered_z)
SSmobs.dead_players_by_zlevel[registered_z] -= src
if (client)
if (new_z)
SSmobs.dead_players_by_zlevel[new_z] += src
registered_z = new_z
else
registered_z = null
+34 -29
View File
@@ -10,23 +10,23 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
icon = 'icons/mob/mob.dmi'
icon_state = "ghost"
layer = 4
layer = GHOST_LAYER
stat = DEAD
density = 0
canmove = 0
density = FALSE
canmove = FALSE
alpha = 127
move_resist = INFINITY // don't get pushed around
invisibility = INVISIBILITY_OBSERVER
var/can_reenter_corpse
var/bootime = 0
var/bootime = FALSE
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
//If you died in the game and are a ghsot - this will remain as null.
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
universal_speak = 1
universal_speak = TRUE
var/atom/movable/following = null
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
var/ghostvision = 1 //is the ghost able to see things humans can't?
var/seedarkness = 1
var/ghostvision = TRUE //is the ghost able to see things humans can't?
var/seedarkness = TRUE
var/data_hud_seen = FALSE //this should one of the defines in __DEFINES/hud.dm
var/ghost_orbit = GHOST_ORBIT_CIRCLE
@@ -95,6 +95,11 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
updateallghostimages()
return ..()
/mob/dead/observer/examine(mob/user)
..()
if(!invisibility)
to_chat(user, "It seems extremely obvious.")
// This seems stupid, but it's the easiest way to avoid absolutely ridiculous shit from happening
// Copying an appearance directly from a mob includes it's verb list, it's invisibility, it's alpha, and it's density
// You might recognize these things as "fucking ridiculous to put in an appearance"
@@ -226,31 +231,31 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
P.despawn_occupant()
return
// Ghosts have no momentum, being massless ectoplasm
/mob/dead/observer/Process_Spacemove(movement_dir)
return 1
/mob/dead/observer/Move(NewLoc, direct)
following = null
dir = direct
ghostimage.dir = dir
setDir(direct)
ghostimage.setDir(dir)
var/oldloc = loc
if(NewLoc)
forceMove(NewLoc)
return
forceMove(get_turf(src)) //Get out of closets and such as a ghost
if((direct & NORTH) && y < world.maxy)
y++
else if((direct & SOUTH) && y > 1)
y--
if((direct & EAST) && x < world.maxx)
x++
else if((direct & WEST) && x > 1)
x--
else
forceMove(get_turf(src)) //Get out of closets and such as a ghost
if((direct & NORTH) && y < world.maxy)
y++
else if((direct & SOUTH) && y > 1)
y--
if((direct & EAST) && x < world.maxx)
x++
else if((direct & WEST) && x > 1)
x--
for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb
S.Crossed(src)
var/area/A = get_area(src)
if(A)
A.Entered(src)
..()
Moved(oldloc, direct)
/mob/dead/observer/can_use_hands() return 0
@@ -399,7 +404,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/area/A = input("Area to jump to", "BOOYEA") as null|anything in ghostteleportlocs
var/area/thearea = ghostteleportlocs[A]
if(!thearea)
return
@@ -720,7 +725,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/updateghostimages()
if(!client)
return
if(!ghostvision)
if(seedarkness || !ghostvision)
client.images -= ghost_images
else
//add images for the 60inv things ghosts can normally see when darkness is enabled so they can see them now
+5 -28
View File
@@ -1,6 +1,4 @@
var/global/list/boo_phrases=list(
GLOBAL_LIST_INIT(boo_phrases, list(
"You feel a chill run down your spine.",
"You think you see a figure in your peripheral vision.",
"What was that?",
@@ -9,16 +7,17 @@ var/global/list/boo_phrases=list(
"Something doesn't feel right...",
"You feel a presence in the room.",
"It feels like someone's standing behind you.",
)
))
/obj/effect/proc_holder/spell/aoe_turf/boo
name = "Boo!"
desc = "Fuck with the living."
ghost = 1
ghost = TRUE
school = "transmutation"
charge_max = 600
starts_charged = FALSE
clothes_req = 0
stat_allowed = 1
invocation = ""
@@ -27,26 +26,4 @@ var/global/list/boo_phrases=list(
/obj/effect/proc_holder/spell/aoe_turf/boo/cast(list/targets, mob/user = usr)
for(var/turf/T in targets)
for(var/atom/A in T.contents)
// Bug humans
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H && H.client)
to_chat(H, "<i>[pick(boo_phrases)]</i>")
// Flicker unblessed lights in range
if(istype(A,/obj/machinery/light))
var/obj/machinery/light/L = A
if(L)
L.flicker()
// OH GOD BLUE APC (single animation cycle)
if(istype(A, /obj/machinery/power/apc))
A:spookify()
if(istype(A, /obj/machinery/status_display))
A:spookymode=1
if(istype(A, /obj/machinery/ai_status_display))
A:spookymode=1
T.get_spooked()
+4
View File
@@ -245,6 +245,10 @@
/mob/proc/get_item_by_slot(slot_id)
switch(slot_id)
if(slot_wear_mask)
return wear_mask
if(slot_back)
return back
if(slot_l_hand)
return l_hand
if(slot_r_hand)
@@ -277,6 +277,7 @@ Des: Removes all infected images from the alien.
grant_death_vision()
return
see_invisible = initial(see_invisible)
sight = SEE_MOBS
if(nightvision)
see_in_dark = 8
@@ -6,7 +6,7 @@ As such, they can either help or harm other aliens. Help works like the human he
In all, this is a lot like the monkey code. /N
*/
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
if(!ticker)
if(!SSticker)
to_chat(M, "You cannot attack people before the game has started.")
return
@@ -85,13 +85,8 @@ Doesn't work on other aliens/AI.*/
return
// TURF CHECK
else if(istype(O, /turf/simulated))
var/turf/T = O
// R WALL
if(istype(T, /turf/simulated/wall/r_wall))
to_chat(src, "<span class='noticealien'>You cannot dissolve this object.</span>")
return
// R FLOOR
if(istype(T, /turf/simulated/floor/engine))
var/turf/simulated/T = O
if(T.unacidable)
to_chat(src, "<span class='noticealien'>You cannot dissolve this object.</span>")
return
else// Not a type we can acid.
@@ -7,8 +7,8 @@
if(stat != CONSCIOUS)
return
if(layer != TURF_LAYER+0.2)
layer = TURF_LAYER+0.2
if(layer != ABOVE_NORMAL_TURF_LAYER)
layer = ABOVE_NORMAL_TURF_LAYER
visible_message("<B>[src] scurries to the ground!</B>", "<span class='noticealien'>You are now hiding.</span>")
else
layer = MOB_LAYER
@@ -93,8 +93,8 @@
spawn(6)
var/mob/living/carbon/alien/larva/new_xeno = new(owner.drop_location())
new_xeno.key = C.key
if(ticker && ticker.mode)
ticker.mode.xenos += new_xeno.mind
if(SSticker && SSticker.mode)
SSticker.mode.xenos += new_xeno.mind
new_xeno.mind.name = new_xeno.name
new_xeno.mind.assigned_role = SPECIAL_ROLE_XENOMORPH
new_xeno.mind.special_role = SPECIAL_ROLE_XENOMORPH
+2 -2
View File
@@ -44,7 +44,7 @@
visible_message("<span class='notice'>[user] sticks \a [O] into \the [src].</span>")
brainmob = B.brainmob
B.brainmob = null
brainmob.loc = src
brainmob.forceMove(src)
brainmob.container = src
brainmob.stat = CONSCIOUS
GLOB.respawnable_list -= brainmob
@@ -152,7 +152,7 @@
held_brain.name = "\the [brainmob.name]'s [initial(held_brain.name)]"
brainmob.container = null//Reset brainmob mmi var.
brainmob.loc = held_brain//Throw mob into brain.
brainmob.forceMove(held_brain) //Throw mob into brain.
GLOB.respawnable_list += brainmob
GLOB.living_mob_list -= brainmob//Get outta here
held_brain.brainmob = brainmob//Set the brain to use the brainmob
@@ -67,10 +67,10 @@
/mob/living/carbon/brain/on_forcemove(atom/newloc)
if(container)
container.loc = newloc
container.forceMove(newloc)
else //something went very wrong.
CRASH("Brainmob without container.")
loc = container
forceMove(container)
/*
This will return true if the brain has a container that leaves it less helpless than a naked brain
+15 -12
View File
@@ -72,7 +72,7 @@
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
A.loc = loc
A.forceMove(drop_location())
stomach_contents.Remove(A)
src.gib()
@@ -712,17 +712,18 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
return back
if(slot_wear_mask)
return wear_mask
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
if(slot_wear_suit)
return wear_suit
if(slot_l_hand)
return l_hand
if(slot_r_hand)
return r_hand
if(slot_handcuffed)
return handcuffed
if(slot_legcuffed)
return legcuffed
return null
//generates realistic-ish pulse output based on preset levels
/mob/living/carbon/proc/get_pulse(var/method) //method 0 is for hands, 1 is for machines, more accurate
var/temp = 0 //see setup.dm:694
@@ -833,7 +834,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
to_chat(src, "<span class='notice'>You successfully remove [I].</span>")
if(I == handcuffed)
handcuffed.loc = loc
handcuffed.forceMove(drop_location())
handcuffed.dropped(src)
handcuffed = null
if(buckled && buckled.buckle_requires_restraints)
@@ -841,7 +842,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
update_handcuffed()
return
if(I == legcuffed)
legcuffed.loc = loc
legcuffed.forceMove(drop_location())
legcuffed.dropped()
legcuffed = null
update_inv_legcuffed()
@@ -935,7 +936,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
if(client)
client.screen -= W
if(W)
W.loc = loc
W.forceMove(drop_location())
W.dropped(src)
if(W)
W.layer = initial(W.layer)
@@ -947,7 +948,7 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
if(client)
client.screen -= W
if(W)
W.loc = loc
W.forceMove(drop_location())
W.dropped(src)
if(W)
W.layer = initial(W.layer)
@@ -1139,9 +1140,11 @@ so that different stomachs can handle things in different ways VB*/
grant_death_vision()
return
see_invisible = initial(see_invisible)
see_in_dark = initial(see_in_dark)
sight = initial(sight)
lighting_alpha = initial(lighting_alpha)
for(var/obj/item/organ/internal/cyberimp/eyes/E in internal_organs)
sight |= E.vision_flags
if(E.see_in_dark)
@@ -1160,6 +1163,6 @@ so that different stomachs can handle things in different ways VB*/
sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -14,11 +14,10 @@
return TRUE
..()
/mob/living/carbon/water_act(volume, temperature, source)
/mob/living/carbon/water_act(volume, temperature, source, method = TOUCH)
. = ..()
if(volume > 10) //anything over 10 volume will make the mob wetter.
wetlevel = min(wetlevel + 1,5)
..()
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
if(lying && surgeries.len)
@@ -112,7 +112,7 @@
if(H.mind)
H.mind.kills += "[key_name(src)]"
if(ticker && ticker.mode)
if(SSticker && SSticker.mode)
// log_world("k")
sql_report_death(src)
@@ -206,9 +206,13 @@
if("hiss", "hisses")
var/M = handle_emote_param(param)
message = "<B>[src]</B> hisses[M ? " at [M]" : ""]."
playsound(loc, 'sound/effects/unathihiss.ogg', 50, 0) //Credit to Jamius (freesound.org) for the sound.
m_type = 2
if(!muzzled)
message = "<B>[src]</B> hisses[M ? " at [M]" : ""]."
playsound(loc, 'sound/effects/unathihiss.ogg', 50, 0) //Credit to Jamius (freesound.org) for the sound.
m_type = 2
else
message = "<B>[src]</B> makes a weak hissing noise."
m_type = 2
if("quill", "quills")
var/M = handle_emote_param(param)
@@ -1711,8 +1711,8 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
/mob/living/carbon/human/IsAdvancedToolUser()
if(dna.species.has_fine_manipulation)
return 1
return 0
return TRUE
return FALSE
/mob/living/carbon/human/get_permeability_protection()
var/list/prot = list("hands"=0, "chest"=0, "groin"=0, "legs"=0, "feet"=0, "arms"=0, "head"=0)
@@ -1977,7 +1977,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
if(7) // Pride
log_game("[src] was influenced by the sin of pride.")
O = new /datum/objective/sintouched/pride
ticker.mode.sintouched += src.mind
SSticker.mode.sintouched += src.mind
src.mind.objectives += O
var/obj_count = 1
to_chat(src, "<span class='notice> Your current objectives:")
@@ -2003,6 +2003,9 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
genemutcheck(src, block, null, MUTCHK_FORCED)
dna.UpdateSE()
/mob/living/carbon/human/get_spooked()
to_chat(src, "<span class='whisper'>[pick(GLOB.boo_phrases)]</span>")
/mob/living/carbon/human/extinguish_light()
// Parent function handles stuff the human may be holding
..()
@@ -362,7 +362,7 @@ This function restores all organs.
if(LAssailant && ishuman(LAssailant)) //superheros still get the comical hit markers
var/mob/living/carbon/human/H = LAssailant
if(H.mind && H.mind in (ticker.mode.superheroes || ticker.mode.supervillains || ticker.mode.greyshirts))
if(H.mind && H.mind in (SSticker.mode.superheroes || SSticker.mode.supervillains || SSticker.mode.greyshirts))
var/list/attack_bubble_recipients = list()
var/mob/living/user
for(var/mob/O in viewers(user, src))
@@ -267,7 +267,7 @@ emp_act
apply_effect(5, WEAKEN, armor)
AdjustConfused(15)
if(prob(I.force + ((100 - health)/2)) && src != user && I.damtype == BRUTE)
ticker.mode.remove_revolutionary(mind)
SSticker.mode.remove_revolutionary(mind)
if(bloody)//Apply blood
if(wear_mask)
@@ -506,9 +506,9 @@ emp_act
return 0
..()
/mob/living/carbon/human/water_act(volume, temperature, source)
..()
dna.species.water_act(src,volume,temperature,source)
/mob/living/carbon/human/water_act(volume, temperature, source, method = TOUCH)
. = ..()
dna.species.water_act(src, volume, temperature, source, method)
/mob/living/carbon/human/is_eyes_covered(check_glasses = TRUE, check_head = TRUE, check_mask = TRUE)
if(check_glasses && glasses && (glasses.flags_cover & GLASSESCOVERSEYES))
+71 -123
View File
@@ -44,9 +44,9 @@
return has_organ("chest")
if(slot_wear_id)
// the only relevant check for this is the uniform check
return 1
return TRUE
if(slot_wear_pda)
return 1
return TRUE
if(slot_l_ear)
return has_organ("head")
if(slot_r_ear)
@@ -70,9 +70,9 @@
if(slot_s_store)
return has_organ("chest")
if(slot_in_backpack)
return 1
return TRUE
if(slot_tie)
return 1
return TRUE
// The actual dropping happens at the mob level - checks to prevent drops should
// come here
@@ -187,82 +187,85 @@
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
//set redraw_mob to 0 if you don't wish the hud to be updated - if you're doing it manually in your own proc.
/mob/living/carbon/human/equip_to_slot(obj/item/W as obj, slot, redraw_mob = 1)
if(!slot) return
if(!istype(W)) return
if(!has_organ_for_slot(slot)) return
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot, redraw_mob = 1)
if(!slot)
return
if(!istype(I))
return
if(!has_organ_for_slot(slot))
return
if(W == src.l_hand)
if(I == src.l_hand)
src.l_hand = null
update_inv_l_hand() //So items actually disappear from hands.
else if(W == src.r_hand)
else if(I == src.r_hand)
src.r_hand = null
update_inv_r_hand()
W.screen_loc = null
W.loc = src
W.equipped(src, slot)
W.layer = ABOVE_HUD_LAYER
W.plane = ABOVE_HUD_PLANE
I.screen_loc = null
I.forceMove(src)
I.equipped(src, slot)
I.layer = ABOVE_HUD_LAYER
I.plane = ABOVE_HUD_PLANE
switch(slot)
if(slot_back)
back = W
back = I
update_inv_back(redraw_mob)
if(slot_wear_mask)
wear_mask = W
wear_mask = I
if((wear_mask.flags & BLOCKHAIR) || (wear_mask.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_fhair(redraw_mob)
update_head_accessory(redraw_mob)
if(hud_list.len)
sec_hud_set_ID()
wear_mask_update(W, toggle_off = TRUE)
wear_mask_update(I, toggle_off = TRUE)
update_inv_wear_mask(redraw_mob)
if(slot_handcuffed)
handcuffed = W
handcuffed = I
update_inv_handcuffed(redraw_mob)
if(slot_legcuffed)
legcuffed = W
legcuffed = I
update_inv_legcuffed(redraw_mob)
if(slot_l_hand)
l_hand = W
l_hand = I
update_inv_l_hand(redraw_mob)
if(slot_r_hand)
r_hand = W
r_hand = I
update_inv_r_hand(redraw_mob)
if(slot_belt)
belt = W
belt = I
update_inv_belt(redraw_mob)
if(slot_wear_id)
wear_id = W
wear_id = I
if(hud_list.len)
sec_hud_set_ID()
update_inv_wear_id(redraw_mob)
if(slot_wear_pda)
wear_pda = W
wear_pda = I
update_inv_wear_pda(redraw_mob)
if(slot_l_ear)
l_ear = W
l_ear = I
if(l_ear.slot_flags & SLOT_TWOEARS)
var/obj/item/clothing/ears/offear/O = new(W)
O.loc = src
var/obj/item/clothing/ears/offear/O = new(I)
O.forceMove(src)
r_ear = O
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
update_inv_ears(redraw_mob)
if(slot_r_ear)
r_ear = W
r_ear = I
if(r_ear.slot_flags & SLOT_TWOEARS)
var/obj/item/clothing/ears/offear/O = new(W)
O.loc = src
var/obj/item/clothing/ears/offear/O = new(I)
O.forceMove(src)
l_ear = O
O.layer = ABOVE_HUD_LAYER
O.plane = ABOVE_HUD_PLANE
update_inv_ears(redraw_mob)
if(slot_glasses)
glasses = W
var/obj/item/clothing/glasses/G = W
glasses = I
var/obj/item/clothing/glasses/G = I
if(G.tint)
update_tint()
if(G.prescription)
@@ -272,49 +275,48 @@
update_inv_glasses(redraw_mob)
update_client_colour()
if(slot_gloves)
gloves = W
gloves = I
update_inv_gloves(redraw_mob)
if(slot_head)
head = W
head = I
if((head.flags & BLOCKHAIR) || (head.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_fhair(redraw_mob)
update_head_accessory(redraw_mob)
// paper + bandanas
if(istype(W, /obj/item/clothing/head))
var/obj/item/clothing/head/hat = W
if(istype(I, /obj/item/clothing/head))
var/obj/item/clothing/head/hat = I
if(hat.vision_flags || hat.see_in_dark || !isnull(hat.lighting_alpha))
update_sight()
head_update(W)
head_update(I)
update_inv_head(redraw_mob)
if(slot_shoes)
shoes = W
shoes = I
update_inv_shoes(redraw_mob)
if(slot_wear_suit)
wear_suit = W
wear_suit = I
update_inv_wear_suit(redraw_mob)
if(slot_w_uniform)
w_uniform = W
w_uniform = I
update_inv_w_uniform(redraw_mob)
if(slot_l_store)
l_store = W
l_store = I
update_inv_pockets(redraw_mob)
if(slot_r_store)
r_store = W
r_store = I
update_inv_pockets(redraw_mob)
if(slot_s_store)
s_store = W
s_store = I
update_inv_s_store(redraw_mob)
if(slot_in_backpack)
if(get_active_hand() == W)
unEquip(W)
W.loc = back
if(get_active_hand() == I)
unEquip(I)
I.forceMove(back)
if(slot_tie)
var/obj/item/clothing/under/uniform = src.w_uniform
uniform.attackby(W,src)
uniform.attackby(I, src)
else
to_chat(src, "<span class='warning'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>")
return
/mob/living/carbon/human/put_in_hands(obj/item/W)
if(!W) return 0
@@ -419,56 +421,34 @@
/mob/living/carbon/human/can_equip(obj/item/I, slot, disable_warning = 0)
switch(dna.species.handle_can_equip(I, slot, disable_warning, src))
if(1) return 1
if(2) return 0 //if it returns 2, it wants no normal handling
if(1) return TRUE
if(2) return FALSE //if it returns 2, it wants no normal handling
if(!has_organ_for_slot(slot))
return FALSE
if(istype(I, /obj/item/clothing/under) || istype(I, /obj/item/clothing/suit))
if(FAT in mutations)
//testing("[M] TOO FAT TO WEAR [src]!")
if(!(I.flags_size & ONESIZEFITSALL))
if(!disable_warning)
to_chat(src, "<span class='alert'>You're too fat to wear the [I].</span>")
return 0
return FALSE
switch(slot)
if(slot_l_hand)
if(l_hand)
return 0
return !incapacitated()
return !l_hand && !incapacitated()
if(slot_r_hand)
if(r_hand)
return 0
return !incapacitated()
return !r_hand && !incapacitated()
if(slot_wear_mask)
if(wear_mask)
return 0
if(!(I.slot_flags & SLOT_MASK))
return 0
return 1
return !wear_mask && (I.slot_flags & SLOT_MASK)
if(slot_back)
if(back)
return 0
if(!(I.slot_flags & SLOT_BACK))
return 0
return 1
return !back && (I.slot_flags & SLOT_BACK)
if(slot_wear_suit)
if(wear_suit)
return 0
if(!(I.slot_flags & SLOT_OCLOTHING))
return 0
return 1
return !wear_suit && (I.slot_flags & SLOT_OCLOTHING)
if(slot_gloves)
if(gloves)
return 0
if(!(I.slot_flags & SLOT_GLOVES))
return 0
return 1
return !gloves && (I.slot_flags & SLOT_GLOVES)
if(slot_shoes)
if(shoes)
return 0
if(!(I.slot_flags & SLOT_FEET))
return 0
return 1
return !shoes && (I.slot_flags & SLOT_FEET)
if(slot_belt)
if(belt)
return 0
@@ -480,39 +460,15 @@
return
return 1
if(slot_glasses)
if(glasses)
return 0
if(!(I.slot_flags & SLOT_EYES))
return 0
return 1
return !glasses && (I.slot_flags & SLOT_EYES)
if(slot_head)
if(head)
return 0
if(!(I.slot_flags & SLOT_HEAD))
return 0
return 1
return !head && (I.slot_flags & SLOT_HEAD)
if(slot_l_ear)
if(l_ear)
return 0
if(!(I.slot_flags & SLOT_EARS))
return 0
if((I.slot_flags & SLOT_TWOEARS) && r_ear )
return 0
return 1
return !l_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && r_ear)
if(slot_r_ear)
if(r_ear)
return 0
if(!(I.slot_flags & SLOT_EARS))
return 0
if((I.slot_flags & SLOT_TWOEARS) && l_ear)
return 0
return 1
return !r_ear && (I.slot_flags & SLOT_EARS) && !((I.slot_flags & SLOT_TWOEARS) && l_ear)
if(slot_w_uniform)
if(w_uniform)
return 0
if(!(I.slot_flags & SLOT_ICLOTHING))
return 0
return 1
return !w_uniform && (I.slot_flags & SLOT_ICLOTHING)
if(slot_wear_id)
if(wear_id)
return 0
@@ -581,17 +537,9 @@
return 1
return 0
if(slot_handcuffed)
if(handcuffed)
return 0
if(!istype(I, /obj/item/restraints/handcuffs))
return 0
return 1
return !handcuffed && istype(I, /obj/item/restraints/handcuffs)
if(slot_legcuffed)
if(legcuffed)
return 0
if(!istype(I, /obj/item/restraints/legcuffs))
return 0
return 1
return !legcuffed && istype(I, /obj/item/restraints/legcuffs)
if(slot_in_backpack)
if(back && istype(back, /obj/item/storage/backpack))
var/obj/item/storage/backpack/B = back
@@ -331,11 +331,11 @@
/datum/species/proc/harm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
//Vampire code
if(user.mind && user.mind.vampire && (user.mind in ticker.mode.vampires) && !user.mind.vampire.draining && user.zone_sel && user.zone_sel.selecting == "head" && target != user)
if(user.mind && user.mind.vampire && (user.mind in SSticker.mode.vampires) && !user.mind.vampire.draining && user.zone_sel && user.zone_sel.selecting == "head" && target != user)
if((NO_BLOOD in target.dna.species.species_traits) || target.dna.species.exotic_blood || !target.blood_volume)
to_chat(user, "<span class='warning'>They have no blood!</span>")
return
if(target.mind && target.mind.vampire && (target.mind in ticker.mode.vampires))
if(target.mind && target.mind.vampire && (target.mind in SSticker.mode.vampires))
to_chat(user, "<span class='warning'>Your fangs fail to pierce [target.name]'s cold flesh</span>")
return
if(SKELETON in target.mutations)
@@ -718,7 +718,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u
H.sync_lighting_plane_alpha()
/datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source)
/datum/species/proc/water_act(mob/living/carbon/human/M, volume, temperature, source, method = TOUCH)
if(abs(temperature - M.bodytemperature) > 10) //If our water and mob temperature varies by more than 10K, cool or/ heat them appropriately
M.bodytemperature = (temperature + M.bodytemperature) * 0.5 //Approximation for gradual heating or cooling
@@ -607,7 +607,6 @@
..()
last_banana = world.time
last_honk = world.time
H.job = "Clown"
H.mutations.Add(COMIC)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store)
@@ -682,7 +681,6 @@
/datum/species/golem/tranquillite/on_species_gain(mob/living/carbon/human/H)
..()
H.job = "Mime"
H.equip_to_slot_or_del(new /obj/item/clothing/head/beret(H), slot_head)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofnothing(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/cane(H), slot_l_hand)
@@ -36,10 +36,38 @@
genemutcheck(H, REMOTETALKBLOCK, null, MUTCHK_FORCED)
H.dna.default_blocks.Add(REMOTETALKBLOCK)
/datum/species/grey/water_act(mob/living/carbon/human/H, volume, temperature, source)
..()
H.take_organ_damage(5, min(volume, 20))
H.emote("scream")
/datum/species/grey/water_act(mob/living/carbon/human/H, volume, temperature, source, method = TOUCH)
. = ..()
if(method == TOUCH)
if(volume > 25)
if(H.wear_mask)
to_chat(H, "<span class='danger'>Your [H.wear_mask] protects you from the acid!</span>")
return
if(H.head)
to_chat(H, "<span class='danger'>Your [H.wear_mask] protects you from the acid!</span>")
return
if(prob(75))
H.take_organ_damage(5, 10)
H.emote("scream")
var/obj/item/organ/external/affecting = H.get_organ("head")
if(affecting)
affecting.disfigure()
else
H.take_organ_damage(5, 10)
else
H.take_organ_damage(5, 10)
else
to_chat(H, "<span class='warning'>The water stings[volume < 10 ? " you, but isn't concentrated enough to harm you" : null]!</span>")
if(volume >= 10)
H.adjustFireLoss(min(max(4, (volume - 10) * 2), 20))
H.emote("scream")
to_chat(H, "<span class='warning'>The water stings[volume < 10 ? " you, but isn't concentrated enough to harm you" : null]!</span>")
if(volume >= 10)
H.adjustFireLoss(min(max(4, (volume - 10) * 2), 20))
H.emote("scream")
/datum/species/grey/after_equip_job(datum/job/J, mob/living/carbon/human/H)
var/translator_pref = H.client.prefs.speciesprefs
@@ -59,6 +59,8 @@
genemutcheck(H, MONKEYBLOCK, null, MUTCHK_FORCED)
/datum/species/monkey/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user)
if(!user.has_organ_for_slot(slot))
return 2
switch(slot)
if(slot_l_hand)
if(user.l_hand)
@@ -130,8 +130,8 @@
suit=/obj/item/clothing/suit/space/eva/plasmaman/cargo
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/cargo
if("Shaft Miner")
suit=/obj/item/clothing/suit/space/eva/plasmaman/miner
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/miner
suit=/obj/item/clothing/suit/space/eva/plasmaman/explorer
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/explorer
if("Botanist")
suit=/obj/item/clothing/suit/space/eva/plasmaman/botanist
helm=/obj/item/clothing/head/helmet/space/eva/plasmaman/botanist
@@ -102,7 +102,18 @@
to_chat(user, "<span class='warning'>You run out of momentum!</span>")
return
/datum/species/unathi/handle_death(mob/living/carbon/human/H)
H.stop_tail_wagging(1)
/datum/species/unathi/ashwalker
name = "Ash Walker"
name_plural = "Ash Walkers"
blurb = "These reptillian creatures appear to be related to the Unathi, but seem significantly less evolved. \
They roam the wastes of Lavaland, worshipping a dead city and capturing unsuspecting miners."
language = "Sinta'unathi"
default_language = "Sinta'unathi"
slowdown = -0.80
species_traits = list(NO_BREATHE, NOGUNS)
@@ -597,7 +597,7 @@ var/global/list/damage_icon_parts = list()
client.screen -= thing // WHAT THE FUCKING FUCK BAY GODDAMNIT
// **I FUCKING HATE YOU AAAAAAAAAA**
if(thing) //
thing.loc = loc //
thing.forceMove(drop_location()) //
thing.dropped(src) //
thing.layer = initial(thing.layer)
thing.plane = initial(thing.plane)
@@ -1223,7 +1223,7 @@ var/global/list/damage_icon_parts = list()
//Adds a collar overlay above the helmet layer if the suit has one
// Suit needs an identically named sprite in icons/mob/collar.dmi
// For suits with species_fit and sprite_sheets, an identically named sprite needs to exist in a file like this icons/mob/species/[species_name_here]/collar.dmi.
// For suits with sprite_sheets, an identically named sprite needs to exist in a file like this icons/mob/species/[species_name_here]/collar.dmi.
/mob/living/carbon/human/proc/update_collar(var/update_icons=1)
remove_overlay(COLLAR_LAYER)
var/icon/C = new('icons/mob/collar.dmi')
@@ -47,7 +47,7 @@
/mob/living/carbon/slime/proc/Feedon(var/mob/living/M)
Victim = M
src.loc = M.loc
forceMove(M.loc)
canmove = 0
anchored = 1
var/lastnut = nutrition
@@ -64,7 +64,7 @@
canmove = 0
if(Adjacent(Victim))
loc = M.loc
forceMove(M.loc)
if(iscarbon(Victim))
Victim.adjustCloneLoss(rand(5,6))
@@ -163,7 +163,7 @@
/mob/living/carbon/slime/proc/UpdateFeed(var/mob/M)
if(Victim)
if(Victim == M)
loc = M.loc // simple "attach to head" effect!
forceMove(M.loc) // simple "attach to head" effect!
/mob/living/carbon/slime/verb/Evolve()
@@ -50,11 +50,11 @@
if(class == "Superhero")
W.assignment = "Superhero"
W.rank = "Superhero"
ticker.mode.superheroes += H.mind
SSticker.mode.superheroes += H.mind
else if(class == "Supervillain")
W.assignment = "Supervillain"
W.rank = "Supervillain"
ticker.mode.supervillains += H.mind
SSticker.mode.supervillains += H.mind
W.icon_state = "lifetimeid"
W.SetOwnerInfo(H)
W.UpdateName()
@@ -157,7 +157,7 @@
/obj/effect/proc_holder/spell/targeted/recruit/cast(list/targets,mob/living/user = usr)
for(var/mob/living/carbon/human/target in targets)
var/obj/item/organ/external/head/head_organ = target.get_organ("head")
if(ticker.mode.greyshirts.len >= 3)
if(SSticker.mode.greyshirts.len >= 3)
to_chat(user, "<span class='warning'>You have already recruited the maximum number of henchmen.</span>")
if(!in_range(user, target))
to_chat(user, "<span class='warning'>You need to be closer to enthrall [target].</span>")
@@ -218,7 +218,7 @@
to_chat(target, "<span class='deadsay'><b>You have decided to enroll as a henchman for [user]. You are now part of the feared 'Greyshirts'.</b></span>")
to_chat(target, "<span class='deadsay'><b>You must follow the orders of [user], and help [user.p_them()] succeed in [user.p_their()] dastardly schemes.</span>")
to_chat(target, "<span class='deadsay'>You may not harm other Greyshirt or [user]. However, you do not need to obey other Greyshirts.</span>")
ticker.mode.greyshirts += target.mind
SSticker.mode.greyshirts += target.mind
target.set_species(/datum/species/human)
head_organ.h_style = "Bald"
head_organ.f_style = "Shaved"
+2 -2
View File
@@ -88,8 +88,8 @@
mind.store_memory("Time of death: [station_time_timestamp("hh:mm:ss", timeofdeath)]", 0)
GLOB.respawnable_list += src
if(ticker && ticker.mode)
ticker.mode.check_win()
if(SSticker && SSticker.mode)
SSticker.mode.check_win()
if(mind && mind.devilinfo) // Expand this into a general-purpose death-response system when appropriate
mind.devilinfo.beginResurrectionCheck(src)
+2 -2
View File
@@ -3,9 +3,9 @@
set background = BACKGROUND_ENABLED
if(notransform)
return 0
return FALSE
if(!loc)
return 0
return FALSE
var/datum/gas_mixture/environment = loc.return_air()
if(client || registered_z) // This is a temporary error tracker to make sure we've caught everything
+2 -13
View File
@@ -519,7 +519,6 @@
var/turf/T = loc
. = ..()
if(.)
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED)
handle_footstep(loc)
step_count++
@@ -691,7 +690,7 @@
return name
/mob/living/update_gravity(has_gravity)
if(!ticker)
if(!SSticker)
return
if(has_gravity)
clear_alert("weightless")
@@ -972,7 +971,7 @@
/mob/living/onTransitZ(old_z,new_z)
..()
update_z(new_z)
update_z(new_z)
/mob/living/proc/owns_soul()
if(mind)
@@ -1039,13 +1038,3 @@
update_transform()
if("lighting_alpha")
sync_lighting_plane_alpha()
/mob/living/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
. = ..()
+4 -8
View File
@@ -216,13 +216,9 @@
fire_stacks += L.fire_stacks
IgniteMob()
//Mobs on Fire end
/mob/living/water_act(volume, temperature)
if(volume >= 20) fire_stacks -= 0.5
if(volume >= 50) fire_stacks -= 1
/mob/living/water_act(volume, temperature, source, method = TOUCH)
. = ..()
adjust_fire_stacks(-(volume * 0.2))
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
@@ -279,7 +275,7 @@
return G
/mob/living/attack_slime(mob/living/carbon/slime/M)
if(!ticker)
if(!SSticker)
to_chat(M, "You cannot attack people before the game has started.")
return
@@ -67,3 +67,5 @@
var/list/status_effects //a list of all status effects the mob has
var/deathgasp_on_death = FALSE
var/stun_absorption = null //converted to a list of stun absorption sources this mob has when one is added
+8
View File
@@ -18,6 +18,14 @@
if(ranged_ability)
ranged_ability.add_ranged_ability(src, "<span class='notice'>You currently have <b>[ranged_ability]</b> active!</span>")
//for when action buttons are lost and need to be regained, such as when the mind enters a new mob
var/datum/changeling/changeling = usr.mind.changeling
if(changeling)
for(var/power in changeling.purchasedpowers)
var/datum/action/changeling/S = power
if(istype(S) && S.needs_button)
S.Grant(src)
//Should update regardless of if we can ventcrawl, since we can end up in pipes in other ways.
update_pipe_vision()
+1 -1
View File
@@ -1303,8 +1303,8 @@ var/list/ai_verbs_default = list(
see_invisible = initial(see_invisible)
see_in_dark = initial(see_in_dark)
lighting_alpha = initial(lighting_alpha)
sight = initial(sight)
lighting_alpha = initial(lighting_alpha)
if(aiRestorePowerRoutine)
sight = sight &~ SEE_TURFS
@@ -1,5 +1,5 @@
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!ticker)
if(!SSticker)
to_chat(M, "You cannot attack people before the game has started.")
return
..()
@@ -101,7 +101,7 @@ var/datum/cameranet/cameranet = new()
/datum/cameranet/proc/updateVisibility(atom/A, opacity_check = 1)
if(!ticker || (opacity_check && !A.opacity))
if(!SSticker || (opacity_check && !A.opacity))
return
majorChunkChange(A, 2)
@@ -184,7 +184,7 @@ var/datum/cameranet/cameranet = new()
/*
/datum/cameranet/proc/stat_entry()
if(!statclick)
statclick = new/obj/effect/statclick/debug("Initializing...", src)
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
stat(name, statclick.update("Cameras: [cameranet.cameras.len] | Chunks: [cameranet.chunks.len]"))
*/
@@ -33,8 +33,8 @@ var/global/list/empty_playable_ai_cores = list()
mind.objectives.Cut()
mind.special_role = null
else
if(ticker.mode.name == "AutoTraitor")
var/datum/game_mode/traitor/autotraitor/current_mode = ticker.mode
if(SSticker.mode.name == "AutoTraitor")
var/datum/game_mode/traitor/autotraitor/current_mode = SSticker.mode
current_mode.possible_traitors.Remove(src)
// Ghost the current player and disallow them to return to the body
+10 -10
View File
@@ -1,12 +1,12 @@
/mob/living/silicon/Login()
SetSleeping(0)
if(mind && ticker && ticker.mode)
ticker.mode.remove_revolutionary(mind, 1)
ticker.mode.remove_cultist(mind, 1)
ticker.mode.remove_wizard(mind)
ticker.mode.remove_changeling(mind)
ticker.mode.remove_vampire(mind)
ticker.mode.remove_thrall(mind, 0)
ticker.mode.remove_shadowling(mind)
ticker.mode.remove_abductor(mind)
..()
if(mind && SSticker && SSticker.mode)
SSticker.mode.remove_revolutionary(mind, 1)
SSticker.mode.remove_cultist(mind, 1)
SSticker.mode.remove_wizard(mind)
SSticker.mode.remove_changeling(mind)
SSticker.mode.remove_vampire(mind)
SSticker.mode.remove_thrall(mind, 0)
SSticker.mode.remove_shadowling(mind)
SSticker.mode.remove_abductor(mind)
..()
@@ -50,8 +50,8 @@ var/datum/paiController/paiController // Global handler for pAI candidates
card.setPersonality(pai)
card.looking_for_personality = 0
ticker.mode.update_cult_icons_removed(card.pai.mind)
ticker.mode.update_rev_icons_removed(card.pai.mind)
SSticker.mode.update_cult_icons_removed(card.pai.mind)
SSticker.mode.update_rev_icons_removed(card.pai.mind)
pai_candidates -= candidate
usr << browse(null, "window=findPai")
@@ -619,12 +619,14 @@
/datum/pai_software/flashlight/toggle(mob/living/silicon/pai/user)
var/atom/movable/actual_location = istype(user.loc, /obj/item/paicard) ? user.loc : user
if(user.flashlight_on)
if(!user.flashlight_on)
actual_location.set_light(2)
user.card.set_light(2)
return
actual_location.set_light(2)
user.card.set_light(0)
else
actual_location.set_light(0)
user.card.set_light(0)
user.flashlight_on = !user.flashlight_on
/datum/pai_software/flashlight/is_active(mob/living/silicon/pai/user)
return user.flashlight_on
@@ -182,7 +182,7 @@
to_chat(user, "<span class='warning'>You swipe the sequencer across [src]'s interface and watch its eyes flicker.</span>")
if(jobban_isbanned(src, ROLE_SYNDICATE))
ticker.mode.replace_jobbanned_player(src, ROLE_SYNDICATE)
SSticker.mode.replace_jobbanned_player(src, ROLE_SYNDICATE)
to_chat(src, "<span class='warning'>You feel a sudden burst of malware loaded into your execute-as-root buffer. Your tiny brain methodically parses, loads and executes the script. You sense you have five minutes before the drone server detects this and automatically shuts you down.</span>")
@@ -27,7 +27,7 @@
/obj/machinery/drone_fabricator/process()
if(ticker.current_state < GAME_STATE_PLAYING)
if(SSticker.current_state < GAME_STATE_PLAYING)
return
if(stat & NOPOWER || !produce_drones)
@@ -98,7 +98,7 @@
to_chat(usr, "<span class='warning'>You are banned from playing drones and cannot spawn as a drone.</span>")
return
if(!ticker || ticker.current_state < 3)
if(!SSticker || SSticker.current_state < 3)
to_chat(src, "<span class='warning'>You can't join as a drone before the game starts!</span>")
return
+29 -4
View File
@@ -289,7 +289,7 @@ var/list/robot_verbs_default = list(
if(islist(force_modules) && force_modules.len)
modules = force_modules.Copy()
if(security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis)
to_chat(src, "<span class='warning'>Crisis mode active. Combat module available.</span>")
to_chat(src, "<span class='warning'>Crisis mode active. The combat module is now available.</span>")
modules += "Combat"
if(mmi != null && mmi.alien)
modules = list("Hunter")
@@ -417,6 +417,31 @@ var/list/robot_verbs_default = list(
radio.config(module.channels)
notify_ai(2)
/mob/living/silicon/robot/proc/reset_module()
notify_ai(2)
uneq_all()
sight_mode = null
hands.icon_state = "nomod"
icon_state = "robot"
module.remove_subsystems_and_actions(src)
QDEL_NULL(module)
camera.network.Remove(list("Engineering", "Medical", "Mining Outpost"))
rename_character(real_name, get_default_name("Default"))
languages = list()
speech_synthesizer_langs = list()
update_icons()
update_headlamp()
speed = 0 // Remove upgrades.
ionpulse = FALSE
magpulse = FALSE
add_language("Robot Talk", 1)
status_flags |= CANPUSH
//for borg hotkeys, here module refers to borg inv slot, not core module
/mob/living/silicon/robot/verb/cmd_toggle_module(module as num)
set name = "Toggle Module"
@@ -1351,9 +1376,9 @@ var/list/robot_verbs_default = list(
mind.special_role = SPECIAL_ROLE_ERT
if(cyborg_unlock)
crisis = 1
if(!(mind in ticker.minds))
ticker.minds += mind
ticker.mode.ert += mind
if(!(mind in SSticker.minds))
SSticker.minds += mind
SSticker.mode.ert += mind
/mob/living/silicon/robot/ert/gamma
crisis = 1
+1 -1
View File
@@ -98,7 +98,7 @@
return 0
/mob/living/silicon/IsAdvancedToolUser()
return 1
return TRUE
/mob/living/silicon/bullet_act(var/obj/item/projectile/Proj)
@@ -594,7 +594,7 @@ var/robot_arm = /obj/item/robot_parts/l_arm
qdel(src)
/obj/item/honkbot_arm_assembly
name = "incomplete honkbot assembly."
name = "incomplete honkbot assembly"
desc = "A clown box with a robot arm permanently grafted to it."
icon = 'icons/obj/aibots.dmi'
icon_state = "honkbot_arm"
@@ -625,8 +625,8 @@ var/robot_arm = /obj/item/robot_parts/l_arm
if(istype(W, /obj/item/instrument/trombone))
if(!user.unEquip(W))
return
to_chat(user, "<span class='notice'>You add the trombone to [src]! Heeeenk! </span>")
to_chat(user, "<span class='notice'>You add the trombone to [src]! Heeeenk!</span>")
qdel(W)
var/mob/living/simple_animal/bot/honkbot/A = new /mob/living/simple_animal/bot/honkbot(T)
var/mob/living/simple_animal/bot/honkbot/A = new /mob/living/simple_animal/bot/honkbot(get_turf(src))
A.robot_arm = robot_arm
qdel(src)
@@ -37,7 +37,7 @@
. = ..()
update_icon()
auto_patrol = TRUE
var/datum/job/clown/J = new/datum/job/clown
var/datum/job/clown/J = new /datum/job/clown()
access_card.access += J.get_access()
prev_access = access_card.access
@@ -29,21 +29,21 @@
/mob/living/simple_animal/hostile/construct/New()
..()
if(!ticker.mode)//work around for maps with runes and cultdat is not loaded all the way
if(!SSticker.mode)//work around for maps with runes and cultdat is not loaded all the way
name = "[const_type] ([rand(1, 1000)])"
real_name = const_type
icon_living = const_type
icon_state = const_type
else
name = "[ticker.cultdat.get_name(const_type)] ([rand(1, 1000)])"
real_name = ticker.cultdat.get_name(const_type)
icon_living = ticker.cultdat.get_icon(const_type)
icon_state = ticker.cultdat.get_icon(const_type)
name = "[SSticker.cultdat.get_name(const_type)] ([rand(1, 1000)])"
real_name = SSticker.cultdat.get_name(const_type)
icon_living = SSticker.cultdat.get_icon(const_type)
icon_state = SSticker.cultdat.get_icon(const_type)
for(var/spell in construct_spells)
AddSpell(new spell(null))
if(ticker.cultdat.theme == "blood")
if(SSticker.cultdat.theme == "blood")
updateglow()
/mob/living/simple_animal/hostile/construct/examine(mob/user)
@@ -112,4 +112,4 @@
uniform = /obj/item/clothing/under/color/lightpurple
suit = /obj/item/clothing/suit/wizrobe
shoes = /obj/item/clothing/shoes/sandal
head = /obj/item/clothing/head/wizard
head = /obj/item/clothing/head/wizard
@@ -16,8 +16,8 @@
turns_per_move = 5
see_in_dark = 6
mob_size = MOB_SIZE_SMALL
simplespecies = /mob/living/simple_animal/pet/cat
childtype = /mob/living/simple_animal/pet/cat/kitten
animal_species = /mob/living/simple_animal/pet/cat
childtype = list(/mob/living/simple_animal/pet/cat/kitten)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 3)
response_help = "pets"
response_disarm = "gently pushes aside"
@@ -48,9 +48,9 @@
..()
/mob/living/simple_animal/pet/cat/Runtime/Life(seconds, times_fired)
if(!cats_deployed && ticker.current_state >= GAME_STATE_SETTING_UP)
if(!cats_deployed && SSticker.current_state >= GAME_STATE_SETTING_UP)
Deploy_The_Cats()
if(!stat && ticker.current_state == GAME_STATE_FINISHED && !memory_saved)
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
Write_Memory()
..()
@@ -117,13 +117,17 @@
//MICE!
if(eats_mice && isturf(loc) && !incapacitated())
for(var/mob/living/simple_animal/mouse/M in view(1,src))
for(var/mob/living/simple_animal/mouse/M in view(1, src))
if(!M.stat && Adjacent(M))
custom_emote(1, "splats \the [M]!")
M.splat()
movement_target = null
stop_automated_movement = 0
break
for(var/obj/item/toy/cattoy/T in view(1, src))
if(T.cooldown < (world.time - 400))
custom_emote(1, "bats \the [T] around with its paw!")
T.cooldown = world.time
make_babies()
/mob/living/simple_animal/pet/cat/handle_automated_movement()
@@ -18,11 +18,11 @@
ventcrawler = 2
gold_core_spawnable = 2
var/squish_chance = 50
loot = list(/obj/effect/decal/cleanable/deadcockroach)
loot = list(/obj/effect/decal/cleanable/insectguts)
del_on_death = 1
/mob/living/simple_animal/cockroach/can_die()
return ..() && !ticker.cinematic //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
return ..() && !SSticker.cinematic //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
/mob/living/simple_animal/cockroach/Crossed(var/atom/movable/AM)
if(isliving(AM))
@@ -40,10 +40,3 @@
/mob/living/simple_animal/cockroach/ex_act() //Explosions are a terrible way to handle a cockroach.
return
/obj/effect/decal/cleanable/deadcockroach
name = "cockroach guts"
desc = "One bug squashed. Four more will rise in its place."
icon = 'icons/effects/blood.dmi'
icon_state = "xfloor1"
random_icon_states = list("xfloor1", "xfloor2", "xfloor3", "xfloor4", "xfloor5", "xfloor6", "xfloor7")
anchored = 1
@@ -22,8 +22,8 @@
response_disarm = "bops"
response_harm = "kicks"
see_in_dark = 5
childtype = /mob/living/simple_animal/pet/corgi/puppy
simplespecies = /mob/living/simple_animal/pet/corgi
childtype = list(/mob/living/simple_animal/pet/corgi)
animal_species = /mob/living/simple_animal/pet/corgi
gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY
var/shaved = 0
var/obj/item/inventory_head
@@ -25,9 +25,18 @@
melee_damage_lower = 1
melee_damage_upper = 2
stop_automated_movement_when_pulled = 1
var/milk_content = 0
can_collar = 1
blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/udder/udder = null
/mob/living/simple_animal/hostile/retaliate/goat/New()
udder = new()
. = ..()
/mob/living/simple_animal/hostile/retaliate/goat/Destroy()
qdel(udder)
udder = null
return ..()
/mob/living/simple_animal/hostile/retaliate/goat/handle_automated_movement()
..()
@@ -51,9 +60,8 @@
/mob/living/simple_animal/hostile/retaliate/goat/Life(seconds, times_fired)
. = ..()
if(stat == CONSCIOUS && prob(5))
milk_content = min(50, milk_content+rand(5, 10))
if(stat == CONSCIOUS)
udder.generateMilk()
/mob/living/simple_animal/hostile/retaliate/goat/Retaliate()
..()
@@ -64,6 +72,12 @@
if(!stat)
eat_plants()
/mob/living/simple_animal/hostile/retaliate/goat/attackby(var/obj/item/O as obj, var/mob/user as mob, params)
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
udder.milkAnimal(O, user)
else
return ..()
/mob/living/simple_animal/hostile/retaliate/goat/proc/eat_plants()
var/eaten = FALSE
var/obj/structure/spacevine/SV = locate(/obj/structure/spacevine) in loc
@@ -79,23 +93,6 @@
if(eaten && prob(10))
say("Nom")
/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/I, mob/user, params)
if(stat == CONSCIOUS && istype(I, /obj/item/reagent_containers/glass))
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/reagent_containers/glass/G = I
var/transfered = min(milk_content, rand(5,10), (G.volume - G.reagents.total_volume))
if(transfered > 0)
user.visible_message("<span class='notice'>[user] milks [src] using [G].</span>")
G.reagents.add_reagent("milk", transfered)
milk_content -= transfered
else if(G.reagents.total_volume >= G.volume)
to_chat(user, "<span class='warning'>[G] is full.</span>")
else
to_chat(user, "<span class='warning'>The udder is dry. Wait a bit longer...</span>")
return TRUE
else
return ..()
/mob/living/simple_animal/hostile/retaliate/goat/AttackingTarget()
..()
if(isdiona(target))
@@ -127,34 +124,31 @@
attack_sound = 'sound/weapons/punch1.ogg'
health = 50
maxHealth = 50
var/milk_content = 0
can_collar = 1
gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY
blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/udder/udder = null
/mob/living/simple_animal/cow/New()
..()
/mob/living/simple_animal/cow/Initialize()
udder = new()
. = ..()
/mob/living/simple_animal/cow/attackby(var/obj/item/O as obj, var/mob/user as mob, params, params)
/mob/living/simple_animal/cow/Destroy()
qdel(udder)
udder = null
return ..()
/mob/living/simple_animal/cow/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/reagent_containers/glass/G = O
var/transfered = min(milk_content, rand(5,10), (G.volume - G.reagents.total_volume))
if(transfered > 0)
user.visible_message("<span class='notice'>[user] milks [src] using \the [O].</span>")
G.reagents.add_reagent("milk", transfered)
milk_content -= transfered
else if(G.reagents.total_volume >= G.volume)
to_chat(user, "<span class='warning'>\The [O] is full.</span>")
else
to_chat(user, "<span class='warning'>The udder is dry. Wait a bit longer...</span>")
udder.milkAnimal(O, user)
return 1
else
..()
return ..()
/mob/living/simple_animal/cow/Life(seconds, times_fired)
. = ..()
if(stat == CONSCIOUS && prob(5))
milk_content = min(50, milk_content+rand(5, 10))
if(stat == CONSCIOUS)
udder.generateMilk()
/mob/living/simple_animal/cow/attack_hand(mob/living/carbon/M as mob)
if(!stat && M.a_intent == INTENT_DISARM && icon_state != icon_dead)
@@ -431,3 +425,26 @@ var/global/chicken_count = 0
can_collar = 1
gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY
blood_volume = BLOOD_VOLUME_NORMAL
/obj/item/udder
name = "udder"
/obj/item/udder/New()
create_reagents(50)
reagents.add_reagent("milk", 20)
. = ..()
/obj/item/udder/proc/generateMilk()
if(prob(5))
reagents.add_reagent("milk", rand(5, 10))
/obj/item/udder/proc/milkAnimal(obj/O, mob/user)
var/obj/item/reagent_containers/glass/G = O
if(G.reagents.total_volume >= G.volume)
to_chat(user, "<span class='danger'>[O] is full.</span>")
return
var/transfered = reagents.trans_to(O, rand(5,10))
if(transfered)
user.visible_message("[user] milks [src] using \the [O].", "<span class='notice'>You milk [src] using \the [O].</span>")
else
to_chat(user, "<span class='danger'>The udder is dry. Wait a bit longer...</span>")
@@ -35,8 +35,9 @@
can_collar = 1
gold_core_spawnable = CHEM_MOB_SPAWN_FRIENDLY
/mob/living/simple_animal/mouse/Initialize()
/mob/living/simple_animal/mouse/Initialize(mapload)
. = ..()
AddComponent(/datum/component/squeak, list('sound/creatures/mousesqueak.ogg' = 1), 100)
/mob/living/simple_animal/mouse/handle_automated_speech()
..()
@@ -56,7 +57,7 @@
/mob/living/simple_animal/mouse/Life()
..()
if(prob(0.5))
if(prob(0.5) && !ckey)
stat = UNCONSCIOUS
icon_state = "mouse_[mouse_color]_sleep"
wander = 0
@@ -92,10 +93,9 @@
/mob/living/simple_animal/mouse/Crossed(AM as mob|obj)
if(ishuman(AM))
if(stat == CONSCIOUS)
if(!stat)
var/mob/M = AM
to_chat(M, "<span class='notice'>[bicon(src)] Squeek!</span>")
SEND_SOUND(M, squeak_sound)
..()
/mob/living/simple_animal/mouse/death(gibbed)
@@ -220,4 +220,4 @@
response_harm = "stamps on"
gold_core_spawnable = CHEM_MOB_SPAWN_INVALID
can_collar = 0
butcher_results = list(/obj/item/stack/sheet/metal = 1)
butcher_results = list(/obj/item/stack/sheet/metal = 1)
@@ -59,9 +59,6 @@
return
target.attack_animal(src)
/obj/item/organ/internal/body_egg/changeling_egg
name = "changeling egg"
desc = "Twitching and disgusting."
@@ -91,7 +88,12 @@
if(origin.changeling.can_absorb_dna(M, owner))
origin.changeling.absorb_dna(owner, M)
origin.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
var/datum/action/changeling/humanform/HF = new
HF.Grant(M)
for(var/power in origin.changeling.purchasedpowers)
var/datum/action/changeling/S = power
if(istype(S) && S.needs_button)
S.Grant(M)
M.key = origin.key
owner.gib()
@@ -46,6 +46,11 @@
var/list/emote_taunt = list()
var/taunt_chance = 0
var/lose_patience_timer_id //id for a timer to call LoseTarget(), used to stop mobs fixating on a target they can't reach
var/lose_patience_timeout = 300 //30 seconds by default, so there's no major changes to AI behaviour, beyond actually bailing if stuck forever
var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects.
/mob/living/simple_animal/hostile/New()
..()
if(!targets_from)
@@ -62,7 +67,7 @@
. = ..()
if(!.)
walk(src, 0)
return 0
return FALSE
/mob/living/simple_animal/hostile/handle_automated_action()
if(AIStatus == AI_OFF)
@@ -198,13 +203,15 @@
return 0
return 1
if(isobj(the_target))
if(is_type_in_typecache(the_target, wanted_objects))
if(attack_all_objects || is_type_in_list(the_target, wanted_objects))
return 1
return 0
/mob/living/simple_animal/hostile/proc/GiveTarget(new_target)//Step 4, give us our selected target
target = new_target
LosePatience()
if(target != null)
GainPatience()
Aggro()
return 1
@@ -231,6 +238,7 @@
if(target)
if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack
AttackingTarget()
GainPatience()
return 1
return 0
if(environment_smash)
@@ -400,6 +408,17 @@
/mob/living/simple_animal/hostile/proc/AIShouldSleep(var/list/possible_targets)
return !FindTarget(possible_targets, 1)
//These two procs handle losing our target if we've failed to attack them for
//more than lose_patience_timeout deciseconds, which probably means we're stuck
/mob/living/simple_animal/hostile/proc/GainPatience()
if(lose_patience_timeout)
LosePatience()
lose_patience_timer_id = addtimer(CALLBACK(src, .proc/LoseTarget), lose_patience_timeout, TIMER_STOPPABLE)
/mob/living/simple_animal/hostile/proc/LosePatience()
deltimer(lose_patience_timer_id)
/mob/living/simple_animal/hostile/consider_wakeup()
..()
var/list/tlist
@@ -432,4 +451,4 @@
if(isturf(M.loc))
. += M
else if(M.loc.type in hostile_machines)
. += M.loc
. += M.loc
@@ -0,0 +1,265 @@
#define MINER_DASH_RANGE 4
/*
BLOOD-DRUNK MINER
Effectively a highly aggressive miner, the blood-drunk miner has very few attacks but compensates by being highly aggressive.
The blood-drunk miner's attacks are as follows
- If not in KA range, it will rapidly dash at its target
- If in KA range, it will fire its kinetic accelerator
- If in melee range, will rapidly attack, akin to an actual player
- After any of these attacks, may transform its cleaving saw:
Untransformed, it attacks very rapidly for smaller amounts of damage
Transformed, it attacks at normal speed for higher damage and cleaves enemies hit
When the blood-drunk miner dies, it leaves behind the cleaving saw it was using and its kinetic accelerator.
Difficulty: Medium
*/
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner
name = "blood-drunk miner"
desc = "A miner destined to wander forever, engaged in an endless hunt."
health = 900
maxHealth = 900
icon_state = "miner"
icon_living = "miner"
icon = 'icons/mob/alienqueen.dmi'
light_color = "#E4C7C5"
speak_emote = list("roars")
speed = 1
move_to_delay = 3
projectiletype = /obj/item/projectile/kinetic/miner
projectilesound = 'sound/weapons/kenetic_accel.ogg'
ranged = 1
ranged_cooldown_time = 16
pixel_x = -16
loot = list(/obj/item/melee/energy/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/melee/energy/cleaving_saw/miner/miner_saw
var/time_until_next_transform = 0
var/dashing = FALSE
var/dash_cooldown = 15
var/guidance = FALSE
deathmessage = "falls to the ground, decaying into glowing particles."
death_sound = "bodyfall"
/obj/item/gps/internal/miner
icon_state = null
gpstag = "Resonant Signal"
desc = "The sweet blood, oh, it sings to me."
invisibility = 100
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/guidance
guidance = TRUE
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/hunter/AttackingTarget()
. = ..()
if(. && prob(12))
INVOKE_ASYNC(src, .proc/dash)
/obj/item/melee/energy/cleaving_saw/miner //nerfed saw because it is very murdery
force = 6
force_on = 10
/obj/item/melee/energy/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user)
target.add_stun_absorption("miner", 10, INFINITY)
..()
target.stun_absorption -= "miner"
/obj/item/projectile/kinetic/miner
damage = 20
speed = 0.9
icon_state = "ka_tracer"
range = MINER_DASH_RANGE
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Initialize()
. = ..()
miner_saw = new(src)
internal_gps = new/obj/item/gps/internal/miner(src)
// Add a zone selection UI; otherwise the mob can't melee attack properly.
zone_sel = new /obj/screen/zone_sel()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
var/adjustment_amount = amount * 0.1
if(world.time + adjustment_amount > next_move)
changeNext_move(adjustment_amount) //attacking it interrupts it attacking, but only briefly
. = ..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/death()
if(health > 0)
return
new /obj/effect/temp_visual/dir_setting/miner_death(loc, dir)
return ..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Move(atom/newloc)
if(dashing || (newloc && newloc.z == z && (islava(newloc) || ischasm(newloc)))) //we're not stupid!
return FALSE
return ..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/ex_act(severity, target)
if(dash())
return
return ..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/AttackingTarget()
if(QDELETED(target))
return
if(next_move > world.time || !Adjacent(target)) //some cheating
INVOKE_ASYNC(src, .proc/quick_attack_loop)
return
face_atom(target)
if(isliving(target))
var/mob/living/L = target
if(L.stat == DEAD)
visible_message("<span class='danger'>[src] butchers [L]!</span>",
"<span class='userdanger'>You butcher [L], restoring your health!</span>")
if(!is_station_level(z) || client) //NPC monsters won't heal while on station
if(guidance)
adjustHealth(-L.maxHealth)
else
adjustHealth(-(L.maxHealth * 0.5))
L.gib()
return TRUE
changeNext_move(CLICK_CD_MELEE)
miner_saw.melee_attack_chain(src, target)
if(guidance)
adjustHealth(-2)
transform_weapon()
INVOKE_ASYNC(src, .proc/quick_attack_loop)
return TRUE
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!used_item && !isturf(A))
used_item = miner_saw
..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/GiveTarget(new_target)
var/targets_the_same = (new_target == target)
. = ..()
if(. && target && !targets_the_same)
wander = TRUE
transform_weapon()
INVOKE_ASYNC(src, .proc/quick_attack_loop)
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/OpenFire()
Goto(target, move_to_delay, minimum_distance)
if(get_dist(src, target) > MINER_DASH_RANGE && dash_cooldown <= world.time)
INVOKE_ASYNC(src, .proc/dash, target)
else
shoot_ka()
transform_weapon()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/shoot_ka()
if(ranged_cooldown <= world.time && get_dist(src, target) <= MINER_DASH_RANGE && !Adjacent(target))
ranged_cooldown = world.time + ranged_cooldown_time
visible_message("<span class='danger'>[src] fires the proto-kinetic accelerator!</span>")
face_atom(target)
new /obj/effect/temp_visual/dir_setting/firing_effect(loc, dir)
Shoot(target)
changeNext_move(CLICK_CD_RANGE)
//I'm still of the belief that this entire proc needs to be wiped from existence.
// do not take my touching of it to be endorsement of it. ~mso
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/quick_attack_loop()
while(!QDELETED(target) && next_move <= world.time) //this is done this way because next_move can change to be sooner while we sleep.
stoplag(1)
sleep((next_move - world.time) * 1.5) //but don't ask me what the fuck this is about
if(QDELETED(target))
return
if(dashing || next_move > world.time || !Adjacent(target))
if(dashing && next_move <= world.time)
next_move = world.time + 1
INVOKE_ASYNC(src, .proc/quick_attack_loop) //lets try that again.
return
AttackingTarget()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/dash(atom/dash_target)
if(world.time < dash_cooldown)
return
var/list/accessable_turfs = list()
var/self_dist_to_target = 0
var/turf/own_turf = get_turf(src)
if(!QDELETED(dash_target))
self_dist_to_target += get_dist(dash_target, own_turf)
for(var/turf/simulated/O in RANGE_TURFS(MINER_DASH_RANGE, own_turf))
var/turf_dist_to_target = 0
if(!QDELETED(dash_target))
turf_dist_to_target += get_dist(dash_target, O)
if(get_dist(src, O) >= MINER_DASH_RANGE && turf_dist_to_target <= self_dist_to_target && !islava(O) && !ischasm(O))
var/valid = TRUE
for(var/turf/T in getline(own_turf, O))
if(is_blocked_turf(T, TRUE))
valid = FALSE
continue
if(valid)
accessable_turfs[O] = turf_dist_to_target
var/turf/target_turf
if(!QDELETED(dash_target))
var/closest_dist = MINER_DASH_RANGE
for(var/t in accessable_turfs)
if(accessable_turfs[t] < closest_dist)
closest_dist = accessable_turfs[t]
for(var/t in accessable_turfs)
if(accessable_turfs[t] != closest_dist)
accessable_turfs -= t
if(!LAZYLEN(accessable_turfs))
return
dash_cooldown = world.time + initial(dash_cooldown)
target_turf = pick(accessable_turfs)
var/turf/step_back_turf = get_step(target_turf, get_cardinal_dir(target_turf, own_turf))
var/turf/step_forward_turf = get_step(own_turf, get_cardinal_dir(own_turf, target_turf))
new /obj/effect/temp_visual/small_smoke/halfsecond(step_back_turf)
new /obj/effect/temp_visual/small_smoke/halfsecond(step_forward_turf)
var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc, src)
animate(D, alpha = 0, time = 5)
forceMove(step_back_turf)
playsound(own_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1)
dashing = TRUE
alpha = 0
animate(src, alpha = 255, time = 5)
sleep(2)
D.forceMove(step_forward_turf)
forceMove(target_turf)
playsound(target_turf, 'sound/weapons/punchmiss.ogg', 40, 1, -1)
sleep(1)
dashing = FALSE
shoot_ka()
return TRUE
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/proc/transform_weapon()
if(time_until_next_transform <= world.time)
miner_saw.transform_cooldown = 0
miner_saw.transform_weapon(src, TRUE)
icon_state = "miner[miner_saw.active ? "_transformed":""]"
icon_living = "miner[miner_saw.active ? "_transformed":""]"
time_until_next_transform = world.time + rand(50, 100)
/obj/effect/temp_visual/dir_setting/miner_death
icon_state = "miner_death"
duration = 15
/obj/effect/temp_visual/dir_setting/miner_death/Initialize(mapload, set_dir)
. = ..()
INVOKE_ASYNC(src, .proc/fade_out)
/obj/effect/temp_visual/dir_setting/miner_death/proc/fade_out()
var/matrix/M = new
M.Turn(pick(90, 270))
var/final_dir = dir
if(dir & (EAST|WEST)) //Facing east or west
final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass
animate(src, transform = M, pixel_y = -6, dir = final_dir, time = 2, easing = EASE_IN|EASE_OUT)
sleep(5)
animate(src, color = list("#A7A19E", "#A7A19E", "#A7A19E", list(0, 0, 0)), time = 10, easing = EASE_IN, flags = ANIMATION_PARALLEL)
sleep(4)
animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags = ANIMATION_PARALLEL)
#undef MINER_DASH_RANGE
@@ -1,5 +1,3 @@
#define MEDAL_PREFIX "Bubblegum"
/*
BUBBLEGUM
@@ -46,7 +44,7 @@ Difficulty: Hard
del_on_death = 1
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
var/charging = 0
medal_type = MEDAL_PREFIX
medal_type = BOSS_MEDAL_BUBBLEGUM
score_type = BUBBLEGUM_SCORE
deathmessage = "sinks into a pool of blood, fleeing the battle. You've won, for now... "
death_sound = 'sound/misc/enter_blood.ogg'
@@ -389,5 +387,3 @@ Difficulty: Hard
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
return 1
return 0
#undef MEDAL_PREFIX
@@ -1,5 +1,4 @@
#define MEDAL_PREFIX "Colossus"
/*
COLOSSUS
@@ -44,7 +43,7 @@ Difficulty: Very Hard
ranged = 1
pixel_x = -32
del_on_death = 1
medal_type = MEDAL_PREFIX
medal_type = BOSS_MEDAL_COLOSSUS
score_type = COLOSSUS_SCORE
loot = list(/obj/machinery/anomalous_crystal/random, /obj/item/organ/internal/vocal_cords/colossus)
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
@@ -262,5 +261,3 @@ Difficulty: Very Hard
gpstag = "Angelic Signal"
desc = "Get in the fucking robot."
invisibility = 100
#undef MEDAL_PREFIX
@@ -1,4 +1,3 @@
#define MEDAL_PREFIX "Drake"
/*
ASH DRAKE
@@ -48,7 +47,7 @@ Difficulty: Medium
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
var/swooping = 0
var/swoop_cooldown = 0
medal_type = MEDAL_PREFIX
medal_type = BOSS_MEDAL_DRAKE
score_type = DRAKE_SCORE
deathmessage = "collapses into a pile of bones, its flesh sloughing away."
death_sound = 'sound/misc/demon_dies.ogg'
@@ -131,7 +130,7 @@ Difficulty: Medium
playsound(T,'sound/magic/fireball.ogg', 200, 1)
new /obj/effect/temp_visual/fireball(T)
sleep(12)
explosion(T, 0, 0, 1, 0, 0, 0, 1)
explosion(T, 0, 0, 1, 0, 0, 0, 1, 1)
/mob/living/simple_animal/hostile/megafauna/dragon/OpenFire()
anger_modifier = Clamp(((maxHealth - health)/50),0,20)
@@ -274,6 +273,4 @@ Difficulty: Medium
loot = list()
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/grant_achievement(medaltype,scoretype)
return
#undef MEDAL_PREFIX
return
@@ -1,4 +1,3 @@
#define MEDAL_PREFIX "Hierophant"
/*
The Hierophant
@@ -66,8 +65,8 @@ Difficulty: Hard
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
medal_type = BOSS_MEDAL_HIEROPHANT
score_type = HIEROPHANT_SCORE
del_on_death = TRUE
death_sound = 'sound/magic/repulse.ogg'
@@ -591,24 +590,3 @@ Difficulty: Hard
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/simulated/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
@@ -1,4 +1,3 @@
#define MEDAL_PREFIX "Legion"
/*
LEGION
@@ -31,6 +30,7 @@ Difficulty: Medium
armour_penetration = 50
melee_damage_lower = 25
melee_damage_upper = 25
wander = 0
speed = 2
ranged = 1
del_on_death = 1
@@ -39,7 +39,7 @@ Difficulty: Medium
ranged_cooldown_time = 20
var/size = 5
var/charging = 0
medal_type = MEDAL_PREFIX
medal_type = BOSS_MEDAL_LEGION
score_type = LEGION_SCORE
pixel_y = -90
pixel_x = -75
@@ -143,5 +143,3 @@ Difficulty: Medium
gpstag = "Echoing Signal"
desc = "The message repeats."
invisibility = 100
#undef MEDAL_PREFIX
@@ -1,5 +1,3 @@
#define MEDAL_PREFIX "Boss"
/mob/living/simple_animal/hostile/megafauna
name = "megafauna"
desc = "Attack the weak point for massive damage."
@@ -33,7 +31,7 @@
/obj/structure/barricade,
/obj/machinery/field,
/obj/machinery/power/emitter)
var/medal_type = MEDAL_PREFIX
var/medal_type
var/score_type = BOSS_SCORE
var/elimination = 0
var/anger_modifier = 0
@@ -42,7 +40,7 @@
move_resist = MOVE_FORCE_OVERPOWERING
pull_force = MOVE_FORCE_OVERPOWERING
mob_size = MOB_SIZE_LARGE
layer = MOB_LAYER + 0.5 //Looks weird with them slipping under mineral walls and cameras and shit otherwise
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
/mob/living/simple_animal/hostile/megafauna/Destroy()
@@ -102,122 +100,16 @@
if(3)
adjustBruteLoss(50)
/mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype,scoretype)
/mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype, scoretype, crusher_kill)
if(!medal_type || admin_spawned || !SSmedals.hub_enabled) //Don't award medals if the medal type isn't set
return FALSE
if(medal_type == "Boss") //Don't award medals if the medal type isn't set
return
if(admin_spawned)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
for(var/mob/living/L in view(7,src))
if(L.stat)
continue
if(L.client)
var/client/C = L.client
var/suffixm = BOSS_KILL_MEDAL
UnlockMedal("Boss [suffixm]",C)
UnlockMedal("[medaltype] [suffixm]",C)
SetScore(BOSS_SCORE,C,1)
SetScore(score_type,C,1)
/proc/UnlockMedal(medal,client/player)
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
spawn()
var/result = world.SetMedal(medal, player, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to award medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to award [medal] medal to [player.ckey]!")
else if(result)
to_chat(player.mob, "<span class='greenannounce'><B>Achievement unlocked: [medal]!</B></span>")
/proc/SetScore(score,client/player,increment,force)
if(!score || !player)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
spawn()
var/list/oldscore = GetScore(score,player,1)
if(increment)
if(!oldscore[score])
oldscore[score] = 1
else
oldscore[score] = (text2num(oldscore[score]) + 1)
else
oldscore[score] = force
var/newscoreparam = list2params(oldscore)
var/result = world.SetScores(player.ckey, newscoreparam, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to set score. Score:[score] player:[player.ckey]")
message_admins("Error! Failed to contact hub to set [score] score for [player.ckey]!")
/proc/GetScore(score,client/player,returnlist)
if(!score || !player)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
var/scoreget = world.GetScores(player.ckey, score, global.medal_hub, global.medal_pass)
if(isnull(scoreget))
global.medals_enabled = FALSE
log_game("SCORE ERROR: Could not contact hub to get score. Score:[score] player:[player.ckey]")
message_admins("Error! Failed to contact hub to get score: [score] for [player.ckey]!")
return
var/list/scoregetlist = params2list(scoreget)
if(returnlist)
return scoregetlist
else
return scoregetlist[score]
/proc/CheckMedal(medal,client/player)
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
var/result = world.GetMedal(medal, player, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to get medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to get [medal] medal for [player.ckey]!")
else if(result)
to_chat(player.mob, "[medal] is unlocked")
/proc/LockMedal(medal,client/player)
if(!player || !medal)
return
if(global.medal_hub && global.medal_pass && global.medals_enabled)
var/result = world.ClearMedal(medal, player, global.medal_hub, global.medal_pass)
if(isnull(result))
global.medals_enabled = FALSE
log_game("MEDAL ERROR: Could not contact hub to clear medal:[medal] player:[player.ckey]")
message_admins("Error! Failed to contact hub to clear [medal] medal for [player.ckey]!")
else if(result)
message_admins("Medal: [medal] removed for [player.ckey]")
else
message_admins("Medal: [medal] was not found for [player.ckey]. Unable to clear.")
/proc/ClearScore(client/player)
world.SetScores(player.ckey, "", global.medal_hub, global.medal_pass)
#undef MEDAL_PREFIX
for(var/mob/living/L in view(7,src))
if(L.stat || !L.client)
continue
var/client/C = L.client
SSmedals.UnlockMedal("Boss [BOSS_KILL_MEDAL]", C)
SSmedals.UnlockMedal("[medaltype] [BOSS_KILL_MEDAL]", C)
SSmedals.SetScore(BOSS_SCORE, C, 1)
SSmedals.SetScore(score_type, C, 1)
return TRUE
@@ -0,0 +1,288 @@
/*
Swarmer Beacon
A strange machine appears anywhere a normal lavaland mob can it produces a swarmer at a rate of
1/15 seconds, until there are GetTotalAISwarmerCap()/2 swarmers, after this it is up to the swarmers themselves to
increase their population (it will repopulate them should they fall under GetTotalAISwarmerCap()/2 again)
tl;dr A million of the little hellraisers spawn (controlled by AI) and try to eat mining
Loot: Not much, besides a shit load of artificial bluespace crystals, Oh and mining doesn't get eaten
that's a plus I suppose.
Difficulty: Special
*/
GLOBAL_LIST_EMPTY(AISwarmers)
GLOBAL_LIST_EMPTY(AISwarmersByType)//AISwarmersByType[.../resource] = list(1st, 2nd, nth), AISwarmersByType[../ranged] = list(1st, 2nd, nth) etc.
GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swarmer/ai/resource = 30, /mob/living/simple_animal/hostile/swarmer/ai/ranged_combat = 20, /mob/living/simple_animal/hostile/swarmer/ai/melee_combat = 10))
//returns a type of AI swarmer that is NOT at max cap
//type order is shuffled, to prevent bias
/proc/GetUncappedAISwarmerType()
var/static/list/swarmerTypes = subtypesof(/mob/living/simple_animal/hostile/swarmer/ai)
LAZYINITLIST(GLOB.AISwarmersByType)
for(var/t in shuffle(swarmerTypes))
var/list/amount = GLOB.AISwarmersByType[t]
if(!amount || amount.len < GLOB.AISwarmerCapsByType[t])
return t
//Total of all subtype caps
/proc/GetTotalAISwarmerCap()
var/static/list/swarmerTypes = subtypesof(/mob/living/simple_animal/hostile/swarmer/ai)
. = 0
LAZYINITLIST(GLOB.AISwarmersByType)
for(var/t in swarmerTypes)
. += GLOB.AISwarmerCapsByType[t]
/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon
name = "swarmer beacon"
desc = "That name is a bit of a mouthful, but stop paying attention to your mouth they're eating everything!"
icon = 'icons/mob/swarmer.dmi'
icon_state = "swarmer_console"
health = 750
maxHealth = 750 //""""low-ish"""" HP because it's a passive boss, and the swarm itself is the real foe
internal_gps = /obj/item/gps/internal/swarmer_beacon
medal_type = BOSS_MEDAL_SWARMERS
score_type = SWARMER_BEACON_SCORE
faction = list("mining", "boss", "swarmer")
weather_immunities = list("lava","ash")
stop_automated_movement = TRUE
wander = FALSE
layer = BELOW_MOB_LAYER
AIStatus = AI_OFF
var/swarmer_spawn_cooldown = 0
var/swarmer_spawn_cooldown_amt = 150 //Deciseconds between the swarmers we spawn
var/call_help_cooldown = 0
var/call_help_cooldown_amt = 150 //Deciseconds between calling swarmers to help us when attacked
var/static/list/swarmer_caps
/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/Initialize(mapload)
. = ..()
swarmer_caps = GLOB.AISwarmerCapsByType //for admin-edits
for(var/ddir in cardinal)
new /obj/structure/swarmer/blockade (get_step(src, ddir))
var/mob/living/simple_animal/hostile/swarmer/ai/resource/R = new(loc)
step(R, ddir) //Step the swarmers, instead of spawning them there, incase the turf is solid
/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/Life()
. = ..()
if(.)
var/createtype = GetUncappedAISwarmerType()
if(createtype && world.time > swarmer_spawn_cooldown && GLOB.AISwarmers.len < (GetTotalAISwarmerCap()*0.5))
swarmer_spawn_cooldown = world.time + swarmer_spawn_cooldown_amt
new createtype(loc)
/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
. = ..()
if(. > 0 && world.time > call_help_cooldown)
call_help_cooldown = world.time + call_help_cooldown_amt
summon_backup(25) //long range, only called max once per 15 seconds, so it's not deathlag
/obj/item/gps/internal/swarmer_beacon
icon_state = null
gpstag = "Hungry Signal"
desc = "Transmitted over the signal is a strange message repeated in every language you know of, and some you don't too..." //the message is "nom nom nom"
invisibility = 100
//SWARMER AI
//AI versions of the swarmer mini-antag
//This is an Abstract Base, it re-enables AI, but does not give the swarmer any goals/targets
/mob/living/simple_animal/hostile/swarmer/ai
wander = 1
faction = list("swarmer", "mining")
weather_immunities = list("ash") //wouldn't be fun otherwise
AIStatus = AI_ON
/mob/living/simple_animal/hostile/swarmer/ai/Initialize(mapload)
. = ..()
ToggleLight() //so you can see them eating you out of house and home/shooting you/stunlocking you for eternity
LAZYINITLIST(GLOB.AISwarmersByType[type])
GLOB.AISwarmers += src
GLOB.AISwarmersByType[type] += src
/mob/living/simple_animal/hostile/swarmer/ai/Destroy()
GLOB.AISwarmers -= src
GLOB.AISwarmersByType[type] -= src
return ..()
/mob/living/simple_animal/hostile/swarmer/ai/SwarmerTypeToCreate()
return GetUncappedAISwarmerType()
/mob/living/simple_animal/hostile/swarmer/ai/resource/handle_automated_action()
. = ..()
if(.)
if(!stop_automated_movement)
if(health < maxHealth*0.25)
StartAction(100)
RepairSelf()
return
/mob/living/simple_animal/hostile/swarmer/ai/Move(atom/newloc)
if(newloc)
if(newloc.z == z) //so these actions are Z-specific
if(islava(newloc))
var/turf/simulated/floor/plating/lava/L = newloc
if(!L.is_safe())
StartAction(20)
new /obj/structure/lattice/catwalk/swarmer_catwalk(newloc)
return FALSE
if(ischasm(newloc) && !throwing)
throw_at(get_edge_target_turf(src, get_dir(src, newloc)), 7 , 3, src, FALSE) //my planet needs me
return FALSE
return ..()
/mob/living/simple_animal/hostile/swarmer/ai/proc/StartAction(deci = 0)
stop_automated_movement = TRUE
AIStatus = AI_OFF
addtimer(CALLBACK(src, .proc/EndAction), deci)
/mob/living/simple_animal/hostile/swarmer/ai/proc/EndAction()
stop_automated_movement = FALSE
AIStatus = AI_ON
//RESOURCE SWARMER:
//Similar to the original Player-Swarmers, these dismantle things to obtain the metal inside
//They then use this medal to produce more swarmers or traps/barricades
/mob/living/simple_animal/hostile/swarmer/ai/resource
search_objects = 1
attack_all_objects = TRUE //attempt to nibble everything
lose_patience_timeout = 150
var/static/list/sharedWanted = typecacheof(list(/turf/simulated/mineral, /turf/simulated/wall)) //eat rocks and walls
var/static/list/sharedIgnore = list()
//This handles viable things to eat/attack
//Place specific cases of AI derpiness here
//Most can be left to the automatic Gain/LosePatience() system
/mob/living/simple_animal/hostile/swarmer/ai/resource/CanAttack(atom/the_target)
//SPECIFIC CASES:
//Smash fulltile windows before grilles
if(istype(the_target, /obj/structure/grille))
for(var/obj/structure/window/rogueWindow in get_turf(the_target))
if(rogueWindow.fulltile) //done this way because the subtypes are weird.
the_target = rogueWindow
break
//GENERAL CASES:
if(is_type_in_typecache(the_target, sharedIgnore)) //always ignore
return FALSE
if(is_type_in_typecache(the_target, sharedWanted)) //always eat
return TRUE
return ..() //else, have a nibble, see if it's food
/mob/living/simple_animal/hostile/swarmer/ai/resource/OpenFire(atom/A)
if(isliving(A)) //don't shoot rocks, sillies.
..()
/mob/living/simple_animal/hostile/swarmer/ai/resource/AttackingTarget()
if(target.swarmer_act(src))
add_type_to_wanted(target.type)
return TRUE
else
add_type_to_ignore(target.type)
return FALSE
/mob/living/simple_animal/hostile/swarmer/ai/resource/handle_automated_action()
. = ..()
if(.)
if(!stop_automated_movement)
if(GLOB.AISwarmers.len < GetTotalAISwarmerCap() && resources >= 50)
StartAction(100) //so they'll actually sit still and use the verbs
CreateSwarmer()
return
if(resources > 5)
if(prob(5)) //lower odds, as to prioritise reproduction
StartAction(10) //not a typo
CreateBarricade()
return
if(prob(5))
CreateTrap()
return
//So swarmers can learn what is and isn't food
/mob/living/simple_animal/hostile/swarmer/ai/resource/proc/add_type_to_wanted(typepath)
if(!sharedWanted[typepath])// this and += is faster than |=
sharedWanted += typecacheof(typepath)
/mob/living/simple_animal/hostile/swarmer/ai/resource/proc/add_type_to_ignore(typepath)
if(!sharedIgnore[typepath])
sharedIgnore += typecacheof(typepath)
//RANGED SWARMER
/mob/living/simple_animal/hostile/swarmer/ai/ranged_combat
icon_state = "swarmer_ranged"
icon_living = "swarmer_ranged"
projectiletype = /obj/item/projectile/beam/laser
projectilesound = 'sound/weapons/laser.ogg'
check_friendly_fire = TRUE //you're supposed to protect the resource swarmers, you poop
retreat_distance = 3
minimum_distance = 3
/mob/living/simple_animal/hostile/swarmer/ai/ranged_combat/Aggro()
..()
summon_backup(15, TRUE) //Exact matching, so that goliaths don't come to aid the swarmers, that'd be silly
//MELEE SWARMER
/mob/living/simple_animal/hostile/swarmer/ai/melee_combat
icon_state = "swarmer_melee"
icon_living = "swarmer_melee"
health = 60
maxHealth = 60
ranged = FALSE
/mob/living/simple_animal/hostile/swarmer/ai/melee_combat/Aggro()
..()
summon_backup(15, TRUE)
/mob/living/simple_animal/hostile/swarmer/ai/melee_combat/AttackingTarget()
if(isliving(target))
if(prob(35))
StartAction(30)
DisperseTarget(target)
else
var/mob/living/L = target
L.attack_animal(src)
L.electrocute_act(10, src, safety = TRUE) //safety = TRUE means we don't check gloves... Ok?
return TRUE
else
return ..()
//SWARMER CATWALKS
//Used so they can survive lavaland better
/obj/structure/lattice/catwalk/swarmer_catwalk
name = "swarmer catwalk"
desc = "A catwalk-like mesh, produced by swarmers to allow them to navigate hostile terrain."
icon = 'icons/obj/smooth_structures/swarmer_catwalk.dmi'
icon_state = "swarmer_catwalk"
@@ -0,0 +1,140 @@
/mob/living/simple_animal/hostile/asteroid/basilisk
name = "basilisk"
desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside."
icon = 'icons/mob/animal.dmi'
icon_state = "Basilisk"
icon_living = "Basilisk"
icon_aggro = "Basilisk_alert"
icon_dead = "Basilisk_dead"
icon_gib = "syndicate_gib"
move_to_delay = 20
projectiletype = /obj/item/projectile/temp/basilisk
projectilesound = 'sound/weapons/pierce.ogg'
ranged = 1
ranged_message = "stares"
ranged_cooldown_time = 30
throw_message = "does nothing against the hard shell of"
vision_range = 2
speed = 3
maxHealth = 200
health = 200
harm_intent_damage = 5
obj_damage = 60
melee_damage_lower = 12
melee_damage_upper = 12
attacktext = "bites into"
a_intent = INTENT_HARM
speak_emote = list("chitters")
attack_sound = 'sound/weapons/bladeslice.ogg'
aggro_vision_range = 9
idle_vision_range = 2
turns_per_move = 5
loot = list(/obj/item/stack/ore/diamond{layer = 4.1},
/obj/item/stack/ore/diamond{layer = 4.1})
/obj/item/projectile/temp/basilisk
name = "freezing blast"
icon_state = "ice_2"
damage = 0
damage_type = BURN
nodamage = 1
flag = "energy"
temperature = 50
/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(var/new_target)
if(..()) //we have a target
if(isliving(target))
var/mob/living/L = target
if(L.bodytemperature > 261)
L.bodytemperature = 261
visible_message("<span class='danger'>The [src.name]'s stare chills [L.name] to the bone!</span>")
/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity)
switch(severity)
if(1.0)
gib()
if(2.0)
adjustBruteLoss(140)
if(3.0)
adjustBruteLoss(110)
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher
name = "watcher"
desc = "A levitating, eye-like creature held aloft by winglike formations of sinew. A sharp spine of crystal protrudes from its body."
icon = 'icons/mob/lavaland/watcher.dmi'
icon_state = "watcher"
icon_living = "watcher"
icon_aggro = "watcher"
icon_dead = "watcher_dead"
pixel_x = -10
throw_message = "bounces harmlessly off of"
melee_damage_lower = 15
melee_damage_upper = 15
attacktext = "impales"
a_intent = INTENT_HARM
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/bladeslice.ogg'
stat_attack = 1
flying = TRUE
robust_searching = 1
loot = list()
butcher_results = list(/obj/item/stack/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1)
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/Initialize()
. = ..()
if(prob(1))
if(prob(75))
new /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/magmawing(loc)
else
new /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/icewing(loc)
return INITIALIZE_HINT_QDEL
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/magmawing
name = "magmawing watcher"
desc = "When raised very close to lava, some watchers adapt to the extreme heat and use lava as both a weapon and wings."
icon_state = "watcher_magmawing"
icon_living = "watcher_magmawing"
icon_aggro = "watcher_magmawing"
icon_dead = "watcher_magmawing_dead"
maxHealth = 215 //Compensate for the lack of slowdown on projectiles with a bit of extra health
health = 215
light_range = 3
light_power = 2.5
light_color = LIGHT_COLOR_ORANGE
projectiletype = /obj/item/projectile/temp/basilisk/magmawing
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/icewing
name = "icewing watcher"
desc = "Very rarely, some watchers will eke out an existence far from heat sources. In the absence of warmth, they become icy and fragile but fire much stronger freezing blasts."
icon_state = "watcher_icewing"
icon_living = "watcher_icewing"
icon_aggro = "watcher_icewing"
icon_dead = "watcher_icewing_dead"
maxHealth = 170
health = 170
projectiletype = /obj/item/projectile/temp/basilisk/icewing
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/bone = 1) //No sinew; the wings are too fragile to be usable
/obj/item/projectile/temp/basilisk/magmawing
name = "scorching blast"
icon_state = "lava"
damage = 5
damage_type = BURN
nodamage = FALSE
temperature = 500 //Heats you up!
/obj/item/projectile/temp/basilisk/magmawing/on_hit(atom/target, blocked = FALSE)
. = ..()
if(.)
var/mob/living/L = target
if (istype(L))
L.adjust_fire_stacks(0.1)
L.IgniteMob()
/obj/item/projectile/temp/basilisk/icewing
damage = 5
damage_type = BURN
nodamage = FALSE
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril
fromtendril = TRUE
@@ -0,0 +1,190 @@
/mob/living/simple_animal/hostile/asteroid/goliath
name = "goliath"
desc = "A massive beast that uses long tentacles to ensare its prey, threatening them is not advised under any conditions."
icon = 'icons/mob/animal.dmi'
icon_state = "Goliath"
icon_living = "Goliath"
icon_aggro = "Goliath_alert"
icon_dead = "Goliath_dead"
icon_gib = "syndicate_gib"
attack_sound = 'sound/weapons/punch4.ogg'
mouse_opacity = MOUSE_OPACITY_OPAQUE
move_to_delay = 40
ranged = TRUE
ranged_cooldown = 2 //By default, start the Goliath with his cooldown off so that people can run away quickly on first sight
ranged_cooldown_time = 120
friendly = "wails at"
speak_emote = list("bellows")
vision_range = 4
speed = 3
maxHealth = 300
health = 300
harm_intent_damage = 1 //Only the manliest of men can kill a Goliath with only their fists.
obj_damage = 100
melee_damage_lower = 25
melee_damage_upper = 25
attacktext = "pulverizes"
attack_sound = 'sound/weapons/punch1.ogg'
throw_message = "does nothing to the rocky hide of the"
aggro_vision_range = 9
idle_vision_range = 5
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
var/pre_attack = FALSE
var/pre_attack_icon = "Goliath_preattack"
loot = list(/obj/item/stack/sheet/animalhide/goliath_hide)
/mob/living/simple_animal/hostile/asteroid/goliath/Life()
. = ..()
handle_preattack()
/mob/living/simple_animal/hostile/asteroid/goliath/proc/handle_preattack()
if(ranged_cooldown <= world.time + ranged_cooldown_time * 0.25 && !pre_attack)
pre_attack++
if(!pre_attack || stat || AIStatus == AI_IDLE)
return
icon_state = pre_attack_icon
/mob/living/simple_animal/hostile/asteroid/goliath/revive()
move_force = MOVE_FORCE_VERY_STRONG
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
..()
/mob/living/simple_animal/hostile/asteroid/goliath/OpenFire()
var/tturf = get_turf(target)
if(get_dist(src, target) <= 7)//Screen range check, so you can't get tentacle'd offscreen
visible_message("<span class='warning'>The [src.name] digs its tentacles under [target.name]!</span>")
new /obj/effect/temp_visual/goliath_tentacle/original(tturf, src)
ranged_cooldown = world.time + ranged_cooldown_time
icon_state = icon_aggro
pre_attack = FALSE
/mob/living/simple_animal/hostile/asteroid/goliath/adjustHealth(damage)
ranged_cooldown--
handle_preattack()
..()
/mob/living/simple_animal/hostile/asteroid/goliath/Aggro()
vision_range = aggro_vision_range
handle_preattack()
if(icon_state != icon_aggro)
icon_state = icon_aggro
// Lavaland Goliath
/mob/living/simple_animal/hostile/asteroid/goliath/beast
name = "goliath"
desc = "A hulking, armor-plated beast with long tendrils arching from its back."
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "goliath"
icon_living = "goliath"
icon_aggro = "goliath"
icon_dead = "goliath_dead"
throw_message = "does nothing to the tough hide of the"
pre_attack_icon = "goliath2"
butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/animalhide/goliath_hide = 1, /obj/item/stack/sheet/bone = 2)
loot = list()
stat_attack = TRUE
robust_searching = TRUE
/mob/living/simple_animal/hostile/asteroid/goliath/beast/random/Initialize()
. = ..()
if(prob(1))
new /mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient(loc)
return INITIALIZE_HINT_QDEL
/mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient
name = "ancient goliath"
desc = "Goliaths are biologically immortal, and rare specimens have survived for centuries. This one is clearly ancient, and its tentacles constantly churn the earth around it."
icon_state = "Goliath"
icon_living = "Goliath"
icon_aggro = "Goliath_alert"
icon_dead = "Goliath_dead"
maxHealth = 400
health = 400
speed = 4
pre_attack_icon = "Goliath_preattack"
throw_message = "does nothing to the rocky hide of the"
loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) //A throwback to the asteroid days
butcher_results = list(/obj/item/reagent_containers/food/snacks/goliath = 2, /obj/item/stack/sheet/bone = 2)
wander = FALSE
var/list/cached_tentacle_turfs
var/turf/last_location
var/tentacle_recheck_cooldown = 100
/mob/living/simple_animal/hostile/asteroid/goliath/beast/ancient/Life()
. = ..()
if(!.) // dead
return
if(isturf(loc))
if(!LAZYLEN(cached_tentacle_turfs) || loc != last_location || tentacle_recheck_cooldown <= world.time)
LAZYCLEARLIST(cached_tentacle_turfs)
last_location = loc
tentacle_recheck_cooldown = world.time + initial(tentacle_recheck_cooldown)
for(var/turf/simulated/floor/T in orange(4, loc))
LAZYADD(cached_tentacle_turfs, T)
for(var/t in cached_tentacle_turfs)
if(isfloorturf(t))
if(prob(10))
new /obj/effect/temp_visual/goliath_tentacle(t, src)
else
cached_tentacle_turfs -= t
/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril
fromtendril = TRUE
// Tentacles
/obj/effect/temp_visual/goliath_tentacle
name = "goliath tentacle"
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "Goliath_tentacle_spawn"
layer = BELOW_MOB_LAYER
var/mob/living/spawner
/obj/effect/temp_visual/goliath_tentacle/Initialize(mapload, mob/living/new_spawner)
. = ..()
for(var/obj/effect/temp_visual/goliath_tentacle/T in loc)
if(T != src)
return INITIALIZE_HINT_QDEL
if(!QDELETED(new_spawner))
spawner = new_spawner
if(ismineralturf(loc))
var/turf/simulated/mineral/M = loc
M.gets_drilled()
deltimer(timerid)
timerid = addtimer(CALLBACK(src, .proc/tripanim), 7, TIMER_STOPPABLE)
/obj/effect/temp_visual/goliath_tentacle/original/Initialize(mapload, new_spawner)
. = ..()
var/list/directions = cardinal.Copy()
for(var/i in 1 to 3)
var/spawndir = pick_n_take(directions)
var/turf/T = get_step(src, spawndir)
if(T)
new /obj/effect/temp_visual/goliath_tentacle(T, spawner)
/obj/effect/temp_visual/goliath_tentacle/proc/tripanim()
icon_state = "Goliath_tentacle_wiggle"
deltimer(timerid)
timerid = addtimer(CALLBACK(src, .proc/trip), 3, TIMER_STOPPABLE)
/obj/effect/temp_visual/goliath_tentacle/proc/trip()
var/latched = FALSE
for(var/mob/living/L in loc)
if((!QDELETED(spawner) && spawner.faction_check_mob(L)) || L.stat == DEAD)
continue
visible_message("<span class='danger'>[src] grabs hold of [L]!</span>")
L.Stun(5)
L.adjustBruteLoss(rand(10,15))
latched = TRUE
if(!latched)
retract()
else
deltimer(timerid)
timerid = addtimer(CALLBACK(src, .proc/retract), 10, TIMER_STOPPABLE)
/obj/effect/temp_visual/goliath_tentacle/proc/retract()
icon_state = "Goliath_tentacle_retract"
deltimer(timerid)
timerid = QDEL_IN(src, 5)
@@ -0,0 +1,114 @@
/mob/living/simple_animal/hostile/asteroid/gutlunch
name = "gutlunch"
desc = "A scavenger that eats raw meat, often found alongside ash walkers. Produces a thick, nutritious milk."
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "gutlunch"
icon_living = "gutlunch"
icon_dead = "gutlunch"
icon_aggro = "gutlunch"
speak_emote = list("warbles", "quavers")
emote_hear = list("trills.")
emote_see = list("sniffs.", "burps.")
weather_immunities = list("lava","ash")
faction = list("mining", "ashwalker")
density = 0
speak_chance = 1
turns_per_move = 8
obj_damage = 0
environment_smash = 0
move_to_delay = 15
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "squishes"
friendly = "pinches"
a_intent = INTENT_HELP
ventcrawler = 2
gold_core_spawnable = 2
stat_attack = 1
gender = NEUTER
stop_automated_movement = FALSE
stop_automated_movement_when_pulled = TRUE
stat_exclusive = TRUE
robust_searching = TRUE
search_objects = TRUE
del_on_death = TRUE
loot = list(/obj/effect/decal/cleanable/blood/gibs)
deathmessage = "is pulped into bugmash."
animal_species = /mob/living/simple_animal/hostile/asteroid/gutlunch
childtype = list(/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck = 45, /mob/living/simple_animal/hostile/asteroid/gutlunch/guthen = 55)
wanted_objects = list(/obj/effect/decal/cleanable/blood/gibs)
var/obj/item/udder/gutlunch/udder = null
/mob/living/simple_animal/hostile/asteroid/gutlunch/New()
udder = new()
..()
/mob/living/simple_animal/hostile/asteroid/gutlunch/Destroy()
qdel(udder)
udder = null
return ..()
/mob/living/simple_animal/hostile/asteroid/gutlunch/regenerate_icons()
cut_overlays()
if(udder.reagents.total_volume == udder.reagents.maximum_volume)
add_overlay("gl_full")
..()
/mob/living/simple_animal/hostile/asteroid/gutlunch/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
udder.milkAnimal(O, user)
regenerate_icons()
else
..()
/mob/living/simple_animal/hostile/asteroid/gutlunch/AttackingTarget()
if(is_type_in_typecache(target, wanted_objects)) //we eats
udder.generateMilk()
regenerate_icons()
visible_message("<span class='notice'>[src] slurps up [target].</span>")
qdel(target)
return
..()
/obj/item/udder/gutlunch
name = "nutrient sac"
/obj/item/udder/gutlunch/New()
reagents = new(50)
reagents.my_atom = src
/obj/item/udder/gutlunch/generateMilk()
if(prob(60))
reagents.add_reagent("cream", rand(2, 5))
if(prob(45))
reagents.add_reagent("salglu_solution", rand(2,5))
//Male gutlunch. They're smaller and more colorful!
/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck
name = "gubbuck"
gender = MALE
/mob/living/simple_animal/hostile/asteroid/gutlunch/gubbuck/New()
..()
add_atom_colour(pick("#E39FBB", "#D97D64", "#CF8C4A"), FIXED_COLOUR_PRIORITY)
resize = 0.85
update_transform()
//Lady gutlunch. They make the babby.
/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen
name = "guthen"
gender = FEMALE
/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen/Life()
..()
if(udder.reagents.total_volume == udder.reagents.maximum_volume) //Only breed when we're full.
make_babies()
/mob/living/simple_animal/hostile/asteroid/gutlunch/guthen/make_babies()
. = ..()
if(.)
udder.reagents.clear_reagents()
regenerate_icons()
@@ -218,7 +218,7 @@
// Legion
/mob/living/simple_animal/hostile/asteroid/hivelord/legion
name = "legion"
desc = "You can still see what was once a human under the shifting mass of corruption."
desc = "You can still see what was once a person under the shifting mass of corruption."
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "legion"
icon_living = "legion"
@@ -236,20 +236,44 @@
del_on_death = 1
stat_attack = 1
robust_searching = 1
var/dwarf_mob = FALSE
var/mob/living/carbon/human/stored_mob
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/Initialize()
. = ..()
if(prob(5))
new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf(loc)
return INITIALIZE_HINT_QDEL
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf
name = "dwarf legion"
desc = "You can still see what was once a midget under the shifting mass of corruption."
icon_state = "dwarf_legion"
icon_living = "dwarf_legion"
icon_aggro = "dwarf_legion"
icon_dead = "dwarf_legion"
maxHealth = 60
health = 60
speed = 2 //faster!
dwarf_mob = TRUE
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril
fromtendril = TRUE
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/death(gibbed)
if(can_die())
visible_message("<span class='warning'>The skulls on [src] wail in anger as they flee from their dying host!</span>")
var/turf/T = get_turf(src)
if(T)
if(stored_mob)
stored_mob.forceMove(get_turf(src))
stored_mob = null
else
new /obj/effect/mob_spawn/human/corpse/charredskeleton(T)
// due to `del_on_death`
return ..(gibbed)
visible_message("<span class='warning'>The skulls on [src] wail in anger as they flee from their dying host!</span>")
var/turf/T = get_turf(src)
if(T)
if(stored_mob)
stored_mob.forceMove(get_turf(src))
stored_mob = null
else if(fromtendril)
new /obj/effect/mob_spawn/human/corpse/charredskeleton(T)
else if(dwarf_mob)
new /obj/effect/mob_spawn/human/corpse/damaged/legioninfested/dwarf(T)
else
new /obj/effect/mob_spawn/human/corpse/damaged/legioninfested(T)
..(gibbed)
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
@@ -286,8 +310,12 @@
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H)
visible_message("<span class='warning'>[name] burrows into the flesh of [H]!</span>")
var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L = new(H.loc)
visible_message("<span class='warning'>[L] staggers to their feet!</span>")
var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L
if((DWARF in H.mutations)) //dwarf legions aren't just fluff!
L = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf(H.loc)
else
L = new(H.loc)
visible_message("<span class='warning'>[L] staggers to [L.p_their()] feet!</span>")
H.death()
H.adjustBruteLoss(1000)
L.stored_mob = H
@@ -337,3 +365,104 @@
husk = FALSE
mob_species = /datum/species/skeleton
mob_color = "#454545"
//Legion infested mobs
/obj/effect/mob_spawn/human/corpse/damaged/legioninfested/dwarf/equip(mob/living/carbon/human/H)
. = ..()
H.dna.SetSEState(SMALLSIZEBLOCK, 1, 1)
H.mutations.Add(DWARF)
genemutcheck(H, SMALLSIZEBLOCK, null, MUTCHK_FORCED)
H.update_mutations()
/obj/effect/mob_spawn/human/corpse/damaged/legioninfested/Initialize()
var/type = pickweight(list("Miner" = 66, "Ashwalker" = 10, "Golem" = 10,"Clown" = 10, pick(list("Shadow", "YeOlde","Operative", "Cultist")) = 4))
switch(type)
if("Miner")
mob_species = pickweight(list(/datum/species/human = 72, /datum/species/unathi = 28))
uniform = /obj/item/clothing/under/rank/miner/lavaland
if (prob(4))
belt = /obj/item/storage/belt/mining
else if(prob(10))
belt = pickweight(list(/obj/item/pickaxe = 8, /obj/item/pickaxe/silver = 2, /obj/item/pickaxe/diamond = 1))
else
belt = /obj/item/tank/emergency_oxygen/engi
if(mob_species != /datum/species/unathi)
shoes = /obj/item/clothing/shoes/workboots/mining
gloves = /obj/item/clothing/gloves/color/black
mask = /obj/item/clothing/mask/gas/explorer
if(prob(20))
suit = pickweight(list(/obj/item/clothing/suit/hooded/explorer = 18, /obj/item/clothing/suit/hooded/goliath = 2))
if(prob(30))
r_pocket = pickweight(list(/obj/item/stack/marker_beacon = 20, /obj/item/stack/spacecash/c1000 = 7, /obj/item/reagent_containers/hypospray/autoinjector/survival = 2, /obj/item/borg/upgrade/modkit/damage = 1 ))
if(prob(10))
l_pocket = pickweight(list(/obj/item/stack/spacecash/c1000 = 7, /obj/item/reagent_containers/hypospray/autoinjector/survival = 2, /obj/item/borg/upgrade/modkit/cooldown = 1 ))
if("Ashwalker")
mob_species = /datum/species/unathi/ashwalker
uniform = /obj/item/clothing/under/gladiator/ash_walker
if(prob(95))
head = /obj/item/clothing/head/helmet/gladiator
else
head = /obj/item/clothing/head/skullhelmet
suit = /obj/item/clothing/suit/armor/bone
if(prob(5))
back = pickweight(list(/obj/item/twohanded/spear/bonespear = 3, /obj/item/twohanded/fireaxe/boneaxe = 2))
if(prob(10))
belt = /obj/item/storage/belt/mining
if(prob(30))
r_pocket = /obj/item/kitchen/knife/combat/survival/bone
if(prob(30))
l_pocket = /obj/item/kitchen/knife/combat/survival/bone
if("Clown")
name = pick(GLOB.clown_names)
outfit = /datum/outfit/job/clown
belt = null
backpack_contents = list()
if(prob(70))
backpack_contents += pick(list(/obj/item/stamp/clown = 1, /obj/item/reagent_containers/spray/waterflower = 1, /obj/item/reagent_containers/food/snacks/grown/banana = 1, /obj/item/megaphone = 1))
if(prob(30))
backpack_contents += list(/obj/item/stack/sheet/mineral/bananium = pickweight(list( 1 = 3, 2 = 2, 3 = 1)))
if(prob(10))
l_pocket = pickweight(list(/obj/item/bikehorn/golden = 3, /obj/item/bikehorn/airhorn= 1 ))
if("Golem")
mob_species = pick(list(/datum/species/golem/adamantine, /datum/species/golem/plasma, /datum/species/golem/diamond, /datum/species/golem/gold, /datum/species/golem/silver, /datum/species/golem/plasteel, /datum/species/golem/titanium, /datum/species/golem/plastitanium))
if(prob(30))
glasses = pickweight(list(/obj/item/clothing/glasses/meson = 2, /obj/item/clothing/glasses/hud/health = 2, /obj/item/clothing/glasses/hud/diagnostic =2, /obj/item/clothing/glasses/science = 2, /obj/item/clothing/glasses/welding = 2, /obj/item/clothing/glasses/night = 1))
if(prob(10))
belt = pick(list(/obj/item/storage/belt/mining, /obj/item/storage/belt/utility/full))
if(prob(50))
back = /obj/item/bedsheet/rd/royal_cape
if(prob(10))
l_pocket = pick(list(/obj/item/crowbar/power, /obj/item/wrench/power, /obj/item/weldingtool/experimental))
if("YeOlde")
mob_gender = FEMALE
uniform = /obj/item/clothing/under/maid
gloves = /obj/item/clothing/gloves/color/white
shoes = /obj/item/clothing/shoes/laceup
head = /obj/item/clothing/head/helmet/riot/knight
suit = /obj/item/clothing/suit/armor/riot/knight
back = /obj/item/shield/riot/buckler
belt = /obj/item/nullrod/claymore
r_pocket = /obj/item/tank/emergency_oxygen
mask = /obj/item/clothing/mask/breath
if("Operative")
id_job = "Operative"
outfit = /datum/outfit/syndicatecommandocorpse
if("Shadow")
mob_species = /datum/species/shadow
uniform = /obj/item/clothing/under/color/black
shoes = /obj/item/clothing/shoes/black
suit = /obj/item/clothing/suit/storage/labcoat
glasses = /obj/item/clothing/glasses/sunglasses/blindfold
back = /obj/item/tank/oxygen
mask = /obj/item/clothing/mask/breath
if("Cultist")
uniform = /obj/item/clothing/under/roman
suit = /obj/item/clothing/suit/hooded/cultrobes
head = /obj/item/clothing/head/culthood
suit_store = /obj/item/tome
r_pocket = /obj/item/restraints/legcuffs/bola/cult
l_pocket = /obj/item/melee/cultblade/dagger
glasses = /obj/item/clothing/glasses/hud/health/night
backpack_contents = list(/obj/item/reagent_containers/food/drinks/bottle/unholywater = 1, /obj/item/cult_shift = 1, /obj/item/flashlight/flare = 1, /obj/item/stack/sheet/runed_metal = 15)
. = ..()
@@ -0,0 +1,48 @@
/mob/living/simple_animal/hostile/asteroid/
vision_range = 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)
unsuitable_atmos_damage = 15
faction = list("mining")
weather_immunities = list("lava","ash")
obj_damage = 30
environment_smash = 2
minbodytemp = 0
heat_damage_per_tick = 20
response_help = "pokes"
response_disarm = "shoves"
response_harm = "strikes"
status_flags = 0
a_intent = INTENT_HARM
var/throw_message = "bounces off of"
var/icon_aggro = null // for swapping to when we get aggressive
var/fromtendril = FALSE
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
mob_size = MOB_SIZE_LARGE
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
icon_state = icon_aggro
/mob/living/simple_animal/hostile/asteroid/LoseAggro()
..()
if(stat == CONSCIOUS)
icon_state = icon_living
/mob/living/simple_animal/hostile/asteroid/bullet_act(var/obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills
if(!stat)
Aggro()
if(P.damage < 30 && P.damage_type != BRUTE)
P.damage = (P.damage / 3)
visible_message("<span class='danger'>The [P] has a reduced effect on [src]!</span>")
..()
/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy
if(istype(AM, /obj/item))
var/obj/item/T = AM
if(!stat)
Aggro()
if(T.throwforce <= 20)
visible_message("<span class='notice'>The [T.name] [src.throw_message] [src.name]!</span>")
return
..()
@@ -0,0 +1,79 @@
/mob/living/simple_animal/hostile/spawner/lavaland
name = "necropolis tendril"
desc = "A vile tendril of corruption, originating deep underground. Terrible monsters are pouring out of it."
icon = 'icons/mob/nest.dmi'
icon_state = "tendril"
icon_living = "tendril"
icon_dead = "tendril"
faction = list("mining")
weather_immunities = list("lava","ash")
luminosity = 1
health = 250
maxHealth = 250
max_mobs = 3
spawn_time = 300 //30 seconds default
mob_type = /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril
spawn_text = "emerges from"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = INFINITY
loot = list(/obj/effect/collapse, /obj/structure/closet/crate/necropolis/tendril)
del_on_death = 1
var/gps = null
/mob/living/simple_animal/hostile/spawner/lavaland/New()
..()
//for(var/F in RANGE_TURFS(1, src)) TODO: Uncomment
//if(ismineralturf(F))
//var/turf/simulated/mineral/M = F
//M.ChangeTurf(M.turf_type, FALSE, TRUE)
gps = new /obj/item/gps/internal(src)
/mob/living/simple_animal/hostile/spawner/lavaland/Destroy()
qdel(gps)
. = ..()
/mob/living/simple_animal/hostile/spawner/lavaland/death()
var/last_tendril = TRUE
for(var/mob/living/simple_animal/hostile/spawner/lavaland/other in GLOB.mob_list)
if(other != src)
last_tendril = FALSE
break
if(last_tendril && !admin_spawned)
if(SSmedals.hub_enabled)
for(var/mob/living/L in view(7,src))
if(L.stat || !L.client)
continue
SSmedals.UnlockMedal("[BOSS_MEDAL_TENDRIL] [ALL_KILL_MEDAL]", L.client)
SSmedals.SetScore(TENDRIL_CLEAR_SCORE, L.client, 1)
..()
/obj/effect/collapse
name = "collapsing necropolis tendril"
desc = "Get clear!"
luminosity = 1
layer = ABOVE_OPEN_TURF_LAYER
icon = 'icons/mob/nest.dmi'
icon_state = "tendril"
anchored = TRUE
/obj/effect/collapse/New()
..()
visible_message("<span class='boldannounce'>The tendril writhes in fury as the earth around it begins to crack and break apart! Get back!</span>")
visible_message("<span class='warning'>Something falls free of the tendril!</span>")
playsound(get_turf(src),'sound/effects/tendril_destroyed.ogg', 200, 0, 50, 1, 1)
spawn(50)
for(var/mob/M in range(7,src))
shake_camera(M, 15, 1)
playsound(get_turf(src),'sound/effects/explosionfar.ogg', 200, 1)
visible_message("<span class='boldannounce'>The tendril falls inward, the ground around it widening into a yawning chasm!</span>")
for(var/turf/T in range(2,src))
if(!T.density)
T.TerraformTurf(/turf/simulated/floor/chasm/straight_down/lava_land_surface)
qdel(src)
/mob/living/simple_animal/hostile/spawner/lavaland/goliath
mob_type = /mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril
/mob/living/simple_animal/hostile/spawner/lavaland/legion
mob_type = /mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril
@@ -140,7 +140,7 @@
move_resist = MOVE_FORCE_VERY_STRONG
pull_force = MOVE_FORCE_VERY_STRONG
var/pre_attack = 0
loot = list(/obj/item/asteroid/goliath_hide{layer = 4.1})
loot = list(/obj/item/stack/sheet/animalhide/goliath_hide{layer = ABOVE_MOB_LAYER})
/mob/living/simple_animal/hostile/asteroid/goliath/Life()
..()
@@ -223,46 +223,3 @@
else
spawn(50)
qdel(src)
/obj/item/asteroid/goliath_hide
name = "goliath hide plates"
desc = "Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna."
icon = 'icons/obj/items.dmi'
icon_state = "goliath_hide"
flags = NOBLUDGEON
w_class = WEIGHT_CLASS_NORMAL
layer = 4
/obj/item/asteroid/goliath_hide/afterattack(atom/target, mob/user, proximity_flag)
if(proximity_flag)
if(istype(target, /obj/item/clothing/suit/space/hardsuit/mining) || istype(target, /obj/item/clothing/head/helmet/space/hardsuit/mining) || istype(target, /obj/item/clothing/suit/space/eva/plasmaman/miner) || istype(target, /obj/item/clothing/head/helmet/space/eva/plasmaman/miner))
var/obj/item/clothing/C = target
var/current_armor = C.armor
if(current_armor["melee"] < 60)
current_armor["melee"] = min(current_armor["melee"] + 10, 60)
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against melee attacks.</span>")
qdel(src)
else
to_chat(user, "<span class='info'>You can't improve [C] any further.</span>")
return
if(istype(target, /obj/mecha/working/ripley))
var/obj/mecha/D = target
if(D.icon_state != "ripley-open")
to_chat(user, "<span class='info'>You can't add armour onto the mech while someone is inside!</span>")
return
var/list/damage_absorption = D.damage_absorption
if(damage_absorption["brute"] > 0.3)
damage_absorption["brute"] = max(damage_absorption["brute"] - 0.1, 0.3)
damage_absorption["bullet"] = damage_absorption["bullet"] - 0.05
damage_absorption["fire"] = damage_absorption["fire"] - 0.05
damage_absorption["laser"] = damage_absorption["laser"] - 0.025
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against melee attacks.</span>")
qdel(src)
D.overlays += image("icon"="mecha.dmi", "icon_state"="ripley-g-open")
D.desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates."
if(damage_absorption["brute"] == 0.3)
D.overlays += image("icon"="mecha.dmi", "icon_state"="ripley-g-full-open")
D.desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - the pilot must be an experienced monster hunter."
else
to_chat(user, "<span class='warning'>You can't improve [D] any further!</span>")
return
@@ -108,7 +108,7 @@
/mob/living/simple_animal/possessed_object/IsAdvancedToolUser() // So we can shoot guns (Mostly ourselves), among other things.
return 1
return TRUE
/mob/living/simple_animal/possessed_object/get_access() // If we've possessed an ID card we've got access to lots of fun things!
@@ -62,10 +62,9 @@
var/can_collar = 0 // can add collar to mob or not
//Hot simple_animal baby making vars
var/childtype = null
var/scan_ready = 1
var/simplespecies //Sorry, no spider+corgi buttbabies.
var/list/childtype = null
var/next_scan_time = 0
var/animal_species //Sorry, no spider+corgi buttbabies.
var/gold_core_spawnable = CHEM_MOB_SPAWN_INVALID //if CHEM_MOB_SPAWN_HOSTILE can be spawned by plasma with gold core, CHEM_MOB_SPAWN_FRIENDLY are 'friendlies' spawned with blood
@@ -446,27 +445,32 @@
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || !scan_ready || !childtype || !simplespecies)
return
scan_ready = 0
spawn(400)
scan_ready = 1
var/alone = 1
if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress())
return FALSE
next_scan_time = world.time + 400
var/alone = TRUE
var/mob/living/simple_animal/partner
var/children = 0
for(var/mob/M in oview(7, src))
if(istype(M, childtype)) //Check for children FIRST.
if(M.stat != CONSCIOUS) //Check if it's conscious FIRST.
continue
else if(istype(M, childtype)) //Check for children SECOND.
children++
else if(istype(M, simplespecies))
if(M.client)
else if(istype(M, animal_species))
if(M.ckey)
continue
else if(!istype(M, childtype) && M.gender == MALE) //Better safe than sorry ;_;
partner = M
else if(istype(M, /mob/))
alone = 0
continue
else if(isliving(M) && !faction_check_mob(M)) //shyness check. we're not shy in front of things that share a faction with us.
return //we never mate when not alone, so just abort early
if(alone && partner && children < 3)
return new childtype(loc)
var/childspawn = pickweight(childtype)
var/turf/target = get_turf(loc)
if(target)
return new childspawn(target)
/mob/living/simple_animal/say_quote(var/message)
var/verb = "says"
@@ -609,4 +613,33 @@
..()
if(AIStatus == AI_Z_OFF)
SSidlenpcpool.idle_mobs_by_zlevel[old_z] -= src
toggle_ai(initial(AIStatus))
toggle_ai(initial(AIStatus))
// Simple animals will not be given night vision upon death, as that would result in issues when they are revived.
/mob/living/simple_animal/grant_death_vision()
sight |= SEE_TURFS
sight |= SEE_MOBS
sight |= SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_OBSERVER
sync_lighting_plane_alpha()
/mob/living/simple_animal/update_sight()
if(!client)
return
if(stat == DEAD)
grant_death_vision()
return
see_invisible = initial(see_invisible)
see_in_dark = initial(see_in_dark)
sight = initial(sight)
if(client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -56,7 +56,7 @@
/mob/living/simple_animal/hostile/spawner/mining
name = "monster den"
desc = "A hole dug into the ground, harboring all kinds of monsters found within most caves or mining asteroids."
desc = "A hole dug into the ground, harboring all kinds of monsters found within most caves or mining areas."
icon_state = "hole"
icon_living = "hole"
health = 200
+34
View File
@@ -549,3 +549,37 @@
dna.SetSEState(block, 0, 1) //Fix the gene
genemutcheck(src, block,null, MUTCHK_FORCED)
dna.UpdateSE()
///////////////////////////////////// STUN ABSORPTION /////////////////////////////////////
/mob/living/proc/add_stun_absorption(key, duration, priority, message, self_message, examine_message)
//adds a stun absorption with a key, a duration in deciseconds, its priority, and the messages it makes when you're stun/examined, if any
if(!islist(stun_absorption))
stun_absorption = list()
if(stun_absorption[key])
stun_absorption[key]["end_time"] = world.time + duration
stun_absorption[key]["priority"] = priority
stun_absorption[key]["stuns_absorbed"] = 0
else
stun_absorption[key] = list("end_time" = world.time + duration, "priority" = priority, "stuns_absorbed" = 0, \
"visible_message" = message, "self_message" = self_message, "examine_message" = examine_message)
/mob/living/proc/absorb_stun(amount, ignoring_flag_presence)
if(!amount || amount <= 0 || stat || ignoring_flag_presence || !islist(stun_absorption))
return FALSE
var/priority_absorb_key
var/highest_priority
for(var/i in stun_absorption)
if(stun_absorption[i]["end_time"] > world.time && (!priority_absorb_key || stun_absorption[i]["priority"] > highest_priority))
priority_absorb_key = stun_absorption[i]
highest_priority = priority_absorb_key["priority"]
if(priority_absorb_key)
if(priority_absorb_key["visible_message"] || priority_absorb_key["self_message"])
if(priority_absorb_key["visible_message"] && priority_absorb_key["self_message"])
visible_message("<span class='warning'>[src][priority_absorb_key["visible_message"]]</span>", "<span class='boldwarning'>[priority_absorb_key["self_message"]]</span>")
else if(priority_absorb_key["visible_message"])
visible_message("<span class='warning'>[src][priority_absorb_key["visible_message"]]</span>")
else if(priority_absorb_key["self_message"])
to_chat(src, "<span class='boldwarning'>[priority_absorb_key["self_message"]]</span>")
priority_absorb_key["stuns_absorbed"] += amount
return TRUE
+2 -2
View File
@@ -93,9 +93,9 @@
density = !lying
if(lying)
if(layer == initial(layer))
layer = MOB_LAYER - 0.2
layer = LYING_MOB_LAYER //so mob lying always appear behind standing mobs
else
if(layer == MOB_LAYER - 0.2)
if(layer == LYING_MOB_LAYER)
layer = initial(layer)
update_transform()
+1 -2
View File
@@ -70,5 +70,4 @@
AA.display_to(list(src))
update_client_colour(0)
callHook("mob_login", list("client" = client, "mob" = src))
update_morgue()
+2 -2
View File
@@ -6,7 +6,7 @@
create_attack_log("<font color='red'>Logged out at [atom_loc_line(get_turf(src))]</font>")
// `holder` is nil'd out by now, so we check the `admin_datums` array directly
//Only report this stuff if we are currently playing.
if(admin_datums[ckey] && ticker && ticker.current_state == GAME_STATE_PLAYING)
if(admin_datums[ckey] && SSticker && SSticker.current_state == GAME_STATE_PLAYING)
var/datum/admins/temp_admin = admin_datums[ckey]
// Triggers on people with banhammer power only - no mentors tripping the alarm
if(temp_admin.rights & R_BAN)
@@ -16,5 +16,5 @@
send2irc(config.admin_notify_irc, "[key_name(src)] logged out - No active admins, [admincounter[2]] non-admin staff, [admincounter[3]] inactive staff.")
..()
callHook("mob_logout", list("client" = client, "mob" = src))
update_morgue()
return 1
+28 -22
View File
@@ -745,7 +745,7 @@ var/list/slot_equipment_priority = list( \
to_chat(usr, "<span class='warning'>Respawning is disabled.</span>")
return
if(stat != DEAD || !ticker)
if(stat != DEAD || !SSticker)
to_chat(usr, "<span class='boldnotice'>You must be dead to use this!</span>")
return
@@ -956,9 +956,6 @@ var/list/slot_equipment_priority = list( \
statpanel("Status") // We only want alt-clicked turfs to come before Status
if(mind && mind.changeling)
add_stings_to_statpanel(mind.changeling.purchasedpowers)
if(mob_spell_list && mob_spell_list.len)
for(var/obj/effect/proc_holder/spell/S in mob_spell_list)
add_spell_to_statpanel(S)
@@ -968,13 +965,6 @@ var/list/slot_equipment_priority = list( \
if(is_admin(src))
if(statpanel("DI")) //not looking at that panel
stat("Loc", "([x], [y], [z]) [loc]")
stat("CPU", "[world.cpu]")
stat("Instances", "[world.contents.len]")
if(processScheduler)
processScheduler.statProcesses()
if(statpanel("MC")) //looking at that panel
var/turf/T = get_turf(client.eye)
stat("Location:", COORD(T))
@@ -1020,17 +1010,11 @@ var/list/slot_equipment_priority = list( \
var/atom/A = foo
if(A.invisibility > see_invisible)
continue
if(is_type_in_list(A, shouldnt_see))
if(is_type_in_list(A, shouldnt_see) || !A.simulated)
continue
statpanel_things += A
statpanel(listed_turf.name, null, statpanel_things)
/mob/proc/add_stings_to_statpanel(var/list/stings)
for(var/obj/effect/proc_holder/changeling/S in stings)
if(S.chemical_cost >=0 && S.can_be_used_by(src))
statpanel("[S.panel]",((S.chemical_cost > 0) ? "[S.chemical_cost]" : ""),S)
/mob/proc/add_spell_to_statpanel(var/obj/effect/proc_holder/spell/S)
switch(S.charge_type)
if("recharge")
@@ -1040,7 +1024,6 @@ var/list/slot_equipment_priority = list( \
if("holdervar")
statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S)
// facing verbs
/mob/proc/canface()
if(!canmove) return 0
@@ -1085,7 +1068,7 @@ var/list/slot_equipment_priority = list( \
/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check
return 0
return FALSE
/mob/proc/swap_hand()
return
@@ -1101,7 +1084,7 @@ var/list/slot_equipment_priority = list( \
to_chat(usr, "<span class='warning'>You are banned from playing as sentient animals.</span>")
return
if(!ticker || ticker.current_state < 3)
if(!SSticker || SSticker.current_state < 3)
to_chat(src, "<span class='warning'>You can't respawn as an NPC before the game starts!</span>")
return
@@ -1348,6 +1331,29 @@ var/list/slot_equipment_priority = list( \
/mob/proc/is_literate()
return FALSE
/mob/proc/faction_check_mob(mob/target, exact_match)
if(exact_match) //if we need an exact match, we need to do some bullfuckery.
var/list/faction_src = faction.Copy()
var/list/faction_target = target.faction.Copy()
if(!("\ref[src]" in faction_target)) //if they don't have our ref faction, remove it from our factions list.
faction_src -= "\ref[src]" //if we don't do this, we'll never have an exact match.
if(!("\ref[target]" in faction_src))
faction_target -= "\ref[target]" //same thing here.
return faction_check(faction_src, faction_target, TRUE)
return faction_check(faction, target.faction, FALSE)
/proc/faction_check(list/faction_A, list/faction_B, exact_match)
var/list/match_list
if(exact_match)
match_list = faction_A & faction_B //only items in both lists
var/length = LAZYLEN(match_list)
if(length)
return (length == LAZYLEN(faction_A)) //if they're not the same len(gth) or we don't have a len, then this isn't an exact match.
else
match_list = faction_A & faction_B
return LAZYLEN(match_list)
return FALSE
/mob/proc/update_sight()
SEND_SIGNAL(src, COMSIG_MOB_UPDATE_SIGHT)
sync_lighting_plane_alpha()
@@ -1356,4 +1362,4 @@ var/list/slot_equipment_priority = list( \
if(hud_used)
var/obj/screen/plane_master/lighting/L = hud_used.plane_masters["[LIGHTING_PLANE]"]
if (L)
L.alpha = lighting_alpha
L.alpha = lighting_alpha
+1 -1
View File
@@ -176,7 +176,7 @@
var/player_ghosted = 0
var/turf/listed_turf = null //the current turf being examined in the stat panel
var/list/shouldnt_see = list(/atom/movable/lighting_object) //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
var/kills = 0
+3 -3
View File
@@ -214,12 +214,12 @@
shift = -10
adir = assailant.dir
affecting.setDir(assailant.dir)
affecting.loc = assailant.loc
affecting.forceMove(assailant.loc)
if(GRAB_KILL)
shift = 0
adir = 1
affecting.setDir(SOUTH)//face up
affecting.loc = assailant.loc
affecting.forceMove(assailant.loc)
switch(adir)
if(NORTH)
@@ -387,7 +387,7 @@
if(M == assailant && state >= GRAB_AGGRESSIVE) //no eatin unless you have an agressive grab
if(checkvalid(user, affecting)) //wut
var/mob/living/carbon/attacker = user
if(affecting.buckled)
to_chat(user, "<span class='warning'>[affecting] is buckled!</span>")
return
-2
View File
@@ -24,8 +24,6 @@
sight |= SEE_TURFS
GLOB.player_list |= src
callHook("mob_login", list("client" = client, "mob" = src))
new_player_panel()
spawn(30)
+22 -21
View File
@@ -59,7 +59,7 @@
real_name = "Random Character Slot"
var/output = "<center><p><a href='byond://?src=[UID()];show_preferences=1'>Setup Character</A><br /><i>[real_name]</i></p>"
if(!ticker || ticker.current_state <= GAME_STATE_PREGAME)
if(!SSticker || SSticker.current_state <= GAME_STATE_PREGAME)
if(!ready) output += "<p><a href='byond://?src=[UID()];ready=1'>Declare Ready</A></p>"
else output += "<p><b>You are ready</b> (<a href='byond://?src=[UID()];ready=2'>Cancel</A>)</p>"
else
@@ -106,21 +106,21 @@
/mob/new_player/Stat()
statpanel("Lobby")
if(client.statpanel=="Lobby" && ticker)
if(ticker.hide_mode)
if(client.statpanel=="Lobby" && SSticker)
if(SSticker.hide_mode)
stat("Game Mode:", "Secret")
else
if(ticker.hide_mode == 0)
if(SSticker.hide_mode == 0)
stat("Game Mode:", "[master_mode]") // Old setting for showing the game mode
else
stat("Game Mode: ", "Secret")
if((ticker.current_state == GAME_STATE_PREGAME) && going)
stat("Time To Start:", ticker.pregame_timeleft)
if((ticker.current_state == GAME_STATE_PREGAME) && !going)
if((SSticker.current_state == GAME_STATE_PREGAME) && going)
stat("Time To Start:", round(SSticker.pregame_timeleft/10))
if((SSticker.current_state == GAME_STATE_PREGAME) && !going)
stat("Time To Start:", "DELAYED")
if(ticker.current_state == GAME_STATE_PREGAME)
if(SSticker.current_state == GAME_STATE_PREGAME)
stat("Players:", "[totalPlayers]")
if(check_rights(R_ADMIN, 0, src))
stat("Players Ready:", "[totalPlayersReady]")
@@ -136,7 +136,7 @@
..()
statpanel("Status")
if(client.statpanel == "Status" && ticker)
if(client.statpanel == "Status" && SSticker)
show_stat_station_time()
@@ -182,7 +182,8 @@
return 0
if(alert(src,"Are you sure you wish to observe? You cannot normally join the round after doing this!","Player Setup","Yes","No") == "Yes")
if(!client) return 1
if(!client)
return 1
var/mob/dead/observer/observer = new()
src << browse(null, "window=playersetup")
spawning = 1
@@ -217,10 +218,9 @@
if(!tos_consent)
to_chat(usr, "<span class='warning'>You must consent to the terms of service before you can join!</span>")
return 0
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
to_chat(usr, "<span class='warning'>The round is either not ready, or has already finished...</span>")
return
if(client.prefs.species in GLOB.whitelisted_species)
if(!is_alien_whitelisted(src, client.prefs.species) && config.usealienwhitelist)
@@ -303,7 +303,7 @@
/mob/new_player/proc/AttemptLateSpawn(rank,var/spawning_at)
if(src != usr)
return 0
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
if(!SSticker || SSticker.current_state != GAME_STATE_PLAYING)
to_chat(usr, "<span class='warning'>The round is either not ready, or has already finished...</span>")
return 0
if(!enter_allowed)
@@ -330,7 +330,7 @@
ai_character.moveToEmptyCore()
AnnounceCyborg(ai_character, rank, "has been downloaded to the empty core in \the [get_area(ai_character)]")
ticker.mode.latespawn(ai_character)
SSticker.mode.latespawn(ai_character)
qdel(src)
return
@@ -370,15 +370,16 @@
character = SSjobs.EquipRank(character, rank, 1) //equips the human
EquipCustomItems(character)
ticker.mode.latespawn(character)
SSticker.mode.latespawn(character)
if(character.mind.assigned_role == "Cyborg")
AnnounceCyborg(character, rank, join_message)
else
data_core.manifest_inject(character)
ticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
AnnounceArrival(character, rank, join_message)
AddEmploymentContract(character)
SSticker.minds += character.mind//Cyborgs and AIs handle this in the transform proc. //TODO!!!!! ~Carn
if(!IsAdminJob(rank))
AnnounceArrival(character, rank, join_message)
AddEmploymentContract(character)
if(!thisjob.is_position_available() && thisjob in SSjobs.prioritized_jobs)
SSjobs.prioritized_jobs -= thisjob
@@ -386,7 +387,7 @@
/mob/new_player/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message)
if(ticker.current_state == GAME_STATE_PLAYING)
if(SSticker.current_state == GAME_STATE_PLAYING)
var/ailist[] = list()
for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
ailist += A
@@ -418,7 +419,7 @@
employmentCabinet.addFile(employee)
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message)
if(ticker.current_state == GAME_STATE_PLAYING)
if(SSticker.current_state == GAME_STATE_PLAYING)
var/ailist[] = list()
for(var/mob/living/silicon/ai/A in GLOB.living_mob_list)
ailist += A
@@ -536,7 +537,7 @@
var/mob/living/carbon/human/new_character = new(loc)
new_character.lastarea = get_area(loc)
if(ticker.random_players || appearance_isbanned(new_character))
if(SSticker.random_players || appearance_isbanned(new_character))
client.prefs.random_character()
client.prefs.real_name = random_name(client.prefs.gender)
client.prefs.copy_to(new_character)