Merge remote-tracking branch 'upstream/master' into the-p-o-o-l
This commit is contained in:
@@ -159,6 +159,11 @@
|
||||
color_src = MATRIXED
|
||||
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
|
||||
|
||||
/datum/sprite_accessory/ears/bunny
|
||||
name = "Bunny"
|
||||
icon_state = "bunny"
|
||||
color_src = MATRIXED
|
||||
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
|
||||
|
||||
/******************************************
|
||||
*************** Furry Ears ****************
|
||||
@@ -301,3 +306,7 @@
|
||||
/datum/sprite_accessory/mam_ears/wolf
|
||||
name = "Wolf"
|
||||
icon_state = "wolf"
|
||||
|
||||
/datum/sprite_accessory/mam_ears/bunny
|
||||
name = "Bunny"
|
||||
icon_state = "bunny"
|
||||
@@ -24,7 +24,7 @@
|
||||
/datum/notificationpanel/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "notificationpanel", "Notification Preferences", 700, 700, master_ui, state)
|
||||
ui = new(user, src, ui_key, "notificationpanel", "Notification Preferences", 270, 360, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/datum/notificationpanel/ui_data(mob/user)
|
||||
|
||||
@@ -232,14 +232,16 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
var/b_val
|
||||
var/g_val
|
||||
var/color_format = length(input_color)
|
||||
if(color_format != length_char(input_color))
|
||||
return 0
|
||||
if(color_format == 3)
|
||||
r_val = hex2num(copytext(input_color, 1, 2))*16
|
||||
g_val = hex2num(copytext(input_color, 2, 3))*16
|
||||
b_val = hex2num(copytext(input_color, 3, 0))*16
|
||||
r_val = hex2num(copytext(input_color, 1, 2)) * 16
|
||||
g_val = hex2num(copytext(input_color, 2, 3)) * 16
|
||||
b_val = hex2num(copytext(input_color, 3, 0)) * 16
|
||||
else if(color_format == 6)
|
||||
r_val = hex2num(copytext(input_color, 1, 3))
|
||||
g_val = hex2num(copytext(input_color, 3, 5))
|
||||
b_val = hex2num(copytext(input_color, 5, 0))
|
||||
b_val = hex2num(copytext(input_color, 5, 7))
|
||||
else
|
||||
return 0 //If the color format is not 3 or 6, you're using an unexpected way to represent a color.
|
||||
|
||||
@@ -253,7 +255,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
if(b_val > 255)
|
||||
b_val = 255
|
||||
|
||||
return num2hex(r_val, 2) + num2hex(g_val, 2) + num2hex(b_val, 2)
|
||||
return copytext(rgb(r_val, g_val, b_val), 2)
|
||||
|
||||
/*
|
||||
Transfer_mind is there to check if mob is being deleted/not going to have a body.
|
||||
@@ -263,7 +265,7 @@ Works together with spawning an observer, noted above.
|
||||
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE)
|
||||
penalize = suiciding || penalize // suicide squad.
|
||||
voluntary_ghosted = voluntary
|
||||
if(!key || cmptext(copytext(key,1,2),"@") || (SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize) & COMPONENT_BLOCK_GHOSTING))
|
||||
if(!key || key[1] == "@" || (SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize) & COMPONENT_BLOCK_GHOSTING))
|
||||
return //mob has no key, is an aghost or some component hijacked.
|
||||
stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now
|
||||
var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc.
|
||||
@@ -365,7 +367,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(!can_reenter_corpse)
|
||||
to_chat(src, "<span class='warning'>You cannot re-enter your body.</span>")
|
||||
return
|
||||
if(mind.current.key && copytext(mind.current.key,1,2)!="@") //makes sure we don't accidentally kick any clients
|
||||
if(mind.current.key && mind.current.key[1] != "@") //makes sure we don't accidentally kick any clients
|
||||
to_chat(usr, "<span class='warning'>Another consciousness is in your body...It is resisting you.</span>")
|
||||
return
|
||||
client.change_view(CONFIG_GET(string/default_view))
|
||||
@@ -794,7 +796,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
update_icon()
|
||||
|
||||
/mob/dead/observer/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
return IsAdminGhost(usr)
|
||||
return IsAdminGhost(usr) || (M.ghost_flags & INTERACT_GHOST_READ)
|
||||
|
||||
/mob/dead/observer/is_literate()
|
||||
return 1
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/mob/dead/observer/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
if (!message)
|
||||
return
|
||||
|
||||
var/message_mode = get_message_mode(message)
|
||||
if(client && (message_mode == MODE_ADMIN || message_mode == MODE_DEADMIN))
|
||||
message = copytext(message, 3)
|
||||
if(findtext(message, " ", 1, 2))
|
||||
message = copytext(message, 2)
|
||||
message = copytext_char(message, 3)
|
||||
message = trim_left(message)
|
||||
|
||||
if(message_mode == MODE_ADMIN)
|
||||
client.cmd_admin_say(message)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
var/param = message
|
||||
var/custom_param = findchar(act, " ")
|
||||
if(custom_param)
|
||||
param = copytext(act, custom_param + 1, length(act) + 1)
|
||||
param = copytext(act, custom_param + length(act[custom_param]))
|
||||
act = copytext(act, 1, custom_param)
|
||||
|
||||
var/datum/emote/E
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
bleed_rate = 0
|
||||
return
|
||||
|
||||
if(bleed_rate <= 0)
|
||||
if(bleed_rate < 0)
|
||||
bleed_rate = 0
|
||||
|
||||
if(HAS_TRAIT(src, TRAIT_NOMARROW)) //Bloodsuckers don't need to be here.
|
||||
@@ -94,12 +94,12 @@
|
||||
|
||||
//We want an accurate reading of .len
|
||||
listclearnulls(BP.embedded_objects)
|
||||
temp_bleed += 0.5*BP.embedded_objects.len
|
||||
temp_bleed += 0.5 * BP.embedded_objects.len
|
||||
|
||||
if(brutedamage >= 20)
|
||||
temp_bleed += (brutedamage * 0.013)
|
||||
|
||||
bleed_rate = max(bleed_rate - 0.50, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
|
||||
bleed_rate = max(bleed_rate - 0.5, temp_bleed)//if no wounds, other bleed effects (heparin) naturally decreases
|
||||
|
||||
if(bleed_rate && !bleedsuppress && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
bleed(bleed_rate)
|
||||
@@ -185,7 +185,7 @@
|
||||
var/datum/disease/D = thing
|
||||
blood_data["viruses"] += D.Copy()
|
||||
|
||||
blood_data["blood_DNA"] = copytext(dna.unique_enzymes,1,0)
|
||||
blood_data["blood_DNA"] = dna.unique_enzymes
|
||||
blood_data["bloodcolor"] = bloodtype_to_color(dna.blood_type)
|
||||
if(disease_resistances && disease_resistances.len)
|
||||
blood_data["resistances"] = disease_resistances.Copy()
|
||||
@@ -204,7 +204,7 @@
|
||||
|
||||
if(!suiciding)
|
||||
blood_data["cloneable"] = 1
|
||||
blood_data["blood_type"] = copytext(dna.blood_type,1,0)
|
||||
blood_data["blood_type"] = dna.blood_type
|
||||
blood_data["gender"] = gender
|
||||
blood_data["real_name"] = real_name
|
||||
blood_data["features"] = dna.features
|
||||
@@ -289,8 +289,7 @@
|
||||
drop.update_icon()
|
||||
return
|
||||
else
|
||||
temp_blood_DNA = list()
|
||||
temp_blood_DNA |= drop.blood_DNA.Copy() //we transfer the dna from the drip to the splatter
|
||||
temp_blood_DNA = drop.blood_DNA.Copy() //transfer dna from drip to splatter.
|
||||
qdel(drop)//the drip is replaced by a bigger splatter
|
||||
else
|
||||
drop = new(T, get_static_viruses())
|
||||
|
||||
@@ -55,16 +55,18 @@
|
||||
//Update the body's icon so it doesnt appear debrained anymore
|
||||
C.update_hair()
|
||||
|
||||
/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE)
|
||||
..()
|
||||
/obj/item/organ/brain/Remove(special = FALSE, no_id_transfer = FALSE)
|
||||
. = ..()
|
||||
var/mob/living/carbon/C = .
|
||||
for(var/X in traumas)
|
||||
var/datum/brain_trauma/BT = X
|
||||
BT.on_lose(TRUE)
|
||||
BT.owner = null
|
||||
|
||||
if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !no_id_transfer)
|
||||
if((!QDELETED(src) || C) && !no_id_transfer)
|
||||
transfer_identity(C)
|
||||
C.update_hair()
|
||||
if(C)
|
||||
C.update_hair()
|
||||
|
||||
/obj/item/organ/brain/prepare_eat()
|
||||
return // Too important to eat.
|
||||
@@ -389,6 +391,7 @@
|
||||
if(resilience)
|
||||
actual_trauma.resilience = resilience
|
||||
SSblackbox.record_feedback("tally", "traumas", 1, actual_trauma.type)
|
||||
return actual_trauma
|
||||
|
||||
//Add a random trauma of a certain subtype
|
||||
/obj/item/organ/brain/proc/gain_trauma_type(brain_trauma_type = /datum/brain_trauma, resilience)
|
||||
|
||||
@@ -120,7 +120,8 @@ Des: Removes all infected images from the alien.
|
||||
/mob/living/carbon/alien/proc/RemoveInfectionImages()
|
||||
if (client)
|
||||
for(var/image/I in client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected"))
|
||||
var/searchfor = "infected"
|
||||
if(findtext(I.icon_state, searchfor, 1, length(searchfor) + 1))
|
||||
qdel(I)
|
||||
return
|
||||
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
M.AddAbility(P)
|
||||
|
||||
|
||||
/obj/item/organ/alien/Remove(mob/living/carbon/M, special = 0)
|
||||
for(var/obj/effect/proc_holder/alien/P in alien_powers)
|
||||
M.RemoveAbility(P)
|
||||
/obj/item/organ/alien/Remove(special = FALSE)
|
||||
if(owner)
|
||||
for(var/obj/effect/proc_holder/alien/P in alien_powers)
|
||||
owner.RemoveAbility(P)
|
||||
..()
|
||||
|
||||
/obj/item/organ/alien/prepare_eat()
|
||||
@@ -100,11 +101,11 @@
|
||||
var/mob/living/carbon/alien/A = M
|
||||
A.updatePlasmaDisplay()
|
||||
|
||||
/obj/item/organ/alien/plasmavessel/Remove(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
if(isalien(M))
|
||||
var/mob/living/carbon/alien/A = M
|
||||
/obj/item/organ/alien/plasmavessel/Remove(special = FALSE)
|
||||
if(owner && isalien(owner))
|
||||
var/mob/living/carbon/alien/A = owner
|
||||
A.updatePlasmaDisplay()
|
||||
return ..()
|
||||
|
||||
#define QUEEN_DEATH_DEBUFF_DURATION 2400
|
||||
|
||||
@@ -121,9 +122,10 @@
|
||||
..()
|
||||
M.faction |= ROLE_ALIEN
|
||||
|
||||
/obj/item/organ/alien/hivenode/Remove(mob/living/carbon/M, special = 0)
|
||||
M.faction -= ROLE_ALIEN
|
||||
..()
|
||||
/obj/item/organ/alien/hivenode/Remove(special = FALSE)
|
||||
if(owner)
|
||||
owner.faction -= ROLE_ALIEN
|
||||
return ..()
|
||||
|
||||
//When the alien queen dies, all aliens suffer a penalty as punishment for failing to protect her.
|
||||
/obj/item/organ/alien/hivenode/proc/queen_death()
|
||||
|
||||
@@ -135,5 +135,6 @@ Des: Removes all images from the mob infected by this embryo
|
||||
for(var/mob/living/carbon/alien/alien in GLOB.player_list)
|
||||
if(alien.client)
|
||||
for(var/image/I in alien.client.images)
|
||||
if(dd_hasprefix_case(I.icon_state, "infected") && I.loc == C)
|
||||
var/searchfor = "infected"
|
||||
if(I.loc == owner && findtext(I.icon_state, searchfor, 1, length(searchfor) + 1))
|
||||
qdel(I)
|
||||
|
||||
@@ -252,7 +252,9 @@
|
||||
return 0
|
||||
if(M.getorgan(/obj/item/organ/alien/hivenode))
|
||||
return 0
|
||||
|
||||
if(isvamp(M))
|
||||
return 0
|
||||
|
||||
if(ismonkey(M))
|
||||
return 1
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
|
||||
dat += "<BR><B>Back:</B> <A href='?src=[REF(src)];item=[SLOT_BACK]'>[back ? back : "Nothing"]</A>"
|
||||
|
||||
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
|
||||
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS) && istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
|
||||
dat += "<BR><A href='?src=[REF(src)];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
|
||||
|
||||
if(handcuffed)
|
||||
@@ -249,7 +249,7 @@
|
||||
..()
|
||||
//strip panel
|
||||
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
if(href_list["internal"])
|
||||
if(href_list["internal"] && !HAS_TRAIT(src, TRAIT_NO_INTERNALS))
|
||||
var/slot = text2num(href_list["internal"])
|
||||
var/obj/item/ITEM = get_item_by_slot(slot)
|
||||
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS))
|
||||
@@ -533,7 +533,7 @@
|
||||
break //Guess we're out of organs!
|
||||
var/obj/item/organ/guts = pick(internal_organs)
|
||||
var/turf/T = get_turf(src)
|
||||
guts.Remove(src)
|
||||
guts.Remove()
|
||||
guts.forceMove(T)
|
||||
var/atom/throw_target = get_edge_target_turf(guts, dir)
|
||||
guts.throw_at(throw_target, power, 4, src)
|
||||
@@ -559,7 +559,7 @@
|
||||
health = round(maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute, DAMAGE_PRECISION)
|
||||
staminaloss = round(total_stamina, DAMAGE_PRECISION)
|
||||
update_stat()
|
||||
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD) && stat == DEAD )
|
||||
if(((maxHealth - total_burn) < HEALTH_THRESHOLD_DEAD*2) && stat == DEAD )
|
||||
become_husk("burn")
|
||||
med_hud_set_health()
|
||||
if(stat == SOFT_CRIT)
|
||||
@@ -872,7 +872,7 @@
|
||||
var/obj/item/organ/O = X
|
||||
if(prob(50))
|
||||
organs_amt++
|
||||
O.Remove(src)
|
||||
O.Remove()
|
||||
O.forceMove(drop_location())
|
||||
if(organs_amt)
|
||||
to_chat(user, "<span class='notice'>You retrieve some of [src]\'s internal organs!</span>")
|
||||
@@ -986,4 +986,4 @@
|
||||
if(H.clothing_flags & SCAN_REAGENTS)
|
||||
return TRUE
|
||||
if(isclothing(wear_mask) && (wear_mask.clothing_flags & SCAN_REAGENTS))
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
return
|
||||
|
||||
if(health >= 0 && !(HAS_TRAIT(src, TRAIT_FAKEDEATH)))
|
||||
|
||||
var/friendly_check = FALSE
|
||||
if(lying)
|
||||
if(buckled)
|
||||
to_chat(M, "<span class='warning'>You need to unbuckle [src] first to do that!")
|
||||
@@ -289,39 +289,35 @@
|
||||
playsound(src, 'sound/items/Nose_boop.ogg', 50, 0)
|
||||
|
||||
else if(check_zone(M.zone_selected) == "head")
|
||||
var/mob/living/carbon/human/H = src
|
||||
var/datum/species/pref_species = H.dna.species
|
||||
var/datum/species/S
|
||||
if(ishuman(src))
|
||||
S = dna.species
|
||||
|
||||
M.visible_message("<span class='notice'>[M] gives [H] a pat on the head to make [p_them()] feel better!</span>", \
|
||||
"<span class='notice'>You give [H] a pat on the head to make [p_them()] feel better!</span>")
|
||||
M.visible_message("<span class='notice'>[M] gives [src] a pat on the head to make [p_them()] feel better!</span>", \
|
||||
"<span class='notice'>You give [src] a pat on the head to make [p_them()] feel better!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "headpat", /datum/mood_event/headpat)
|
||||
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
|
||||
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
|
||||
if (mood.sanity >= SANITY_GREAT)
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/besthug, M)
|
||||
else if (mood.sanity >= SANITY_DISTURBED)
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/betterhug, M)
|
||||
if(H.dna.species.can_wag_tail(H))
|
||||
if("tail_human" in pref_species.default_features)
|
||||
if(H.dna.features["tail_human"] == "None")
|
||||
friendly_check = TRUE
|
||||
if(S?.can_wag_tail(src))
|
||||
if("tail_human" in S.default_features)
|
||||
if(dna.features["tail_human"] == "None")
|
||||
return
|
||||
else
|
||||
if(!H.dna.species.is_wagging_tail())
|
||||
H.emote("wag")
|
||||
if(!dna.species.is_wagging_tail())
|
||||
emote("wag")
|
||||
|
||||
if("tail_lizard" in pref_species.default_features)
|
||||
if(H.dna.features["tail_lizard"] == "None")
|
||||
if("tail_lizard" in S.default_features)
|
||||
if(dna.features["tail_lizard"] == "None")
|
||||
return
|
||||
else
|
||||
if(!H.dna.species.is_wagging_tail())
|
||||
H.emote("wag")
|
||||
if(!dna.species.is_wagging_tail())
|
||||
emote("wag")
|
||||
|
||||
if("mam_tail" in pref_species.default_features)
|
||||
if(H.dna.features["mam_tail"] == "None")
|
||||
if("mam_tail" in S.default_features)
|
||||
if(dna.features["mam_tail"] == "None")
|
||||
return
|
||||
else
|
||||
if(!H.dna.species.is_wagging_tail())
|
||||
H.emote("wag")
|
||||
if(!dna.species.is_wagging_tail())
|
||||
emote("wag")
|
||||
|
||||
else
|
||||
return
|
||||
@@ -335,8 +331,11 @@
|
||||
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
|
||||
"<span class='notice'>You hug [src] to make [p_them()] feel better!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "hug", /datum/mood_event/hug)
|
||||
if(HAS_TRAIT(M, TRAIT_FRIENDLY))
|
||||
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
|
||||
friendly_check = TRUE
|
||||
|
||||
if(friendly_check && HAS_TRAIT(M, TRAIT_FRIENDLY))
|
||||
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
|
||||
if(mood)
|
||||
if (mood.sanity >= SANITY_GREAT)
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "friendly_hug", /datum/mood_event/besthug, M)
|
||||
else if (mood.sanity >= SANITY_DISTURBED)
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
//Gets filled up in create_bodyparts()
|
||||
|
||||
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
|
||||
var/list/leg_bodyparts = list()
|
||||
|
||||
var/icon_render_key = ""
|
||||
var/static/list/limb_icon_cache = list()
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
. += SOFTCRIT_ADD_SLOWDOWN
|
||||
|
||||
/mob/living/carbon/slip(knockdown_amount, obj/O, lube)
|
||||
if(movement_type & FLYING)
|
||||
return 0
|
||||
if(movement_type & FLYING && !(lube & FLYING_DOESNT_HELP))
|
||||
return FALSE
|
||||
if(!(lube&SLIDE_ICE))
|
||||
log_combat(src, (O ? O : get_turf(src)), "slipped on the", null, ((lube & SLIDE) ? "(LUBE)" : null))
|
||||
return loc.handle_slip(src, knockdown_amount, O, lube)
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
if(!forced && HAS_TRAIT(src, TRAIT_TOXINLOVER)) //damage becomes healing and healing becomes damage
|
||||
amount = -amount
|
||||
if(amount > 0)
|
||||
blood_volume -= 3*amount // x5 is too much, x3 should be still penalizing enough.
|
||||
blood_volume -= 3 * amount //5x was too much, this is punishing enough.
|
||||
else
|
||||
blood_volume -= amount
|
||||
return ..()
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
continue
|
||||
var/org_zone = check_zone(O.zone) //both groin and chest organs.
|
||||
if(org_zone == BODY_ZONE_CHEST)
|
||||
O.Remove(src)
|
||||
O.Remove()
|
||||
O.forceMove(Tsec)
|
||||
O.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
|
||||
else
|
||||
@@ -55,7 +55,7 @@
|
||||
if(no_organs && !istype(I, /obj/item/organ/brain))
|
||||
qdel(I)
|
||||
continue
|
||||
I.Remove(src)
|
||||
I.Remove()
|
||||
I.forceMove(Tsec)
|
||||
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
|
||||
|
||||
|
||||
@@ -16,10 +16,6 @@
|
||||
. += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face."
|
||||
if (wear_neck)
|
||||
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
|
||||
if(can_be_held)
|
||||
. += "[t_He] looks small enough to be picked up with <b>Alt+Click</b>!\n"
|
||||
|
||||
|
||||
|
||||
for(var/obj/item/I in held_items)
|
||||
if(!(I.item_flags & ABSTRACT))
|
||||
@@ -116,4 +112,5 @@
|
||||
. += "[t_He] look[p_s()] very happy."
|
||||
if(MOOD_LEVEL_HAPPY4 to INFINITY)
|
||||
. += "[t_He] look[p_s()] ecstatic."
|
||||
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
|
||||
. += "*---------*</span>"
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
/mob/living/carbon/human/spawn_gibs(with_bodyparts, atom/loc_override)
|
||||
var/location = loc_override ? loc_override.drop_location() : drop_location()
|
||||
if(dna?.species?.gib_types)
|
||||
var/blood_dna = get_blood_dna_list()
|
||||
var/datum/species/S = dna.species
|
||||
var/length = length(S.gib_types)
|
||||
if(length)
|
||||
var/path = (with_bodyparts && length > 1) ? S.gib_types[2] : S.gib_types[1]
|
||||
new path(location, src, get_static_viruses())
|
||||
else
|
||||
new S.gib_types(location, src, get_static_viruses())
|
||||
new S.gib_types(location, src, get_static_viruses(), blood_dna)
|
||||
else
|
||||
if(with_bodyparts)
|
||||
new /obj/effect/gibspawner/human(location, src, get_static_viruses())
|
||||
@@ -67,4 +68,4 @@
|
||||
/mob/living/carbon/proc/makeUncloneable()
|
||||
ADD_TRAIT(src, TRAIT_NOCLONE, MADE_UNCLONEABLE)
|
||||
blood_volume = 0
|
||||
return TRUE
|
||||
return TRUE
|
||||
|
||||
@@ -396,6 +396,7 @@
|
||||
var/temp_flavor = print_flavor_text_2()
|
||||
if(temp_flavor)
|
||||
. += temp_flavor
|
||||
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
|
||||
. += "*---------*</span>"
|
||||
|
||||
/mob/living/proc/status_effect_examines(pronoun_replacement) //You can include this in any mob's examine() to show the examine texts of status effects!
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/mob/living/carbon/human/proc/examine_nutrition()
|
||||
var/message = ""
|
||||
var/nutrition_examine = round(nutrition)
|
||||
var/t_He = "It" //capitalised for use at the start of each line.
|
||||
var/t_His = "Its"
|
||||
var/t_his = "its"
|
||||
var/t_is = "is"
|
||||
var/t_has = "has"
|
||||
switch(gender)
|
||||
if(MALE)
|
||||
t_He = "He"
|
||||
t_his = "his"
|
||||
t_His = "His"
|
||||
if(FEMALE)
|
||||
t_He = "She"
|
||||
t_his = "her"
|
||||
t_His = "Her"
|
||||
if(PLURAL)
|
||||
t_He = "They"
|
||||
t_his = "their"
|
||||
t_His = "Their"
|
||||
t_is = "are"
|
||||
t_has = "have"
|
||||
if(NEUTER)
|
||||
t_He = "It"
|
||||
t_his = "its"
|
||||
t_His = "Its"
|
||||
switch(nutrition_examine)
|
||||
if(0 to 49)
|
||||
message = "<span class='warning'>[t_He] [t_is] starving! You can hear [t_his] stomach snarling from across the room!</span>\n"
|
||||
if(50 to 99)
|
||||
message = "<span class='warning'>[t_He] [t_is] extremely hungry. A deep growl occasionally rumbles from [t_his] empty stomach.</span>\n"
|
||||
if(100 to 499)
|
||||
return message //Well that's pretty normal, really.
|
||||
if(500 to 864) // Fat.
|
||||
message = "[t_He] [t_has] a stuffed belly, bloated fat and round from eating too much.\n"
|
||||
if(1200 to 1934) // One person fully digested.
|
||||
message = "<span class='warning'>[t_He] [t_is] sporting a large, round, sagging stomach. It's contains at least their body weight worth of glorping slush.</span>\n"
|
||||
if(1935 to 3004) // Two people.
|
||||
message = "<span class='warning'>[t_He] [t_is] engorged with a huge stomach that sags and wobbles as they move. [t_He] must have consumed at least twice their body weight. It looks incredibly soft.</span>\n"
|
||||
if(3005 to 4074) // Three people.
|
||||
message = "<span class='warning'>[t_His] stomach is firmly packed with digesting slop. [t_He] must have eaten at least a few times worth their body weight! It looks hard for them to stand, and [t_his] gut jiggles when they move.</span>\n"
|
||||
if(4075 to 10000) // Four or more people.
|
||||
message = "<span class='warning'>[t_He] [t_is] so absolutely stuffed that you aren't sure how it's possible to move. [t_He] can't seem to swell any bigger. The surface of [t_his] belly looks sorely strained!</span>\n"
|
||||
return message
|
||||
@@ -25,8 +25,7 @@
|
||||
create_internal_organs() //most of it is done in set_species now, this is only for parent call
|
||||
physiology = new()
|
||||
|
||||
handcrafting = new()
|
||||
|
||||
AddComponent(/datum/component/personal_crafting)
|
||||
. = ..()
|
||||
|
||||
if(CONFIG_GET(flag/disable_stambuffer))
|
||||
@@ -45,10 +44,6 @@
|
||||
QDEL_NULL_LIST(vore_organs) // CITADEL EDIT belly stuff
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/carbon/human/OpenCraftingMenu()
|
||||
handcrafting.ui_interact(src)
|
||||
|
||||
/mob/living/carbon/human/prepare_data_huds()
|
||||
//Update med hud images...
|
||||
..()
|
||||
@@ -85,7 +80,7 @@
|
||||
var/obj/item/clothing/suit/space/space_ninja/SN = wear_suit
|
||||
if(statpanel("SpiderOS"))
|
||||
stat("SpiderOS Status:","[SN.s_initialized ? "Initialized" : "Disabled"]")
|
||||
stat("Current Time:", "[STATION_TIME_TIMESTAMP("hh:mm:ss")]")
|
||||
stat("Current Time:", "[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]")
|
||||
if(SN.s_initialized)
|
||||
//Suit gear
|
||||
stat("Energy Charge:", "[round(SN.cell.charge/100)]%")
|
||||
@@ -439,7 +434,7 @@
|
||||
return
|
||||
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss"))
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time))
|
||||
GLOB.data_core.addMinorCrime(R.fields["id"], crime)
|
||||
investigate_log("New Minor Crime: <strong>[t1]</strong>: [t2] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
|
||||
to_chat(usr, "<span class='notice'>Successfully added a minor crime.</span>")
|
||||
@@ -455,7 +450,7 @@
|
||||
return
|
||||
else if (!istype(H.glasses, /obj/item/clothing/glasses/hud/security) && !istype(H.getorganslot(ORGAN_SLOT_HUD), /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
return
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss"))
|
||||
var/crime = GLOB.data_core.createCrimeEntry(t1, t2, allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss", world.time))
|
||||
GLOB.data_core.addMajorCrime(R.fields["id"], crime)
|
||||
investigate_log("New Major Crime: <strong>[t1]</strong>: [t2] | Added to [R.fields["name"]] by [key_name(usr)]", INVESTIGATE_RECORDS)
|
||||
to_chat(usr, "<span class='notice'>Successfully added a major crime.</span>")
|
||||
@@ -488,7 +483,7 @@
|
||||
var/counter = 1
|
||||
while(R.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
|
||||
R.fields["com_[counter]"] = "Made by [allowed_access] on [STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)] [time2text(world.realtime, "MMM DD")], [GLOB.year_integer]<BR>[t1]"
|
||||
to_chat(usr, "<span class='notice'>Successfully added comment.</span>")
|
||||
return
|
||||
to_chat(usr, "<span class='warning'>Unable to locate a data core entry for this person.</span>")
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
|
||||
var/custom_species = null
|
||||
|
||||
var/datum/personal_crafting/handcrafting
|
||||
var/datum/physiology/physiology
|
||||
|
||||
var/list/datum/bioware = list()
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
var/obj/effect/decal/cleanable/blood/footprints/oldFP = locate(/obj/effect/decal/cleanable/blood/footprints) in T
|
||||
if(oldFP && (oldFP.blood_state == S.blood_state && oldFP.color == bloodtype_to_color(S.last_bloodtype)))
|
||||
return
|
||||
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state]-BLOOD_LOSS_PER_STEP)
|
||||
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
|
||||
var/obj/effect/decal/cleanable/blood/footprints/FP = new /obj/effect/decal/cleanable/blood/footprints(T)
|
||||
FP.blood_state = S.blood_state
|
||||
FP.entered_dirs |= dir
|
||||
|
||||
@@ -87,30 +87,22 @@
|
||||
/mob/living/carbon/human/proc/forcesay(list/append) //this proc is at the bottom of the file because quote fuckery makes notepad++ cri
|
||||
if(stat == CONSCIOUS)
|
||||
if(client)
|
||||
var/virgin = 1 //has the text been modified yet?
|
||||
var/temp = winget(client, "input", "text")
|
||||
if(findtextEx(temp, "Say \"", 1, 7) && length(temp) > 5) //"case sensitive means
|
||||
var/say_starter = "Say \"" //"
|
||||
if(findtextEx(temp, say_starter, 1, length(say_starter) + 1) && length(temp) > length(say_starter)) //case sensitive means
|
||||
|
||||
temp = replacetext(temp, ";", "") //general radio
|
||||
temp = trim_left(copytext(temp, length(say_starter) + 1))
|
||||
temp = replacetext(temp, ";", "", 1, 2) //general radio
|
||||
while(trim_left(temp)[1] == ":") //dept radio again (necessary)
|
||||
temp = copytext_char(trim_left(temp), 3)
|
||||
|
||||
if(findtext(trim_left(temp), ":", 6, 7)) //dept radio
|
||||
temp = copytext(trim_left(temp), 8)
|
||||
virgin = 0
|
||||
|
||||
if(virgin)
|
||||
temp = copytext(trim_left(temp), 6) //normal speech
|
||||
virgin = 0
|
||||
|
||||
while(findtext(trim_left(temp), ":", 1, 2)) //dept radio again (necessary)
|
||||
temp = copytext(trim_left(temp), 3)
|
||||
|
||||
if(findtext(temp, "*", 1, 2)) //emotes
|
||||
if(temp[1] == "*") //emotes
|
||||
return
|
||||
|
||||
var/trimmed = trim_left(temp)
|
||||
if(length(trimmed))
|
||||
if(append)
|
||||
temp += pick(append)
|
||||
trimmed += pick(append)
|
||||
|
||||
say(temp)
|
||||
say(trimmed)
|
||||
winset(client, "input", "text=[null]")
|
||||
|
||||
@@ -189,21 +189,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
if(brain && (replace_current || !should_have_brain))
|
||||
if(!brain.decoy_override)//Just keep it if it's fake
|
||||
brain.Remove(C,TRUE,TRUE)
|
||||
brain.Remove(TRUE,TRUE)
|
||||
QDEL_NULL(brain)
|
||||
if(should_have_brain && !brain)
|
||||
brain = new mutant_brain()
|
||||
brain.Insert(C, TRUE, TRUE)
|
||||
|
||||
if(heart && (!should_have_heart || replace_current))
|
||||
heart.Remove(C,1)
|
||||
heart.Remove(TRUE)
|
||||
QDEL_NULL(heart)
|
||||
if(should_have_heart && !heart)
|
||||
heart = new mutant_heart()
|
||||
heart.Insert(C)
|
||||
|
||||
if(lungs && (!should_have_lungs || replace_current))
|
||||
lungs.Remove(C,1)
|
||||
lungs.Remove(TRUE)
|
||||
QDEL_NULL(lungs)
|
||||
if(should_have_lungs && !lungs)
|
||||
if(mutantlungs)
|
||||
@@ -213,7 +213,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
lungs.Insert(C)
|
||||
|
||||
if(liver && (!should_have_liver || replace_current))
|
||||
liver.Remove(C,1)
|
||||
liver.Remove(TRUE)
|
||||
QDEL_NULL(liver)
|
||||
if(should_have_liver && !liver)
|
||||
if(mutantliver)
|
||||
@@ -223,7 +223,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
liver.Insert(C)
|
||||
|
||||
if(stomach && (!should_have_stomach || replace_current))
|
||||
stomach.Remove(C,1)
|
||||
stomach.Remove(TRUE)
|
||||
QDEL_NULL(stomach)
|
||||
if(should_have_stomach && !stomach)
|
||||
if(mutantstomach)
|
||||
@@ -233,14 +233,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
stomach.Insert(C)
|
||||
|
||||
if(appendix && (!should_have_appendix || replace_current))
|
||||
appendix.Remove(C,1)
|
||||
appendix.Remove(TRUE)
|
||||
QDEL_NULL(appendix)
|
||||
if(should_have_appendix && !appendix)
|
||||
appendix = new()
|
||||
appendix.Insert(C)
|
||||
|
||||
if(tail && (!should_have_tail || replace_current))
|
||||
tail.Remove(C,1)
|
||||
tail.Remove(TRUE)
|
||||
QDEL_NULL(tail)
|
||||
if(should_have_tail && !tail)
|
||||
tail = new mutanttail()
|
||||
@@ -248,21 +248,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
if(C.get_bodypart(BODY_ZONE_HEAD))
|
||||
if(eyes && (replace_current || !should_have_eyes))
|
||||
eyes.Remove(C,1)
|
||||
eyes.Remove(TRUE)
|
||||
QDEL_NULL(eyes)
|
||||
if(should_have_eyes && !eyes)
|
||||
eyes = new mutanteyes
|
||||
eyes.Insert(C, TRUE)
|
||||
|
||||
if(ears && (replace_current || !should_have_ears))
|
||||
ears.Remove(C,1)
|
||||
ears.Remove(TRUE)
|
||||
QDEL_NULL(ears)
|
||||
if(should_have_ears && !ears)
|
||||
ears = new mutantears
|
||||
ears.Insert(C)
|
||||
|
||||
if(tongue && (replace_current || !should_have_tongue))
|
||||
tongue.Remove(C,1)
|
||||
tongue.Remove(TRUE)
|
||||
QDEL_NULL(tongue)
|
||||
if(should_have_tongue && !tongue)
|
||||
tongue = new mutanttongue
|
||||
@@ -272,7 +272,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
for(var/mutantorgan in old_species.mutant_organs)
|
||||
var/obj/item/organ/I = C.getorgan(mutantorgan)
|
||||
if(I)
|
||||
I.Remove(C)
|
||||
I.Remove()
|
||||
QDEL_NULL(I)
|
||||
|
||||
for(var/path in mutant_organs)
|
||||
@@ -1585,7 +1585,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if (!HAS_TRAIT(target, TRAIT_PERMABONER))
|
||||
stop_wagging_tail(target)
|
||||
return FALSE
|
||||
else if(aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
|
||||
else if(!(user.client?.prefs.cit_toggles & NO_ASS_SLAP) && aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
|
||||
if(target.client?.prefs.cit_toggles & NO_ASS_SLAP)
|
||||
to_chat(user,"A force stays your hand, preventing you from slapping \the [target]'s ass!")
|
||||
return FALSE
|
||||
@@ -1601,7 +1601,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
"<span class='danger'>\The [user] slaps \the [target]'s ass!</span>",\
|
||||
"<span class='notice'>You slap [user == target ? "your" : "\the [target]'s"] ass!</span>",\
|
||||
"You hear a slap."
|
||||
)
|
||||
)
|
||||
return FALSE
|
||||
else if(attacker_style && attacker_style.disarm_act(user,target))
|
||||
return 1
|
||||
@@ -1884,6 +1884,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(get_turf(target) == target_oldturf)
|
||||
shove_blocked = TRUE
|
||||
|
||||
var/append_message = ""
|
||||
if(shove_blocked && !target.buckled)
|
||||
var/directional_blocked = !target.Adjacent(target_shove_turf)
|
||||
var/targetatrest = target.resting
|
||||
@@ -1897,33 +1898,30 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL)
|
||||
user.visible_message("<span class='danger'>[user.name] shoves [target.name] into [target_collateral_human.name]!</span>",
|
||||
"<span class='danger'>You shove [target.name] into [target_collateral_human.name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(user, target, "shoved", "into [target_collateral_human.name]")
|
||||
append_message += ", into [target_collateral_human.name]"
|
||||
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user.name] shoves [target.name]!</span>",
|
||||
"<span class='danger'>You shove [target.name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/target_held_item = target.get_active_held_item()
|
||||
var/knocked_item = FALSE
|
||||
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
|
||||
target_held_item = null
|
||||
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
|
||||
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
|
||||
if(target_held_item)
|
||||
var/obj/item/target_held_item = target.get_active_held_item()
|
||||
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
|
||||
target_held_item = null
|
||||
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
|
||||
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
|
||||
if(target_held_item)
|
||||
if(!HAS_TRAIT(target_held_item, TRAIT_NODROP))
|
||||
target.visible_message("<span class='danger'>[target.name]'s grip on \the [target_held_item] loosens!</span>",
|
||||
"<span class='danger'>Your grip on \the [target_held_item] loosens!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
|
||||
else if(target_held_item)
|
||||
target.dropItemToGround(target_held_item)
|
||||
knocked_item = TRUE
|
||||
append_message += ", loosening their grip on [target_held_item]"
|
||||
else
|
||||
append_message += ", but couldn't loose their grip on [target_held_item]"
|
||||
addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
|
||||
else if(target_held_item)
|
||||
if(target.dropItemToGround(target_held_item))
|
||||
target.visible_message("<span class='danger'>[target.name] drops \the [target_held_item]!!</span>",
|
||||
"<span class='danger'>You drop \the [target_held_item]!!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/append_message = ""
|
||||
if(target_held_item)
|
||||
if(knocked_item)
|
||||
append_message = "causing them to drop [target_held_item]"
|
||||
else
|
||||
append_message = "loosening their grip on [target_held_item]"
|
||||
log_combat(user, target, "shoved", append_message)
|
||||
append_message += ", causing them to drop [target_held_item]"
|
||||
log_combat(user, target, "shoved", append_message)
|
||||
|
||||
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
|
||||
var/hit_percent = (100-(blocked+armor))/100
|
||||
|
||||
@@ -132,14 +132,14 @@
|
||||
return INITIALIZE_HINT_QDEL
|
||||
owner = new_owner
|
||||
START_PROCESSING(SSobj, src)
|
||||
RegisterSignal(owner, COMSIG_MOB_EXAMINATE, .proc/examinate_check)
|
||||
RegisterSignal(owner, COMSIG_CLICK_SHIFT, .proc/examinate_check)
|
||||
RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner)
|
||||
RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head)
|
||||
RegisterSignal(owner, COMSIG_LIVING_FULLY_HEAL, .proc/retrieve_head)
|
||||
|
||||
/obj/item/dullahan_relay/proc/examinate_check(mob/source, atom/A)
|
||||
if(source.client.eye == src && ((A in view(source.client.view, src)) || (isturf(A) && source.sight & SEE_TURFS) || (ismob(A) && source.sight & SEE_MOBS) || (isobj(A) && source.sight & SEE_OBJS)))
|
||||
return COMPONENT_ALLOW_EXAMINE
|
||||
/obj/item/dullahan_relay/proc/examinate_check(atom/source, mob/user)
|
||||
if(user.client.eye == src)
|
||||
return COMPONENT_ALLOW_EXAMINATE
|
||||
|
||||
/obj/item/dullahan_relay/proc/include_owner(datum/source, list/processing_list, list/hearers)
|
||||
if(!QDELETED(owner))
|
||||
|
||||
@@ -31,6 +31,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
. = ..()
|
||||
var/dwarf_hair = pick("Beard (Dwarf)", "Beard (Very Long)", "Beard (Long)") //beard roullette
|
||||
var/mob/living/carbon/human/H = C
|
||||
H.grant_language(/datum/language/dwarf)
|
||||
H.facial_hair_style = dwarf_hair
|
||||
H.update_hair()
|
||||
H.transform = H.transform.Scale(1, 0.8) //We use scale, and yeah. Dwarves can become gnomes with DWARFISM.
|
||||
@@ -41,6 +42,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
. = ..()
|
||||
H.transform = H.transform.Scale(1, 1.25) //And we undo it.
|
||||
UnregisterSignal(H, COMSIG_MOB_SAY) //We register handle_speech is not being used.
|
||||
H.remove_language(/datum/language/dwarf)
|
||||
|
||||
//Dwarf Name stuff
|
||||
/proc/dwarf_name() //hello caller: my name is urist mcuristurister
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
if(NT)
|
||||
NT.Insert(H, drop_if_replaced = FALSE)
|
||||
else
|
||||
tail.Remove(H)
|
||||
tail.Remove()
|
||||
|
||||
/proc/mass_purrbation()
|
||||
for(var/M in GLOB.mob_list)
|
||||
|
||||
@@ -31,14 +31,15 @@
|
||||
|
||||
/datum/species/mush/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(!H.dna.features["caps"])
|
||||
H.dna.features["caps"] = "Round"
|
||||
handle_mutant_bodyparts(H)
|
||||
H.faction |= "mushroom"
|
||||
mush = new()
|
||||
mush.teach(H, TRUE)
|
||||
if(!ishuman(C))
|
||||
return
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(!H.dna.features["caps"])
|
||||
H.dna.features["caps"] = "Round"
|
||||
handle_mutant_bodyparts(H)
|
||||
H.faction |= "mushroom"
|
||||
mush = new()
|
||||
mush.teach(H, TRUE)
|
||||
RegisterSignal(C, COMSIG_MOB_ON_NEW_MIND, .proc/on_new_mind)
|
||||
|
||||
/datum/species/mush/proc/on_new_mind(mob/owner)
|
||||
|
||||
@@ -84,10 +84,10 @@
|
||||
shadowwalk = SW
|
||||
|
||||
|
||||
/obj/item/organ/brain/nightmare/Remove(mob/living/carbon/M, special = 0)
|
||||
if(shadowwalk)
|
||||
M.RemoveSpell(shadowwalk)
|
||||
..()
|
||||
/obj/item/organ/brain/nightmare/Remove(special = FALSE)
|
||||
if(shadowwalk && owner)
|
||||
owner.RemoveSpell(shadowwalk)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/organ/heart/nightmare
|
||||
@@ -120,12 +120,12 @@
|
||||
blade = new/obj/item/light_eater
|
||||
M.put_in_hands(blade)
|
||||
|
||||
/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/heart/nightmare/Remove(special = FALSE)
|
||||
respawn_progress = 0
|
||||
if(blade && special != HEART_SPECIAL_SHADOWIFY)
|
||||
M.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
|
||||
if(!QDELETED(owner) && blade && special != HEART_SPECIAL_SHADOWIFY)
|
||||
owner.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
|
||||
QDEL_NULL(blade)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/heart/nightmare/Stop()
|
||||
return 0
|
||||
@@ -146,7 +146,7 @@
|
||||
owner.revive(full_heal = TRUE)
|
||||
if(!(owner.dna.species.id == "shadow" || owner.dna.species.id == "nightmare"))
|
||||
var/mob/living/carbon/old_owner = owner
|
||||
Remove(owner, HEART_SPECIAL_SHADOWIFY)
|
||||
Remove(HEART_SPECIAL_SHADOWIFY)
|
||||
old_owner.set_species(/datum/species/shadow)
|
||||
Insert(old_owner, HEART_SPECIAL_SHADOWIFY)
|
||||
to_chat(owner, "<span class='userdanger'>You feel the shadows invade your skin, leaping into the center of your chest! You're alive!</span>")
|
||||
|
||||
@@ -182,10 +182,10 @@ There are several things that need to be remembered:
|
||||
|
||||
if(!gloves && bloody_hands)
|
||||
var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
|
||||
if(get_num_arms() < 2)
|
||||
if(has_left_hand())
|
||||
if(get_num_arms(FALSE) < 2)
|
||||
if(has_left_hand(FALSE))
|
||||
bloody_overlay.icon_state = "bloodyhands_left"
|
||||
else if(has_right_hand())
|
||||
else if(has_right_hand(FALSE))
|
||||
bloody_overlay.icon_state = "bloodyhands_right"
|
||||
|
||||
overlays_standing[GLOVES_LAYER] = bloody_overlay
|
||||
@@ -265,7 +265,7 @@ There are several things that need to be remembered:
|
||||
/mob/living/carbon/human/update_inv_shoes()
|
||||
remove_overlay(SHOES_LAYER)
|
||||
|
||||
if(get_num_legs() <2)
|
||||
if(get_num_legs(FALSE) <2)
|
||||
return
|
||||
|
||||
if(client && hud_used)
|
||||
@@ -461,6 +461,8 @@ There are several things that need to be remembered:
|
||||
var/alt_icon = M.alternate_worn_icon || 'icons/mob/mask.dmi'
|
||||
var/muzzled = FALSE
|
||||
var/variation_flag = NONE
|
||||
if(head && (head.flags_inv & HIDEMASK))
|
||||
return
|
||||
if(("mam_snouts" in dna.species.default_features) && dna.features["mam_snouts"] != "None")
|
||||
muzzled = TRUE
|
||||
if(!muzzled && ("snout" in dna.species.default_features) && dna.features["snout"] != "None")
|
||||
|
||||
@@ -334,9 +334,10 @@
|
||||
var/obj/item/clothing/check
|
||||
var/internals = FALSE
|
||||
|
||||
for(check in GET_INTERNAL_SLOTS(src))
|
||||
if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
|
||||
internals = TRUE
|
||||
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS))
|
||||
for(check in GET_INTERNAL_SLOTS(src))
|
||||
if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
|
||||
internals = TRUE
|
||||
if(internal)
|
||||
if(internal.loc != src)
|
||||
internal = null
|
||||
@@ -357,7 +358,7 @@
|
||||
return
|
||||
|
||||
// No decay if formaldehyde in corpse or when the corpse is charred
|
||||
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 15) || HAS_TRAIT(src, TRAIT_HUSK))
|
||||
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1) || HAS_TRAIT(src, TRAIT_HUSK))
|
||||
return
|
||||
|
||||
// Also no decay if corpse chilled or not organic/undead
|
||||
@@ -396,6 +397,8 @@
|
||||
if(O)
|
||||
O.on_life()
|
||||
else
|
||||
if(reagents.has_reagent(/datum/reagent/toxin/formaldehyde, 1)) // No organ decay if the body contains formaldehyde.
|
||||
return
|
||||
for(var/V in internal_organs)
|
||||
var/obj/item/organ/O = V
|
||||
if(O)
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
|
||||
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
|
||||
hud_type = /datum/hud/monkey
|
||||
can_be_held = "monkey"
|
||||
|
||||
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
|
||||
verbs += /mob/living/proc/mob_sleep
|
||||
@@ -42,14 +41,15 @@
|
||||
create_dna(src)
|
||||
dna.initialize_dna(random_blood_type())
|
||||
|
||||
/mob/living/carbon/monkey/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/mob_holder, "monkey", null, null, null, SLOT_HEAD)
|
||||
|
||||
|
||||
/mob/living/carbon/monkey/Destroy()
|
||||
SSmobs.cubemonkeys -= src
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/generate_mob_holder()
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "monkey", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
|
||||
return holder
|
||||
|
||||
/mob/living/carbon/monkey/create_internal_organs()
|
||||
internal_organs += new /obj/item/organ/appendix
|
||||
internal_organs += new /obj/item/organ/lungs
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
stat = DEAD
|
||||
unset_machine()
|
||||
timeofdeath = world.time
|
||||
tod = STATION_TIME_TIMESTAMP("hh:mm:ss")
|
||||
tod = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)
|
||||
for(var/obj/item/I in contents)
|
||||
I.on_mob_death(src, gibbed)
|
||||
if(mind)
|
||||
|
||||
@@ -200,25 +200,25 @@
|
||||
message_param = "blows a kiss to %t."
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
|
||||
/datum/emote/living/laugh
|
||||
/datum/emote/living/audio_emote
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
|
||||
/datum/emote/living/audio_emote/can_run_emote(mob/living/user, status_check = TRUE)
|
||||
. = ..()
|
||||
if(. && iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
return !C.silent && (!C.mind || !C.mind.miming)
|
||||
|
||||
/datum/emote/living/audio_emote/laugh
|
||||
key = "laugh"
|
||||
key_third_person = "laughs"
|
||||
message = "laughs."
|
||||
message_mime = "laughs silently!"
|
||||
emote_type = EMOTE_AUDIBLE
|
||||
|
||||
/datum/emote/living/laugh/can_run_emote(mob/living/user, status_check = TRUE)
|
||||
. = ..()
|
||||
if(. && iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
return !C.silent
|
||||
|
||||
/datum/emote/living/laugh/run_emote(mob/user, params)
|
||||
/datum/emote/living/audio_emote/laugh/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
if(. && iscarbon(user)) //Citadel Edit because this is hilarious
|
||||
var/mob/living/carbon/C = user
|
||||
if(!C.mind || C.mind.miming)
|
||||
return
|
||||
if(iscatperson(C)) //we ask for is cat first because they're a subtype that tests true for ishumanbasic because HERESY
|
||||
playsound(C, pick('sound/voice/catpeople/nyahaha1.ogg',
|
||||
'sound/voice/catpeople/nyahaha2.ogg',
|
||||
@@ -226,12 +226,27 @@
|
||||
'sound/voice/catpeople/nyahehe.ogg'),
|
||||
50, 1)
|
||||
return
|
||||
if(ishumanbasic(C))
|
||||
else if(ismoth(C))
|
||||
playsound(C, 'sound/voice/moth/mothlaugh.ogg', 50, 1)
|
||||
else if(ishumanbasic(C))
|
||||
if(user.gender == FEMALE)
|
||||
playsound(C, 'sound/voice/human/womanlaugh.ogg', 50, 1)
|
||||
else
|
||||
playsound(C, pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg'), 50, 1)
|
||||
|
||||
/datum/emote/living/audio_emote/chitter
|
||||
key = "chitter"
|
||||
key_third_person = "chitters"
|
||||
message = "chitters."
|
||||
message_mime = "chitters silently!"
|
||||
|
||||
/datum/emote/living/audio_emote/chitter/run_emote(mob/user, params)
|
||||
. = ..()
|
||||
if(. && iscarbon(user)) //Citadel Edit because this is hilarious
|
||||
var/mob/living/carbon/C = user
|
||||
if(ismoth(C))
|
||||
playsound(C, 'sound/voice/moth/mothchitter.ogg', 50, 1)
|
||||
|
||||
/datum/emote/living/look
|
||||
key = "look"
|
||||
key_third_person = "looks"
|
||||
@@ -411,17 +426,10 @@
|
||||
message = null
|
||||
|
||||
/datum/emote/living/custom/proc/check_invalid(mob/user, input)
|
||||
. = TRUE
|
||||
if(copytext(input,1,5) == "says")
|
||||
if(stop_bad_mime.Find(input, 1, 1))
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,9) == "exclaims")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,6) == "yells")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,5) == "asks")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else
|
||||
. = FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/emote/living/custom/run_emote(mob/user, params, type_override = null)
|
||||
if(jobban_isbanned(user, "emote"))
|
||||
@@ -433,7 +441,7 @@
|
||||
to_chat(user, "You cannot send IC messages (muted).")
|
||||
return FALSE
|
||||
else if(!params)
|
||||
var/custom_emote = copytext(sanitize(input("Choose an emote to display.") as message|null), 1, MAX_MESSAGE_LEN) //CIT CHANGE - expands emote textbox
|
||||
var/custom_emote = stripped_multiline_input("Choose an emote to display.", "Custom Emote", null, MAX_MESSAGE_LEN)
|
||||
if(custom_emote && !check_invalid(user, custom_emote))
|
||||
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
|
||||
switch(type)
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
//Generic system for picking up mobs.
|
||||
//Currently works for head and hands.
|
||||
/obj/item/clothing/head/mob_holder
|
||||
name = "bugged mob"
|
||||
desc = "Yell at coderbrush."
|
||||
icon = null
|
||||
icon_state = ""
|
||||
var/mob/living/held_mob
|
||||
var/can_head = FALSE
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
|
||||
. = ..()
|
||||
|
||||
if(M)
|
||||
M.setDir(SOUTH)
|
||||
held_mob = M
|
||||
M.forceMove(src)
|
||||
appearance = M.appearance
|
||||
name = M.name
|
||||
desc = M.desc
|
||||
|
||||
if(_can_head_override)
|
||||
can_head = _can_head_override
|
||||
if(alt_worn)
|
||||
alternate_worn_icon = alt_worn
|
||||
if(_worn_state)
|
||||
item_state = _worn_state
|
||||
icon_state = _worn_state
|
||||
if(lh_icon)
|
||||
lefthand_file = lh_icon
|
||||
if(rh_icon)
|
||||
righthand_file = rh_icon
|
||||
if(!can_head)
|
||||
slot_flags = NONE
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Destroy()
|
||||
if(held_mob)
|
||||
release()
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/dropped()
|
||||
..()
|
||||
if(isturf(loc))//don't release on soft-drops
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/proc/release()
|
||||
if(isliving(loc))
|
||||
var/mob/living/L = loc
|
||||
L.dropItemToGround(src)
|
||||
if(held_mob)
|
||||
var/mob/living/m = held_mob
|
||||
m.forceMove(get_turf(m))
|
||||
m.reset_perspective()
|
||||
m.setDir(SOUTH)
|
||||
held_mob = null
|
||||
qdel(src)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
|
||||
return
|
||||
|
||||
/obj/item/clothing/head/mob_holder/container_resist()
|
||||
if(isliving(loc))
|
||||
var/mob/living/L = loc
|
||||
visible_message("<span class='warning'>[src] escapes [L]!</span>")
|
||||
release()
|
||||
|
||||
/mob/living/proc/mob_pickup(mob/living/L)
|
||||
var/obj/item/clothing/head/mob_holder/holder = generate_mob_holder()
|
||||
if(!holder)
|
||||
return
|
||||
drop_all_held_items()
|
||||
L.put_in_hands(holder)
|
||||
return
|
||||
|
||||
/mob/living/proc/mob_try_pickup(mob/living/user)
|
||||
if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
|
||||
return FALSE
|
||||
if(user.get_active_held_item())
|
||||
to_chat(user, "<span class='warning'>Your hands are full!</span>")
|
||||
return FALSE
|
||||
if(buckled)
|
||||
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
|
||||
return FALSE
|
||||
if(src == user)
|
||||
to_chat(user, "<span class='warning'>You can't pick yourself up.</span>")
|
||||
return FALSE
|
||||
visible_message("<span class='warning'>[user] starts picking up [src].</span>", \
|
||||
"<span class='userdanger'>[user] starts picking you up!</span>")
|
||||
if(!do_after(user, 20, target = src))
|
||||
return FALSE
|
||||
|
||||
if(user.get_active_held_item()||buckled)
|
||||
return FALSE
|
||||
|
||||
visible_message("<span class='warning'>[user] picks up [src]!</span>", \
|
||||
"<span class='userdanger'>[user] picks you up!</span>")
|
||||
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
|
||||
mob_pickup(user)
|
||||
return TRUE
|
||||
|
||||
/mob/living/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(mob_try_pickup(user))
|
||||
return TRUE
|
||||
|
||||
|
||||
// I didn't define these for mobs, because you shouldn't be able to breathe out of mobs and using their loc isn't always the logical thing to do.
|
||||
|
||||
/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
|
||||
var/atom/location = loc
|
||||
if(!loc)
|
||||
return //null
|
||||
var/turf/T = get_turf(loc)
|
||||
while(location != T)
|
||||
location = location.loc
|
||||
if(ismob(location))
|
||||
return location.loc.assume_air(env)
|
||||
return loc.assume_air(env)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/remove_air(amount)
|
||||
var/atom/location = loc
|
||||
if(!loc)
|
||||
return //null
|
||||
var/turf/T = get_turf(loc)
|
||||
while(location != T)
|
||||
location = location.loc
|
||||
if(ismob(location))
|
||||
return location.loc.remove_air(amount)
|
||||
return loc.remove_air(amount)
|
||||
@@ -40,11 +40,6 @@
|
||||
QDEL_LIST(diseases)
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/proc/generate_mob_holder()
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
|
||||
return holder
|
||||
|
||||
/mob/living/onZImpact(turf/T, levels)
|
||||
if(!isgroundlessturf(T))
|
||||
ZImpactDamage(T, levels)
|
||||
@@ -763,10 +758,22 @@
|
||||
if(HAS_TRAIT(what, TRAIT_NODROP))
|
||||
to_chat(src, "<span class='warning'>You can't remove \the [what.name], it appears to be stuck!</span>")
|
||||
return
|
||||
who.visible_message("<span class='danger'>[src] tries to remove [who]'s [what.name].</span>", \
|
||||
var/strip_mod = 1
|
||||
var/strip_silence = FALSE
|
||||
if (ishuman(src)) //carbon doesn't actually wear gloves
|
||||
var/mob/living/carbon/C = src
|
||||
var/obj/item/clothing/gloves/g = C.gloves
|
||||
if (istype(g))
|
||||
strip_mod = g.strip_mod
|
||||
strip_silence = g.strip_silence
|
||||
if (!strip_silence)
|
||||
who.visible_message("<span class='danger'>[src] tries to remove [who]'s [what.name].</span>", \
|
||||
"<span class='userdanger'>[src] tries to remove [who]'s [what.name].</span>")
|
||||
what.add_fingerprint(src)
|
||||
if(do_mob(src, who, what.strip_delay, ignorehelditem = TRUE))
|
||||
what.add_fingerprint(src)
|
||||
else
|
||||
to_chat(src,"<span class='notice'>You try to remove [who]'s [what.name].</span>")
|
||||
what.add_fingerprint(src)
|
||||
if(do_mob(src, who, round(what.strip_delay / strip_mod), ignorehelditem = TRUE))
|
||||
if(what && Adjacent(who))
|
||||
if(islist(where))
|
||||
var/list/L = where
|
||||
@@ -1172,8 +1179,6 @@
|
||||
return
|
||||
if(!over.Adjacent(src) || (user != src) || !canUseTopic(over))
|
||||
return
|
||||
if(can_be_held)
|
||||
mob_try_pickup(over)
|
||||
|
||||
/mob/living/proc/get_static_viruses() //used when creating blood and other infective objects
|
||||
if(!LAZYLEN(diseases))
|
||||
|
||||
@@ -101,8 +101,6 @@
|
||||
|
||||
var/list/obj/effect/proc_holder/abilities = list()
|
||||
|
||||
var/can_be_held = FALSE //whether this can be picked up and held.
|
||||
|
||||
var/radiation = 0 //If the mob is irradiated.
|
||||
var/ventcrawl_layer = PIPING_LAYER_DEFAULT
|
||||
var/losebreath = 0
|
||||
|
||||
@@ -89,7 +89,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
|
||||
|
||||
if(sanitize)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
if(!message || message == "")
|
||||
return
|
||||
|
||||
@@ -99,12 +99,12 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
var/in_critical = InCritical()
|
||||
|
||||
if(one_character_prefix[message_mode])
|
||||
message = copytext(message, 2)
|
||||
message = copytext_char(message, 2)
|
||||
else if(message_mode || saymode)
|
||||
message = copytext(message, 3)
|
||||
if(findtext(message, " ", 1, 2))
|
||||
message = copytext(message, 2)
|
||||
|
||||
message = copytext_char(message, 3)
|
||||
message = trim_left(message)
|
||||
if(!message)
|
||||
return
|
||||
if(message_mode == MODE_ADMIN)
|
||||
if(client)
|
||||
client.cmd_admin_say(message)
|
||||
@@ -135,11 +135,10 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
// No, you cannot speak in xenocommon just because you know the key
|
||||
if(can_speak_in_language(message_language))
|
||||
language = message_language
|
||||
message = copytext(message, 3)
|
||||
message = copytext_char(message, 3)
|
||||
|
||||
// Trim the space if they said ",0 I LOVE LANGUAGES"
|
||||
if(findtext(message, " ", 1, 2))
|
||||
message = copytext(message, 2)
|
||||
message = trim_left(message)
|
||||
|
||||
if(!language)
|
||||
language = get_default_language()
|
||||
@@ -167,8 +166,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
if(fullcrit)
|
||||
var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
|
||||
// If we cut our message short, abruptly end it with a-..
|
||||
var/message_len = length(message)
|
||||
message = copytext(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
|
||||
var/message_len = length_char(message)
|
||||
message = copytext_char(message, 1, health_diff) + "[message_len > health_diff ? "-.." : "..."]"
|
||||
message = Ellipsis(message, 10, 1)
|
||||
message_mode = MODE_WHISPER_CRIT
|
||||
succumbed = TRUE
|
||||
@@ -326,13 +325,13 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
|
||||
return 1
|
||||
|
||||
/mob/living/proc/get_key(message)
|
||||
var/key = copytext(message, 1, 2)
|
||||
var/key = message[1]
|
||||
if(key in GLOB.department_radio_prefixes)
|
||||
return lowertext(copytext(message, 2, 3))
|
||||
return lowertext(message[1 + length(key)])
|
||||
|
||||
/mob/living/proc/get_message_language(message)
|
||||
if(copytext(message, 1, 2) == ",")
|
||||
var/key = copytext(message, 2, 3)
|
||||
if(message[1] == ",")
|
||||
var/key = message[1 + length(message[1])]
|
||||
for(var/ld in GLOB.all_languages)
|
||||
var/datum/language/LD = ld
|
||||
if(initial(LD.key) == key)
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
..()
|
||||
|
||||
/mob/living/silicon/ai/get_message_mode(message)
|
||||
if(copytext(message, 1, 3) in list(":h", ":H", ".h", ".H", "#h", "#H"))
|
||||
var/static/regex/holopad_finder = regex(@"[:.#][hH]")
|
||||
if(holopad_finder.Find(message, 1, 1))
|
||||
return MODE_HOLOPAD
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
health = 500
|
||||
maxHealth = 500
|
||||
layer = BELOW_MOB_LAYER
|
||||
can_be_held = TRUE
|
||||
var/datum/element/mob_holder/current_mob_holder //because only a few of their chassis can be actually held.
|
||||
|
||||
var/network = "ss13"
|
||||
var/obj/machinery/camera/current = null
|
||||
@@ -64,9 +64,6 @@
|
||||
var/list/possible_chassis //initialized in initialize.
|
||||
var/list/dynamic_chassis_icons //ditto.
|
||||
var/list/chassis_pixel_offsets_x //stupid dogborgs
|
||||
var/static/item_head_icon = 'icons/mob/pai_item_head.dmi'
|
||||
var/static/item_lh_icon = 'icons/mob/pai_item_lh.dmi'
|
||||
var/static/item_rh_icon = 'icons/mob/pai_item_rh.dmi'
|
||||
|
||||
var/emitterhealth = 20
|
||||
var/emittermaxhealth = 20
|
||||
|
||||
@@ -96,6 +96,12 @@
|
||||
dynamic_chassis = choice
|
||||
resist_a_rest(FALSE, TRUE)
|
||||
update_icon()
|
||||
if(possible_chassis[chassis])
|
||||
current_mob_holder = AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', SLOT_HEAD)
|
||||
else
|
||||
current_mob_holder?.Detach(src)
|
||||
current_mob_holder = null
|
||||
return
|
||||
to_chat(src, "<span class='boldnotice'>You switch your holochassis projection composite to [chassis]</span>")
|
||||
|
||||
/mob/living/silicon/pai/lay_down()
|
||||
@@ -117,19 +123,6 @@
|
||||
set_light(0)
|
||||
to_chat(src, "<span class='notice'>You disable your integrated light.</span>")
|
||||
|
||||
/mob/living/silicon/pai/mob_pickup(mob/living/L)
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, chassis, item_head_icon, item_lh_icon, item_rh_icon)
|
||||
if(!L.put_in_hands(holder))
|
||||
qdel(holder)
|
||||
else
|
||||
L.visible_message("<span class='warning'>[L] scoops up [src]!</span>")
|
||||
|
||||
/mob/living/silicon/pai/mob_try_pickup(mob/living/user)
|
||||
if(!possible_chassis[chassis])
|
||||
to_chat(user, "<span class='warning'>[src]'s current form isn't able to be carried!</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/pai/verb/toggle_chassis_sit()
|
||||
set name = "Toggle Chassis Sit"
|
||||
set category = "IC"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
/datum/paiCandidate/proc/savefile_path(mob/user)
|
||||
return "data/player_saves/[copytext(user.ckey, 1, 2)]/[user.ckey]/pai.sav"
|
||||
return "data/player_saves/[user.ckey[1]]/[user.ckey]/pai.sav"
|
||||
|
||||
/datum/paiCandidate/proc/savefile_save(mob/user)
|
||||
if(IsGuestKey(user.key))
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
else if(istype(I, /obj/item/gun/energy))
|
||||
var/obj/item/gun/energy/EG = I
|
||||
if(EG.cell?.charge < EG.cell.maxcharge)
|
||||
var/obj/item/ammo_casing/energy/S = EG.ammo_type[EG.select]
|
||||
var/obj/item/ammo_casing/energy/S = EG.ammo_type[EG.current_firemode_index]
|
||||
EG.cell.give(S.e_cost * coeff)
|
||||
if(!EG.chambered)
|
||||
EG.recharge_newshot(TRUE)
|
||||
|
||||
@@ -182,8 +182,9 @@
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/bot/death(gibbed)
|
||||
explode()
|
||||
..()
|
||||
. = ..()
|
||||
if(!gibbed)
|
||||
explode()
|
||||
|
||||
/mob/living/simple_animal/bot/proc/explode()
|
||||
qdel(src)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
icon_state = "mulebot0"
|
||||
density = TRUE
|
||||
move_resist = MOVE_FORCE_STRONG
|
||||
animate_movement = 1
|
||||
animate_movement = FORWARD_STEPS
|
||||
health = 50
|
||||
maxHealth = 50
|
||||
damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
|
||||
@@ -29,10 +29,14 @@
|
||||
model = "MULE"
|
||||
bot_core_type = /obj/machinery/bot_core/mulebot
|
||||
|
||||
var/ui_x = 350
|
||||
var/ui_y = 425
|
||||
|
||||
var/id
|
||||
|
||||
path_image_color = "#7F5200"
|
||||
|
||||
var/base_icon = "mulebot"
|
||||
var/atom/movable/load = null
|
||||
var/mob/living/passenger = null
|
||||
var/turf/target // this is turf to navigate to (location of beacon)
|
||||
@@ -74,16 +78,16 @@
|
||||
/mob/living/simple_animal/bot/mulebot/proc/set_id(new_id)
|
||||
id = new_id
|
||||
if(paicard)
|
||||
bot_name = "\improper MULEbot ([new_id])"
|
||||
bot_name = "[initial(name)] ([new_id])"
|
||||
else
|
||||
name = "\improper MULEbot ([new_id])"
|
||||
name = "[initial(name)] ([new_id])"
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/bot_reset()
|
||||
..()
|
||||
reached_target = 0
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/screwdriver))
|
||||
if(I.tool_behaviour == TOOL_SCREWDRIVER)
|
||||
..()
|
||||
if(open)
|
||||
on = FALSE
|
||||
@@ -91,13 +95,13 @@
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
cell = I
|
||||
visible_message("[user] inserts a cell into [src].",
|
||||
visible_message("<span class='notice'>[user] inserts a cell into [src].</span>",
|
||||
"<span class='notice'>You insert the new cell into [src].</span>")
|
||||
else if(istype(I, /obj/item/crowbar) && open && cell)
|
||||
else if(I.tool_behaviour == TOOL_CROWBAR && open && cell)
|
||||
cell.add_fingerprint(usr)
|
||||
cell.forceMove(loc)
|
||||
cell = null
|
||||
visible_message("[user] crowbars out the power cell from [src].",
|
||||
visible_message("<span class='notice'>[user] crowbars out the power cell from [src].</span>",
|
||||
"<span class='notice'>You pry the powercell out of [src].</span>")
|
||||
else if(is_wire_tool(I) && open)
|
||||
return attack_hand(user)
|
||||
@@ -115,21 +119,19 @@
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/emag_act(mob/user)
|
||||
. = SEND_SIGNAL(src, COMSIG_ATOM_EMAG_ACT)
|
||||
if(emagged < 1)
|
||||
emagged = TRUE
|
||||
if(!open)
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src]'s controls!</span>")
|
||||
flick("mulebot-emagged", src)
|
||||
playsound(src, "sparks", 100, 0)
|
||||
return TRUE
|
||||
playsound(src, "sparks", 100, FALSE)
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/update_icon()
|
||||
if(open)
|
||||
icon_state="mulebot-hatch"
|
||||
icon_state="[base_icon]-hatch"
|
||||
else
|
||||
icon_state = "mulebot[wires.is_cut(WIRE_AVOIDANCE)]"
|
||||
icon_state = "[base_icon][wires.is_cut(WIRE_AVOIDANCE)]"
|
||||
cut_overlays()
|
||||
if(load && !ismob(load))//buckling handles the mob offsets
|
||||
load.pixel_y = initial(load.pixel_y) + 9
|
||||
@@ -152,7 +154,7 @@
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/bullet_act(obj/item/projectile/Proj)
|
||||
. = ..()
|
||||
if(. == BULLET_ACT_HIT && !QDELETED(src)) //Got hit and not blown up yet.)
|
||||
if(. && !QDELETED(src)) //Got hit and not blown up yet.
|
||||
if(prob(50) && !isnull(load))
|
||||
unload(0)
|
||||
if(prob(25))
|
||||
@@ -171,7 +173,7 @@
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "mulebot", name, 600, 375, master_ui, state)
|
||||
ui = new(user, src, ui_key, "mulebot", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/ui_data(mob/user)
|
||||
@@ -191,12 +193,15 @@
|
||||
else
|
||||
data["load"] = load ? load.name : null
|
||||
data["destination"] = destination ? destination : null
|
||||
data["home"] = home_destination
|
||||
data["destinations"] = GLOB.deliverybeacontags
|
||||
data["cell"] = cell ? TRUE : FALSE
|
||||
data["cellPercent"] = cell ? cell.percent() : null
|
||||
data["autoReturn"] = auto_return
|
||||
data["autoPickup"] = auto_pickup
|
||||
data["reportDelivery"] = report_delivery
|
||||
data["haspai"] = paicard ? TRUE : FALSE
|
||||
data["id"] = id
|
||||
return data
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/ui_act(action, params)
|
||||
@@ -216,10 +221,10 @@
|
||||
return
|
||||
. = TRUE
|
||||
else
|
||||
bot_control(action, usr) // Kill this later.
|
||||
bot_control(action, usr, params) // Kill this later.
|
||||
. = TRUE
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/bot_control(command, mob/user, pda = FALSE)
|
||||
/mob/living/simple_animal/bot/mulebot/bot_control(command, mob/user, list/params = list(), pda = FALSE)
|
||||
if(pda && wires.is_cut(WIRE_RX)) // MULE wireless is controlled by wires.
|
||||
return
|
||||
|
||||
@@ -234,15 +239,27 @@
|
||||
if(mode == BOT_IDLE || mode == BOT_DELIVER)
|
||||
start_home()
|
||||
if("destination")
|
||||
var/new_dest = input(user, "Enter Destination:", name, destination) as null|anything in GLOB.deliverybeacontags
|
||||
var/new_dest
|
||||
if(pda)
|
||||
new_dest = input(user, "Enter Destination:", name, destination) as null|anything in GLOB.deliverybeacontags
|
||||
else
|
||||
new_dest = params["value"]
|
||||
if(new_dest)
|
||||
set_destination(new_dest)
|
||||
if("setid")
|
||||
var/new_id = stripped_input(user, "Enter ID:", name, id, MAX_NAME_LEN)
|
||||
var/new_id
|
||||
if(pda)
|
||||
new_id = stripped_input(user, "Enter ID:", name, id, MAX_NAME_LEN)
|
||||
else
|
||||
new_id = params["value"]
|
||||
if(new_id)
|
||||
set_id(new_id)
|
||||
if("sethome")
|
||||
var/new_home = input(user, "Enter Home:", name, home_destination) as null|anything in GLOB.deliverybeacontags
|
||||
var/new_home
|
||||
if(pda)
|
||||
new_home = input(user, "Enter Home:", name, home_destination) as null|anything in GLOB.deliverybeacontags
|
||||
else
|
||||
new_home = params["value"]
|
||||
if(new_home)
|
||||
home_destination = new_home
|
||||
if("unload")
|
||||
@@ -317,26 +334,28 @@
|
||||
/mob/living/simple_animal/bot/mulebot/proc/buzz(type)
|
||||
switch(type)
|
||||
if(SIGH)
|
||||
audible_message("[src] makes a sighing buzz.", "<span class='italics'>You hear an electronic buzzing sound.</span>")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
|
||||
audible_message("<span class='hear'>[src] makes a sighing buzz.</span>")
|
||||
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
if(ANNOYED)
|
||||
audible_message("[src] makes an annoyed buzzing sound.", "<span class='italics'>You hear an electronic buzzing sound.</span>")
|
||||
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
|
||||
audible_message("<span class='hear'>[src] makes an annoyed buzzing sound.</span>")
|
||||
playsound(loc, 'sound/machines/buzz-two.ogg', 50, FALSE)
|
||||
if(DELIGHT)
|
||||
audible_message("[src] makes a delighted ping!", "<span class='italics'>You hear a ping.</span>")
|
||||
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
|
||||
audible_message("<span class='hear'>[src] makes a delighted ping!</span>")
|
||||
playsound(loc, 'sound/machines/ping.ogg', 50, FALSE)
|
||||
|
||||
|
||||
// mousedrop a crate to load the bot
|
||||
// can load anything if hacked
|
||||
/mob/living/simple_animal/bot/mulebot/MouseDrop_T(atom/movable/AM, mob/user)
|
||||
|
||||
if(user.incapacitated() || user.lying)
|
||||
return
|
||||
|
||||
if(!istype(AM))
|
||||
return
|
||||
|
||||
if(!istype(AM) || isdead(AM) || iscameramob(AM) || istype(AM, /obj/effect/dummy/phased_mob))
|
||||
return
|
||||
|
||||
load(AM)
|
||||
|
||||
// called to load a crate
|
||||
@@ -449,10 +468,8 @@
|
||||
process_bot()
|
||||
num_steps--
|
||||
if(mode != BOT_IDLE)
|
||||
spawn(0)
|
||||
for(var/i=num_steps,i>0,i--)
|
||||
sleep(2)
|
||||
process_bot()
|
||||
var/process_timer = addtimer(CALLBACK(src, .proc/process_bot), 2, TIMER_LOOP|TIMER_STOPPABLE)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, /proc/deltimer, process_timer), (num_steps*2) + 1)
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/proc/process_bot()
|
||||
if(!on || client)
|
||||
@@ -477,7 +494,7 @@
|
||||
if(isturf(next))
|
||||
if(bloodiness)
|
||||
var/obj/effect/decal/cleanable/blood/tracks/B = new(loc)
|
||||
if(blood_DNA && blood_DNA.len)
|
||||
if(length(blood_DNA))
|
||||
B.blood_DNA |= blood_DNA.Copy()
|
||||
var/newdir = get_dir(next, loc)
|
||||
if(newdir == dir)
|
||||
@@ -491,6 +508,7 @@
|
||||
B.setDir(newdir)
|
||||
bloodiness--
|
||||
|
||||
|
||||
var/oldloc = loc
|
||||
var/moved = step_towards(src, next) // attempt to move
|
||||
if(cell)
|
||||
@@ -516,11 +534,7 @@
|
||||
buzz(SIGH)
|
||||
mode = BOT_WAIT_FOR_NAV
|
||||
blockcount = 0
|
||||
spawn(20)
|
||||
calc_path(avoid=next)
|
||||
if(path.len > 0)
|
||||
buzz(DELIGHT)
|
||||
mode = BOT_BLOCKED
|
||||
addtimer(CALLBACK(src, .proc/process_blocked, next), 2 SECONDS)
|
||||
return
|
||||
return
|
||||
else
|
||||
@@ -533,18 +547,26 @@
|
||||
|
||||
if(BOT_NAV) // calculate new path
|
||||
mode = BOT_WAIT_FOR_NAV
|
||||
spawn(0)
|
||||
calc_path()
|
||||
INVOKE_ASYNC(src, .proc/process_nav)
|
||||
|
||||
if(path.len > 0)
|
||||
blockcount = 0
|
||||
mode = BOT_BLOCKED
|
||||
buzz(DELIGHT)
|
||||
/mob/living/simple_animal/bot/mulebot/proc/process_blocked(turf/next)
|
||||
calc_path(avoid=next)
|
||||
if(path.len > 0)
|
||||
buzz(DELIGHT)
|
||||
mode = BOT_BLOCKED
|
||||
|
||||
else
|
||||
buzz(SIGH)
|
||||
/mob/living/simple_animal/bot/mulebot/proc/process_nav()
|
||||
calc_path()
|
||||
|
||||
mode = BOT_NO_ROUTE
|
||||
if(path.len > 0)
|
||||
blockcount = 0
|
||||
mode = BOT_BLOCKED
|
||||
buzz(DELIGHT)
|
||||
|
||||
else
|
||||
buzz(SIGH)
|
||||
|
||||
mode = BOT_NO_ROUTE
|
||||
|
||||
// calculates a path to the current destination
|
||||
// given an optional turf to avoid
|
||||
@@ -574,26 +596,28 @@
|
||||
/mob/living/simple_animal/bot/mulebot/proc/start_home()
|
||||
if(!on)
|
||||
return
|
||||
spawn(0)
|
||||
set_destination(home_destination)
|
||||
mode = BOT_BLOCKED
|
||||
INVOKE_ASYNC(src, .proc/do_start_home)
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/proc/do_start_home()
|
||||
set_destination(home_destination)
|
||||
mode = BOT_BLOCKED
|
||||
|
||||
// called when bot reaches current target
|
||||
/mob/living/simple_animal/bot/mulebot/proc/at_target()
|
||||
if(!reached_target)
|
||||
radio_channel = "Supply" //Supply channel
|
||||
audible_message("[src] makes a chiming sound!", "<span class='italics'>You hear a chime.</span>")
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
|
||||
radio_channel = RADIO_CHANNEL_SUPPLY //Supply channel
|
||||
audible_message("<span class='hear'>[src] makes a chiming sound!</span>")
|
||||
playsound(loc, 'sound/machines/chime.ogg', 50, FALSE)
|
||||
reached_target = 1
|
||||
|
||||
if(pathset) //The AI called us here, so notify it of our arrival.
|
||||
loaddir = dir //The MULE will attempt to load a crate in whatever direction the MULE is "facing".
|
||||
if(calling_ai)
|
||||
to_chat(calling_ai, "<span class='notice'>[icon2html(src, calling_ai)] [src] wirelessly plays a chiming sound!</span>")
|
||||
playsound(calling_ai, 'sound/machines/chime.ogg',40, 0)
|
||||
playsound(calling_ai, 'sound/machines/chime.ogg',40, FALSE)
|
||||
calling_ai = null
|
||||
radio_channel = "AI Private" //Report on AI Private instead if the AI is controlling us.
|
||||
radio_channel = RADIO_CHANNEL_AI_PRIVATE //Report on AI Private instead if the AI is controlling us.
|
||||
|
||||
if(load) // if loaded, unload at target
|
||||
if(report_delivery)
|
||||
@@ -645,7 +669,7 @@
|
||||
log_combat(src, H, "run over", null, "(DAMTYPE: [uppertext(BRUTE)])")
|
||||
H.visible_message("<span class='danger'>[src] drives over [H]!</span>", \
|
||||
"<span class='userdanger'>[src] drives over you!</span>")
|
||||
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
|
||||
playsound(loc, 'sound/effects/splat.ogg', 50, TRUE)
|
||||
|
||||
var/damage = rand(5,15)
|
||||
H.apply_damage(2*damage, BRUTE, BODY_ZONE_HEAD, run_armor_check(BODY_ZONE_HEAD, "melee"))
|
||||
@@ -734,7 +758,7 @@
|
||||
|
||||
/mob/living/simple_animal/bot/mulebot/insertpai(mob/user, obj/item/paicard/card)
|
||||
if(..())
|
||||
visible_message("[src] safeties are locked on.")
|
||||
visible_message("<span class='notice'>[src] safeties are locked on.</span>")
|
||||
|
||||
#undef SIGH
|
||||
#undef ANNOYED
|
||||
@@ -742,3 +766,4 @@
|
||||
|
||||
/obj/machinery/bot_core/mulebot
|
||||
req_access = list(ACCESS_CARGO)
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
/datum/outfit/russiancorpse/officer
|
||||
name = "Russian Officer Corpse"
|
||||
uniform = /obj/item/clothing/under/rank/security/navyblue/russian
|
||||
suit = /obj/item/clothing/suit/security/officer/russian
|
||||
suit = /obj/item/clothing/suit/armor/navyblue/russian
|
||||
shoes = /obj/item/clothing/shoes/combat
|
||||
ears = /obj/item/radio/headset
|
||||
head = /obj/item/clothing/head/ushanka
|
||||
@@ -207,7 +207,7 @@
|
||||
/obj/effect/mob_spawn/human/corpse/bee_terrorist
|
||||
name = "BLF Operative"
|
||||
outfit = /datum/outfit/bee_terrorist
|
||||
|
||||
|
||||
/datum/outfit/bee_terrorist
|
||||
name = "BLF Operative"
|
||||
uniform = /obj/item/clothing/under/color/yellow
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
var/mob/living/simple_animal/mouse/movement_target
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
collar_type = "cat"
|
||||
can_be_held = "cat2"
|
||||
var/held_icon = "cat2"
|
||||
do_footstep = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/cat/Initialize()
|
||||
@@ -41,6 +41,7 @@
|
||||
/mob/living/simple_animal/pet/cat/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/wuv, "purrs!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "hisses!", EMOTE_AUDIBLE)
|
||||
AddElement(/datum/element/mob_holder, held_icon)
|
||||
|
||||
/mob/living/simple_animal/pet/cat/update_canmove()
|
||||
..()
|
||||
@@ -60,6 +61,7 @@
|
||||
icon_state = "spacecat"
|
||||
icon_living = "spacecat"
|
||||
icon_dead = "spacecat_dead"
|
||||
held_icon = "spacecat"
|
||||
unsuitable_atmos_damage = 0
|
||||
minbodytemp = TCMB
|
||||
maxbodytemp = T0C + 40
|
||||
@@ -71,6 +73,7 @@
|
||||
icon_state = "original"
|
||||
icon_living = "original"
|
||||
icon_dead = "original_dead"
|
||||
held_icon = "original"
|
||||
collar_type = null
|
||||
unique_pet = TRUE
|
||||
|
||||
@@ -84,7 +87,7 @@
|
||||
pass_flags = PASSMOB
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
collar_type = "kitten"
|
||||
can_be_held = "cat"
|
||||
held_icon = "cat"
|
||||
|
||||
//RUNTIME IS ALIVE! SQUEEEEEEEE~
|
||||
/mob/living/simple_animal/pet/cat/Runtime
|
||||
@@ -249,7 +252,7 @@
|
||||
attacked_sound = 'sound/items/eatfood.ogg'
|
||||
deathmessage = "loses its false life and collapses!"
|
||||
death_sound = "bodyfall"
|
||||
can_be_held = "cak"
|
||||
held_icon = "cak"
|
||||
|
||||
/mob/living/simple_animal/pet/cat/cak/CheckParts(list/parts)
|
||||
..()
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
see_in_dark = 5
|
||||
speak_chance = 1
|
||||
turns_per_move = 10
|
||||
var/held_icon = "corgi"
|
||||
|
||||
do_footstep = TRUE
|
||||
can_be_held = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/dog/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/wuv, "yaps_happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
|
||||
AddElement(/datum/element/mob_holder, held_icon)
|
||||
|
||||
//Corgis and pugs are now under one dog subtype
|
||||
|
||||
@@ -34,13 +35,11 @@
|
||||
childtype = list(/mob/living/simple_animal/pet/dog/corgi/puppy = 95, /mob/living/simple_animal/pet/dog/corgi/puppy/void = 5)
|
||||
animal_species = /mob/living/simple_animal/pet/dog
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
can_be_held = TRUE
|
||||
collar_type = "corgi"
|
||||
var/obj/item/inventory_head
|
||||
var/obj/item/inventory_back
|
||||
var/shaved = FALSE
|
||||
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
|
||||
can_be_held = "corgi"
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Destroy()
|
||||
QDEL_NULL(inventory_head)
|
||||
@@ -69,7 +68,7 @@
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
collar_type = "pug"
|
||||
can_be_held = "pug"
|
||||
held_icon = "pug"
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi
|
||||
name = "Exotic Corgi"
|
||||
@@ -156,13 +155,6 @@
|
||||
..()
|
||||
update_corgi_fluff()
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/mob_pickup(mob/living/L)
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "corgi", null, 'icons/mob/pets_held_lh.dmi', 'icons/mob/pets_held_rh.dmi', FALSE)
|
||||
if(!L.put_in_hands(holder))
|
||||
qdel(holder)
|
||||
else
|
||||
L.visible_message("<span class='warning'>[L] scoops up [src]!</span>")
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
|
||||
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
usr << browse(null, "window=mob[REF(src)]")
|
||||
@@ -371,7 +363,10 @@
|
||||
icon_dead = "old_corgi_dead"
|
||||
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
|
||||
turns_per_move = 20
|
||||
can_be_held = "old_corgi"
|
||||
var/datum/element/mob_holder/ele = SSdcs.GetElement(/datum/element/mob_holder, held_icon)
|
||||
if(ele)
|
||||
ele.Detach(src)
|
||||
AddElement(/datum/element/mob_holder, "old_corgi")
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
|
||||
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
|
||||
@@ -594,7 +589,7 @@
|
||||
unsuitable_atmos_damage = 0
|
||||
minbodytemp = TCMB
|
||||
maxbodytemp = T0C + 40
|
||||
can_be_held = "void_puppy"
|
||||
held_icon = "void_puppy"
|
||||
|
||||
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
|
||||
return 1 //Void puppies can navigate space.
|
||||
@@ -616,7 +611,7 @@
|
||||
response_harm = "kicks"
|
||||
var/turns_since_scan = 0
|
||||
var/puppies = 0
|
||||
can_be_held = "lisa"
|
||||
held_icon = "lisa"
|
||||
|
||||
//Lisa already has a cute bow!
|
||||
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
see_in_dark = 7
|
||||
blood_volume = 0
|
||||
can_be_held = TRUE
|
||||
var/can_be_held = TRUE //mob holder element.
|
||||
held_items = list(null, null)
|
||||
var/staticChoice = "static"
|
||||
var/list/staticChoices = list("static", "blank", "letter", "animal")
|
||||
@@ -101,6 +101,11 @@
|
||||
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
|
||||
diag_hud.add_to_hud(src)
|
||||
|
||||
/mob/living/simple_animal/drone/ComponentInitialize()
|
||||
. = ..()
|
||||
if(can_be_held)
|
||||
//icon/item state is defined in mob_holder/drone_worn_icon()
|
||||
AddElement(/datum/element/mob_holder, null, 'icons/mob/head.dmi', 'icons/mob/inhands/clothing_righthand.dmi', 'icons/mob/inhands/clothing_lefthand.dmi', TRUE, /datum/element/mob_holder.proc/drone_worn_icon)
|
||||
|
||||
/mob/living/simple_animal/drone/med_hud_set_health()
|
||||
var/image/holder = hud_list[DIAG_HUD]
|
||||
@@ -283,7 +288,3 @@
|
||||
var/obj/item/clothing/H = head
|
||||
if(H.clothing_flags & SCAN_REAGENTS)
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/drone/generate_mob_holder()
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "[visualAppearence]_hat", null, null, null, TRUE)
|
||||
return holder
|
||||
|
||||
@@ -130,10 +130,6 @@
|
||||
hacked = TRUE
|
||||
visualAppearence = CLOCKDRONE
|
||||
can_be_held = FALSE
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
flavortext = "<b><span class='nezbere'>You are a cogscarab,</span> a tiny building construct of Ratvar. While you're weak and can't recite scripture, \
|
||||
you have a set of quick tools, as well as a replica fabricator that can create brass and convert objects.<br><br>Work with the servants of Ratvar \
|
||||
to construct and maintain defenses at the City of Cogs. If there are no servants, use this time to experiment with base designs!"
|
||||
|
||||
/mob/living/simple_animal/drone/cogscarab/ratvar //a subtype for spawning when ratvar is alive, has a slab that it can use and a normal fabricator
|
||||
default_storage = /obj/item/storage/toolbox/brass/prefilled/ratvar
|
||||
|
||||
@@ -29,12 +29,6 @@
|
||||
if("Nothing")
|
||||
return
|
||||
|
||||
//picky up the drone c:
|
||||
/mob/living/simple_animal/drone/attack_hand(mob/user)
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return ..() // TODO: convert picking up mobs into an element or component.
|
||||
mob_try_pickup(user)
|
||||
|
||||
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
|
||||
var/mob/dead/observer/G = get_ghost()
|
||||
if(!client && (!G || !G.client))
|
||||
|
||||
@@ -18,9 +18,12 @@
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
can_be_held = "fox"
|
||||
do_footstep = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/fox/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/mob_holder, "fox")
|
||||
|
||||
//Captain fox
|
||||
/mob/living/simple_animal/pet/fox/Renault
|
||||
name = "Renault"
|
||||
|
||||
@@ -23,7 +23,10 @@
|
||||
obj_damage = 0
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
var/static/list/edibles = typecacheof(list(/mob/living/simple_animal/butterfly, /mob/living/simple_animal/cockroach)) //list of atoms, however turfs won't affect AI, but will affect consumption.
|
||||
can_be_held = "lizard" //you can hold lizards now.
|
||||
|
||||
/mob/living/simple_animal/hostile/lizard/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/mob_holder, "lizard", null, null, null, SLOT_HEAD) //you can hold lizards now.
|
||||
|
||||
/mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target?
|
||||
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
|
||||
@@ -40,7 +43,3 @@
|
||||
return TRUE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/lizard/generate_mob_holder()
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "lizard", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
|
||||
return holder
|
||||
|
||||
@@ -26,17 +26,16 @@
|
||||
var/body_color //brown, gray and white, leave blank for random
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
var/chew_probability = 1
|
||||
can_be_held = TRUE
|
||||
|
||||
/mob/living/simple_animal/mouse/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg'=1), 100)
|
||||
if(!body_color)
|
||||
body_color = pick( list("brown","gray","white") )
|
||||
body_color = pick(list("brown","gray","white"))
|
||||
AddElement(/datum/element/mob_holder, "mouse_[body_color]")
|
||||
icon_state = "mouse_[body_color]"
|
||||
icon_living = "mouse_[body_color]"
|
||||
icon_dead = "mouse_[body_color]_dead"
|
||||
can_be_held = "mouse_[body_color]"
|
||||
|
||||
/mob/living/simple_animal/mouse/proc/splat()
|
||||
src.health = 0
|
||||
@@ -89,17 +88,14 @@
|
||||
/mob/living/simple_animal/mouse/white
|
||||
body_color = "white"
|
||||
icon_state = "mouse_white"
|
||||
can_be_held = "mouse_white"
|
||||
|
||||
/mob/living/simple_animal/mouse/gray
|
||||
body_color = "gray"
|
||||
icon_state = "mouse_gray"
|
||||
can_be_held = "mouse_gray"
|
||||
|
||||
/mob/living/simple_animal/mouse/brown
|
||||
body_color = "brown"
|
||||
icon_state = "mouse_brown"
|
||||
can_be_held = "mouse_brown"
|
||||
|
||||
//TOM IS ALIVE! SQUEEEEEEEE~K :)
|
||||
/mob/living/simple_animal/mouse/brown/Tom
|
||||
@@ -124,7 +120,3 @@
|
||||
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
|
||||
reagents.clear_reagents()
|
||||
|
||||
/mob/living/simple_animal/mouse/generate_mob_holder()
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
|
||||
holder.w_class = WEIGHT_CLASS_TINY
|
||||
return holder
|
||||
|
||||
@@ -22,9 +22,11 @@
|
||||
maxHealth = 50
|
||||
speed = 10
|
||||
glide_size = 2
|
||||
can_be_held = "sloth" //finally oranges can be held
|
||||
do_footstep = TRUE
|
||||
|
||||
/mob/living/simple_animal/pet/fox/ComponentInitialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/mob_holder, "sloth") //finally oranges can be held
|
||||
|
||||
//Cargo Sloth
|
||||
/mob/living/simple_animal/sloth/paperwork
|
||||
|
||||
@@ -17,10 +17,9 @@
|
||||
emote_taunt = list("gnashes")
|
||||
taunt_chance = 30
|
||||
speed = 0
|
||||
maxHealth = 25
|
||||
health = 25
|
||||
maxHealth = 35
|
||||
health = 35
|
||||
spacewalk = TRUE
|
||||
|
||||
harm_intent_damage = 8
|
||||
obj_damage = 50
|
||||
melee_damage_lower = 15
|
||||
@@ -28,7 +27,6 @@
|
||||
attacktext = "bites"
|
||||
attack_sound = 'sound/weapons/bite.ogg'
|
||||
speak_emote = list("gnashes")
|
||||
|
||||
//Space carp aren't affected by cold.
|
||||
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)
|
||||
minbodytemp = 0
|
||||
@@ -37,6 +35,19 @@
|
||||
movement_type = FLYING
|
||||
pressure_resistance = 200
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
//some carps heal over time
|
||||
var/regen_cooldown = 0 //Used for how long it takes before a healing will take place default in 60 seconds
|
||||
var/regen_amount = 0 //How much is healed pre regen cooldown
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
. = ..()
|
||||
if(regen_amount)
|
||||
regen_cooldown = world.time + REGENERATION_DELAY
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/Life()
|
||||
. = ..()
|
||||
if(regen_amount && regen_cooldown < world.time)
|
||||
heal_overall_damage(regen_amount)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/AttackingTarget()
|
||||
. = ..()
|
||||
@@ -59,8 +70,11 @@
|
||||
icon_living = "megacarp"
|
||||
icon_dead = "megacarp_dead"
|
||||
icon_gib = "megacarp_gib"
|
||||
maxHealth = 20
|
||||
health = 20
|
||||
|
||||
regen_amount = 6
|
||||
|
||||
maxHealth = 30
|
||||
health = 30
|
||||
pixel_x = -16
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
|
||||
@@ -68,35 +82,26 @@
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 20
|
||||
|
||||
var/regen_cooldown = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp/Initialize()
|
||||
. = ..()
|
||||
name = "[pick(GLOB.megacarp_first_names)] [pick(GLOB.megacarp_last_names)]"
|
||||
melee_damage_lower += rand(2, 10)
|
||||
melee_damage_lower += rand(4, 10)
|
||||
melee_damage_upper += rand(10,20)
|
||||
maxHealth += rand(30,60)
|
||||
maxHealth += rand(40,60)
|
||||
move_to_delay = rand(3,7)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
regen_cooldown = world.time + REGENERATION_DELAY
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/megacarp/Life()
|
||||
. = ..()
|
||||
if(regen_cooldown < world.time)
|
||||
heal_overall_damage(4)
|
||||
|
||||
/mob/living/simple_animal/hostile/carp/cayenne
|
||||
name = "Cayenne"
|
||||
desc = "A failed Syndicate experiment in weaponized space carp technology, it now serves as a lovable mascot."
|
||||
gender = FEMALE
|
||||
|
||||
regen_amount = 8
|
||||
|
||||
speak_emote = list("squeaks")
|
||||
maxHealth = 90
|
||||
health = 90
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
faction = list(ROLE_SYNDICATE)
|
||||
faction = list(ROLE_SYNDICATE, "carp") //They are still a carp
|
||||
AIStatus = AI_OFF
|
||||
|
||||
harm_intent_damage = 12
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
var/obj/item/organ/tail/cat/tail = L.getorgan(/obj/item/organ/tail/cat)
|
||||
if(!QDELETED(tail))
|
||||
visible_message("[src] severs [L]'s tail in one swift swipe!", "<span class='notice'>You sever [L]'s tail in one swift swipe.</span>")
|
||||
tail.Remove(L)
|
||||
tail.Remove()
|
||||
var/obj/item/organ/tail/cat/dropped_tail = new(target.drop_location())
|
||||
dropped_tail.color = L.hair_color
|
||||
return 1
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
time++
|
||||
if(time >= EGG_INCUBATION_TIME)
|
||||
Pop()
|
||||
Remove(owner)
|
||||
Remove()
|
||||
qdel(src)
|
||||
|
||||
/obj/item/organ/body_egg/changeling_egg/proc/Pop()
|
||||
|
||||
@@ -432,6 +432,7 @@ Difficulty: Very Hard
|
||||
H.dropItemToGround(W)
|
||||
var/datum/job/clown/C = new /datum/job/clown()
|
||||
C.equip(H)
|
||||
C.after_spawn(H, H, TRUE)
|
||||
qdel(C)
|
||||
affected_targets.Add(H)
|
||||
|
||||
|
||||
@@ -197,8 +197,6 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/ranged
|
||||
var/obj/item/gun/TrueGun = null
|
||||
var/obj/item/gun/magic/Zapstick
|
||||
@@ -229,14 +227,13 @@ GLOBAL_LIST_INIT(protected_objects, list(/obj/structure/table, /obj/structure/ca
|
||||
casingtype = initial(M.ammo_type)
|
||||
if(istype(G, /obj/item/gun/energy))
|
||||
Zapgun = G
|
||||
var/selectfiresetting = Zapgun.select
|
||||
var/obj/item/ammo_casing/energy/E = Zapgun.ammo_type[selectfiresetting]
|
||||
var/obj/item/ammo_casing/energy/E = Zapgun.ammo_type[Zapgun.current_firemode_index]
|
||||
projectiletype = initial(E.projectile_type)
|
||||
|
||||
/mob/living/simple_animal/hostile/mimic/copy/ranged/OpenFire(the_target)
|
||||
if(Zapgun)
|
||||
if(Zapgun.cell)
|
||||
var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.select]
|
||||
var/obj/item/ammo_casing/energy/shot = Zapgun.ammo_type[Zapgun.current_firemode_index]
|
||||
if(Zapgun.cell.charge >= shot.e_cost)
|
||||
Zapgun.cell.use(shot.e_cost)
|
||||
Zapgun.update_icon()
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
|
||||
/obj/item/projectile/temp/basilisk/magmawing/on_hit(atom/target, blocked = FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
if(. && isliving(target))
|
||||
var/mob/living/L = target
|
||||
if (istype(L))
|
||||
L.adjust_fire_stacks(0.1)
|
||||
@@ -144,7 +144,7 @@
|
||||
|
||||
/obj/item/projectile/temp/basilisk/icewing/on_hit(atom/target, blocked = FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
if(. && isliving(target))
|
||||
var/mob/living/L = target
|
||||
L.apply_status_effect(/datum/status_effect/freon/watcher)
|
||||
|
||||
|
||||
@@ -62,8 +62,9 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
|
||||
. = ..()
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
|
||||
if(.)
|
||||
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
|
||||
|
||||
/datum/action/innate/elite_attack/herald_trishot
|
||||
name = "Triple Shot"
|
||||
button_icon_state = "herald_trishot"
|
||||
|
||||
@@ -208,8 +208,8 @@
|
||||
ears.forceMove(drop_location())
|
||||
ears = null
|
||||
for(var/possible_phrase in speak)
|
||||
if(copytext(possible_phrase,1,3) in GLOB.department_radio_keys)
|
||||
possible_phrase = copytext(possible_phrase,3)
|
||||
if(copytext_char(possible_phrase, 2, 3) in GLOB.department_radio_keys)
|
||||
possible_phrase = copytext_char(possible_phrase, 3)
|
||||
|
||||
//Adding things to inventory
|
||||
else if(href_list["add_inv"])
|
||||
@@ -332,8 +332,8 @@
|
||||
speak_chance *= 1.27 // 20 crackers to go from 1% to 100%
|
||||
speech_shuffle_rate += 10
|
||||
to_chat(user, "<span class='notice'>[src] eagerly devours the cracker.</span>")
|
||||
..()
|
||||
return
|
||||
return // the cracker was deleted
|
||||
return ..()
|
||||
|
||||
//Bullets
|
||||
/mob/living/simple_animal/parrot/bullet_act(obj/item/projectile/Proj)
|
||||
@@ -419,8 +419,8 @@
|
||||
if(prob(50))
|
||||
useradio = 1
|
||||
|
||||
if((copytext(possible_phrase,1,2) in GLOB.department_radio_prefixes) && (copytext(possible_phrase,2,3) in GLOB.department_radio_keys))
|
||||
possible_phrase = "[useradio?pick(available_channels):""][copytext(possible_phrase,3)]" //crop out the channel prefix
|
||||
if((possible_phrase[1] in GLOB.department_radio_prefixes) && (copytext_char(possible_phrase, 2, 3) in GLOB.department_radio_keys))
|
||||
possible_phrase = "[useradio?pick(available_channels):""][copytext_char(possible_phrase, 3)]" //crop out the channel prefix
|
||||
else
|
||||
possible_phrase = "[useradio?pick(available_channels):""][possible_phrase]"
|
||||
|
||||
@@ -428,8 +428,8 @@
|
||||
|
||||
else //If we have no headset or channels to use, dont try to use any!
|
||||
for(var/possible_phrase in speak)
|
||||
if((copytext(possible_phrase,1,2) in GLOB.department_radio_prefixes) && (copytext(possible_phrase,2,3) in GLOB.department_radio_keys))
|
||||
possible_phrase = copytext(possible_phrase,3) //crop out the channel prefix
|
||||
if((possible_phrase[1] in GLOB.department_radio_prefixes) && (copytext_char(possible_phrase, 2, 3) in GLOB.department_radio_keys))
|
||||
possible_phrase = copytext_char(possible_phrase, 3) //crop out the channel prefix
|
||||
newspeak.Add(possible_phrase)
|
||||
speak = newspeak
|
||||
|
||||
|
||||
@@ -81,7 +81,6 @@
|
||||
|
||||
var/dextrous = FALSE //If the creature has, and can use, hands
|
||||
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), AI_Z_OFF (Temporarily off due to nonpresence of players)
|
||||
var/can_have_ai = TRUE //once we have become sentient, we can never go back
|
||||
@@ -98,7 +97,6 @@
|
||||
/mob/living/simple_animal/Initialize()
|
||||
. = ..()
|
||||
GLOB.simple_animals[AIStatus] += src
|
||||
handcrafting = new()
|
||||
if(gender == PLURAL)
|
||||
gender = pick(MALE,FEMALE)
|
||||
if(!real_name)
|
||||
@@ -106,6 +104,8 @@
|
||||
if(!loc)
|
||||
stack_trace("Simple animal being instantiated in nullspace")
|
||||
update_simplemob_varspeed()
|
||||
if(dextrous)
|
||||
AddComponent(/datum/component/personal_crafting)
|
||||
|
||||
/mob/living/simple_animal/Destroy()
|
||||
GLOB.simple_animals[AIStatus] -= src
|
||||
@@ -471,10 +471,6 @@
|
||||
/mob/living/simple_animal/get_idcard(hand_first = TRUE)
|
||||
return ..() || access_card
|
||||
|
||||
/mob/living/simple_animal/OpenCraftingMenu()
|
||||
if(dextrous)
|
||||
handcrafting.ui_interact(src)
|
||||
|
||||
/mob/living/simple_animal/can_hold_items()
|
||||
return dextrous
|
||||
|
||||
|
||||
@@ -212,7 +212,7 @@
|
||||
emote("deathgasp")
|
||||
ADD_TRAIT(src, TRAIT_FAKEDEATH, source)
|
||||
ADD_TRAIT(src, TRAIT_DEATHCOMA, source)
|
||||
tod = STATION_TIME_TIMESTAMP("hh:mm:ss")
|
||||
tod = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)
|
||||
update_stat()
|
||||
|
||||
/mob/living/proc/unignore_slowdown(list/sources)
|
||||
|
||||
@@ -53,3 +53,5 @@
|
||||
CB.Invoke()
|
||||
|
||||
log_message("Client [key_name(src)] has taken ownership of mob [src]([src.type])", LOG_OWNERSHIP)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_CLIENT_LOGIN, client)
|
||||
|
||||
|
||||
+19
-29
@@ -82,7 +82,7 @@
|
||||
if(!client)
|
||||
return
|
||||
|
||||
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
|
||||
msg = copytext_char(msg, 1, MAX_MESSAGE_LEN)
|
||||
|
||||
if(type)
|
||||
if(type & MSG_VISUAL && eye_blind )//Vision related
|
||||
@@ -321,20 +321,18 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
|
||||
set name = "Examine"
|
||||
set category = "IC"
|
||||
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(!(SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) & COMPONENT_ALLOW_EXAMINE) && ((client.eye != src && client.eye != loc) || (isturf(A) && !(sight & SEE_TURFS) && !(A in view(client ? client.view : world.view, src)))))
|
||||
//cameras & co don't allow users to examine far away things, also shift-click catcher may issue examinate() calls for out-of-sight turfs
|
||||
if(isturf(A) && !(sight & SEE_TURFS) && !(A in view(client ? client.view : world.view, src)))
|
||||
// shift-click catcher may issue examinate() calls for out-of-sight turfs
|
||||
return
|
||||
|
||||
if(is_blind(src))
|
||||
to_chat(src, "<span class='notice'>Something is there but you can't see it.</span>")
|
||||
to_chat(src, "<span class='warning'>Something is there but you can't see it!</span>")
|
||||
return
|
||||
|
||||
face_atom(A)
|
||||
var/list/result = A.examine(src)
|
||||
to_chat(src, result.Join("\n"))
|
||||
SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
|
||||
|
||||
//same as above
|
||||
//note: ghosts can point, this is intended
|
||||
@@ -414,7 +412,7 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
|
||||
set name = "Add Note"
|
||||
set category = "IC"
|
||||
|
||||
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
|
||||
msg = copytext_char(msg, 1, MAX_MESSAGE_LEN)
|
||||
msg = sanitize(msg)
|
||||
|
||||
if(mind)
|
||||
@@ -513,7 +511,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
|
||||
if(href_list["flavor2_more"])
|
||||
usr << browse(text("<HTML><HEAD><TITLE>[]</TITLE></HEAD><BODY><TT>[]</TT></BODY></HTML>", name, replacetext(flavor_text_2, "\n", "<BR>")), text("window=[];size=500x200", name))
|
||||
onclose(usr, "[name]")
|
||||
|
||||
|
||||
if(href_list["flavor_change"])
|
||||
update_flavor_text()
|
||||
|
||||
@@ -571,29 +569,23 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
|
||||
M.show_inv(user)
|
||||
|
||||
/mob/proc/is_muzzled()
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/mob/Stat()
|
||||
..()
|
||||
|
||||
if(statpanel("Status"))
|
||||
if (client)
|
||||
stat(null, "Ping: [round(client.lastping, 1)]ms (Average: [round(client.avgping, 1)]ms)")
|
||||
stat(null, "Map: [SSmapping.config?.map_name || "Loading..."]")
|
||||
var/datum/map_config/cached = SSmapping.next_map_config
|
||||
if(cached)
|
||||
stat(null, "Next Map: [cached.map_name]")
|
||||
stat(null, "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]")
|
||||
stat(null, "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]")
|
||||
stat(null, "Round Time: [WORLDTIME2TEXT("hh:mm:ss")]")
|
||||
stat(null, "Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]")
|
||||
stat(null, "Time Dilation: [round(SStime_track.time_dilation_current,1)]% AVG:([round(SStime_track.time_dilation_avg_fast,1)]%, [round(SStime_track.time_dilation_avg,1)]%, [round(SStime_track.time_dilation_avg_slow,1)]%)")
|
||||
if(SSshuttle.emergency)
|
||||
var/ETA = SSshuttle.emergency.getModeStr()
|
||||
if(ETA)
|
||||
stat(null, "[ETA] [SSshuttle.emergency.getTimerStr()]")
|
||||
//This is only called from client/Stat(), let's assume client exists.
|
||||
|
||||
if(client && client.holder)
|
||||
if(statpanel("Status"))
|
||||
var/list/L = list()
|
||||
L += "Ping: [round(client.lastping,1)]ms (Avg: [round(client.avgping,1)]ms)"
|
||||
L += SSmapping.stat_map_name
|
||||
L += "Round ID: [GLOB.round_id || "NULL"]"
|
||||
L += SStime_track.stat_time_text
|
||||
L += SSshuttle.emergency_shuttle_stat_text
|
||||
stat(null, "[L.Join("\n\n")]")
|
||||
|
||||
if(client.holder)
|
||||
if(statpanel("MC"))
|
||||
var/turf/T = get_turf(client.eye)
|
||||
stat("Location:", COORD(T))
|
||||
@@ -643,8 +635,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
|
||||
if(A.IsObscured())
|
||||
continue
|
||||
statpanel(listed_turf.name, null, A)
|
||||
|
||||
|
||||
if(mind)
|
||||
add_spells_to_statpanel(mind.spell_list)
|
||||
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
|
||||
|
||||
+153
-148
@@ -42,128 +42,131 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
/proc/stars(n, pr)
|
||||
n = html_encode(n)
|
||||
if (pr == null)
|
||||
pr = 25
|
||||
if (pr <= 0)
|
||||
return null
|
||||
else
|
||||
if (pr >= 100)
|
||||
return n
|
||||
var/te = n
|
||||
var/t = ""
|
||||
n = length(n)
|
||||
var/p = null
|
||||
p = 1
|
||||
while(p <= n)
|
||||
if ((copytext(te, p, p + 1) == " " || prob(pr)))
|
||||
t = text("[][]", t, copytext(te, p, p + 1))
|
||||
/**
|
||||
* Convert random parts of a passed in message to stars
|
||||
*
|
||||
* * phrase - the string to convert
|
||||
* * probability - probability any character gets changed
|
||||
*
|
||||
* This proc is dangerously laggy, avoid it or die
|
||||
*/
|
||||
/proc/stars(phrase, probability = 25)
|
||||
if(probability <= 0)
|
||||
return phrase
|
||||
phrase = html_decode(phrase)
|
||||
var/leng = length(phrase)
|
||||
. = ""
|
||||
var/char = ""
|
||||
for(var/i = 1, i <= leng, i += length(char))
|
||||
char = phrase[i]
|
||||
if(char == " " || !prob(probability))
|
||||
. += char
|
||||
else
|
||||
t = text("[]*", t)
|
||||
p++
|
||||
return sanitize(t)
|
||||
. += "*"
|
||||
return sanitize(.)
|
||||
|
||||
/proc/slur(n,var/strength=50)
|
||||
strength = min(strength,50)
|
||||
var/phrase = html_decode(n)
|
||||
/**
|
||||
* Makes you speak like you're drunk
|
||||
*/
|
||||
/proc/slur(phrase, strength = 50)
|
||||
strength = min(50, strength)
|
||||
phrase = html_decode(phrase)
|
||||
var/leng = length(phrase)
|
||||
var/counter=length(phrase)
|
||||
var/newphrase=""
|
||||
var/newletter=""
|
||||
while(counter>=1)
|
||||
newletter=copytext(phrase,(leng-counter)+1,(leng-counter)+2)
|
||||
if(rand(1,100)<=strength*0.5)
|
||||
if(lowertext(newletter)=="o")
|
||||
newletter="u"
|
||||
if(lowertext(newletter)=="s")
|
||||
newletter="ch"
|
||||
if(lowertext(newletter)=="a")
|
||||
newletter="ah"
|
||||
if(lowertext(newletter)=="u")
|
||||
newletter="oo"
|
||||
if(lowertext(newletter)=="c")
|
||||
newletter="k"
|
||||
if(rand(1,100) <= strength*0.25)
|
||||
if(newletter==" ")
|
||||
newletter="...huuuhhh..."
|
||||
if(newletter==".")
|
||||
newletter=" BURP!"
|
||||
if(rand(1,100) <= strength*0.5)
|
||||
if(rand(1,5) == 1)
|
||||
newletter+="'"
|
||||
if(rand(1,5) == 1)
|
||||
newletter+="[newletter]"
|
||||
if(rand(1,5) == 1)
|
||||
newletter+="[newletter][newletter]"
|
||||
newphrase+="[newletter]";counter-=1
|
||||
return newphrase
|
||||
|
||||
|
||||
/proc/cultslur(n) // Inflicted on victims of a stun talisman
|
||||
var/phrase = html_decode(n)
|
||||
var/leng = length(phrase)
|
||||
var/counter=length(phrase)
|
||||
var/newphrase=""
|
||||
var/newletter=""
|
||||
while(counter>=1)
|
||||
newletter=copytext(phrase,(leng-counter)+1,(leng-counter)+2)
|
||||
if(rand(1,2)==2)
|
||||
if(lowertext(newletter)=="o")
|
||||
newletter="u"
|
||||
if(lowertext(newletter)=="t")
|
||||
newletter="ch"
|
||||
if(lowertext(newletter)=="a")
|
||||
newletter="ah"
|
||||
if(lowertext(newletter)=="u")
|
||||
newletter="oo"
|
||||
if(lowertext(newletter)=="c")
|
||||
newletter=" NAR "
|
||||
if(lowertext(newletter)=="s")
|
||||
newletter=" SIE "
|
||||
if(rand(1,4)==4)
|
||||
if(newletter==" ")
|
||||
newletter=" no hope... "
|
||||
if(newletter=="H")
|
||||
newletter=" IT COMES... "
|
||||
|
||||
switch(rand(1,15))
|
||||
. = ""
|
||||
var/newletter = ""
|
||||
var/rawchar = ""
|
||||
for(var/i = 1, i <= leng, i += length(rawchar))
|
||||
rawchar = newletter = phrase[i]
|
||||
if(rand(1,100)<=strength * 0.5)
|
||||
var/lowerletter = lowertext(newletter)
|
||||
if(lowerletter == "o")
|
||||
newletter = "u"
|
||||
else if(lowerletter == "s")
|
||||
newletter = "ch"
|
||||
else if(lowerletter == "a")
|
||||
newletter = "ah"
|
||||
else if(lowerletter == "u")
|
||||
newletter = "oo"
|
||||
else if(lowerletter == "c")
|
||||
newletter = "k"
|
||||
if(rand(1,100) <= strength * 0.25)
|
||||
if(newletter == " ")
|
||||
newletter = "...huuuhhh..."
|
||||
else if(newletter == ".")
|
||||
newletter = " *BURP*."
|
||||
switch(rand(1,100) <= strength * 0.5)
|
||||
if(1)
|
||||
newletter="'"
|
||||
newletter += "'"
|
||||
if(10)
|
||||
newletter += "[newletter]"
|
||||
if(20)
|
||||
newletter += "[newletter][newletter]"
|
||||
. += "[newletter]"
|
||||
return sanitize(.)
|
||||
|
||||
/// Makes you talk like you got cult stunned, which is slurring but with some dark messages
|
||||
/proc/cultslur(phrase) // Inflicted on victims of a stun talisman
|
||||
phrase = html_decode(phrase)
|
||||
var/leng = length(phrase)
|
||||
. = ""
|
||||
var/newletter = ""
|
||||
var/rawchar = ""
|
||||
for(var/i = 1, i <= leng, i += length(rawchar))
|
||||
rawchar = newletter = phrase[i]
|
||||
if(rand(1, 2) == 2)
|
||||
var/lowerletter = lowertext(newletter)
|
||||
if(lowerletter == "o")
|
||||
newletter = "u"
|
||||
else if(lowerletter == "t")
|
||||
newletter = "ch"
|
||||
else if(lowerletter == "a")
|
||||
newletter = "ah"
|
||||
else if(lowerletter == "u")
|
||||
newletter = "oo"
|
||||
else if(lowerletter == "c")
|
||||
newletter = " NAR "
|
||||
else if(lowerletter == "s")
|
||||
newletter = " SIE "
|
||||
if(rand(1, 4) == 4)
|
||||
if(newletter == " ")
|
||||
newletter = " no hope... "
|
||||
else if(newletter == "H")
|
||||
newletter = " IT COMES... "
|
||||
|
||||
switch(rand(1, 15))
|
||||
if(1)
|
||||
newletter = "'"
|
||||
if(2)
|
||||
newletter+="agn"
|
||||
newletter += "agn"
|
||||
if(3)
|
||||
newletter="fth"
|
||||
newletter = "fth"
|
||||
if(4)
|
||||
newletter="nglu"
|
||||
newletter = "nglu"
|
||||
if(5)
|
||||
newletter="glor"
|
||||
newphrase+="[newletter]";counter-=1
|
||||
return newphrase
|
||||
newletter = "glor"
|
||||
. += newletter
|
||||
return sanitize(.)
|
||||
|
||||
|
||||
/proc/stutter(n)
|
||||
var/te = html_decode(n)
|
||||
var/t = ""//placed before the message. Not really sure what it's for.
|
||||
n = length(n)//length of the entire word
|
||||
var/p = null
|
||||
p = 1//1 is the start of any word
|
||||
while(p <= n)//while P, which starts at 1 is less or equal to N which is the length.
|
||||
var/n_letter = copytext(te, p, p + 1)//copies text from a certain distance. In this case, only one letter at a time.
|
||||
if (prob(80) && (ckey(n_letter) in list("b","c","d","f","g","h","j","k","l","m","n","p","q","r","s","t","v","w","x","y","z")))
|
||||
if (prob(10))
|
||||
n_letter = text("[n_letter]-[n_letter]-[n_letter]-[n_letter]")//replaces the current letter with this instead.
|
||||
///Adds stuttering to the message passed in
|
||||
/proc/stutter(phrase)
|
||||
phrase = html_decode(phrase)
|
||||
var/leng = length(phrase)
|
||||
. = ""
|
||||
var/newletter = ""
|
||||
var/rawchar
|
||||
for(var/i = 1, i <= leng, i += length(rawchar))
|
||||
rawchar = newletter = phrase[i]
|
||||
if(prob(80) && !(lowertext(newletter) in list("a", "e", "i", "o", "u", " ")))
|
||||
if(prob(10))
|
||||
newletter = "[newletter]-[newletter]-[newletter]-[newletter]"
|
||||
else if(prob(20))
|
||||
newletter = "[newletter]-[newletter]-[newletter]"
|
||||
else if (prob(5))
|
||||
newletter = ""
|
||||
else
|
||||
if (prob(20))
|
||||
n_letter = text("[n_letter]-[n_letter]-[n_letter]")
|
||||
else
|
||||
if (prob(5))
|
||||
n_letter = null
|
||||
else
|
||||
n_letter = text("[n_letter]-[n_letter]")
|
||||
t = text("[t][n_letter]")//since the above is ran through for each letter, the text just adds up back to the original word.
|
||||
p++//for each letter p is increased to find where the next letter will be.
|
||||
return copytext(sanitize(t),1,MAX_MESSAGE_LEN)
|
||||
newletter = "[newletter]-[newletter]"
|
||||
. += newletter
|
||||
return sanitize(.)
|
||||
|
||||
/proc/derpspeech(message, stuttering)
|
||||
message = replacetext(message, " am ", " ")
|
||||
@@ -183,52 +186,42 @@
|
||||
return message
|
||||
|
||||
|
||||
/proc/Gibberish(t, p)//t is the inputted message, and any value higher than 70 for p will cause letters to be replaced instead of added
|
||||
/* Turn text into complete gibberish! */
|
||||
var/returntext = ""
|
||||
for(var/i = 1, i <= length(t), i++)
|
||||
|
||||
var/letter = copytext(t, i, i+1)
|
||||
if(prob(50))
|
||||
if(p >= 70)
|
||||
/proc/Gibberish(text, replace_characters = FALSE, chance = 50)
|
||||
text = html_decode(text)
|
||||
. = ""
|
||||
var/rawchar = ""
|
||||
var/letter = ""
|
||||
var/lentext = length(text)
|
||||
for(var/i = 1, i <= lentext, i += length(rawchar))
|
||||
rawchar = letter = text[i]
|
||||
if(prob(chance))
|
||||
if(replace_characters)
|
||||
letter = ""
|
||||
for(var/j in 1 to rand(0, 2))
|
||||
letter += pick("#", "@", "*", "&", "%", "$", "/", "<", ">", ";", "*", "*", "*", "*", "*", "*", "*")
|
||||
. += letter
|
||||
return sanitize(.)
|
||||
|
||||
for(var/j = 1, j <= rand(0, 2), j++)
|
||||
letter += pick("#","@","*","&","%","$","/", "<", ">", ";","*","*","*","*","*","*","*")
|
||||
|
||||
returntext += letter
|
||||
|
||||
return returntext
|
||||
|
||||
|
||||
/proc/ninjaspeak(n) //NINJACODE
|
||||
/*
|
||||
The difference with stutter is that this proc can stutter more than 1 letter
|
||||
The issue here is that anything that does not have a space is treated as one word (in many instances). For instance, "LOOKING," is a word, including the comma.
|
||||
It's fairly easy to fix if dealing with single letters but not so much with compounds of letters./N
|
||||
*/
|
||||
var/te = html_decode(n)
|
||||
var/t = ""
|
||||
n = length(n)
|
||||
var/p = 1
|
||||
while(p <= n)
|
||||
var/n_letter
|
||||
var/n_mod = rand(1,4)
|
||||
if(p+n_mod>n+1)
|
||||
n_letter = copytext(te, p, n+1)
|
||||
else
|
||||
n_letter = copytext(te, p, p+n_mod)
|
||||
/proc/ninjaspeak(phrase) //NINJACODE
|
||||
. = ""
|
||||
var/lentext = length_char(phrase)
|
||||
var/rawchars = ""
|
||||
var/letter = ""
|
||||
for(var/i = 1, i <= lentext, i += length_char(rawchars))
|
||||
var/end = i + rand(1,4)
|
||||
letter = rawchars = copytext_char(phrase, i, end > lentext ? 0 : end)
|
||||
if (prob(50))
|
||||
if (prob(30))
|
||||
n_letter = text("[n_letter]-[n_letter]-[n_letter]")
|
||||
letter = "[letter]-[letter]-[letter]"
|
||||
else
|
||||
n_letter = text("[n_letter]-[n_letter]")
|
||||
else
|
||||
n_letter = text("[n_letter]")
|
||||
t = text("[t][n_letter]")
|
||||
p=p+n_mod
|
||||
return copytext(sanitize(t),1,MAX_MESSAGE_LEN)
|
||||
|
||||
letter = "[letter]-[letter]"
|
||||
. += letter
|
||||
return copytext_char(sanitize(.),1,MAX_MESSAGE_LEN)
|
||||
|
||||
/proc/shake_camera(mob/M, duration, strength=1)
|
||||
if(!M || !M.client || duration < 1)
|
||||
@@ -409,6 +402,18 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/proc/canGhostWrite(var/mob/A, var/obj/target, var/desc="", var/allow_all=FALSE)
|
||||
if(allow_all & TRUE)
|
||||
if(!target.GetComponent(/datum/component/anti_magic))
|
||||
return 1
|
||||
if(IsAdminGhost(A))
|
||||
if (desc != "")
|
||||
log_admin("GHOST: [key_name(A)] [desc] ([target.name] at [loc_name(target)])")
|
||||
else
|
||||
log_admin("GHOST: [key_name(A)] fucked with the [target.name] at [loc_name(target)]")
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/proc/offer_control(mob/M)
|
||||
to_chat(M, "Control of your mob has been offered to dead players.")
|
||||
if(usr)
|
||||
|
||||
@@ -9,37 +9,36 @@
|
||||
mob.dropItemToGround(mob.get_active_held_item())
|
||||
return
|
||||
|
||||
/client/proc/Move_object(direct)
|
||||
/client/proc/Move_object(direction)
|
||||
if(mob && mob.control_object)
|
||||
if(mob.control_object.density)
|
||||
step(mob.control_object,direct)
|
||||
step(mob.control_object,direction)
|
||||
if(!mob.control_object)
|
||||
return
|
||||
mob.control_object.setDir(direct)
|
||||
mob.control_object.setDir(direction)
|
||||
else
|
||||
mob.control_object.forceMove(get_step(mob.control_object,direct))
|
||||
mob.control_object.forceMove(get_step(mob.control_object,direction))
|
||||
|
||||
#define MOVEMENT_DELAY_BUFFER 0.75
|
||||
#define MOVEMENT_DELAY_BUFFER_DELTA 1.25
|
||||
|
||||
/client/Move(n, direct)
|
||||
/client/Move(n, direction)
|
||||
if(world.time < move_delay) //do not move anything ahead of this check please
|
||||
return FALSE
|
||||
else
|
||||
next_move_dir_add = 0
|
||||
next_move_dir_sub = 0
|
||||
next_move_dir_add = next_move_dir_sub = NONE
|
||||
var/old_move_delay = move_delay
|
||||
move_delay = world.time + world.tick_lag //this is here because Move() can now be called mutiple times per tick
|
||||
if(!mob || !mob.loc)
|
||||
return FALSE
|
||||
if(!n || !direct)
|
||||
if(!n || !direction || !mob?.loc)
|
||||
return FALSE
|
||||
//GET RID OF THIS SOON AS MOBILITY FLAGS IS DONE
|
||||
if(mob.notransform)
|
||||
return FALSE //This is sota the goto stop mobs from moving var
|
||||
return FALSE
|
||||
|
||||
if(mob.control_object)
|
||||
return Move_object(direct)
|
||||
return Move_object(direction)
|
||||
if(!isliving(mob))
|
||||
return mob.Move(n, direct)
|
||||
return mob.Move(n, direction)
|
||||
if(mob.stat == DEAD)
|
||||
mob.ghostize()
|
||||
return FALSE
|
||||
@@ -48,29 +47,29 @@
|
||||
|
||||
var/mob/living/L = mob //Already checked for isliving earlier
|
||||
if(L.incorporeal_move) //Move though walls
|
||||
Process_Incorpmove(direct)
|
||||
Process_Incorpmove(direction)
|
||||
return FALSE
|
||||
|
||||
if(mob.remote_control) //we're controlling something, our movement is relayed to it
|
||||
return mob.remote_control.relaymove(mob, direct)
|
||||
return mob.remote_control.relaymove(mob, direction)
|
||||
|
||||
if(isAI(mob))
|
||||
return AIMove(n,direct,mob)
|
||||
return AIMove(n,direction,mob)
|
||||
|
||||
if(Process_Grab()) //are we restrained by someone's grip?
|
||||
return
|
||||
|
||||
if(mob.buckled) //if we're buckled to something, tell it we moved.
|
||||
return mob.buckled.relaymove(mob, direct)
|
||||
return mob.buckled.relaymove(mob, direction)
|
||||
|
||||
if(!mob.canmove)
|
||||
return FALSE
|
||||
|
||||
if(isobj(mob.loc) || ismob(mob.loc)) //Inside an object, tell it we moved
|
||||
var/atom/O = mob.loc
|
||||
return O.relaymove(mob, direct)
|
||||
return O.relaymove(mob, direction)
|
||||
|
||||
if(!mob.Process_Spacemove(direct))
|
||||
if(!mob.Process_Spacemove(direction))
|
||||
return FALSE
|
||||
//We are now going to move
|
||||
var/add_delay = mob.movement_delay()
|
||||
@@ -85,16 +84,16 @@
|
||||
if(L.confused > 40)
|
||||
newdir = pick(GLOB.alldirs)
|
||||
else if(prob(L.confused * 1.5))
|
||||
newdir = angle2dir(dir2angle(direct) + pick(90, -90))
|
||||
newdir = angle2dir(dir2angle(direction) + pick(90, -90))
|
||||
else if(prob(L.confused * 3))
|
||||
newdir = angle2dir(dir2angle(direct) + pick(45, -45))
|
||||
newdir = angle2dir(dir2angle(direction) + pick(45, -45))
|
||||
if(newdir)
|
||||
direct = newdir
|
||||
n = get_step(L, direct)
|
||||
direction = newdir
|
||||
n = get_step(L, direction)
|
||||
|
||||
. = ..()
|
||||
|
||||
if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully
|
||||
if((direction & (direction - 1)) && mob.loc == n) //moved diagonally successfully
|
||||
add_delay *= 2
|
||||
move_delay += add_delay
|
||||
if(.) // If mob is null here, we deserve the runtime
|
||||
@@ -102,7 +101,7 @@
|
||||
mob.throwing.finalize(FALSE)
|
||||
|
||||
for(var/obj/O in mob.user_movement_hooks)
|
||||
O.intercept_user_move(direct, mob, n, oldloc)
|
||||
O.intercept_user_move(direction, mob, n, oldloc)
|
||||
|
||||
var/atom/movable/P = mob.pulling
|
||||
if(P && !ismob(P) && P.density)
|
||||
@@ -126,22 +125,22 @@
|
||||
///Process_Incorpmove
|
||||
///Called by client/Move()
|
||||
///Allows mobs to run though walls
|
||||
/client/proc/Process_Incorpmove(direct)
|
||||
/client/proc/Process_Incorpmove(direction)
|
||||
var/turf/mobloc = get_turf(mob)
|
||||
if(!isliving(mob))
|
||||
return
|
||||
var/mob/living/L = mob
|
||||
switch(L.incorporeal_move)
|
||||
if(INCORPOREAL_MOVE_BASIC)
|
||||
var/T = get_step(L,direct)
|
||||
var/T = get_step(L,direction)
|
||||
if(T)
|
||||
L.forceMove(T)
|
||||
L.setDir(direct)
|
||||
L.setDir(direction)
|
||||
if(INCORPOREAL_MOVE_SHADOW)
|
||||
if(prob(50))
|
||||
var/locx
|
||||
var/locy
|
||||
switch(direct)
|
||||
switch(direction)
|
||||
if(NORTH)
|
||||
locx = mobloc.x
|
||||
locy = (mobloc.y+2)
|
||||
@@ -175,12 +174,12 @@
|
||||
break
|
||||
else
|
||||
new /obj/effect/temp_visual/dir_setting/ninja/shadow(mobloc, L.dir)
|
||||
var/T = get_step(L,direct)
|
||||
var/T = get_step(L,direction)
|
||||
if(T)
|
||||
L.forceMove(T)
|
||||
L.setDir(direct)
|
||||
L.setDir(direction)
|
||||
if(INCORPOREAL_MOVE_JAUNT) //Incorporeal move, but blocked by holy-watered tiles and salt piles.
|
||||
var/turf/open/floor/stepTurf = get_step(L, direct)
|
||||
var/turf/open/floor/stepTurf = get_step(L, direction)
|
||||
if(stepTurf)
|
||||
for(var/obj/effect/decal/cleanable/salt/S in stepTurf)
|
||||
to_chat(L, "<span class='warning'>[S] bars your passage!</span>")
|
||||
@@ -197,7 +196,7 @@
|
||||
return
|
||||
|
||||
L.forceMove(stepTurf)
|
||||
L.setDir(direct)
|
||||
L.setDir(direction)
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
var/customsayverb = findtext(input, "*")
|
||||
if(customsayverb && message_mode != MODE_WHISPER_CRIT)
|
||||
message_mode = MODE_CUSTOM_SAY
|
||||
return lowertext(copytext(input, 1, customsayverb))
|
||||
return lowertext(copytext_char(input, 1, customsayverb))
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
|
||||
return
|
||||
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
message = trim(copytext_char(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
|
||||
usr.emote("me",1,message,TRUE)
|
||||
|
||||
@@ -83,9 +83,9 @@
|
||||
deadchat_broadcast(rendered, follow_target = src, speaker_key = key)
|
||||
|
||||
/mob/proc/check_emote(message)
|
||||
if(copytext(message, 1, 2) == "*")
|
||||
emote(copytext(message, 2), intentional = TRUE)
|
||||
return 1
|
||||
if(message[1] == "*")
|
||||
emote(copytext(message, length(message[1]) + 1), intentional = TRUE)
|
||||
return TRUE
|
||||
|
||||
/mob/proc/hivecheck()
|
||||
return 0
|
||||
@@ -94,11 +94,11 @@
|
||||
return LINGHIVE_NONE
|
||||
|
||||
/mob/proc/get_message_mode(message)
|
||||
var/key = copytext(message, 1, 2)
|
||||
var/key = message[1]
|
||||
if(key == "#")
|
||||
return MODE_WHISPER
|
||||
else if(key == ";")
|
||||
return MODE_HEADSET
|
||||
else if(length(message) > 2 && (key in GLOB.department_radio_prefixes))
|
||||
var/key_symbol = lowertext(copytext(message, 2, 3))
|
||||
else if((length(message) > (length(key) + 1)) && (key in GLOB.department_radio_prefixes))
|
||||
var/key_symbol = lowertext(message[length(key) + 1])
|
||||
return GLOB.department_radio_keys[key_symbol]
|
||||
|
||||
+20
-46
@@ -9,25 +9,19 @@
|
||||
set src in usr
|
||||
if(usr != src)
|
||||
to_chat(usr, "No.")
|
||||
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(flavor_text), MAX_MESSAGE_LEN*2, TRUE)
|
||||
var/msg = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", html_decode(flavor_text), MAX_MESSAGE_LEN, TRUE)
|
||||
|
||||
if(!isnull(msg))
|
||||
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
|
||||
msg = html_encode(msg)
|
||||
|
||||
flavor_text = msg
|
||||
if(msg)
|
||||
flavor_text = html_encode(msg)
|
||||
|
||||
/mob/proc/update_flavor_text_2()
|
||||
set src in usr
|
||||
if(usr != src)
|
||||
to_chat(usr, "No.")
|
||||
var/msg = stripped_multiline_input(usr, "Set the temporary flavor text in your 'examine' verb. This should be used only for things pertaining to the current round!", "Short-Term Flavor Text", html_decode(flavor_text_2), MAX_MESSAGE_LEN*2, TRUE)
|
||||
var/msg = stripped_multiline_input(usr, "Set the temporary flavor text in your 'examine' verb. This should be used only for things pertaining to the current round!", "Short-Term Flavor Text", html_decode(flavor_text_2), MAX_MESSAGE_LEN, TRUE)
|
||||
|
||||
if(!isnull(msg))
|
||||
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
|
||||
msg = html_encode(msg)
|
||||
|
||||
flavor_text_2 = msg
|
||||
if(msg)
|
||||
flavor_text_2 = html_encode(msg)
|
||||
|
||||
|
||||
/mob/proc/warn_flavor_changed()
|
||||
@@ -39,19 +33,19 @@
|
||||
if(flavor_text && flavor_text != "")
|
||||
// We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown.
|
||||
var/msg = html_decode(replacetext(flavor_text, "\n", " "))
|
||||
if(length(msg) <= 40)
|
||||
if(length_char(msg) <= 40)
|
||||
return "<span class='notice'>[html_encode(msg)]</span>"
|
||||
else
|
||||
return "<span class='notice'>[html_encode(copytext(msg, 1, 37))]... <a href='?src=[REF(src)];flavor_more=1'>More...</span></a>"
|
||||
return "<span class='notice'>[html_encode(copytext_char(msg, 1, 37))]... <a href='?src=[REF(src)];flavor_more=1'>More...</span></a>"
|
||||
|
||||
/mob/proc/print_flavor_text_2()
|
||||
if(flavor_text && flavor_text != "")
|
||||
// We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown.
|
||||
var/msg = html_decode(replacetext(flavor_text_2, "\n", " "))
|
||||
if(length(msg) <= 40)
|
||||
if(length_char(msg) <= 40)
|
||||
return "<span class='notice'>[html_encode(msg)]</span>"
|
||||
else
|
||||
return "<span class='notice'>[html_encode(copytext(msg, 1, 37))]... <a href='?src=[REF(src)];flavor2_more=1'>More...</span></a>"
|
||||
return "<span class='notice'>[html_encode(copytext_char(msg, 1, 37))]... <a href='?src=[REF(src)];flavor2_more=1'>More...</span></a>"
|
||||
|
||||
|
||||
/mob/proc/get_top_level_mob()
|
||||
@@ -80,17 +74,10 @@ proc/get_top_level_mob(var/mob/S)
|
||||
|
||||
|
||||
/datum/emote/living/subtle/proc/check_invalid(mob/user, input)
|
||||
. = TRUE
|
||||
if(copytext(input,1,5) == "says")
|
||||
if(stop_bad_mime.Find(input, 1, 1))
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,9) == "exclaims")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,6) == "yells")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,5) == "asks")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else
|
||||
. = FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/emote/living/subtle/run_emote(mob/user, params, type_override = null)
|
||||
if(jobban_isbanned(user, "emote"))
|
||||
@@ -100,7 +87,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
to_chat(user, "You cannot send IC messages (muted).")
|
||||
return FALSE
|
||||
else if(!params)
|
||||
var/subtle_emote = copytext(sanitize(input("Choose an emote to display.") as message|null), 1, MAX_MESSAGE_LEN)
|
||||
var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN)
|
||||
if(subtle_emote && !check_invalid(user, subtle_emote))
|
||||
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
|
||||
switch(type)
|
||||
@@ -122,7 +109,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
if(!can_run_emote(user))
|
||||
return FALSE
|
||||
|
||||
user.log_message(message, INDIVIDUAL_EMOTE_LOG)
|
||||
user.log_message(message, LOG_EMOTE)
|
||||
message = "<b>[user]</b> " + "<i>[message]</i>"
|
||||
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
@@ -136,10 +123,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
user.audible_message(message=message,hearing_distance=1)
|
||||
else
|
||||
user.visible_message(message=message,self_message=message,vision_distance=1)
|
||||
log_emote("[key_name(user)] : [message]")
|
||||
|
||||
message = null
|
||||
emote_type = EMOTE_VISIBLE
|
||||
|
||||
///////////////// SUBTLE 2: NO GHOST BOOGALOO
|
||||
|
||||
@@ -151,17 +135,10 @@ proc/get_top_level_mob(var/mob/S)
|
||||
|
||||
|
||||
/datum/emote/living/subtler/proc/check_invalid(mob/user, input)
|
||||
. = TRUE
|
||||
if(copytext(input,1,5) == "says")
|
||||
if(stop_bad_mime.Find(input, 1, 1))
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,9) == "exclaims")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,6) == "yells")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else if(copytext(input,1,5) == "asks")
|
||||
to_chat(user, "<span class='danger'>Invalid emote.</span>")
|
||||
else
|
||||
. = FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/emote/living/subtler/run_emote(mob/user, params, type_override = null)
|
||||
if(jobban_isbanned(user, "emote"))
|
||||
@@ -171,7 +148,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
to_chat(user, "You cannot send IC messages (muted).")
|
||||
return FALSE
|
||||
else if(!params)
|
||||
var/subtle_emote = copytext(sanitize(input("Choose an emote to display.") as message|null), 1, MAX_MESSAGE_LEN)
|
||||
var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN)
|
||||
if(subtle_emote && !check_invalid(user, subtle_emote))
|
||||
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
|
||||
switch(type)
|
||||
@@ -193,16 +170,13 @@ proc/get_top_level_mob(var/mob/S)
|
||||
if(!can_run_emote(user))
|
||||
return FALSE
|
||||
|
||||
user.log_message(message, INDIVIDUAL_EMOTE_LOG)
|
||||
user.log_message(message, LOG_SUBTLER)
|
||||
message = "<b>[user]</b> " + "<i>[message]</i>"
|
||||
|
||||
if(emote_type == EMOTE_AUDIBLE)
|
||||
user.audible_message(message=message,hearing_distance=1, ignored_mobs = GLOB.dead_mob_list)
|
||||
else
|
||||
user.visible_message(message=message,self_message=message,vision_distance=1, ignored_mobs = GLOB.dead_mob_list)
|
||||
log_emote("[key_name(user)] : (SUBTLER) [message]")
|
||||
|
||||
message = null
|
||||
|
||||
///////////////// VERB CODE
|
||||
/mob/living/verb/subtle()
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
|
||||
// hash the original name?
|
||||
if(tr_flags & TR_HASHNAME)
|
||||
O.name = "monkey ([copytext(md5(real_name), 2, 6)])"
|
||||
O.real_name = "monkey ([copytext(md5(real_name), 2, 6)])"
|
||||
O.name = "monkey ([copytext_char(md5(real_name), 2, 6)])"
|
||||
O.real_name = "monkey ([copytext_char(md5(real_name), 2, 6)])"
|
||||
|
||||
//handle DNA and other attributes
|
||||
dna.transfer_identity(O)
|
||||
@@ -90,7 +90,7 @@
|
||||
if(tr_flags & TR_KEEPORGANS)
|
||||
for(var/X in O.internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
I.Remove(O, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
if(mind)
|
||||
mind.transfer_to(O)
|
||||
@@ -103,7 +103,7 @@
|
||||
for(var/X in internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
int_organs += I
|
||||
I.Remove(src, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
for(var/X in int_organs)
|
||||
var/obj/item/organ/I = X
|
||||
@@ -202,7 +202,7 @@
|
||||
dna.transfer_identity(O)
|
||||
O.updateappearance(mutcolor_update=1)
|
||||
|
||||
if(cmptext("monkey",copytext(O.dna.real_name,1,7)))
|
||||
if(findtext(O.dna.real_name, "monkey", 1, 7)) //7 == length("monkey") + 1
|
||||
O.real_name = random_unique_name(O.gender)
|
||||
O.dna.generate_unique_enzymes(O)
|
||||
else
|
||||
@@ -250,7 +250,7 @@
|
||||
if(tr_flags & TR_KEEPORGANS)
|
||||
for(var/X in O.internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
I.Remove(O, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
if(mind)
|
||||
mind.transfer_to(O)
|
||||
@@ -262,7 +262,7 @@
|
||||
for(var/X in internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
int_organs += I
|
||||
I.Remove(src, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
for(var/X in int_organs)
|
||||
var/obj/item/organ/I = X
|
||||
|
||||
Reference in New Issue
Block a user