Merge branch 'master' into upstream-merge-31737

This commit is contained in:
Poojawa
2017-10-21 07:18:14 -05:00
committed by GitHub
591 changed files with 181531 additions and 178280 deletions
@@ -61,7 +61,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/plant
name = "Plant Weeds"
desc = "Plants some alien weeds"
desc = "Plants some alien weeds."
plasma_cost = 50
check_turf = 1
action_icon_state = "alien_plant"
@@ -76,7 +76,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/whisper
name = "Whisper"
desc = "Whisper to someone"
desc = "Whisper to someone."
plasma_cost = 10
action_icon_state = "alien_whisper"
@@ -104,7 +104,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/transfer
name = "Transfer Plasma"
desc = "Transfer Plasma to another alien"
desc = "Transfer Plasma to another alien."
plasma_cost = 0
action_icon_state = "alien_transfer"
@@ -169,7 +169,8 @@ Doesn't work on other aliens/AI.*/
return
var/mob/living/carbon/user = usr
var/obj/effect/proc_holder/alien/acid/A = locate() in user.abilities
if(!A) return
if(!A)
return
if(user.getPlasma() > A.plasma_cost && A.corrode(O))
user.adjustPlasma(-A.plasma_cost)
@@ -214,8 +215,7 @@ Doesn't work on other aliens/AI.*/
user.visible_message("<span class='danger'>[user] spits neurotoxin!", "<span class='alertalien'>You spit neurotoxin.</span>")
var/obj/item/projectile/bullet/neurotoxin/A = new /obj/item/projectile/bullet/neurotoxin(user.loc)
A.current = U
A.preparePixelProjectile(target, get_turf(target), user, params)
A.preparePixelProjectile(target, user, params)
A.fire()
user.newtonian_move(get_dir(U, T))
user.adjustPlasma(-p_cost)
@@ -269,7 +269,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/regurgitate
name = "Regurgitate"
desc = "Empties the contents of your stomach"
desc = "Empties the contents of your stomach."
plasma_cost = 0
action_icon_state = "alien_barf"
@@ -306,13 +306,15 @@ Doesn't work on other aliens/AI.*/
/mob/living/carbon/proc/getPlasma()
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
if(!vessel) return 0
if(!vessel)
return 0
return vessel.storedPlasma
/mob/living/carbon/proc/adjustPlasma(amount)
var/obj/item/organ/alien/plasmavessel/vessel = getorgan(/obj/item/organ/alien/plasmavessel)
if(!vessel) return 0
if(!vessel)
return 0
vessel.storedPlasma = max(vessel.storedPlasma + amount,0)
vessel.storedPlasma = min(vessel.storedPlasma, vessel.max_plasma) //upper limit of max_plasma, lower limit of 0
for(var/X in abilities)
+2 -1
View File
@@ -1,7 +1,8 @@
/mob/living/proc/alien_talk(message, shown_name = real_name)
log_talk(src,"[key_name(src)] : [message]",LOGSAY)
message = trim(message)
if(!message) return
if(!message)
return
var/message_a = say_quote(message, get_spans())
var/rendered = "<i><span class='alien'>Hivemind, <span class='name'>[shown_name]</span> <span class='message'>[message_a]</span></span></i>"
+8 -12
View File
@@ -7,19 +7,15 @@
..()
/mob/living/carbon/Destroy()
for(var/guts in internal_organs)
qdel(guts)
for(var/atom/movable/food in stomach_contents)
qdel(food)
for(var/BP in bodyparts)
qdel(BP)
for(var/imp in implants)
qdel(imp)
bodyparts = list()
//This must be done first, so the mob ghosts correctly before DNA etc is nulled
. = ..()
QDEL_LIST(internal_organs)
QDEL_LIST(stomach_contents)
QDEL_LIST(bodyparts)
QDEL_LIST(implants)
remove_from_all_data_huds()
if(dna)
qdel(dna)
return ..()
QDEL_NULL(dna)
/mob/living/carbon/relaymove(mob/user, direction)
if(user in src.stomach_contents)
@@ -696,10 +696,10 @@
/mob/living/carbon/human/wash_cream()
//clean both to prevent a rare bug
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_lizard"))
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_human"))
if(creamed) //clean both to prevent a rare bug
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_lizard"))
cut_overlay(mutable_appearance('icons/effects/creampie.dmi', "creampie_human"))
creamed = FALSE
//Turns a mob black, flashes a skeleton overlay
//Just like a cartoon!
@@ -62,7 +62,6 @@
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
@@ -1,48 +1,50 @@
/mob/living/carbon/human
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
pressure_resistance = 25
//Hair colour and style
var/hair_color = "000"
var/hair_style = "Bald"
//Facial hair colour and style
var/facial_hair_color = "000"
var/facial_hair_style = "Shaved"
//Eye colour
var/eye_color = "000"
var/skin_tone = "caucasian1" //Skin tone
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
var/lip_color = "white"
var/age = 30 //Player's age (pure fluff)
var/underwear = "Nude" //Which underwear the player wants
var/undershirt = "Nude" //Which undershirt the player wants
var/socks = "Nude" //Which socks the player wants
var/backbag = DBACKPACK //Which backpack type the player has chosen.
//Equipment slots
var/obj/item/wear_suit = null
var/obj/item/w_uniform = null
var/obj/item/belt = null
var/obj/item/wear_id = null
var/obj/item/r_store = null
var/obj/item/l_store = null
var/obj/item/s_store = null
var/special_voice = "" // For changing our voice. Used by a symptom.
var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
var/name_override //For temporary visible name changes
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/datum/personal_crafting/handcrafting
can_buckle = TRUE
buckle_lying = FALSE
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)
/mob/living/carbon/human
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
pressure_resistance = 25
//Hair colour and style
var/hair_color = "000"
var/hair_style = "Bald"
//Facial hair colour and style
var/facial_hair_color = "000"
var/facial_hair_style = "Shaved"
//Eye colour
var/eye_color = "000"
var/skin_tone = "caucasian1" //Skin tone
var/lip_style = null //no lipstick by default- arguably misleading, as it could be used for general makeup
var/lip_color = "white"
var/age = 30 //Player's age (pure fluff)
var/underwear = "Nude" //Which underwear the player wants
var/undershirt = "Nude" //Which undershirt the player wants
var/socks = "Nude" //Which socks the player wants
var/backbag = DBACKPACK //Which backpack type the player has chosen.
//Equipment slots
var/obj/item/wear_suit = null
var/obj/item/w_uniform = null
var/obj/item/belt = null
var/obj/item/wear_id = null
var/obj/item/r_store = null
var/obj/item/l_store = null
var/obj/item/s_store = null
var/special_voice = "" // For changing our voice. Used by a symptom.
var/bleed_rate = 0 //how much are we bleeding
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
var/name_override //For temporary visible name changes
var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects
var/datum/personal_crafting/handcrafting
can_buckle = TRUE
buckle_lying = FALSE
can_ride_typecache = list(/mob/living/carbon/human, /mob/living/simple_animal/slime, /mob/living/simple_animal/parrot)
var/creamed = FALSE //to use with creampie overlays
+11 -1
View File
@@ -59,6 +59,8 @@
return ONE_ATMOSPHERE
if(ismob(loc))
return ONE_ATMOSPHERE
if(istype(loc, /obj/item/device/dogborg/sleeper))
return ONE_ATMOSPHERE
else
return pressure
@@ -133,6 +135,12 @@
/mob/living/carbon/human/proc/get_thermal_protection()
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
if(istype(loc, /obj/item/device/dogborg/sleeper))
return FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
if(ismob(loc))
return FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
if(wear_suit)
if(wear_suit.max_heat_protection_temperature >= FIRE_SUIT_MAX_TEMP_PROTECT)
thermal_protection += (wear_suit.max_heat_protection_temperature*0.7)
@@ -244,7 +252,9 @@
if(dna && (RESISTCOLD in dna.species.species_traits))
return 1
if(istype(loc, /obj/item/device/dogborg/sleeper))
return 1 //freezing to death in sleepers ruins fun.
if(ismob(loc))
return 1 //because lazy and being inside somemone insulates you from space
+6 -3
View File
@@ -16,7 +16,8 @@
for(var/i=1, ((i <= D.stage) && (i <= temp_message.len)), i++) //Loop for each stage of the disease or until we run out of words
if(prob(3 * D.stage)) //Stage 1: 3% Stage 2: 6% Stage 3: 9% Stage 4: 12%
var/H = pick(pick_list)
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":"))
continue
temp_message[H] = "HONK"
pick_list -= H //Make sure that you dont HONK the same word twice
message = jointext(temp_message, " ")
@@ -69,8 +70,10 @@
/mob/living/carbon/human/binarycheck()
if(ears)
var/obj/item/device/radio/headset/dongle = ears
if(!istype(dongle)) return 0
if(dongle.translate_binary) return 1
if(!istype(dongle))
return 0
if(dongle.translate_binary)
return 1
/mob/living/carbon/human/radio(message, message_mode, list/spans, language)
. = ..()
+23 -15
View File
@@ -8,7 +8,6 @@
#define COLD_DAMAGE_LEVEL_2 1.5
#define COLD_DAMAGE_LEVEL_3 3
/datum/species
var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this
var/limbs_id //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
@@ -18,8 +17,7 @@
var/sexes = 1 // whether or not the race has sexual characteristics. at the moment this is only 0 for skeletons and shadows
var/face_y_offset = 0
var/hair_y_offset = 0
var/list/offset_features = list(OFFSET_UNIFORM = list(0,0), OFFSET_ID = list(0,0), OFFSET_GLOVES = list(0,0), OFFSET_GLASSES = list(0,0), OFFSET_EARS = list(0,0), OFFSET_SHOES = list(0,0), OFFSET_S_STORE = list(0,0), OFFSET_FACEMASK = list(0,0), OFFSET_HEAD = list(0,0), OFFSET_FACE = list(0,0), OFFSET_BELT = list(0,0), OFFSET_BACK = list(0,0), OFFSET_SUIT = list(0,0), OFFSET_NECK = list(0,0))
var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
@@ -263,11 +261,11 @@
C.dropItemToGround(I)
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
C.put_in_hands(new mutanthands())
if(VIRUSIMMUNE in species_traits)
for(var/datum/disease/A in C.viruses)
A.cure(FALSE)
if(NOAROUSAL in species_traits)
C.canbearoused = FALSE
@@ -411,7 +409,9 @@
else
hair_overlay.color = forced_colour
hair_overlay.alpha = hair_alpha
hair_overlay.pixel_y += hair_y_offset
if(OFFSET_FACE in H.dna.species.offset_features)
hair_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
hair_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
if(hair_overlay.icon)
standing += hair_overlay
@@ -432,14 +432,18 @@
if(H.lip_style && (LIPS in species_traits) && HD)
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER)
lip_overlay.color = H.lip_color
lip_overlay.pixel_y += face_y_offset
if(OFFSET_FACE in H.dna.species.offset_features)
lip_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
lip_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
standing += lip_overlay
// eyes
if((EYECOLOR in species_traits) && HD)
var/mutable_appearance/eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
eye_overlay.color = "#" + H.eye_color
eye_overlay.pixel_y += face_y_offset
if(OFFSET_FACE in H.dna.species.offset_features)
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
standing += eye_overlay
//Underwear, Undershirts & Socks
@@ -1140,11 +1144,14 @@
radiation = 0
return TRUE
if(radiation > RAD_MOB_KNOCKDOWN)
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
if(!H.IsKnockdown())
H.emote("collapse")
H.Knockdown(RAD_KNOCKDOWN_TIME)
H.Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT)
to_chat(H, "<span class='danger'>You feel weak.</span>")
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
H.vomit(10, TRUE)
if(radiation > RAD_MOB_MUTATE)
if(prob(1))
@@ -1154,10 +1161,9 @@
H.domutcheck()
if(radiation > RAD_MOB_HAIRLOSS)
if(prob(15))
if(!( H.hair_style == "Shaved") || !(H.hair_style == "Bald") || (HAIR in species_traits))
to_chat(H, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
addtimer(CALLBACK(src, .proc/go_bald, H), 50)
if(prob(15) && !(H.hair_style == "Bald") && (HAIR in species_traits))
to_chat(H, "<span class='danger'>Your hair starts to fall out in clumps...</span>")
addtimer(CALLBACK(src, .proc/go_bald, H), 50)
/datum/species/proc/go_bald(mob/living/carbon/human/H)
if(QDELETED(H)) //may be called from a timer
@@ -1475,7 +1481,9 @@
H.adjust_blurriness(10)
if(prob(I.force + ((100 - H.health)/2)) && H != user)
SSticker.mode.remove_revolutionary(H.mind, FALSE, user)
var/datum/antagonist/rev/rev = H.mind.has_antag_datum(/datum/antagonist/rev)
if(rev)
rev.remove_revolutionary(FALSE, user)
if(bloody) //Apply blood
if(H.wear_mask)
@@ -360,16 +360,9 @@
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(H)
var/turf/target = get_turf(P.starting)
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.firer = H
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
P.Angle = null
P.preparePixelProjectile(locate(Clamp(target.x + new_x, 1, world.maxx), Clamp(target.y + new_y, 1, world.maxy), H.z), H)
return -1
return 0
@@ -145,10 +145,10 @@
bodies = old_species.bodies
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H)
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
/*if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
if(prob(5))
to_chat(H, "<span class='notice'>You feel very bloated!</span>")
else if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
to_chat(H, "<span class='notice'>You feel very bloated!</span>")*/
if(H.nutrition >= NUTRITION_LEVEL_WELL_FED)
H.blood_volume += 3
H.nutrition -= 2.5
@@ -63,7 +63,7 @@ There are several things that need to be remembered:
..()
/mob/living/carbon/human/update_fire()
..("Standing")
..((fire_stacks > 3) ? "Standing" : "Generic_mob_burning")
/* --------------------------------------- */
@@ -134,6 +134,10 @@ There are several things that need to be remembered:
if(!uniform_overlay)
uniform_overlay = U.build_worn_icon(state = "[t_color]", default_layer = UNIFORM_LAYER, default_icon_file = ((w_uniform.icon_override) ? w_uniform.icon_override : 'icons/mob/uniform.dmi'), isinhands = FALSE)
if(OFFSET_UNIFORM in dna.species.offset_features)
uniform_overlay.pixel_x += dna.species.offset_features[OFFSET_UNIFORM][1]
uniform_overlay.pixel_y += dna.species.offset_features[OFFSET_UNIFORM][2]
overlays_standing[UNIFORM_LAYER] = uniform_overlay
apply_overlay(UNIFORM_LAYER)
@@ -147,6 +151,8 @@ There are several things that need to be remembered:
var/obj/screen/inventory/inv = hud_used.inv_slots[slot_wear_id]
inv.update_icon()
var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER]
if(wear_id)
wear_id.screen_loc = ui_id
if(client && hud_used && hud_used.hud_shown)
@@ -154,8 +160,11 @@ There are several things that need to be remembered:
update_observer_view(wear_id)
//TODO: add an icon file for ID slot stuff, so it's less snowflakey
overlays_standing[ID_LAYER] = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = ((wear_id.icon_override) ? wear_id.icon_override : 'icons/mob/mob.dmi'))
id_overlay = wear_id.build_worn_icon(state = wear_id.item_state, default_layer = ID_LAYER, default_icon_file = 'icons/mob/mob.dmi')
if(OFFSET_ID in dna.species.offset_features)
id_overlay.pixel_x += dna.species.offset_features[OFFSET_ID][1]
id_overlay.pixel_y += dna.species.offset_features[OFFSET_ID][2]
overlays_standing[ID_LAYER] = id_overlay
apply_overlay(ID_LAYER)
@@ -176,6 +185,7 @@ There are several things that need to be remembered:
overlays_standing[GLOVES_LAYER] = bloody_overlay
var/mutable_appearance/gloves_overlay = overlays_standing[GLOVES_LAYER]
if(gloves)
gloves.screen_loc = ui_gloves
if(client && hud_used && hud_used.hud_shown)
@@ -185,8 +195,12 @@ There are several things that need to be remembered:
var/t_state = gloves.item_state
if(!t_state)
t_state = gloves.icon_state
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = ((gloves.icon_override) ? gloves.icon_override : 'icons/mob/hands.dmi'))
overlays_standing[GLOVES_LAYER] = gloves.build_worn_icon(state = t_state, default_layer = GLOVES_LAYER, default_icon_file = 'icons/mob/hands.dmi')
gloves_overlay = overlays_standing[GLOVES_LAYER]
if(OFFSET_GLOVES in dna.species.offset_features)
gloves_overlay.pixel_x += dna.species.offset_features[OFFSET_GLOVES][1]
gloves_overlay.pixel_y += dna.species.offset_features[OFFSET_GLOVES][2]
overlays_standing[GLOVES_LAYER] = gloves_overlay
apply_overlay(GLOVES_LAYER)
@@ -207,9 +221,13 @@ There are several things that need to be remembered:
client.screen += glasses //Either way, add the item to the HUD
update_observer_view(glasses,1)
if(!(head && (head.flags_inv & HIDEEYES)) && !(wear_mask && (wear_mask.flags_inv & HIDEEYES)))
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = ((glasses.icon_override) ? glasses.icon_override : 'icons/mob/eyes.dmi'))
overlays_standing[GLASSES_LAYER] = glasses.build_worn_icon(state = glasses.icon_state, default_layer = GLASSES_LAYER, default_icon_file = 'icons/mob/eyes.dmi')
var/mutable_appearance/glasses_overlay = overlays_standing[GLASSES_LAYER]
if(glasses_overlay)
if(OFFSET_GLASSES in dna.species.offset_features)
glasses_overlay.pixel_x += dna.species.offset_features[OFFSET_GLASSES][1]
glasses_overlay.pixel_y += dna.species.offset_features[OFFSET_GLASSES][2]
overlays_standing[GLASSES_LAYER] = glasses_overlay
apply_overlay(GLASSES_LAYER)
@@ -230,8 +248,12 @@ There are several things that need to be remembered:
client.screen += ears //add it to the client's screen
update_observer_view(ears,1)
overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = ((ears.icon_override) ? ears.icon_override : 'icons/mob/ears.dmi'))
overlays_standing[EARS_LAYER] = ears.build_worn_icon(state = ears.icon_state, default_layer = EARS_LAYER, default_icon_file = 'icons/mob/ears.dmi')
var/mutable_appearance/ears_overlay = overlays_standing[EARS_LAYER]
if(OFFSET_EARS in dna.species.offset_features)
ears_overlay.pixel_x += dna.species.offset_features[OFFSET_EARS][1]
ears_overlay.pixel_y += dna.species.offset_features[OFFSET_EARS][2]
overlays_standing[EARS_LAYER] = ears_overlay
apply_overlay(EARS_LAYER)
@@ -251,8 +273,12 @@ There are several things that need to be remembered:
if(hud_used.inventory_shown) //if the inventory is open
client.screen += shoes //add it to client's screen
update_observer_view(shoes,1)
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = ((shoes.icon_override) ? shoes.icon_override : 'icons/mob/feet.dmi'))
overlays_standing[SHOES_LAYER] = shoes.build_worn_icon(state = shoes.icon_state, default_layer = SHOES_LAYER, default_icon_file = 'icons/mob/feet.dmi')
var/mutable_appearance/shoes_overlay = overlays_standing[SHOES_LAYER]
if(OFFSET_SHOES in dna.species.offset_features)
shoes_overlay.pixel_x += dna.species.offset_features[OFFSET_SHOES][1]
shoes_overlay.pixel_y += dna.species.offset_features[OFFSET_SHOES][2]
overlays_standing[SHOES_LAYER] = shoes_overlay
apply_overlay(SHOES_LAYER)
@@ -272,13 +298,25 @@ There are several things that need to be remembered:
if(!t_state)
t_state = s_store.icon_state
overlays_standing[SUIT_STORE_LAYER] = mutable_appearance('icons/mob/belt_mirror.dmi', t_state, -SUIT_STORE_LAYER)
var/mutable_appearance/s_store_overlay = overlays_standing[SUIT_LAYER]
if(OFFSET_S_STORE in dna.species.offset_features)
s_store_overlay.pixel_x += dna.species.offset_features[OFFSET_S_STORE][1]
s_store_overlay.pixel_y += dna.species.offset_features[OFFSET_S_STORE][2]
overlays_standing[SUIT_STORE_LAYER] = s_store_overlay
apply_overlay(SUIT_STORE_LAYER)
/mob/living/carbon/human/update_inv_head()
..()
update_mutant_bodyparts()
var/mutable_appearance/head_overlay = overlays_standing[HEAD_LAYER]
if(head_overlay)
remove_overlay(HEAD_LAYER)
if(OFFSET_HEAD in dna.species.offset_features)
head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1]
head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2]
overlays_standing[HEAD_LAYER] = head_overlay
apply_overlay(HEAD_LAYER)
/mob/living/carbon/human/update_inv_belt()
remove_overlay(BELT_LAYER)
@@ -297,9 +335,12 @@ There are several things that need to be remembered:
if(!t_state)
t_state = belt.icon_state
overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = ((belt.icon_override) ? belt.icon_override : 'icons/mob/belt.dmi'))
overlays_standing[BELT_LAYER] = belt.build_worn_icon(state = t_state, default_layer = BELT_LAYER, default_icon_file = 'icons/mob/belt.dmi')
var/mutable_appearance/belt_overlay = overlays_standing[BELT_LAYER]
if(OFFSET_BELT in dna.species.offset_features)
belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1]
belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2]
overlays_standing[BELT_LAYER] = belt_overlay
apply_overlay(BELT_LAYER)
@@ -318,8 +359,12 @@ There are several things that need to be remembered:
client.screen += wear_suit
update_observer_view(wear_suit,1)
overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = ((wear_suit.icon_override) ? wear_suit.icon_override : 'icons/mob/suit.dmi'))
overlays_standing[SUIT_LAYER] = wear_suit.build_worn_icon(state = wear_suit.icon_state, default_layer = SUIT_LAYER, default_icon_file = 'icons/mob/suit.dmi')
var/mutable_appearance/suit_overlay = overlays_standing[SUIT_LAYER]
if(OFFSET_SUIT in dna.species.offset_features)
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
overlays_standing[SUIT_LAYER] = suit_overlay
update_hair()
update_mutant_bodyparts()
@@ -351,8 +396,26 @@ There are several things that need to be remembered:
/mob/living/carbon/human/update_inv_wear_mask()
..()
var/mutable_appearance/mask_overlay = overlays_standing[FACEMASK_LAYER]
if(mask_overlay)
remove_overlay(FACEMASK_LAYER)
if(OFFSET_FACEMASK in dna.species.offset_features)
mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1]
mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2]
overlays_standing[FACEMASK_LAYER] = mask_overlay
apply_overlay(FACEMASK_LAYER)
update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout
/mob/living/carbon/human/update_inv_back()
..()
var/mutable_appearance/back_overlay = overlays_standing[BACK_LAYER]
if(back_overlay)
remove_overlay(BACK_LAYER)
if(OFFSET_BACK in dna.species.offset_features)
back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1]
back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2]
overlays_standing[BACK_LAYER] = back_overlay
apply_overlay(BACK_LAYER)
/mob/living/carbon/human/update_inv_legcuffed()
remove_overlay(LEGCUFF_LAYER)
@@ -24,10 +24,10 @@
/mob/living/carbon/monkey/handle_mutations_and_radiation()
if(radiation)
if(radiation > RAD_MOB_KNOCKDOWN)
if(radiation > RAD_MOB_KNOCKDOWN && prob(RAD_MOB_KNOCKDOWN_PROB))
if(!IsKnockdown())
emote("collapse")
Knockdown(200)
Knockdown(RAD_MOB_KNOCKDOWN_AMOUNT)
to_chat(src, "<span class='danger'>You feel weak.</span>")
if(radiation > RAD_MOB_MUTATE)
if(prob(1))
@@ -39,6 +39,8 @@
if(radiation > RAD_MOB_MUTATE * 2 && prob(50))
gorillize()
return
if(radiation > RAD_MOB_VOMIT && prob(RAD_MOB_VOMIT_PROB))
vomit(10, TRUE)
return ..()
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
+15 -26
View File
@@ -41,39 +41,28 @@
clear_fullscreen("eye_damage")
/mob/living/carbon/adjust_drugginess(amount)
var/old_druggy = druggy
if(amount>0)
druggy += amount
if(!old_druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
else if(old_druggy)
druggy = max(druggy+amount, 0)
if(!druggy)
clear_fullscreen("high")
clear_alert("high")
druggy = max(druggy+amount, 0)
if(druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
else
clear_fullscreen("high")
clear_alert("high")
/mob/living/carbon/set_drugginess(amount)
var/old_druggy = druggy
druggy = amount
if(amount>0)
if(!old_druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
else if(old_druggy)
druggy = max(amount, 0)
if(druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
else
clear_fullscreen("high")
clear_alert("high")
/mob/living/carbon/adjust_disgust(amount)
var/old_disgust = disgust
if(amount>0)
disgust = min(disgust+amount, DISGUST_LEVEL_MAXEDOUT)
else if(old_disgust)
disgust = max(disgust+amount, 0)
disgust = Clamp(disgust+amount, 0, DISGUST_LEVEL_MAXEDOUT)
/mob/living/carbon/set_disgust(amount)
if(amount >= 0)
disgust = amount
disgust = Clamp(amount, 0, DISGUST_LEVEL_MAXEDOUT)
/mob/living/carbon/cure_blind()
if(disabilities & BLIND)
@@ -153,6 +153,7 @@
if(back)
overlays_standing[BACK_LAYER] = back.build_worn_icon(state = back.icon_state, default_layer = BACK_LAYER, default_icon_file = 'icons/mob/back.dmi')
update_hud_back(back)
apply_overlay(BACK_LAYER)
/mob/living/carbon/update_inv_head()
+1 -1
View File
@@ -34,7 +34,7 @@
dust_animation()
spawn_dust(just_ash)
qdel(src)
QDEL_IN(src,5) // since this is sometimes called in the middle of movement, allow half a second for movement to finish, ghosting to happen and animation to play. Looks much nicer and doesn't cause multiple runtimes.
/mob/living/proc/dust_animation()
return
+1 -1
View File
@@ -586,7 +586,7 @@
if(!force_moving)
..(pressure_difference, direction, pressure_resistance_prob_delta)
/mob/living/proc/can_resist()
/mob/living/can_resist()
return !((next_move > world.time) || incapacitated(ignore_restraints = TRUE))
/mob/living/verb/resist()
+14 -10
View File
@@ -86,7 +86,7 @@
var/chnotify = 0
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
..()
. = ..()
if(!target_ai) //If there is no player/brain inside.
new/obj/structure/AIcore/deactivated(loc) //New empty terminal.
qdel(src)//Delete AI.
@@ -143,8 +143,8 @@
if(isturf(loc))
verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall,\
/mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/set_automatic_say_channel)
/mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, \
/mob/living/silicon/ai/proc/set_automatic_say_channel)
GLOB.ai_list += src
GLOB.shuttle_caller_list += src
@@ -813,12 +813,16 @@
return FALSE
if(be_close && !in_range(M, src))
return FALSE
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
if(M && GLOB.cameranet && !GLOB.cameranet.checkTurfVis(get_turf_pixel(M)) && !apc_override)
return FALSE
return TRUE
return can_see(M) //stop AIs from leaving windows open and using then after they lose vision
/mob/living/silicon/ai/proc/can_see(atom/A)
if(isturf(loc)) //AI in core, check if on cameras
//get_turf_pixel() is because APCs in maint aren't actually in view of the inner camera
//apc_override is needed here because AIs use their own APC when depowered
return (GLOB.cameranet && GLOB.cameranet.checkTurfVis(get_turf_pixel(A))) || apc_override
//AI is carded/shunted
//view(src) returns nothing for carded/shunted AIs and they have x-ray vision so just use get_dist
return get_dist(src, A) <= client.view
/mob/living/silicon/ai/proc/relay_speech(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
raw_message = lang_treat(speaker, message_language, raw_message, spans, message_mode)
@@ -988,6 +992,6 @@
return
/mob/living/silicon/ai/spawned/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
. = ..()
if(!target_ai)
target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct
..()
+6 -3
View File
@@ -139,9 +139,12 @@
ai_restore_power()
return
switch(PRP)
if (1) to_chat(src, "APC located. Optimizing route to APC to avoid needless power waste.")
if (2) to_chat(src, "Best route identified. Hacking offline APC power port.")
if (3) to_chat(src, "Power port upload access confirmed. Loading control program into APC power port software.")
if (1)
to_chat(src, "APC located. Optimizing route to APC to avoid needless power waste.")
if (2)
to_chat(src, "Best route identified. Hacking offline APC power port.")
if (3)
to_chat(src, "Power port upload access confirmed. Loading control program into APC power port software.")
if (4)
to_chat(src, "Transfer complete. Forcing APC to execute program.")
sleep(50)
+3 -1
View File
@@ -1,5 +1,7 @@
/mob/living/silicon/Login()
if(mind && SSticker.mode)
SSticker.mode.remove_cultist(mind, 0, 0)
SSticker.mode.remove_revolutionary(mind, TRUE)
var/datum/antagonist/rev/rev = mind.has_antag_datum(/datum/antagonist/rev)
if(rev)
rev.remove_revolutionary(TRUE)
..()
@@ -17,12 +17,12 @@
var/savefile/F = new /savefile(src.savefile_path(user))
WRITE_FILE(F["name"], name)
WRITE_FILE(F["description"], description)
WRITE_FILE(F["role"], role)
WRITE_FILE(F["comments"], comments)
WRITE_FILE(F["name"], name)
WRITE_FILE(F["description"], description)
WRITE_FILE(F["role"], role)
WRITE_FILE(F["comments"], comments)
WRITE_FILE(F["version"], 1)
WRITE_FILE(F["version"], 1)
return 1
@@ -42,7 +42,8 @@
var/savefile/F = new /savefile(path)
if(!F) return //Not everyone has a pai savefile.
if(!F)
return //Not everyone has a pai savefile.
var/version = null
F["version"] >> version
@@ -196,7 +196,8 @@
var/mob/living/M = card.loc
var/count = 0
while(!isliving(M))
if(!M || !M.loc) return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
if(!M || !M.loc)
return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
M = M.loc
count++
if(count >= 6)
@@ -248,7 +249,7 @@
medHUD = !medHUD
if(medHUD)
add_med_hud()
else
var/datum/atom_hud/med = GLOB.huds[med_hud]
med.remove_hud_from(src)
@@ -11,33 +11,21 @@
/mob/living/silicon/robot/proc/uneq_module(obj/item/O)
if(!O)
return 0
O.mouse_opacity = MOUSE_OPACITY_OPAQUE
if(istype(O, /obj/item/borg/sight))
O.mouse_opacity = MOUSE_OPACITY_OPAQUE
if(istype(O, /obj/item/borg/sight))
var/obj/item/borg/sight/S = O
sight_mode &= ~S.sight_mode
update_sight()
else if(istype(O, /obj/item/storage/bag/tray/))
var/obj/item/storage/bag/tray/T = O
T.do_quick_empty()
else if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = 0
update_icons()
else if(istype(O,/obj/item/gun/energy/disabler/cyborg))
disabler = 0
update_icons()
else if(istype(O,/obj/item/device/dogborg/sleeper))
sleeper_g = 0
sleeper_r = 0
update_icons()
var/obj/item/device/dogborg/sleeper/S = O
S.go_out()
if(client)
client.screen -= O
observer_screen_update(O,FALSE)
O.forceMove(module) //Return item to module so it appears in its contents, so it can be taken out again.
if(O.flags_1 & DROPDEL_1)
O.flags_1 &= ~DROPDEL_1 //we shouldn't HAVE things with DROPDEL_1 in our modules, but better safe than runtiming horribly
if(O.flags_1 & DROPDEL_1)
O.flags_1 &= ~DROPDEL_1 //we shouldn't HAVE things with DROPDEL_1 in our modules, but better safe than runtiming horribly
O.dropped(src)
@@ -62,12 +50,6 @@
if(activated(O))
to_chat(src, "<span class='warning'>That module is already activated.</span>")
return
if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = 1
update_icons()
if(istype(O,/obj/item/gun/energy/disabler/cyborg))
disabler = 1
update_icons()
if(!held_items[1])
held_items[1] = O
O.screen_loc = inv1.screen_loc
@@ -194,7 +176,8 @@
//toggle_module(module) - Toggles the selection of the module slot specified by "module".
/mob/living/silicon/robot/proc/toggle_module(module) //Module is 1-3
if(module < 1 || module > 3) return
if(module < 1 || module > 3)
return
if(module_selected(module))
deselect_module(module)
@@ -305,6 +305,7 @@
/obj/item/device/multitool/cyborg,
/obj/item/device/t_scanner,
/obj/item/device/analyzer,
/obj/item/device/geiger_counter,
/obj/item/device/assembly/signaler/cyborg,
/obj/item/areaeditor/blueprints/cyborg,
/obj/item/device/electroadaptive_pseudocircuit,
@@ -386,9 +387,9 @@
/obj/item/device/analyzer/nose,
/obj/item/soap/tongue,
/obj/item/device/healthanalyzer,
/obj/item/device/dogborg/sleeper,
/obj/item/device/dogborg/sleeper/medihound,
/obj/item/twohanded/shockpaddles/hound,
/obj/item/reagent_containers/borghypo,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/device/sensor_device)
emag_modules = list(/obj/item/dogborg/pounce)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/medical,
@@ -193,7 +193,7 @@
//Floorbot assemblies
/obj/item/toolbox_tiles
desc = "It's a toolbox with tiles sticking out the top"
desc = "It's a toolbox with tiles sticking out the top."
name = "tiles and toolbox"
icon = 'icons/mob/aibots.dmi'
icon_state = "toolbox_tiles"
@@ -205,7 +205,7 @@
var/created_name = "Floorbot"
/obj/item/toolbox_tiles_sensor
desc = "It's a toolbox with tiles sticking out the top and a sensor attached"
desc = "It's a toolbox with tiles sticking out the top and a sensor attached."
name = "tiles, toolbox and sensor arrangement"
icon = 'icons/mob/aibots.dmi'
icon_state = "toolbox_tiles_sensor"
@@ -347,6 +347,51 @@
S.name = created_name
qdel(src)
//Honkbot Assembly
/obj/item/honkbot_assembly
name = "incomplete honkbot assembly"
desc = "The clown's up to no good once more"
icon = 'icons/mob/aibots.dmi'
icon_state = "honkbot_arm"
var/build_step = ASSEMBLY_FIRST_STEP
var/created_name = "Honkbot"
/obj/item/honkbot_assembly/attackby(obj/item/I, mob/user, params)
if(isprox(I) && (build_step == ASSEMBLY_FIRST_STEP))
if(!user.temporarilyRemoveItemFromInventory(I))
return
build_step++
to_chat(user, "<span class='notice'>You add the [I] to [src]!</span>")
icon_state = "honkbot_proxy"
name = "incomplete Honkbot assembly"
qdel(I)
else if(istype(I, /obj/item/bikehorn) && (build_step == ASSEMBLY_SECOND_STEP))
if(istype(loc, /obj/item/storage/backpack)) //don't build them in your backpacks!
return
if(!user.temporarilyRemoveItemFromInventory(I))
return
to_chat(user, "<span class='notice'>You add the [I] to [src]! Honk!</span>")
var/T = get_turf(loc) //important to spawn on turf.
var/mob/living/simple_animal/bot/honkbot/S = new(drop_location(T))
S.name = created_name
S.spam_flag = TRUE // only long enough to hear the first ping.
addtimer(CALLBACK (S, .mob/living/simple_animal/bot/honkbot/proc/react_ping), 5)
qdel(I)
qdel(src)
else if(istype(I, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
if(!in_range(src, usr) && loc != usr)
return
created_name = t
else return ..()
//Secbot Assembly
/obj/item/secbot_assembly
name = "incomplete securitron assembly"
@@ -444,9 +444,7 @@ Auto Patrol[]"},
var/obj/item/projectile/A = new projectile (loc)
playsound(loc, shoot_sound, 50, 1)
A.current = U
A.yo = U.y - T.y
A.xo = U.x - T.x
A.preparePixelProjectile(target, src)
A.fire()
/mob/living/simple_animal/bot/ed209/attack_alien(mob/living/carbon/alien/user)
@@ -287,11 +287,11 @@
anchored = TRUE
if(PLACE_TILE)
F = scan_target
if(istype(F, /turf/open/floor/plating)) //The floor must not already have a tile.
if(isplatingturf(F)) //The floor must not already have a tile.
result = F
if(REPLACE_TILE)
F = scan_target
if(isfloorturf(F) && !istype(F, /turf/open/floor/plating)) //The floor must already have a tile.
if(isfloorturf(F) && !isplatingturf(F)) //The floor must already have a tile.
result = F
if(FIX_TILE) //Selects only damaged floors.
F = scan_target
@@ -299,7 +299,7 @@
result = F
if(TILE_EMAG) //Emag mode! Rip up the floor and cause breaches to space!
F = scan_target
if(!istype(F, /turf/open/floor/plating))
if(!isplatingturf(F))
result = F
else //If no special processing is needed, simply return the result.
result = scan_target
@@ -329,7 +329,7 @@
else
var/turf/open/floor/F = target_turf
if(F.type != initial(tiletype.turf_type) && (F.broken || F.burnt || istype(F, /turf/open/floor/plating)) || F.type == (initial(tiletype.turf_type) && (F.broken || F.burnt)))
if(F.type != initial(tiletype.turf_type) && (F.broken || F.burnt || isplatingturf(F)) || F.type == (initial(tiletype.turf_type) && (F.broken || F.burnt)))
anchored = TRUE
icon_state = "floorbot-c"
mode = BOT_REPAIRING
@@ -340,7 +340,7 @@
F.burnt = 0
F.ChangeTurf(/turf/open/floor/plasteel)
if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !istype(F, /turf/open/floor/plating))
if(replacetiles && F.type != initial(tiletype.turf_type) && specialtiles && !isplatingturf(F))
anchored = TRUE
icon_state = "floorbot-c"
mode = BOT_REPAIRING
@@ -0,0 +1,372 @@
/mob/living/simple_animal/bot/honkbot
name = "\improper honkbot"
desc = "A little robot. It looks happy with its bike horn."
icon = 'icons/mob/aibots.dmi'
icon_state = "honkbot"
density = FALSE
anchored = FALSE
health = 25
maxHealth = 25
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
pass_flags = PASSMOB
radio_key = /obj/item/device/encryptionkey/headset_service //doesn't have security key
radio_channel = "Service" //Doesn't even use the radio anyway.
bot_type = HONK_BOT
model = "Honkbot"
bot_core_type = /obj/machinery/bot_core/honkbot
window_id = "autohonk"
window_name = "Honkomatic Bike Horn Unit v1.0.7"
data_hud_type = DATA_HUD_SECURITY_BASIC // show jobs
var/honksound = 'sound/items/bikehorn.ogg' //customizable sound
var/spam_flag = FALSE
var/cooldowntime = 30
var/cooldowntimehorn = 10
var/mob/living/carbon/target
var/oldtarget_name
var/target_lastloc = FALSE //Loc of target when arrested.
var/last_found = FALSE //There's a delay
var/threatlevel = FALSE
var/declare_arrests = FALSE // speak, you shall not, unless to Honk
var/idcheck = TRUE
var/fcheck = TRUE
var/check_records = TRUE
var/arrest_type = FALSE
var/weaponscheck = TRUE
/mob/living/simple_animal/bot/honkbot/Initialize()
. = ..()
icon_state = "honkbot[on]"
auto_patrol = TRUE
var/datum/job/clown/J = new/datum/job/clown
access_card.access += J.get_access()
prev_access = access_card.access
/mob/living/simple_animal/bot/honkbot/proc/spam_flag_false() //used for addtimer
spam_flag = FALSE
/mob/living/simple_animal/bot/honkbot/proc/blink_end() //used for addtimer
icon_state = "honkbot[on]"
/mob/living/simple_animal/bot/honkbot/proc/sensor_blink()
icon_state = "honkbot-c"
addtimer(CALLBACK(src, .proc/blink_end), 5)
//honkbots react with sounds.
/mob/living/simple_animal/bot/honkbot/proc/react_ping()
playsound(src, 'sound/machines/ping.ogg', 50, 1, -1) //the first sound upon creation!
spam_flag = TRUE
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), 18) // calibrates before starting the honk
/mob/living/simple_animal/bot/honkbot/proc/react_buzz()
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1, -1)
sensor_blink()
/mob/living/simple_animal/bot/honkbot/bot_reset()
..()
target = null
oldtarget_name = null
anchored = FALSE
walk_to(src,0)
last_found = world.time
spam_flag = FALSE
/mob/living/simple_animal/bot/honkbot/set_custom_texts()
text_hack = "You overload [name]'s sound control system"
text_dehack = "You reboot [name] and restore the sound control system."
text_dehack_fail = "[name] refuses to accept your authority!"
/mob/living/simple_animal/bot/honkbot/get_controls(mob/user)
var/dat
dat += hack(user)
dat += showpai(user)
dat += text({"
<TT><B>Honkomatic Bike Horn Unit v1.0.7 controls</B></TT><BR><BR>
Status: []<BR>
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
Maintenance panel panel is [open ? "opened" : "closed"]"},
"<A href='?src=\ref[src];power=[TRUE]'>[on ? "On" : "Off"]</A>" )
if(!locked || issilicon(user) || IsAdminGhost(user))
dat += text({"<BR> Auto Patrol: []"},
"<A href='?src=\ref[src];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
return dat
/mob/living/simple_animal/bot/honkbot/proc/judgement_criteria()
var/final = NONE
if(check_records)
final = final|JUDGE_RECORDCHECK
if(emagged)
final = final|JUDGE_EMAGGED
return final
/mob/living/simple_animal/bot/honkbot/proc/retaliate(mob/living/carbon/human/H)
var/judgement_criteria = judgement_criteria()
threatlevel = H.assess_threat(judgement_criteria)
threatlevel += 6
if(threatlevel >= 4)
target = H
mode = BOT_HUNT
/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
if(H.a_intent == "harm")
retaliate(H)
addtimer(CALLBACK(src, .proc/react_buzz), 5)
return ..()
/mob/living/simple_animal/bot/honkbot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM).
return
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Check for welding tool to fix #2432.
retaliate(user)
addtimer(CALLBACK(src, .proc/react_buzz), 5)
..()
/mob/living/simple_animal/bot/honkbot/emag_act(mob/user)
..()
if(emagged == 2)
if(user)
user << "<span class='danger'>You short out [src]'s sound control system. It gives out an evil laugh!!</span>"
oldtarget_name = user.name
audible_message("<span class='danger'>[src] gives out an evil laugh!</span>")
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 75, 1, -1) // evil laughter
icon_state = "honkbot[on]"
/mob/living/simple_animal/bot/honkbot/bullet_act(obj/item/projectile/Proj)
if((istype(Proj,/obj/item/projectile/beam)) || (istype(Proj,/obj/item/projectile/bullet) && (Proj.damage_type == BURN))||(Proj.damage_type == BRUTE) && (!Proj.nodamage && Proj.damage < health))
retaliate(Proj.firer)
..()
/mob/living/simple_animal/bot/honkbot/UnarmedAttack(atom/A)
if(!on)
return
if(iscarbon(A))
var/mob/living/carbon/C = A
if (emagged <= 1)
honk_attack(A)
else
if(!C.IsStun() || arrest_type)
stun_attack(A)
..()
else if (!spam_flag) //honking at the ground
bike_horn(A)
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
playsound(src, honksound, 50, 1, -1)
var/obj/item/I = AM
if(I.throwforce < health && I.thrownby && (istype(I.thrownby, /mob/living/carbon/human)))
var/mob/living/carbon/human/H = I.thrownby
retaliate(H)
..()
/mob/living/simple_animal/bot/honkbot/proc/bike_horn() //use bike_horn
if (emagged <= 1)
if (!spam_flag)
playsound(src, honksound, 50, 1, -1)
spam_flag = TRUE //prevent spam
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
else if (emagged == 2) //emagged honkbots will spam short and memorable sounds.
if (!spam_flag)
playsound(src, "honkbot_e", 50, 0)
spam_flag = TRUE // prevent spam
icon_state = "honkbot-e"
addtimer(CALLBACK(src, .proc/blink_end), 30)
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
/mob/living/simple_animal/bot/honkbot/proc/honk_attack(mob/living/carbon/C) // horn attack
if(!spam_flag)
playsound(loc, honksound, 50, 1, -1)
spam_flag = TRUE // prevent spam
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
/mob/living/simple_animal/bot/honkbot/proc/stun_attack(mob/living/carbon/C) // airhorn stun
if(!spam_flag)
playsound(loc, 'sound/items/AirHorn.ogg', 100, 1, -1) //HEEEEEEEEEEEENK!!
sensor_blink()
if(spam_flag == 0)
if(ishuman(C))
C.stuttering = 20
C.adjustEarDamage(0, 5) //far less damage than the H.O.N.K.
C.Jitter(50)
C.Knockdown(60)
var/mob/living/carbon/human/H = C
if(client) //prevent spam from players..
spam_flag = TRUE
if (emagged <= 1) //HONK once, then leave
var/judgement_criteria = judgement_criteria()
threatlevel = H.assess_threat(judgement_criteria)
threatlevel -= 6
target = oldtarget_name
else // you really don't want to hit an emagged honkbot
threatlevel = 6 // will never let you go
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntime)
add_logs(src,C,"honked")
C.visible_message("<span class='danger'>[src] has honked [C]!</span>",\
"<span class='userdanger'>[src] has honked you!</span>")
else
C.stuttering = 20
C.Knockdown(80)
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntime)
/mob/living/simple_animal/bot/honkbot/handle_automated_action()
if(!..())
return
switch(mode)
if(BOT_IDLE) // idle
walk_to(src,0)
look_for_perp()
if(!mode && auto_patrol)
mode = BOT_START_PATROL
if(BOT_HUNT)
// if can't reach perp for long enough, go idle
if(frustration >= 5) //gives up easier than beepsky
walk_to(src,0)
back_to_idle()
return
if(target) // make sure target exists
if(Adjacent(target) && isturf(target.loc))
if(threatlevel <= 4)
honk_attack(target)
else
if(threatlevel >= 6)
set waitfor = 0
stun_attack(target)
anchored = FALSE
target_lastloc = target.loc
return
else // not next to perp
var/turf/olddist = get_dist(src, target)
walk_to(src, target,1,4)
if((get_dist(src, target)) >= (olddist))
frustration++
else
frustration = 0
else
back_to_idle()
if(BOT_START_PATROL)
look_for_perp()
start_patrol()
if(BOT_PATROL)
look_for_perp()
bot_patrol()
return
/mob/living/simple_animal/bot/honkbot/proc/back_to_idle()
anchored = FALSE
mode = BOT_IDLE
target = null
last_found = world.time
frustration = 0
INVOKE_ASYNC(src, .proc/handle_automated_action) //responds quickly
/mob/living/simple_animal/bot/honkbot/proc/back_to_hunt()
anchored = FALSE
frustration = 0
mode = BOT_HUNT
INVOKE_ASYNC(src, .proc/handle_automated_action) // responds quickly
/mob/living/simple_animal/bot/honkbot/proc/look_for_perp()
anchored = FALSE
for (var/mob/living/carbon/C in view(7,src))
if((C.stat) || (C.handcuffed))
continue
if((C.name == oldtarget_name) && (world.time < last_found + 100))
continue
var/judgement_criteria = judgement_criteria()
threatlevel = C.assess_threat(judgement_criteria)
if(threatlevel <= 3)
if(C in view(4,src)) //keep the range short for patrolling
if(!spam_flag)
bike_horn()
else if(threatlevel >= 10)
bike_horn() //just spam the shit outta this
else if(threatlevel >= 4)
if(!spam_flag)
target = C
oldtarget_name = C.name
bike_horn()
speak("Honk!")
visible_message("<b>[src]</b> starts chasing [C.name]!")
mode = BOT_HUNT
INVOKE_ASYNC(src, .proc/handle_automated_action)
break
else
continue
/mob/living/simple_animal/bot/honkbot/explode()
walk_to(src,0)
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
//doesn't drop cardboard nor its assembly, since its a very frail material.
if(prob(50))
new /obj/item/bodypart/l_arm/robot/(Tsec)
new /obj/item/bikehorn(Tsec)
new /obj/item/device/assembly/prox_sensor(Tsec)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, 1, src)
s.start()
new /obj/effect/decal/cleanable/oil(loc)
..()
/mob/living/simple_animal/bot/honkbot/attack_alien(var/mob/living/carbon/alien/user as mob)
..()
if(!isalien(target))
target = user
mode = BOT_HUNT
/mob/living/simple_animal/bot/honkbot/Crossed(atom/movable/AM)
if(ismob(AM) && (on)) //only if its online
if(prob(30)) //you're far more likely to trip on a honkbot
var/mob/living/carbon/C = AM
if(!istype(C) || !C || in_range(src, target))
return
C.visible_message("<span class='warning'>[pick( \
"[C] dives out of [src]'s way!", \
"[C] stumbles over [src]!", \
"[C] jumps out of [src]'s path!", \
"[C] trips over [src] and falls!", \
"[C] topples over [src]!", \
"[C] leaps out of [src]'s way!")]</span>")
C.Knockdown(10)
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, 1, -1)
if(!client)
speak("Honk!")
sensor_blink()
return
..()
/obj/machinery/bot_core/honkbot
req_one_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
@@ -490,7 +490,8 @@
var/oldloc = loc
var/moved = step_towards(src, next) // attempt to move
if(cell) cell.use(1)
if(cell)
cell.use(1)
if(moved && oldloc!=loc) // successful move
blockcount = 0
path -= loc
@@ -145,7 +145,6 @@
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.current = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
@@ -38,7 +38,7 @@
/mob/living/simple_animal/pet/cat/update_canmove()
..()
if(client)
if(client && stat != DEAD)
if (resting)
icon_state = "[icon_living]_rest"
else
@@ -63,7 +63,8 @@
/mob/living/simple_animal/pet/dog/corgi/show_inv(mob/user)
user.set_machine(src)
if(user.stat) return
if(user.stat)
return
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
if(inventory_head)
@@ -123,7 +124,8 @@
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
if(usr.stat) return
if(usr.stat)
return
//Removing from inventory
if(href_list["remove_inv"])
@@ -460,7 +460,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/obj/item/guardiancreator
name = "deck of tarot cards"
desc = "An enchanted deck of tarot cards, rumored to be a source of unimaginable power. "
desc = "An enchanted deck of tarot cards, rumored to be a source of unimaginable power."
icon = 'icons/obj/toy.dmi'
icon_state = "deck_syndicate_full"
var/used = FALSE
@@ -49,6 +49,8 @@
var/idle = 0
var/isqueen = FALSE
var/icon_base = "bee"
var/static/beehometypecache = typecacheof(/obj/structure/beebox)
var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics)
/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0)
@@ -118,7 +120,7 @@
if(istype(A, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/Hydro = A
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit)
wanted_objects |= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
wanted_objects |= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
return TRUE
return FALSE
@@ -132,8 +134,9 @@
if(target == beehome)
var/obj/structure/beebox/BB = target
forceMove(BB)
toggle_ai(AI_IDLE)
target = null
wanted_objects -= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home
return //no don't attack the goddamm box
else
. = ..()
@@ -157,7 +160,7 @@
return
target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity
wanted_objects -= typecacheof(/obj/machinery/hydroponics) //so we only hunt them while they're alive/seeded/not visisted
wanted_objects -= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
Hydro.recent_bee_visit = TRUE
spawn(BEE_TRAY_RECENT_VISIT)
if(Hydro)
@@ -187,12 +190,13 @@
if(loc == beehome)
idle = min(100, ++idle)
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
toggle_ai(AI_ON)
forceMove(beehome.drop_location())
else
idle = max(0, --idle)
if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
if(!FindTarget())
wanted_objects |= typecacheof(/obj/structure/beebox) //so we don't attack beeboxes when not going home
wanted_objects |= beehometypecache //so we don't attack beeboxes when not going home
target = beehome
if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home
for(var/obj/structure/beebox/BB in view(vision_range, src))
@@ -285,3 +289,11 @@
QDEL_NULL(queen)
return ..()
/mob/living/simple_animal/hostile/poison/bees/consider_wakeup()
if (beehome && loc == beehome) // If bees are chilling in their nest, they're not actively looking for targets
idle = min(100, ++idle)
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
toggle_ai(AI_ON)
forceMove(beehome.drop_location())
else
..()
@@ -87,7 +87,7 @@
boss.atb.refund(boss_cost)
/mob/living/simple_animal/hostile/boss/paper_wizard/copy
desc = "tis a ruse!"
desc = "'Tis a ruse!"
health = 1
maxHealth = 1
alpha = 200
@@ -1,6 +1,6 @@
/mob/living/simple_animal/hostile/faithless
name = "The Faithless"
desc = "The Wish Granter's faith in humanity, incarnate"
desc = "The Wish Granter's faith in humanity, incarnate."
icon_state = "faithless"
icon_living = "faithless"
icon_dead = "faithless_dead"
@@ -41,4 +41,4 @@
var/mob/living/carbon/C = target
C.Knockdown(60)
C.visible_message("<span class='danger'>\The [src] knocks down \the [C]!</span>", \
"<span class='userdanger'>\The [src] knocks you down!</span>")
"<span class='userdanger'>\The [src] knocks you down!</span>")
@@ -49,7 +49,6 @@
var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead.
var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses
var/attack_same = 0 //Set us to 1 to allow us to attack our own faction
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such
var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects.
@@ -88,7 +87,7 @@
DestroySurroundings()
if(!MoveToTarget(possible_targets)) //if we lose our target
if(AIShouldSleep(possible_targets)) // we try to acquire a new one
AIStatus = AI_IDLE // otherwise we go idle
toggle_ai(AI_IDLE) // otherwise we go idle
return 1
/mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user)
@@ -289,7 +288,7 @@
target = null
LoseSearchObjects()
if(AIStatus == AI_IDLE)
AIStatus = AI_ON
toggle_ai(AI_ON)
FindTarget()
else if(target != null && prob(40))//No more pulling a mob forever and having a second player attack it, it can switch targets now if it finds a more suitable one
FindTarget()
@@ -362,7 +361,6 @@
else if(projectiletype)
var/obj/item/projectile/P = new projectiletype(startloc)
playsound(src, projectilesound, 100, 1)
P.current = startloc
P.starting = startloc
P.firer = src
P.yo = targeted_atom.y - startloc.y
@@ -370,6 +368,7 @@
if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space
newtonian_move(get_dir(targeted_atom, targets_from))
P.original = targeted_atom
P.preparePixelProjectile(targeted_atom, src)
P.fire()
return P
@@ -424,7 +423,7 @@
if(AI_IDLE)
if(FindTarget(possible_targets, 1))
. = 1
AIStatus = AI_ON //Wake up for more than one Life() cycle.
toggle_ai(AI_ON) //Wake up for more than one Life() cycle.
else
. = 0
@@ -455,3 +454,9 @@
if(!value)
value = initial(search_objects)
search_objects = value
/mob/living/simple_animal/hostile/consider_wakeup()
..()
if(AIStatus == AI_IDLE && FindTarget(ListTargets(), 1))
toggle_ai(AI_ON)
@@ -209,7 +209,7 @@
/obj/effect/temp_visual/mook_dust
name = "dust"
desc = "it's just a dust cloud!"
desc = "It's just a dust cloud!"
icon = 'icons/mob/jungle/mook.dmi'
icon_state = "mook_leap_cloud"
layer = BELOW_MOB_LAYER
@@ -182,12 +182,7 @@
return
var/turf/our_turf = get_turf(src)
var/obj/item/projectile/seedling/readied_shot = new /obj/item/projectile/seedling(our_turf)
readied_shot.current = our_turf
readied_shot.starting = our_turf
readied_shot.firer = src
readied_shot.original = target
readied_shot.yo = target.y - our_turf.y + rand(-1,1)
readied_shot.xo = target.x - our_turf.x + rand(-1,1)
readied_shot.preparePixelProjectile(target, src, null, rand(-10, 10))
readied_shot.fire()
playsound(src, projectilesound, 100, 1)
@@ -93,7 +93,7 @@ Difficulty: Medium
return ..()
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner/Move(atom/newloc)
if(dashing || (newloc && newloc.z == z && (istype(newloc, /turf/open/lava) || istype(newloc, /turf/open/chasm)))) //we're not stupid!
if(dashing || (newloc && newloc.z == z && (islava(newloc) || ischasm(newloc)))) //we're not stupid!
return FALSE
return ..()
@@ -186,7 +186,7 @@ Difficulty: Medium
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 && !istype(O, /turf/open/lava) && !istype(O, /turf/open/chasm))
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))
@@ -164,7 +164,6 @@ Difficulty: Very Hard
return
var/turf/startloc = get_turf(src)
var/obj/item/projectile/P = new /obj/item/projectile/colossus(startloc)
P.current = startloc
P.starting = startloc
P.firer = src
if(marker)
@@ -758,7 +757,7 @@ Difficulty: Very Hard
/obj/effect/proc_holder/spell/targeted/exit_possession
name = "Exit Possession"
desc = "Exits the body you are possessing"
desc = "Exits the body you are possessing."
charge_max = 60
clothes_req = 0
invocation_type = "none"
@@ -129,7 +129,7 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/CanAttack(atom/the_target)
. = ..()
if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permenant targets
if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permanent targets
return FALSE
/mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target)
@@ -137,14 +137,14 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
/mob/living/simple_animal/hostile/swarmer/ai/Move(atom/newloc)
if(newloc)
if(newloc.z == z) //so these actions are Z-specific
if(istype(newloc, /turf/open/lava))
if(islava(newloc))
var/turf/open/lava/L = newloc
if(!L.is_safe())
StartAction(20)
new /obj/structure/lattice/catwalk/swarmer_catwalk(newloc)
return FALSE
if(istype(newloc, /turf/open/chasm) && !throwing)
if(ischasm(newloc) && !throwing)
throw_at(get_edge_target_turf(src, get_dir(src, newloc)), 7 , 3, spin = FALSE) //my planet needs me
return FALSE
@@ -299,7 +299,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
//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."
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"
@@ -1,6 +1,6 @@
/mob/living/simple_animal/hostile/retaliate/clown
name = "Clown"
desc = "A denizen of clown planet"
desc = "A denizen of clown planet."
icon = 'icons/mob/simple_human.dmi'
icon_state = "clown"
icon_living = "clown"
@@ -2,7 +2,7 @@
/mob/living/simple_animal/hostile/statue
name = "statue" // matches the name of the statue with the flesh-to-stone spell
desc = "An incredibly lifelike marble carving. Its eyes seems to follow you.." // same as an ordinary statue with the added "eye following you" description
desc = "An incredibly lifelike marble carving. Its eyes seem to follow you.." // same as an ordinary statue with the added "eye following you" description
icon = 'icons/obj/statue.dmi'
icon_state = "human_male"
icon_living = "human_male"
@@ -62,7 +62,7 @@
/mob/living/simple_animal/hostile/tree/festivus
name = "festivus pole"
desc = "serenity now... SERENITY NOW!"
desc = "Serenity now... SERENITY NOW!"
icon_state = "festivus_pole"
icon_living = "festivus_pole"
icon_dead = "festivus_pole"
@@ -514,7 +514,8 @@
return
walk_to(src, parrot_interest, 1, parrot_speed)
if(isStuck()) return
if(isStuck())
return
return
@@ -534,7 +535,8 @@
return
walk_to(src, parrot_perch, 1, parrot_speed)
if(isStuck()) return
if(isStuck())
return
return
@@ -547,7 +549,8 @@
walk_away(src, parrot_interest, 1, parrot_speed)
/*if(parrot_been_shot > 0)
parrot_been_shot-- didn't work anyways, and besides, any bullet poly survives isn't worth the speed boost.*/
if(isStuck()) return
if(isStuck())
return
return
@@ -586,7 +589,8 @@
//Otherwise, fly towards the mob!
else
walk_to(src, parrot_interest, 1, parrot_speed)
if(isStuck()) return
if(isStuck())
return
return
//-----STATE MISHAP
@@ -901,9 +905,6 @@
/mob/living/simple_animal/parrot/Poly/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
rounds_survived = max(++rounds_survived,1)
if(rounds_survived > longest_survival)
longest_survival = rounds_survived
Write_Memory(FALSE)
memory_saved = TRUE
..()
@@ -969,7 +970,7 @@
/mob/living/simple_animal/parrot/Poly/ghost
name = "The Ghost of Poly"
desc = "Doomed to squawk the earth."
desc = "Doomed to squawk the Earth."
color = "#FFFFFF77"
speak_chance = 20
status_flags = GODMODE
@@ -1004,7 +1005,6 @@
parrot_interest = null
H.visible_message("<span class='danger'>[src] dive bombs into [H]'s chest and vanishes!</span>", "<span class='userdanger'>[src] dive bombs into your chest, vanishing! This can't be good!</span>")
/mob/living/simple_animal/parrot/clock_hawk
name = "clock hawk"
desc = "Cbyl jnaan penpxre! Fdhnnnjx!"
@@ -1,7 +1,7 @@
/mob/living/simple_animal/shade
name = "Shade"
real_name = "Shade"
desc = "A bound spirit"
desc = "A bound spirit."
gender = PLURAL
icon = 'icons/mob/mob.dmi'
icon_state = "shade"
@@ -82,6 +82,10 @@
var/dextrous_hud_type = /datum/hud/dextrous
var/datum/personal_crafting/handcrafting
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
var/shouldwakeup = FALSE //convenience var for forcibly waking up an idling AI on next check.
//domestication
var/tame = 0
@@ -89,7 +93,7 @@
/mob/living/simple_animal/Initialize()
. = ..()
GLOB.simple_animals += src
GLOB.simple_animals[AIStatus] += src
handcrafting = new()
if(gender == PLURAL)
gender = pick(MALE,FEMALE)
@@ -102,7 +106,7 @@
verbs |= /mob/living/proc/animal_nom
/mob/living/simple_animal/Destroy()
GLOB.simple_animals -= src
GLOB.simple_animals[AIStatus] -= src
return ..()
/mob/living/simple_animal/updatehealth()
@@ -281,6 +285,7 @@
return 1
/mob/living/simple_animal/death(gibbed)
movement_type &= ~FLYING
if(nest)
nest.spawned_mobs -= src
nest = null
@@ -336,6 +341,7 @@
density = initial(density)
lying = 0
. = 1
movement_type = initial(movement_type)
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress())
@@ -422,7 +428,7 @@
/mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion
return
toggle_ai(AI_OFF) // To prevent any weirdness.
/mob/living/simple_animal/update_sight()
if(!client)
@@ -545,3 +551,23 @@
/mob/living/simple_animal/buckle_mob(mob/living/buckled_mob, force = 0, check_loc = 1)
. = ..()
riding_datum = new/datum/riding/animal
/mob/living/simple_animal/proc/toggle_ai(togglestatus)
if (AIStatus != togglestatus)
if (togglestatus > 0 && togglestatus < 4)
GLOB.simple_animals[AIStatus] -= src
GLOB.simple_animals[togglestatus] += src
AIStatus = togglestatus
else
stack_trace("Something attempted to set simple animals AI to an invalid state: [togglestatus]")
/mob/living/simple_animal/proc/consider_wakeup()
if (pulledby || shouldwakeup)
toggle_ai(AI_ON)
/mob/living/simple_animal/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
. = ..()
if(!ckey && !stat)//Not unconscious
if(AIStatus == AI_IDLE)
toggle_ai(AI_ON)
@@ -30,7 +30,7 @@
spawned_mobs = null
return ..()
/mob/living/simple_animal/hostile/spawner/handle_automated_action()
/mob/living/simple_animal/hostile/spawner/Life()
. = ..()
spawn_mob()