module things, jfc

This commit is contained in:
Poojawa
2018-09-11 07:51:01 -05:00
parent 8b9ef1e400
commit 284e9d0325
695 changed files with 11343 additions and 5661 deletions
+1 -1
View File
@@ -28,5 +28,5 @@
/mob/camera/forceMove(atom/destination)
loc = destination
/mob/camera/emote(act, m_type=1, message = null)
/mob/camera/emote(act, m_type=1, message = null, intentional = FALSE)
return
+34 -4
View File
@@ -4,6 +4,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
/mob/dead
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
throwforce = 0
/mob/dead/Initialize()
if(flags_1 & INITIALIZED_1)
@@ -14,12 +15,12 @@ INITIALIZE_IMMEDIATE(/mob/dead)
prepare_huds()
if(length(CONFIG_GET(keyed_string_list/cross_server)))
if(length(CONFIG_GET(keyed_list/cross_server)))
verbs += /mob/dead/proc/server_hop
set_focus(src)
return INITIALIZE_HINT_NORMAL
/mob/dead/dust() //ghosts can't be vaporised.
/mob/dead/dust(just_ash, drop_items, force) //ghosts can't be vaporised.
return
/mob/dead/gib() //ghosts can't be gibbed.
@@ -29,6 +30,10 @@ INITIALIZE_IMMEDIATE(/mob/dead)
return
/mob/dead/forceMove(atom/destination)
var/turf/old_turf = get_turf(src)
var/turf/new_turf = get_turf(destination)
if (old_turf?.z != new_turf?.z)
onTransitZ(old_turf?.z, new_turf?.z)
loc = destination
/mob/dead/Stat()
@@ -36,7 +41,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
if(!statpanel("Status"))
return
//stat(null, "Game Mode: [SSticker.hide_mode ? "Secret" : "[GLOB.master_mode]"]") CIT CHANGE - obfuscates gamemode from player view
//stat(null, "Game Mode: [SSticker.hide_mode ? "Secret" : "[GLOB.master_mode]"]")
if(SSticker.HasRoundStarted())
return
@@ -59,7 +64,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
set desc= "Jump to the other server"
if(notransform)
return
var/list/csa = CONFIG_GET(keyed_string_list/cross_server)
var/list/csa = CONFIG_GET(keyed_list/cross_server)
var/pick
switch(csa.len)
if(0)
@@ -92,3 +97,28 @@ INITIALIZE_IMMEDIATE(/mob/dead)
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
C << link("[addr]?server_hop=[key]")
/mob/dead/proc/update_z(new_z) // 1+ to register, null to unregister
if (registered_z != new_z)
if (registered_z)
SSmobs.dead_players_by_zlevel[registered_z] -= src
if (client)
if (new_z)
SSmobs.dead_players_by_zlevel[new_z] += src
registered_z = new_z
else
registered_z = null
/mob/dead/Login()
. = ..()
var/turf/T = get_turf(src)
if (isturf(T))
update_z(T.z)
/mob/dead/Logout()
update_z(null)
return ..()
/mob/dead/onTransitZ(old_z,new_z)
..()
update_z(new_z)
@@ -53,7 +53,7 @@
var/isadmin = 0
if(src.client && src.client.holder)
isadmin = 1
var/datum/DBQuery/query_get_new_polls = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[ckey]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[ckey]\")")
var/datum/DBQuery/query_get_new_polls = SSdbcore.NewQuery("SELECT id FROM [format_table_name("poll_question")] WHERE [(isadmin ? "" : "adminonly = false AND")] Now() BETWEEN starttime AND endtime AND id NOT IN (SELECT pollid FROM [format_table_name("poll_vote")] WHERE ckey = \"[sanitizeSQL(ckey)]\") AND id NOT IN (SELECT pollid FROM [format_table_name("poll_textreply")] WHERE ckey = \"[sanitizeSQL(ckey)]\")")
var/rs = REF(src)
if(query_get_new_polls.Execute())
var/newpoll = 0
+36 -24
View File
@@ -103,23 +103,20 @@
var/output = "<div align='center'><B>Player poll</B><hr>"
output += "<b>Question: [pollquestion]</b><br>"
output += "<font size='2'>Feedback gathering runs from <b>[pollstarttime]</b> until <b>[pollendtime]</b></font><p>"
if(!vote_text)
output += "<form name='cardcomp' action='?src=[REF(src)]' method='get'>"
output += "<input type='hidden' name='src' value='[REF(src)]'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value=[POLLTYPE_TEXT]>"
output += "<font size='2'>Please provide feedback below. You can use any letters of the English alphabet, numbers and the symbols: . , ! ? : ; -</font><br>"
output += "<textarea name='replytext' cols='50' rows='14'></textarea>"
output += "<p><input type='submit' value='Submit'></form>"
output += "<form name='cardcomp' action='?src=[REF(src)]' method='get'>"
output += "<input type='hidden' name='src' value='[REF(src)]'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value=[POLLTYPE_TEXT]>"
output += "<input type='hidden' name='replytext' value='ABSTAIN'>"
output += "<input type='submit' value='Abstain'></form>"
else
vote_text = replacetext(vote_text, "\n", "<br>")
output += "[vote_text]"
output += "<form name='cardcomp' action='?src=[REF(src)]' method='get'>"
output += "<input type='hidden' name='src' value='[REF(src)]'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value=[POLLTYPE_TEXT]>"
output += "<font size='2'>Please provide feedback below. You can use any letters of the English alphabet, numbers and the symbols: . , ! ? : ; -</font><br>"
output += "<textarea name='replytext' cols='50' rows='14'>[vote_text]</textarea>"
output += "<p><input type='submit' value='Submit'></form>"
output += "<form name='cardcomp' action='?src=[REF(src)]' method='get'>"
output += "<input type='hidden' name='src' value='[REF(src)]'>"
output += "<input type='hidden' name='votepollid' value='[pollid]'>"
output += "<input type='hidden' name='votetype' value=[POLLTYPE_TEXT]>"
output += "<input type='hidden' name='replytext' value='ABSTAIN'>"
output += "<input type='submit' value='Abstain'></form>"
src << browse(null ,"window=playerpolllist")
src << browse(output,"window=playerpoll;size=500x500")
if(POLLTYPE_RATING)
@@ -348,7 +345,8 @@
src << browse(output,"window=playerpoll;size=500x500")
return
/mob/dead/new_player/proc/poll_check_voted(pollid, text = FALSE)
//Returns null on failure, TRUE if already voted, FALSE if not voted yet.
/mob/dead/new_player/proc/poll_check_voted(pollid, text = FALSE, silent = FALSE)
var/table = "poll_vote"
if (text)
table = "poll_textreply"
@@ -361,13 +359,17 @@
return
if(query_hasvoted.NextRow())
qdel(query_hasvoted)
to_chat(usr, "<span class='danger'>You've already replied to this poll.</span>")
return
if(!silent)
to_chat(usr, "<span class='danger'>You've already replied to this poll.</span>")
return TRUE
qdel(query_hasvoted)
return FALSE
//Returns adminrank for use in polls.
/mob/dead/new_player/proc/poll_rank()
. = "Player"
if(client.holder)
. = client.holder.rank.name
return .
/mob/dead/new_player/proc/vote_rig_check()
@@ -487,7 +489,10 @@
//validate the poll
if (!vote_valid_check(pollid, client.holder, POLLTYPE_OPTION))
return 0
var/adminrank = sanitizeSQL(poll_check_voted(pollid))
var/voted = poll_check_voted(pollid)
if(isnull(voted) || voted) //Failed or already voted.
return
var/adminrank = sanitizeSQL(poll_rank())
if(!adminrank)
return
var/datum/DBQuery/query_option_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_vote")] (datetime, pollid, optionid, ckey, ip, adminrank) VALUES (Now(), [pollid], [optionid], '[ckey]', INET_ATON('[client.address]'), '[adminrank]')")
@@ -513,14 +518,21 @@
if(!replytext)
to_chat(usr, "The text you entered was blank. Please correct the text and submit again.")
return
var/adminrank = sanitizeSQL(poll_check_voted(pollid, TRUE))
var/voted = poll_check_voted(pollid, text = TRUE, silent = TRUE)
if(isnull(voted))
return
var/adminrank = sanitizeSQL(poll_rank())
if(!adminrank)
return
replytext = sanitizeSQL(replytext)
if(!(length(replytext) > 0) || !(length(replytext) <= 8000))
to_chat(usr, "The text you entered was invalid or too long. Please correct the text and submit again.")
return
var/datum/DBQuery/query_text_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (Now(), [pollid], '[ckey]', INET_ATON('[client.address]'), '[replytext]', '[adminrank]')")
var/datum/DBQuery/query_text_vote
if(!voted)
query_text_vote = SSdbcore.NewQuery("INSERT INTO [format_table_name("poll_textreply")] (datetime ,pollid ,ckey ,ip ,replytext ,adminrank) VALUES (Now(), [pollid], '[ckey]', INET_ATON('[client.address]'), '[replytext]', '[adminrank]')")
else
query_text_vote = SSdbcore.NewQuery("UPDATE [format_table_name("poll_textreply")] SET datetime = Now(), ip = INET_ATON('[client.address]'), replytext = '[replytext]' WHERE pollid = '[pollid]' AND ckey = '[ckey]'")
if(!query_text_vote.warn_execute())
qdel(query_text_vote)
return
File diff suppressed because it is too large Load Diff
+4
View File
@@ -12,5 +12,9 @@
preferred_form = client.prefs.ghost_form
ghost_orbit = client.prefs.ghost_orbit
var/turf/T = get_turf(src)
if (isturf(T))
update_z(T.z)
update_icon(preferred_form)
updateghostimages()
+1
View File
@@ -1,4 +1,5 @@
/mob/dead/observer/Logout()
update_z(null)
if (client)
client.images -= (GLOB.ghost_images_default+GLOB.ghost_images_simple)
@@ -16,6 +16,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
see_invisible = SEE_INVISIBLE_OBSERVER
see_in_dark = 100
invisibility = INVISIBILITY_OBSERVER
hud_type = /datum/hud/ghost
var/can_reenter_corpse
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
@@ -135,6 +136,10 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
grant_all_languages()
/mob/dead/observer/get_photo_description(obj/item/camera/camera)
if(!invisibility || camera.see_ghosts)
return "You can also see a g-g-g-g-ghooooost!"
/mob/dead/observer/narsie_act()
var/old_color = color
color = "#960000"
@@ -267,6 +272,7 @@ Works together with spawning an observer, noted above.
/*
This is the proc mobs get to turn into a ghost. Forked from ghostize due to compatibility issues.
*/
/mob/living/verb/ghost()
set category = "OOC"
set name = "Ghost"
@@ -281,6 +287,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
C.despawn_occupant()
return
// END EDIT
if(stat != DEAD)
succumb()
if(stat == DEAD)
@@ -386,6 +393,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(!L || !L.len)
to_chat(usr, "No area available.")
return
usr.forceMove(pick(L))
update_parallax_contents()
+3 -2
View File
@@ -1,4 +1,4 @@
/mob/dead/observer/say(message)
/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))
if (!message)
return
@@ -15,7 +15,7 @@
client.dsay(message)
return
log_talk(src,"Ghost/[src.key] : [message]", LOGSAY)
src.log_talk(message, LOG_SAY, tag="ghost")
if(check_emote(message))
return
@@ -37,3 +37,4 @@
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
to_chat(src, "[link] [message]")
+2 -1
View File
@@ -6,8 +6,9 @@
//This is the proc for turning a mob into ash. Mostly a copy of gib code (above).
//Originally created for wizard disintegrate. I've removed the virus code since it's irrelevant here.
//Dusting robots does not eject the MMI, so it's a bit more powerful than gib() /N
/mob/proc/dust()
/mob/proc/dust(just_ash, drop_items, force)
return
/mob/proc/death(gibbed)
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
return
+2 -2
View File
@@ -1,5 +1,5 @@
//The code execution of the emote datum is located at code/datums/emotes.dm
/mob/proc/emote(act, m_type = null, message = null)
/mob/proc/emote(act, m_type = null, message = null, intentional = FALSE)
act = lowertext(act)
var/param = message
var/custom_param = findchar(act, " ")
@@ -12,7 +12,7 @@
if(!E)
to_chat(src, "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>")
return
E.run_emote(src, param, m_type)
E.run_emote(src, param, m_type, intentional)
/datum/emote/flip
key = "flip"
+5 -3
View File
@@ -170,8 +170,10 @@
return FALSE
return !held_items[hand_index]
/mob/proc/put_in_hand(obj/item/I, hand_index, forced = FALSE)
/mob/proc/put_in_hand(obj/item/I, hand_index, forced = FALSE, ignore_anim = TRUE)
if(forced || can_put_in_hand(I, hand_index))
if(isturf(I.loc) && !ignore_anim)
I.do_pickup_animation(src)
if(hand_index == null)
return FALSE
if(get_item_for_held_index(hand_index) != null)
@@ -208,8 +210,8 @@
//Puts the item into our active hand if possible. returns TRUE on success.
/mob/proc/put_in_active_hand(obj/item/I, forced = FALSE)
return put_in_hand(I, active_hand_index, forced)
/mob/proc/put_in_active_hand(obj/item/I, forced = FALSE, ignore_animation = TRUE)
return put_in_hand(I, active_hand_index, forced, ignore_animation)
//Puts the item into our inactive hand if possible, returns TRUE on success
+3 -1
View File
@@ -254,7 +254,7 @@
// Only a certain number of drips (or one large splatter) can be on a given turf.
var/obj/effect/decal/cleanable/blood/drip/drop = locate() in T
if(drop)
if(drop.drips < 3)
if(drop.drips < 5)
drop.drips++
drop.add_overlay(pick(drop.random_icon_states))
drop.transfer_mob_blood_dna(src)
@@ -271,6 +271,8 @@
var/obj/effect/decal/cleanable/blood/B = locate() in T
if(!B)
B = new /obj/effect/decal/cleanable/blood/splatter(T, get_static_viruses())
if (B.bloodiness < MAX_SHOE_BLOODINESS) //add more blood, up to a limit
B.bloodiness += BLOOD_AMOUNT_PER_DECAL
B.transfer_mob_blood_dna(src) //give blood info to the blood decal.
if(temp_blood_DNA)
B.add_blood_DNA(temp_blood_DNA)
+5 -5
View File
@@ -21,7 +21,7 @@
name = "brain"
if(C.mind && C.mind.has_antag_datum(/datum/antagonist/changeling) && !no_id_transfer) //congrats, you're trapped in a body you don't control
if(brainmob && !(C.stat == DEAD || (C.has_trait(TRAIT_FAKEDEATH))))
if(brainmob && !(C.stat == DEAD || (C.has_trait(TRAIT_DEATHCOMA))))
to_chat(brainmob, "<span class = danger>You can't feel your body! You're still just a brain!</span>")
forceMove(C)
C.update_hair()
@@ -144,7 +144,7 @@
/obj/item/organ/brain/proc/get_brain_damage()
var/brain_damage_threshold = max_integrity * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER
var/offset_integrity = obj_integrity - (max_integrity - brain_damage_threshold)
. = round((1 - (offset_integrity / brain_damage_threshold)) * BRAIN_DAMAGE_DEATH,0.1)
. = round((1 - (offset_integrity / brain_damage_threshold)) * BRAIN_DAMAGE_DEATH, DAMAGE_PRECISION)
/obj/item/organ/brain/proc/adjust_brain_damage(amount, maximum)
var/adjusted_amount
@@ -157,11 +157,11 @@
else
adjusted_amount = amount
adjusted_amount = round(adjusted_amount * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER,0.1)
adjusted_amount = round(adjusted_amount * BRAIN_DAMAGE_INTEGRITY_MULTIPLIER, DAMAGE_PRECISION)
if(adjusted_amount)
if(adjusted_amount >= 0.1)
if(adjusted_amount >= DAMAGE_PRECISION)
take_damage(adjusted_amount)
else if(adjusted_amount <= -0.1)
else if(adjusted_amount <= -DAMAGE_PRECISION)
obj_integrity = min(max_integrity, obj_integrity-adjusted_amount)
. = adjusted_amount
+1 -1
View File
@@ -1,4 +1,4 @@
/mob/living/brain/say(message, language)
/mob/living/brain/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
if(!(container && istype(container, /obj/item/mmi)))
return //No MMI, can't speak, bucko./N
else
@@ -38,7 +38,7 @@ In all, this is a lot like the monkey code. /N
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
"<span class='userdanger'>[M.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
adjustBruteLoss(1)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
updatehealth()
else
to_chat(M, "<span class='warning'>[name] is too injured for that.</span>")
@@ -97,7 +97,7 @@ In all, this is a lot like the monkey code. /N
if(M.is_adult)
damage = rand(10, 40)
adjustBruteLoss(damage)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
updatehealth()
/mob/living/carbon/alien/ex_act(severity, target, origin)
@@ -97,7 +97,7 @@ Doesn't work on other aliens/AI.*/
return 0
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
log_talk(user,"AlienWhisper: [key_name(user)]->[key_name(M)] : [msg]",LOGSAY)
log_directed_talk(user, M, msg, LOG_SAY, tag="alien whisper")
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...</span>[msg]")
to_chat(user, "<span class='noticealien'>You said: \"[msg]\" to [M]</span>")
for(var/ded in GLOB.dead_mob_list)
@@ -233,19 +233,19 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/neurotoxin/on_lose(mob/living/carbon/user)
remove_ranged_ability()
/obj/effect/proc_holder/alien/neurotoxin/add_ranged_ability(mob/living/user, msg)
/obj/effect/proc_holder/alien/neurotoxin/add_ranged_ability(mob/living/user,msg,forced)
..()
if(isalienadult(user))
var/mob/living/carbon/alien/humanoid/A = user
A.drooling = 1
A.update_icons()
/obj/effect/proc_holder/alien/neurotoxin/remove_ranged_ability(mob/living/user, msg)
..()
if(isalienadult(user))
var/mob/living/carbon/alien/humanoid/A = user
/obj/effect/proc_holder/alien/neurotoxin/remove_ranged_ability(msg)
if(isalienadult(ranged_ability_user))
var/mob/living/carbon/alien/humanoid/A = ranged_ability_user
A.drooling = 0
A.update_icons()
..()
/obj/effect/proc_holder/alien/resin
name = "Secrete Resin"
@@ -5,21 +5,16 @@
health = 125
icon_state = "aliend"
/mob/living/carbon/alien/humanoid/drone/Initialize()
AddAbility(new/obj/effect/proc_holder/alien/evolve(null))
. = ..()
/mob/living/carbon/alien/humanoid/drone/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/large
internal_organs += new /obj/item/organ/alien/resinspinner
internal_organs += new /obj/item/organ/alien/acid
..()
/mob/living/carbon/alien/humanoid/drone/movement_delay()
. = ..()
/obj/effect/proc_holder/alien/evolve
name = "Evolve to Praetorian"
desc = "Praetorian"
@@ -10,11 +10,6 @@
internal_organs += new /obj/item/organ/alien/plasmavessel/small
..()
/mob/living/carbon/alien/humanoid/hunter/movement_delay()
. = -1 //hunters are sanic
. += ..() //but they still need to slow down on stun
//Hunter verbs
/mob/living/carbon/alien/humanoid/hunter/proc/toggle_leap(message = 1)
@@ -26,7 +21,6 @@
else
return
/mob/living/carbon/alien/humanoid/hunter/ClickOn(atom/A, params)
face_atom(A)
if(leap_on_click)
@@ -34,7 +28,6 @@
else
..()
#define MAX_ALIEN_LEAP_DIST 7
/mob/living/carbon/alien/humanoid/hunter/proc/leap_at(atom/A)
@@ -54,7 +47,7 @@
leaping = 1
weather_immunities += "lava"
update_icons()
throw_at(A, MAX_ALIEN_LEAP_DIST, 1, src, FALSE, TRUE, callback = CALLBACK(src, .leap_end))
throw_at(A, MAX_ALIEN_LEAP_DIST, 1, src, FALSE, TRUE, callback = CALLBACK(src, .proc/leap_end))
/mob/living/carbon/alien/humanoid/hunter/proc/leap_end()
leaping = 0
@@ -5,12 +5,8 @@
health = 250
icon_state = "alienp"
/mob/living/carbon/alien/humanoid/royal/praetorian/Initialize()
real_name = name
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new /obj/effect/proc_holder/alien/royal/praetorian/evolve())
. = ..()
@@ -22,11 +18,6 @@
internal_organs += new /obj/item/organ/alien/neurotoxin
..()
/mob/living/carbon/alien/humanoid/royal/praetorian/movement_delay()
. = ..()
. += 1
/obj/effect/proc_holder/alien/royal/praetorian/evolve
name = "Evolve"
desc = "Produce an internal egg sac capable of spawning children. Only one queen can exist at a time."
@@ -5,7 +5,6 @@
health = 150
icon_state = "aliens"
/mob/living/carbon/alien/humanoid/sentinel/Initialize()
AddAbility(new /obj/effect/proc_holder/alien/sneak)
. = ..()
@@ -15,7 +14,3 @@
internal_organs += new /obj/item/organ/alien/acid
internal_organs += new /obj/item/organ/alien/neurotoxin
..()
/mob/living/carbon/alien/humanoid/sentinel/movement_delay()
. = ..()
@@ -5,6 +5,7 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
limb_destroyer = 1
hud_type = /datum/hud/alien
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
@@ -25,16 +26,8 @@
AddAbility(new/obj/effect/proc_holder/alien/regurgitate(null))
. = ..()
/mob/living/carbon/alien/humanoid/movement_delay()
. = ..()
var/static/config_alien_delay
if(isnull(config_alien_delay))
config_alien_delay = CONFIG_GET(number/alien_delay)
. += move_delay_add + config_alien_delay + sneaking //move_delay_add is used to slow aliens with stun
/mob/living/carbon/alien/humanoid/restrained(ignore_grab)
. = handcuffed
return handcuffed
/mob/living/carbon/alien/humanoid/show_inv(mob/user)
user.set_machine(src)
@@ -35,7 +35,7 @@
"<span class='userdanger'>[M] has knocked [src] down!</span>")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='userdanger'>[M] has attempted to punch [src]!</span>", \
@@ -46,7 +46,7 @@
if (prob(5))
Unconscious(40)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
log_combat(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else
@@ -40,7 +40,7 @@
AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/repulse/xeno(src))
AddAbility(new/obj/effect/proc_holder/alien/royal/queen/promote())
smallsprite.Grant(src)
..()
return ..()
/mob/living/carbon/alien/humanoid/royal/queen/create_internal_organs()
internal_organs += new /obj/item/organ/alien/plasmavessel/large/queen
@@ -50,10 +50,6 @@
internal_organs += new /obj/item/organ/alien/eggsac
..()
/mob/living/carbon/alien/humanoid/royal/queen/movement_delay()
. = ..()
. += 3
//Queen verbs
/obj/effect/proc_holder/alien/lay_egg
name = "Lay Egg"
@@ -5,6 +5,7 @@
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
density = FALSE
hud_type = /datum/hud/larva
maxHealth = 25
health = 25
@@ -5,7 +5,7 @@
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ((stat != DEAD) && (damage > 4.9))
@@ -18,7 +18,7 @@
if(health<= -maxHealth || !getorgan(/obj/item/organ/brain))
death()
return
if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (has_trait(TRAIT_FAKEDEATH)) || health <= HEALTH_THRESHOLD_CRIT)
if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (has_trait(TRAIT_DEATHCOMA)) || health <= crit_threshold)
if(stat == CONSCIOUS)
stat = UNCONSCIOUS
blind_eyes(1)
@@ -30,4 +30,4 @@
adjust_blindness(-1)
update_canmove()
update_damage_hud()
update_health_hud()
update_health_hud()
@@ -15,7 +15,7 @@
"<span class='noticealien'>You are now hiding.</span>")
else
user.layer = MOB_LAYER
user.visible_message("[user.] slowly peeks up from the ground...", \
user.visible_message("[user] slowly peeks up from the ground...", \
"<span class='noticealien'>You stop hiding.</span>")
return 1
@@ -9,6 +9,10 @@
alien_powers -= A
alien_powers += new A(src)
/obj/item/organ/alien/Destroy()
QDEL_LIST(alien_powers)
return ..()
/obj/item/organ/alien/Insert(mob/living/carbon/M, special = 0)
..()
for(var/obj/effect/proc_holder/alien/P in alien_powers)
+1 -1
View File
@@ -1,5 +1,5 @@
/mob/living/proc/alien_talk(message, shown_name = real_name)
log_talk(src,"[key_name(src)] : [message]",LOGSAY)
src.log_talk(message, LOG_SAY)
message = trim(message)
if(!message)
return
+33 -14
View File
@@ -19,6 +19,9 @@
QDEL_NULL(dna)
GLOB.carbon_list -= src
/mob/living/carbon/initialize_footstep()
AddComponent(/datum/component/footstep, 1, 2)
/mob/living/carbon/relaymove(mob/user, direction)
if(user in src.stomach_contents)
if(prob(40))
@@ -84,9 +87,9 @@
/mob/living/carbon/attackby(obj/item/I, mob/user, params)
if(lying && surgeries.len)
if(user != src && user.a_intent == INTENT_HELP)
if(user != src && (user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM))
for(var/datum/surgery/S in surgeries)
if(S.next_step(user))
if(S.next_step(user,user.a_intent))
return 1
return ..()
@@ -169,7 +172,7 @@
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
var/turf/end_T = get_turf(target)
if(start_T && end_T)
add_logs(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
else if(!(I.item_flags & (NODROP | ABSTRACT)))
thrown_thing = I
@@ -183,7 +186,7 @@
if(thrown_thing)
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
add_logs(src, thrown_thing, "thrown")
src.log_message("has thrown [thrown_thing]", LOG_ATTACK)
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
@@ -409,6 +412,7 @@
//dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100
var/modifier = 0
if(has_trait(TRAIT_CLUMSY))
modifier -= 40 //Clumsy people are more likely to hit themselves -Honk!
@@ -419,7 +423,7 @@
if(modifier < 100)
dropItemToGround(I)
//END OF CIT CHANGES
switch(rand(1,100)+modifier) //91-100=Nothing special happens
if(-INFINITY to 0) //attack yourself
I.attack(src,src)
@@ -523,15 +527,29 @@
var/total_stamina = 0
for(var/X in bodyparts) //hardcoded to streamline things a bit
var/obj/item/bodypart/BP = X
total_brute += BP.brute_dam
total_burn += BP.burn_dam
total_stamina += BP.stamina_dam
health = maxHealth - getOxyLoss() - getToxLoss() - getCloneLoss() - total_burn - total_brute
staminaloss = total_stamina
total_brute += (BP.brute_dam * BP.body_damage_coeff)
total_burn += (BP.burn_dam * BP.body_damage_coeff)
total_stamina += (BP.stamina_dam * BP.stam_damage_coeff)
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 )
become_husk("burn")
med_hud_set_health()
if(stat == SOFT_CRIT)
add_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE, multiplicative_slowdown = SOFTCRIT_ADD_SLOWDOWN)
else
remove_movespeed_modifier(MOVESPEED_ID_CARBON_SOFTCRIT, TRUE)
/mob/living/carbon/update_stamina()
var/stam = getStaminaLoss()
if(stam > DAMAGE_PRECISION)
var/total_health = (health - stam)
if(total_health <= crit_threshold && !stat)
if(!IsKnockdown())
to_chat(src, "<span class='notice'>You're too exhausted to keep going...</span>")
Knockdown(100)
update_health_hud()
/mob/living/carbon/update_sight()
if(!client)
@@ -616,7 +634,7 @@
if(!client)
return
if(health <= HEALTH_THRESHOLD_CRIT)
if(health <= crit_threshold)
var/severity = 0
switch(health)
if(-20 to -10)
@@ -741,11 +759,11 @@
if(health <= HEALTH_THRESHOLD_DEAD && !has_trait(TRAIT_NODEATH))
death()
return
if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (has_trait(TRAIT_FAKEDEATH)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !has_trait(TRAIT_NOHARDCRIT)))
if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (has_trait(TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !has_trait(TRAIT_NOHARDCRIT)))
stat = UNCONSCIOUS
blind_eyes(1)
else
if(health <= HEALTH_THRESHOLD_CRIT && !has_trait(TRAIT_NOSOFTCRIT))
if(health <= crit_threshold && !has_trait(TRAIT_NOSOFTCRIT))
stat = SOFT_CRIT
else
stat = CONSCIOUS
@@ -839,7 +857,7 @@
"<span class='userdanger'>[src] devours you!</span>")
C.forceMove(src)
stomach_contents.Add(C)
add_logs(src, C, "devoured")
log_combat(src, C, "devoured")
/mob/living/carbon/proc/create_bodyparts()
var/l_arm_index_next = -1
@@ -881,6 +899,7 @@
.["Modify bodypart"] = "?_src_=vars;[HrefToken()];editbodypart=[REF(src)]"
.["Modify organs"] = "?_src_=vars;[HrefToken()];editorgans=[REF(src)]"
.["Hallucinate"] = "?_src_=vars;[HrefToken()];hallucinate=[REF(src)]"
.["Give martial arts"] = "?_src_=vars;[HrefToken()];givemartialart=[REF(src)]"
.["Give brain trauma"] = "?_src_=vars;[HrefToken()];givetrauma=[REF(src)]"
.["Cure brain traumas"] = "?_src_=vars;[HrefToken()];curetraumas=[REF(src)]"
@@ -1,13 +1,6 @@
/mob/living/carbon/movement_delay()
var/FP = FALSE
var/obj/item/flightpack/F = get_flightpack()
if(istype(F) && F.flight)
FP = TRUE
. = ..(FP)
if(!FP)
. += grab_state * 1 //Flightpacks are too powerful to be slowed too much by the weight of a corpse.
else
. += grab_state * 3 //can't go fast while grabbing something.
. = ..()
. += grab_state * 3 //can't go fast while grabbing something.
if(!get_leg_ignore()) //ignore the fact we lack legs
var/leg_amount = get_num_legs()
@@ -16,7 +9,6 @@
. += 6 - 3*get_num_arms() //crawling is harder with fewer arms
if(legcuffed)
. += legcuffed.slowdown
if(stat == SOFT_CRIT)
. += SOFTCRIT_ADD_SLOWDOWN
@@ -24,7 +16,7 @@
if(movement_type & FLYING)
return 0
if(!(lube&SLIDE_ICE))
add_logs(src, (O ? O : get_turf(src)), "slipped on the", null, ((lube & SLIDE) ? "(LUBE)" : null))
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)
/mob/living/carbon/Process_Spacemove(movement_dir = 0)
@@ -33,10 +25,6 @@
if(!isturf(loc))
return 0
var/obj/item/flightpack/F = get_flightpack()
if(istype(F) && (F.flight) && F.allow_thrust(0.01, src))
return 1
// Do we have a jetpack implant (and is it on)?
var/obj/item/organ/cyberimp/chest/thrusters/T = getorganslot(ORGAN_SLOT_THRUSTERS)
if(istype(T) && movement_dir && T.allow_thrust(0.01))
+12 -12
View File
@@ -95,7 +95,7 @@
. = 0
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
. += BP.stamina_dam
. += round(BP.stamina_dam * BP.stam_damage_coeff, DAMAGE_PRECISION)
/mob/living/carbon/adjustStaminaLoss(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
@@ -120,7 +120,7 @@
var/list/obj/item/bodypart/parts = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(!isnull(status) && (BP.status != status))
if(status && BP.status != status)
continue
if((brute && BP.brute_dam) || (burn && BP.burn_dam) || (stamina && BP.stamina_dam))
parts += BP
@@ -171,13 +171,14 @@
update |= picked.heal_damage(brute, burn, stamina, only_robotic, only_organic, FALSE)
brute -= (brute_was - picked.brute_dam)
burn -= (burn_was - picked.burn_dam)
stamina -= (stamina_was - picked.stamina_dam)
brute = round(brute - (brute_was - picked.brute_dam), DAMAGE_PRECISION)
burn = round(burn - (burn_was - picked.burn_dam), DAMAGE_PRECISION)
stamina = round(stamina - (stamina_was - picked.stamina_dam), DAMAGE_PRECISION)
parts -= picked
if(updating_health)
updatehealth()
update_stamina()
if(update)
update_damage_overlays()
update_stamina() //CIT CHANGE - makes sure update_stamina() always gets called after a health update
@@ -191,9 +192,9 @@
var/update = 0
while(parts.len && (brute > 0 || burn > 0 || stamina > 0))
var/obj/item/bodypart/picked = pick(parts)
var/brute_per_part = round(brute/parts.len, 0.01)
var/burn_per_part = round(burn/parts.len, 0.01)
var/stamina_per_part = round(stamina/parts.len, 0.01)
var/brute_per_part = round(brute/parts.len, DAMAGE_PRECISION)
var/burn_per_part = round(burn/parts.len, DAMAGE_PRECISION)
var/stamina_per_part = round(stamina/parts.len, DAMAGE_PRECISION)
var/brute_was = picked.brute_dam
var/burn_was = picked.burn_dam
@@ -202,9 +203,9 @@
update |= picked.receive_damage(brute_per_part, burn_per_part, stamina_per_part, FALSE)
brute -= (picked.brute_dam - brute_was)
burn -= (picked.burn_dam - burn_was)
stamina -= (picked.stamina_dam - stamina_was)
brute = round(brute - (picked.brute_dam - brute_was), DAMAGE_PRECISION)
burn = round(burn - (picked.burn_dam - burn_was), DAMAGE_PRECISION)
stamina = round(stamina - (picked.stamina_dam - stamina_was), DAMAGE_PRECISION)
parts -= picked
if(updating_health)
@@ -253,4 +254,3 @@
if(B)
var/adjusted_amount = amount - B.get_brain_damage()
B.adjust_brain_damage(adjusted_amount, null)
+5
View File
@@ -9,6 +9,11 @@
emote("deathgasp")
. = ..()
for(var/T in get_traumas())
var/datum/brain_trauma/BT = T
BT.on_death()
if(SSticker.mode)
SSticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
+9 -42
View File
@@ -77,60 +77,27 @@
if(!.)
return
var/mob/living/carbon/human/H = user
if(!H.is_wagging_tail())
H.startTailWag()
if(!istype(H) || !H.dna || !H.dna.species || !H.dna.species.can_wag_tail(H))
return
if(!H.dna.species.is_wagging_tail())
H.dna.species.start_wagging_tail(H)
else
H.endTailWag()
/mob/living/carbon/human/proc/is_wagging_tail()
return (dna && dna.species && (("waggingtail_lizard" in dna.species.mutant_bodyparts) || ("waggingtail_human" in dna.species.mutant_bodyparts)|| ("mam_waggingtail" in dna.species.mutant_bodyparts)))
H.dna.species.stop_wagging_tail(H)
/datum/emote/living/carbon/human/wag/can_run_emote(mob/user, status_check = TRUE)
if(!..())
return FALSE
var/mob/living/carbon/human/H = user
if(H.dna && H.dna.species && (("tail_lizard" in H.dna.species.mutant_bodyparts) || ("waggingtail_lizard" in H.dna.species.mutant_bodyparts) || ("tail_human" in H.dna.species.mutant_bodyparts) || ("waggingtail_human" in H.dna.species.mutant_bodyparts)|| ("mam_tail" in H.dna.species.mutant_bodyparts) || ("mam_waggingtail" in H.dna.species.mutant_bodyparts)))
return TRUE
return H.dna && H.dna.species && H.dna.species.can_wag_tail(user)
/datum/emote/living/carbon/human/wag/select_message_type(mob/user)
. = ..()
var/mob/living/carbon/human/H = user
if(H.is_wagging_tail())
if(!H.dna || !H.dna.species)
return
if(H.dna.species.is_wagging_tail())
. = null
//Don't know where else to put this, it's basically an emote
/mob/living/carbon/human/proc/startTailWag()
if(!dna || !dna.species)
return
if("tail_lizard" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "tail_lizard"
dna.species.mutant_bodyparts -= "spines"
dna.species.mutant_bodyparts |= "waggingtail_lizard"
dna.species.mutant_bodyparts |= "waggingspines"
if("tail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "tail_human"
dna.species.mutant_bodyparts |= "waggingtail_human"
if("mam_tail" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "mam_tail"
dna.species.mutant_bodyparts |= "mam_waggingtail"
update_body()
/mob/living/carbon/human/proc/endTailWag()
if(!dna || !dna.species)
return
if("waggingtail_lizard" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_lizard"
dna.species.mutant_bodyparts -= "waggingspines"
dna.species.mutant_bodyparts |= "tail_lizard"
dna.species.mutant_bodyparts |= "spines"
if("waggingtail_human" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "waggingtail_human"
dna.species.mutant_bodyparts |= "tail_human"
if("mam_waggingtail" in dna.species.mutant_bodyparts)
dna.species.mutant_bodyparts -= "mam_waggingtail"
dna.species.mutant_bodyparts |= "mam_tail"
update_body()
/datum/emote/living/carbon/human/wing
key = "wing"
key_third_person = "wings"
+25 -10
View File
@@ -1,4 +1,4 @@
/mob/living/carbon/human/examine(mob/user)
/mob/living/carbon/human/examine(mob/user) //User is the person being examined
//this is very slightly better than it was because you can use it more places. still can't do \his[src] though.
var/t_He = p_they(TRUE)
var/t_His = p_their(TRUE)
@@ -51,7 +51,7 @@
if(gloves && !(SLOT_GLOVES in obscured))
msg += "[t_He] [t_has] [gloves.get_examine_string(user)] on [t_his] hands.\n"
else if(FR && length(FR.blood_DNA))
var/hand_number = get_num_arms()
var/hand_number = get_num_arms(FALSE)
if(hand_number)
msg += "<span class='warning'>[t_He] [t_has] [hand_number > 1 ? "" : "a"] blood-stained hand[hand_number > 1 ? "s" : ""]!</span>\n"
@@ -80,8 +80,11 @@
msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
//eyes
if(glasses && !(SLOT_GLASSES in obscured))
msg += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes.\n"
if(!(SLOT_GLASSES in obscured))
if(glasses)
msg += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes.\n"
else if(eye_color == BLOODCULT_EYE && iscultist(src) && has_trait(CULT_EYES))
msg += "<span class='warning'><B>[t_His] eyes are glowing an unnatural red!</B></span>\n"
//ears
if(ears && !(SLOT_EARS in obscured))
@@ -91,16 +94,17 @@
if(wear_id)
msg += "[t_He] [t_is] wearing [wear_id.get_examine_string(user)].\n"
//CIT CHANGES START HERE - adds genital details to examine text
//Status effects
msg += status_effect_examines()
//CIT CHANGES START HERE - adds genital details to examine text
if(LAZYLEN(internal_organs))
for(var/obj/item/organ/genital/dicc in internal_organs)
if(istype(dicc) && dicc.is_exposed())
msg += "[dicc.desc]\n"
msg += attempt_vr(src,"examine_bellies",args) //vore Code
//END OF CIT CHANGES
//Status effects
msg += status_effect_examines()
//Jitters
switch(jitteriness)
@@ -141,12 +145,25 @@
msg += "<span class='warning'>"
var/list/missing = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/list/disabled = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(BP.disabled)
disabled += BP
missing -= BP.body_zone
for(var/obj/item/I in BP.embedded_objects)
msg += "<B>[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!</B>\n"
for(var/X in disabled)
var/obj/item/bodypart/BP = X
var/damage_text
if(!(BP.get_damage(include_stamina = FALSE) >= BP.max_damage)) //Stamina is disabling the limb
damage_text = "limp and lifeless"
else
var/more_brute = BP.brute_dam >= BP.burn_dam
damage_text = more_brute ? "broken and mangled" : "burnt and blistered"
msg += "<B>[capitalize(t_his)] [BP.name] is [damage_text]!</B>\n"
//stores missing limbs
var/l_limbs_missing = 0
var/r_limbs_missing = 0
@@ -321,13 +338,11 @@
msg += "<a href='?src=[REF(src)];hud=s;add_crime=1'>\[Add crime\]</a> "
msg += "<a href='?src=[REF(src)];hud=s;view_comment=1'>\[View comment log\]</a> "
msg += "<a href='?src=[REF(src)];hud=s;add_comment=1'>\[Add comment\]</a>\n"
else if(isobserver(user) && traitstring)
msg += "<span class='info'><b>Traits:</b> [traitstring]</span><br>"
if(print_flavor_text() && get_visible_name() != "Unknown")//Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation.
msg += "[print_flavor_text()]\n"
msg += "*---------*</span>"
to_chat(user, msg)
+22 -43
View File
@@ -28,7 +28,7 @@
. = ..()
AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT), CALLBACK(src, .proc/clean_blood))
AddComponent(/datum/component/redirect, list(COMSIG_COMPONENT_CLEAN_ACT = CALLBACK(src, .proc/clean_blood)))
/mob/living/carbon/human/ComponentInitialize()
@@ -207,33 +207,6 @@
spreadFire(AM)
/mob/living/carbon/human/resist()
. = ..()
if(wear_suit && wear_suit.breakouttime)//added in human cuff breakout proc
return
if(.)
if(canmove && !on_fire)
for(var/obj/item/bodypart/L in bodyparts)
if(istype(L) && L.embedded_objects.len)
for(var/obj/item/I in L.embedded_objects)
if(istype(I) && I.w_class >= WEIGHT_CLASS_NORMAL) //minimum weight class to insta-ripout via resist
remove_embedded_unsafe(L, I, src, 1.5) //forcefully call the remove embedded unsafe proc but with extra pain multiplier. if you want to remove it less painfully, examine and remove it carefully.
return FALSE //Hands are occupied
return .
/mob/living/carbon/human/proc/remove_embedded_unsafe(obj/item/bodypart/L, obj/item/I, mob/user, painmul = 1)
if(!I || !L || I.loc != src || !(I in L.embedded_objects))
return
L.embedded_objects -= I
L.receive_damage(I.embedding.embedded_unsafe_removal_pain_multiplier*I.w_class*painmul)//It hurts to rip it out, get surgery you dingus. And if you're ripping it out quickly via resist, it's gonna hurt even more
I.forceMove(get_turf(src))
user.put_in_hands(I)
user.emote("scream")
user.visible_message("[user] rips [I] out of [user.p_their()] [L.name]!","<span class='notice'>You remove [I] from your [L.name].</span>")
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(user, COMSIG_CLEAR_MOOD_EVENT, "embedded")
return
/mob/living/carbon/human/Topic(href, href_list)
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
@@ -244,10 +217,20 @@
var/obj/item/I = locate(href_list["embedded_object"]) in L.embedded_objects
if(!I || I.loc != src) //no item, no limb, or item is not in limb or in the person anymore
return
var/time_taken = I.embedding.embedded_unsafe_removal_time/I.w_class
var/time_taken = I.embedding.embedded_unsafe_removal_time*I.w_class
usr.visible_message("<span class='warning'>[usr] attempts to remove [I] from [usr.p_their()] [L.name].</span>","<span class='notice'>You attempt to remove [I] from your [L.name]... (It will take [DisplayTimeText(time_taken)].)</span>")
if(do_after(usr, time_taken, needhand = 1, target = src))
remove_embedded_unsafe(L, I, usr)
if(!I || !L || I.loc != src || !(I in L.embedded_objects))
return
L.embedded_objects -= I
L.receive_damage(I.embedding.embedded_unsafe_removal_pain_multiplier*I.w_class)//It hurts to rip it out, get surgery you dingus.
I.forceMove(get_turf(src))
usr.put_in_hands(I)
usr.emote("scream")
usr.visible_message("[usr] successfully rips [I] out of [usr.p_their()] [L.name]!","<span class='notice'>You successfully remove [I] from your [L.name].</span>")
if(!has_embedded_objects())
clear_alert("embeddedobject")
SEND_SIGNAL(usr, COMSIG_CLEAR_MOOD_EVENT, "embedded")
return
if(href_list["item"])
@@ -624,7 +607,7 @@
//Agent cards lower threatlevel.
if(istype(idcard, /obj/item/card/id/syndicate))
threatcount -= 5
threatcount -= 2
return threatcount
@@ -638,8 +621,8 @@
hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3")
underwear = "Nude"
update_body()
update_genitals()
update_hair()
update_genitals()
/mob/living/carbon/human/singularity_pull(S, current_size)
..()
@@ -675,13 +658,13 @@
var/they_breathe = !C.has_trait(TRAIT_NOBREATH)
var/they_lung = C.getorganslot(ORGAN_SLOT_LUNGS)
if(C.health > HEALTH_THRESHOLD_CRIT)
if(C.health > C.crit_threshold)
return
src.visible_message("[src] performs CPR on [C.name]!", "<span class='notice'>You perform CPR on [C.name].</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "perform_cpr", /datum/mood_event/perform_cpr)
C.cpr_time = world.time
add_logs(src, C, "CPRed")
log_combat(src, C, "CPRed")
if(they_breathe && they_lung)
var/suff = min(C.getOxyLoss(), 7)
@@ -695,14 +678,14 @@
/mob/living/carbon/human/cuff_resist(obj/item/I)
if(dna && dna.check_mutation(HULK))
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk")
if(..(I, cuff_break = FAST_CUFFBREAK))
dropItemToGround(I)
else
if(..())
dropItemToGround(I)
/mob/living/carbon/human/proc/clean_blood(strength)
/mob/living/carbon/human/proc/clean_blood(datum/source, strength)
if(strength < CLEAN_STRENGTH_BLOOD)
return
if(gloves)
@@ -810,6 +793,8 @@
hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[BP.body_zone][icon_num]"))
for(var/t in get_missing_limbs()) //Missing limbs
hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[t]6"))
for(var/t in get_disabled_limbs()) //Disabled limbs
hud_used.healthdoll.add_overlay(mutable_appearance('icons/mob/screen_gen.dmi', "[t]7"))
else
hud_used.healthdoll.icon_state = "healthdoll_DEAD"
@@ -851,13 +836,6 @@
return 1
..()
/mob/living/carbon/human/Collide(atom/A)
..()
var/crashdir = get_dir(src, A)
var/obj/item/flightpack/FP = get_flightpack()
if(FP)
FP.flight_impact(A, crashdir)
/mob/living/carbon/human/vv_get_dropdown()
. = ..()
. += "---"
@@ -867,6 +845,7 @@
.["Make alien"] = "?_src_=vars;[HrefToken()];makealien=[REF(src)]"
.["Make slime"] = "?_src_=vars;[HrefToken()];makeslime=[REF(src)]"
.["Toggle Purrbation"] = "?_src_=vars;[HrefToken()];purrbation=[REF(src)]"
.["Copy outfit"] = "?_src_=vars;[HrefToken()];copyoutfit=[REF(src)]"
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
//If they dragged themselves and we're currently aggressively grabbing them try to piggyback
@@ -156,7 +156,7 @@
else
..()
/mob/living/carbon/human/grippedby(mob/living/user)
/mob/living/carbon/human/grippedby(mob/living/user, instant = FALSE)
if(w_uniform)
w_uniform.add_fingerprint(user)
..()
@@ -220,7 +220,7 @@
else if(!M.client || prob(5)) // only natural monkeys get to stun reliably, (they only do it occasionaly)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
Knockdown(100)
add_logs(M, src, "tackled")
log_combat(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
@@ -259,7 +259,7 @@
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting, armor_block)
@@ -273,7 +273,7 @@
else
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
Knockdown(100)
add_logs(M, src, "tackled")
log_combat(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
@@ -357,7 +357,7 @@
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
..()
@@ -788,7 +788,7 @@
if(wear_suit && ((wear_suit.body_parts_covered & HANDS) || (wear_suit.body_parts_covered & ARMS)))
arm_clothes = wear_suit
if(arm_clothes)
torn_items += arm_clothes
torn_items |= arm_clothes
//LEGS & FEET//
if(!def_zone || def_zone == BODY_ZONE_L_LEG || def_zone == BODY_ZONE_R_LEG)
@@ -800,7 +800,7 @@
if(wear_suit && ((wear_suit.body_parts_covered & FEET) || (wear_suit.body_parts_covered & LEGS)))
leg_clothes = wear_suit
if(leg_clothes)
torn_items += leg_clothes
torn_items |= leg_clothes
for(var/obj/item/I in torn_items)
I.take_damage(damage_amount, damage_type, damage_flag, 0)
@@ -1,5 +1,6 @@
/mob/living/carbon/human
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD, NANITE_HUD, DIAG_NANITE_FULL_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD,ANTAG_HUD,GLAND_HUD,SENTIENT_DISEASE_HUD)
hud_possible = list(HEALTH_HUD,STATUS_HUD,ID_HUD,WANTED_HUD,IMPLOYAL_HUD,IMPCHEM_HUD,IMPTRACK_HUD, NANITE_HUD, DIAG_NANITE_FULL_HUD,ANTAG_HUD,GLAND_HUD,SENTIENT_DISEASE_HUD)
hud_type = /datum/hud/human
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
pressure_resistance = 25
can_buckle = TRUE
@@ -4,7 +4,7 @@
/mob/living/carbon/human/canBeHandcuffed()
if(get_num_arms() >= 2)
if(get_num_arms(FALSE) >= 2)
return TRUE
else
return FALSE
@@ -1,9 +1,16 @@
/mob/living/carbon/human/get_movespeed_modifiers()
var/list/considering = ..()
. = considering
if(has_trait(TRAIT_IGNORESLOWDOWN))
for(var/id in .)
var/list/data = .[id]
if(data[MOVESPEED_DATA_INDEX_FLAGS] & IGNORE_NOSLOW)
.[id] = data
/mob/living/carbon/human/movement_delay()
. = 0
var/static/config_human_delay
if(isnull(config_human_delay))
config_human_delay = CONFIG_GET(number/human_delay)
. += ..() + config_human_delay + dna.species.movement_delay(src)
. = ..()
if(dna && dna.species)
. += dna.species.movement_delay(src)
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(has_trait(TRAIT_NOSLIPALL))
@@ -49,20 +56,19 @@
//Bloody footprints
var/turf/T = get_turf(src)
if(S.bloody_shoes && S.bloody_shoes[S.blood_state])
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)
return
else
//No oldFP or it's a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
if (S.bloody_shoes[S.blood_state] > BLOOD_LOSS_IN_SPREAD)
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
FP.bloodiness = S.bloody_shoes[S.blood_state] - BLOOD_LOSS_IN_SPREAD
FP.add_blood_DNA(S.return_blood_DNA())
FP.update_icon()
update_inv_shoes()
for(var/obj/effect/decal/cleanable/blood/footprints/oldFP in T)
if (oldFP.blood_state == S.blood_state)
return
//No oldFP or they're all a different kind of blood
S.bloody_shoes[S.blood_state] = max(0, S.bloody_shoes[S.blood_state] - BLOOD_LOSS_PER_STEP)
if (S.bloody_shoes[S.blood_state] > BLOOD_LOSS_IN_SPREAD)
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
FP.bloodiness = S.bloody_shoes[S.blood_state] - BLOOD_LOSS_IN_SPREAD
FP.add_blood_DNA(S.return_blood_DNA())
FP.update_icon()
update_inv_shoes()
//End bloody footprints
S.step_action()
+12 -15
View File
@@ -23,7 +23,12 @@
if (notransform)
return
if(..()) //not dead
. = ..()
if (QDELETED(src))
return 0
if(.) //not dead
handle_active_genes()
if(stat != DEAD)
@@ -44,15 +49,15 @@
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if(istype(loc, /obj/belly)) //START OF CIT CHANGES - Makes it so you don't suffocate while inside vore organs. Remind me to modularize this some time - Bhijn
return ONE_ATMOSPHERE
if(istype(loc, /obj/item/dogborg/sleeper))
return ONE_ATMOSPHERE //END OF CIT CHANGES
if (wear_suit && head && istype(wear_suit, /obj/item/clothing) && istype(head, /obj/item/clothing))
var/obj/item/clothing/CS = wear_suit
var/obj/item/clothing/CH = head
if (CS.clothing_flags & CH.clothing_flags & STOPSPRESSUREDAMAGE)
return ONE_ATMOSPHERE
if(istype(loc, /obj/belly)) //START OF CIT CHANGES - Makes it so you don't suffocate while inside vore organs. Remind me to modularize this some time - Bhijn
return ONE_ATMOSPHERE
if(istype(loc, /obj/item/dogborg/sleeper))
return ONE_ATMOSPHERE //END OF CIT CHANGES
return pressure
@@ -65,7 +70,7 @@
else if(eye_blurry) //blurry eyes heal slowly
adjust_blurriness(-1)
if (getBrainLoss() >= 60 && !incapacitated(TRUE))
if (getBrainLoss() >= 60)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "brain_damage", /datum/mood_event/brain_damage)
if(prob(3))
if(prob(25))
@@ -88,7 +93,7 @@
var/L = getorganslot(ORGAN_SLOT_LUNGS)
if(!L)
if(health >= HEALTH_THRESHOLD_CRIT)
if(health >= crit_threshold)
adjustOxyLoss(HUMAN_MAX_OXYLOSS + 1)
else if(!has_trait(TRAIT_NOCRITDAMAGE))
adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
@@ -320,19 +325,11 @@
HM.on_life(src)
/mob/living/carbon/human/proc/handle_heart()
if(!can_heartattack())
return
var/we_breath = !has_trait(TRAIT_NOBREATH, SPECIES_TRAIT)
if(!undergoing_cardiac_arrest())
return
// Cardiac arrest, unless heart is stabilized
if(has_trait(TRAIT_STABLEHEART))
return
if(we_breath)
adjustOxyLoss(8)
Unconscious(80)
+70 -71
View File
@@ -78,6 +78,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/whitelisted = 0 //Is this species restricted to certain players?
var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both.
///////////
// PROCS //
///////////
@@ -100,7 +101,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
GLOB.roundstart_races += "human"
/datum/species/proc/check_roundstart_eligible()
if(id in (CONFIG_GET(keyed_flag_list/roundstart_races)))
if(id in (CONFIG_GET(keyed_list/roundstart_races)))
return TRUE
return FALSE
@@ -247,7 +248,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/obj/item/organ/I = new path()
I.Insert(C)
/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species)
/datum/species/proc/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
// Drop the items the new species can't wear
for(var/slot_id in no_equip)
var/obj/item/thing = C.get_item_by_slot(slot_id)
@@ -263,6 +264,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
C.Digitigrade_Leg_Swap(FALSE)
C.mob_biotypes = inherent_biotypes
regenerate_organs(C,old_species)
if(exotic_bloodtype && C.dna.blood_type != exotic_bloodtype)
@@ -289,6 +291,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(TRAIT_VIRUSIMMUNE in inherent_traits)
for(var/datum/disease/A in C.diseases)
A.cure(FALSE)
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
//CITADEL EDIT
@@ -299,18 +302,18 @@ GLOBAL_LIST_EMPTY(roundstart_races)
C.canbearoused = C.client.prefs.arousable
// EDIT ENDS
/datum/species/proc/on_species_loss(mob/living/carbon/C)
/datum/species/proc/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
if(C.dna.species.exotic_bloodtype)
C.dna.blood_type = random_blood_type()
if(DIGITIGRADE in species_traits)
C.Digitigrade_Leg_Swap(TRUE)
for(var/X in inherent_traits)
C.remove_trait(X, SPECIES_TRAIT)
SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src)
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
H.remove_overlay(HAIR_LAYER)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
if(!HD) //Decapitated
return
@@ -496,7 +499,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
else
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in species_traits))
if(H.socks && H.get_num_legs(FALSE) >= 2 && !(DIGITIGRADE in species_traits))
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks]
if(socks)
standing += mutable_appearance(socks.icon, socks.icon_state, -BODY_LAYER)
@@ -652,15 +655,15 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if("tail_lizard")
S = GLOB.tails_list_lizard[H.dna.features["tail_lizard"]]
if("waggingtail_lizard")
S.= GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]]
S = GLOB.animated_tails_list_lizard[H.dna.features["tail_lizard"]]
if("tail_human")
S = GLOB.tails_list_human[H.dna.features["tail_human"]]
if("waggingtail_human")
S.= GLOB.animated_tails_list_human[H.dna.features["tail_human"]]
S = GLOB.animated_tails_list_human[H.dna.features["tail_human"]]
if("spines")
S = GLOB.spines_list[H.dna.features["spines"]]
if("waggingspines")
S.= GLOB.animated_spines_list[H.dna.features["spines"]]
S = GLOB.animated_spines_list[H.dna.features["spines"]]
if("snout")
S = GLOB.snouts_list[H.dna.features["snout"]]
if("frills")
@@ -683,18 +686,17 @@ GLOBAL_LIST_EMPTY(roundstart_races)
S = GLOB.caps_list[H.dna.features["caps"]]
else
S = citadel_mutant_bodyparts(bodypart, H)
if(!S || S.icon_state == "none")
continue
var/mutable_appearance/accessory_overlay = mutable_appearance(S.icon, layer = -layer)
//A little rename so we don't have to use tail_lizard or tail_human when naming the sprites.
if(bodypart == "tail_lizard" || bodypart == "tail_human" || bodypart == "mam_tail" || bodypart == "slimecoontail" || bodypart == "xenotail")
if(bodypart == "tail_lizard" || bodypart == "tail_human" || bodypart == "mam_tail" || bodypart == "xenotail")
bodypart = "tail"
else if(bodypart == "waggingtail_lizard" || bodypart == "waggingtail_human" || bodypart == "mam_waggingtail")
bodypart = "waggingtail"
if(bodypart == "mam_ears")
if(bodypart == "mam_ears" || bodypart == "ears")
bodypart = "ears"
if(bodypart == "xenohead")
bodypart = "xhead"
@@ -703,6 +705,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
accessory_overlay.icon_state = "[g]_[bodypart]_[S.icon_state]_[layertext]"
else
accessory_overlay.icon_state = "m_[bodypart]_[S.icon_state]_[layertext]"
if(S.center)
accessory_overlay = center_image(accessory_overlay, S.dimension_x, S.dimension_y)
@@ -818,6 +821,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
extra2_accessory_overlay.color = "#[H.hair_color]"
standing += extra2_accessory_overlay
H.overlays_standing[layer] = standing.Copy()
standing = list()
@@ -826,6 +830,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
H.apply_overlay(BODY_FRONT_LAYER)
H.apply_overlay(BODY_TAUR_LAYER) // CITADEL EDIT
//This exists so sprite accessories can still be per-layer without having to include that layer's
//number in their sprite name, which causes issues when those numbers change.
/datum/species/proc/mutant_bodyparts_layertext(layer)
@@ -841,13 +846,14 @@ GLOBAL_LIST_EMPTY(roundstart_races)
return "TAUR"
//END EDIT
/datum/species/proc/spec_life(mob/living/carbon/human/H)
if(H.has_trait(TRAIT_NOBREATH))
H.setOxyLoss(0)
H.losebreath = 0
var/takes_crit_damage = (!H.has_trait(TRAIT_NOCRITDAMAGE))
if((H.health < HEALTH_THRESHOLD_CRIT) && takes_crit_damage)
if((H.health < H.crit_threshold) && takes_crit_damage)
H.adjustBruteLoss(1)
/datum/species/proc/spec_death(gibbed, mob/living/carbon/human/H)
@@ -862,8 +868,8 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(!I.species_exception || !is_type_in_list(src, I.species_exception))
return FALSE
var/num_arms = H.get_num_arms()
var/num_legs = H.get_num_legs()
var/num_arms = H.get_num_arms(FALSE)
var/num_legs = H.get_num_legs(FALSE)
switch(slot)
if(SLOT_HANDS)
@@ -1140,22 +1146,12 @@ GLOBAL_LIST_EMPTY(roundstart_races)
switch(H.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "nutrition", /datum/mood_event/nutrition/fat)
H.throw_alert("nutrition", /obj/screen/alert/fat)
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "nutrition", /datum/mood_event/nutrition/wellfed)
H.clear_alert("nutrition")
if( NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "nutrition", /datum/mood_event/nutrition/fed)
H.clear_alert("nutrition")
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "nutrition")
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FULL)
H.clear_alert("nutrition")
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "nutrition", /datum/mood_event/nutrition/hungry)
H.throw_alert("nutrition", /obj/screen/alert/hungry)
if(0 to NUTRITION_LEVEL_STARVING)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "nutrition", /datum/mood_event/nutrition/starving)
H.throw_alert("nutrition", /obj/screen/alert/starving)
/datum/species/proc/update_health_hud(mob/living/carbon/human/H)
@@ -1204,18 +1200,14 @@ GLOBAL_LIST_EMPTY(roundstart_races)
/datum/species/proc/movement_delay(mob/living/carbon/human/H)
. = 0 //We start at 0.
var/flight = 0 //Check for flight and flying items
var/flightpack = 0
var/ignoreslow = 0
var/gravity = 0
var/obj/item/flightpack/F = H.get_flightpack()
if(istype(F) && F.flight)
flightpack = 1
if(H.movement_type & FLYING)
flight = 1
gravity = H.has_gravity()
if(!flightpack && gravity) //Check for chemicals and innate speedups and slowdowns if we're moving using our body and not a flying suit
if(gravity && !flight) //Check for chemicals and innate speedups and slowdowns if we're on the ground
if(H.has_trait(TRAIT_GOTTAGOFAST))
. -= 1
if(H.has_trait(TRAIT_GOTTAGOREALLYFAST))
@@ -1237,12 +1229,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
else if(istype(T) && T.allow_thrust(0.01, H))
. -= 2
if(flightpack && F.boost)
. -= F.boost_speed
else if(flightpack && F.brake)
. += 1
if(!ignoreslow && !flightpack && gravity)
if(!ignoreslow && gravity)
if(H.wear_suit)
. += H.wear_suit.slowdown
if(H.shoes)
@@ -1297,7 +1284,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(target.health >= 0 && !(target.has_trait(TRAIT_FAKEDEATH)))
target.help_shake_act(user)
if(target != user)
add_logs(user, target, "shaked")
log_combat(user, target, "shaked")
return 1
else
var/we_breathe = !user.has_trait(TRAIT_NOBREATH)
@@ -1387,7 +1374,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(user.limb_destroyer)
target.dismembering_strike(user, affecting.body_zone)
target.apply_damage(damage, BRUTE, affecting, armor_block)
add_logs(user, target, "punched")
log_combat(user, target, "punched")
if((target.stat != DEAD) && damage >= user.dna.species.punchstunthreshold)
target.visible_message("<span class='danger'>[user] has knocked [target] down!</span>", \
"<span class='userdanger'>[user] has knocked [target] down!</span>", null, COMBAT_MESSAGE_RANGE)
@@ -1397,7 +1384,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
target.forcesay(GLOB.hit_appends)
/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
// CITADEL EDIT slap mouthy gits
// CITADEL EDIT slap mouthy gits
var/aim_for_mouth = user.zone_selected == "mouth"
var/target_on_help_and_unarmed = target.a_intent == INTENT_HELP && !target.get_active_held_item()
var/target_aiming_for_mouth = target.zone_selected == "mouth"
@@ -1434,9 +1421,8 @@ GLOBAL_LIST_EMPTY(roundstart_races)
"<span class='userdanger'>[user] has pushed [target]!</span>", null, COMBAT_MESSAGE_RANGE)
target.apply_effect(40, EFFECT_KNOCKDOWN, target.run_armor_check(affecting, "melee", "Your armor prevents your fall!", "Your armor softens your fall!"))
target.forcesay(GLOB.hit_appends)
add_logs(user, target, "disarmed", " pushing them to the ground")
log_combat(user, target, "pushed over")
return*/
if(!target.combatmode) // CITADEL CHANGE
randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed
if(user.resting) //CITADEL CHANGE
@@ -1457,14 +1443,14 @@ GLOBAL_LIST_EMPTY(roundstart_races)
else
I = null
playsound(target, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(user, target, "disarmed", "[I ? " removing \the [I]" : ""]")
log_combat(user, target, "disarmed", "[I ? " removing \the [I]" : ""]")
return
playsound(target, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
target.visible_message("<span class='danger'>[user] attempted to disarm [target]!</span>", \
"<span class='userdanger'>[user] attemped to disarm [target]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(user, target, "attempted to disarm")
log_combat(user, target, "attempted to disarm")
/datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
@@ -1481,7 +1467,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(M.mind)
attacker_style = M.mind.martial_art
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
add_logs(M, H, "attempted to touch")
log_combat(M, H, "attempted to touch")
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
return 0
switch(M.a_intent)
@@ -1516,7 +1502,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/armor_block = H.run_armor_check(affecting, "melee", "<span class='notice'>Your armor has protected your [hit_area].</span>", "<span class='notice'>Your armor has softened a hit to your [hit_area].</span>",I.armour_penetration)
armor_block = min(90,armor_block) //cap damage reduction at 90%
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(iscarbon(user))
@@ -1529,7 +1514,6 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(!H.combatmode)
totitemdamage *= 1.5
//CIT CHANGES END HERE
var/weakness = H.check_weakness(I, user)
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage
@@ -1540,7 +1524,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
//dismemberment
var/probability = I.get_dismemberment_chance(affecting)
if(prob(probability) || (H.has_trait(TRAIT_EASYDISMEMBER) && prob(2*probability)))
if(prob(probability) || (H.has_trait(TRAIT_EASYDISMEMBER) && prob(probability))) //try twice
if(affecting.dismember(I.damtype))
I.add_mob_blood(H)
playsound(get_turf(H), I.get_dismember_sound(), 80, 1)
@@ -1559,20 +1543,20 @@ GLOBAL_LIST_EMPTY(roundstart_races)
switch(hit_area)
if(BODY_ZONE_HEAD)
if(H.stat == CONSCIOUS && armor_block < 50)
if(!I.is_sharp() && armor_block < 50)
if(prob(I.force))
H.visible_message("<span class='danger'>[H] has been knocked senseless!</span>", \
"<span class='userdanger'>[H] has been knocked senseless!</span>")
H.confused = max(H.confused, 20)
H.adjustBrainLoss(20)
H.adjust_blurriness(10)
if(H.stat == CONSCIOUS)
H.visible_message("<span class='danger'>[H] has been knocked senseless!</span>", \
"<span class='userdanger'>[H] has been knocked senseless!</span>")
H.confused = max(H.confused, 20)
H.adjust_blurriness(10)
if(prob(10))
H.gain_trauma(/datum/brain_trauma/mild/concussion)
else
if(!I.is_sharp())
H.adjustBrainLoss(I.force * 0.2)
H.adjustBrainLoss(I.force * 0.2)
if(!I.is_sharp() && prob(I.force + ((100 - H.health) * 0.5)) && H != user) // rev deconversion through blunt trauma.
if(H.stat == CONSCIOUS && H != user && prob(I.force + ((100 - H.health) * 0.5))) // rev deconversion through blunt trauma.
var/datum/antagonist/rev/rev = H.mind.has_antag_datum(/datum/antagonist/rev)
if(rev)
rev.remove_revolutionary(FALSE, user)
@@ -1589,7 +1573,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
H.update_inv_glasses()
if(BODY_ZONE_CHEST)
if(H.stat == CONSCIOUS && armor_block < 50)
if(H.stat == CONSCIOUS && !I.is_sharp() && armor_block < 50)
if(prob(I.force))
H.visible_message("<span class='danger'>[H] has been knocked down!</span>", \
"<span class='userdanger'>[H] has been knocked down!</span>")
@@ -1713,19 +1697,20 @@ GLOBAL_LIST_EMPTY(roundstart_races)
SEND_SIGNAL(H, COMSIG_ADD_MOOD_EVENT, "hot", /datum/mood_event/hot)
var/burn_damage
switch(H.bodytemperature)
if(BODYTEMP_HEAT_DAMAGE_LIMIT to 400)
H.throw_alert("temp", /obj/screen/alert/hot, 1)
burn_damage = HEAT_DAMAGE_LEVEL_1
if(400 to 460)
H.throw_alert("temp", /obj/screen/alert/hot, 2)
burn_damage = HEAT_DAMAGE_LEVEL_2
else
H.throw_alert("temp", /obj/screen/alert/hot, 3)
if(H.on_fire)
burn_damage = HEAT_DAMAGE_LEVEL_3
var/firemodifier = H.fire_stacks / 50
if (H.on_fire)
burn_damage = max(log(2-firemodifier,(H.bodytemperature-BODYTEMP_NORMAL))-5,0)
else
firemodifier = min(firemodifier, 0)
burn_damage = max(log(2-firemodifier,(H.bodytemperature-BODYTEMP_NORMAL))-5,0) // this can go below 5 at log 2.5
if (burn_damage)
switch(burn_damage)
if(0 to 2)
H.throw_alert("temp", /obj/screen/alert/hot, 1)
if(2 to 4)
H.throw_alert("temp", /obj/screen/alert/hot, 2)
else
burn_damage = HEAT_DAMAGE_LEVEL_2
H.throw_alert("temp", /obj/screen/alert/hot, 3)
burn_damage = burn_damage * heatmod * H.physiology.heat_mod
if (H.stat < UNCONSCIOUS && (prob(burn_damage) * 10) / 4) //40% for level 3 damage on humans
H.emote("scream")
@@ -1816,7 +1801,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(H.wear_suit && ((H.wear_suit.body_parts_covered & HANDS) || (H.wear_suit.body_parts_covered & ARMS)))
arm_clothes = H.wear_suit
if(arm_clothes)
burning_items += arm_clothes
burning_items |= arm_clothes
//LEGS & FEET//
var/obj/item/clothing/leg_clothes = null
@@ -1827,7 +1812,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
if(H.wear_suit && ((H.wear_suit.body_parts_covered & FEET) || (H.wear_suit.body_parts_covered & LEGS)))
leg_clothes = H.wear_suit
if(leg_clothes)
burning_items += leg_clothes
burning_items |= leg_clothes
for(var/X in burning_items)
var/obj/item/I = X
@@ -1836,7 +1821,7 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/thermal_protection = H.get_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT && !no_protection)
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT && !no_protection)
return
if(thermal_protection >= FIRE_SUIT_MAX_TEMP_PROTECT && !no_protection)
H.adjust_bodytemperature(11)
@@ -1869,3 +1854,17 @@ GLOBAL_LIST_EMPTY(roundstart_races)
/datum/species/proc/negates_gravity(mob/living/carbon/human/H)
return 0
////////////////
//Tail Wagging//
////////////////
/datum/species/proc/can_wag_tail(mob/living/carbon/human/H)
return FALSE
/datum/species/proc/is_wagging_tail(mob/living/carbon/human/H)
return FALSE
/datum/species/proc/start_wagging_tail(mob/living/carbon/human/H)
/datum/species/proc/stop_wagging_tail(mob/living/carbon/human/H)
@@ -1,5 +1,5 @@
/datum/species/dullahan
name = "dullahan"
name = "Dullahan"
id = "dullahan"
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS)
@@ -129,6 +129,7 @@
else
qdel(src)
/obj/item/dullahan_relay/Destroy()
if(!QDELETED(owner))
var/mob/living/carbon/human/H = owner
@@ -0,0 +1,130 @@
//Subtype of human
/datum/species/human/felinid
name = "Felinid"
id = "felinid"
limbs_id = "human"
mutant_bodyparts = list("ears", "tail_human")
default_features = list("mcolor" = "FFF", "tail_human" = "Cat", "ears" = "Cat", "wings" = "None")
mutantears = /obj/item/organ/ears/cat
mutanttail = /obj/item/organ/tail/cat
/datum/species/human/felinid/qualifies_for_rank(rank, list/features)
return TRUE
//Curiosity killed the cat's wagging tail.
/datum/species/human/felinid/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
stop_wagging_tail(H)
/datum/species/human/felinid/spec_stun(mob/living/carbon/human/H,amount)
if(H)
stop_wagging_tail(H)
. = ..()
/datum/species/human/felinid/can_wag_tail(mob/living/carbon/human/H)
return ("tail_human" in mutant_bodyparts) || ("waggingtail_human" in mutant_bodyparts)
/datum/species/human/felinid/is_wagging_tail(mob/living/carbon/human/H)
return ("waggingtail_human" in mutant_bodyparts)
/datum/species/human/felinid/start_wagging_tail(mob/living/carbon/human/H)
if("tail_human" in mutant_bodyparts)
mutant_bodyparts -= "tail_human"
mutant_bodyparts |= "waggingtail_human"
H.update_body()
/datum/species/human/felinid/stop_wagging_tail(mob/living/carbon/human/H)
if("waggingtail_human" in mutant_bodyparts)
mutant_bodyparts -= "waggingtail_human"
mutant_bodyparts |= "tail_human"
H.update_body()
/datum/species/human/felinid/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(!pref_load) //Hah! They got forcefully purrbation'd. Force default felinid parts on them if they have no mutant parts in those areas!
if(H.dna.features["tail_human"] == "None")
H.dna.features["tail_human"] = "Cat"
if(H.dna.features["ears"] == "None")
H.dna.features["ears"] = "Cat"
if(H.dna.features["ears"] == "Cat")
var/obj/item/organ/ears/cat/ears = new
ears.Insert(H, drop_if_replaced = FALSE)
else
mutantears = /obj/item/organ/ears
if(H.dna.features["tail_human"] == "Cat")
var/obj/item/organ/tail/cat/tail = new
tail.Insert(H, drop_if_replaced = FALSE)
else
mutanttail = null
return ..()
/datum/species/human/felinid/on_species_loss(mob/living/carbon/H, datum/species/new_species, pref_load)
var/obj/item/organ/ears/cat/ears = H.getorgan(/obj/item/organ/ears/cat)
var/obj/item/organ/tail/cat/tail = H.getorgan(/obj/item/organ/tail/cat)
if(ears)
var/obj/item/organ/ears/NE
if(new_species && new_species.mutantears)
// Roundstart cat ears override new_species.mutantears, reset it here.
new_species.mutantears = initial(new_species.mutantears)
if(new_species.mutantears)
NE = new new_species.mutantears
if(!NE)
// Go with default ears
NE = new /obj/item/organ/ears
NE.Insert(H, drop_if_replaced = FALSE)
if(tail)
var/obj/item/organ/tail/NT
if(new_species && new_species.mutanttail)
// Roundstart cat tail overrides new_species.mutanttail, reset it here.
new_species.mutanttail = initial(new_species.mutanttail)
if(new_species.mutanttail)
NT = new new_species.mutanttail
if(NT)
NT.Insert(H, drop_if_replaced = FALSE)
else
tail.Remove(H)
/proc/mass_purrbation()
for(var/M in GLOB.mob_list)
if(ishumanbasic(M))
purrbation_apply(M)
CHECK_TICK
/proc/mass_remove_purrbation()
for(var/M in GLOB.mob_list)
if(ishumanbasic(M))
purrbation_remove(M)
CHECK_TICK
/proc/purrbation_toggle(mob/living/carbon/human/H, silent = FALSE)
if(!ishumanbasic(H))
return
if(!iscatperson(H))
purrbation_apply(H, silent)
. = TRUE
else
purrbation_remove(H, silent)
. = FALSE
/proc/purrbation_apply(mob/living/carbon/human/H, silent = FALSE)
if(!ishuman(H) || iscatperson(H))
return
H.set_species(/datum/species/human/felinid)
if(!silent)
to_chat(H, "Something is nya~t right.")
playsound(get_turf(H), 'sound/effects/meow1.ogg', 50, 1, -1)
/proc/purrbation_remove(mob/living/carbon/human/H, silent = FALSE)
if(!ishuman(H) || !iscatperson(H))
return
H.set_species(/datum/species/human)
if(!silent)
to_chat(H, "You are no longer a cat.")
@@ -27,7 +27,7 @@
var/random_eligible = TRUE //If false, the golem subtype can't be made through golem mutation toxin
var/prefix = "Iron"
var/list/special_names
var/list/special_names = list("Tarkus")
var/human_surname_chance = 3
var/special_name_chance = 5
@@ -68,8 +68,9 @@
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine
mutant_organs = list(/obj/item/organ/adamantine_resonator, /obj/item/organ/vocal_cords/adamantine)
fixed_mut_color = "4ed"
info_text = "As an <span class='danger'>Adamantine Golem</span>, you possess special vocal cords allowing you to \"resonate\" messages to all golems."
info_text = "As an <span class='danger'>Adamantine Golem</span>, you possess special vocal cords allowing you to \"resonate\" messages to all golems. Your unique mineral makeup makes you immune to most types of magic."
prefix = "Adamantine"
special_names = null
/datum/species/golem/adamantine/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
@@ -86,7 +87,7 @@
fixed_mut_color = "a3d"
meat = /obj/item/stack/ore/plasma
//Can burn and takes damage from heat
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER) //no RESISTHEAT, NOFIRE
info_text = "As a <span class='danger'>Plasma Golem</span>, you burn easily. Be careful, if you get hot enough while burning, you'll blow up!"
heatmod = 0 //fine until they blow up
prefix = "Plasma"
@@ -135,7 +136,7 @@
if(H.fire_stacks)
to_chat(owner, "<span class='notice'>You ignite yourself!</span>")
else
to_chat(owner, "<span class='warning'>You try ignite yourself, but fail!</span>")
to_chat(owner, "<span class='warning'>You try to ignite yourself, but fail!</span>")
H.IgniteMob() //firestacks are already there passively
//Harder to hurt
@@ -159,6 +160,7 @@
meat = /obj/item/stack/ore/gold
info_text = "As a <span class='danger'>Gold Golem</span>, you are faster but less resistant than the average golem."
prefix = "Golden"
special_names = list("Boy")
//Heavier, thus higher chance of stunning when punching
/datum/species/golem/silver
@@ -167,7 +169,7 @@
fixed_mut_color = "ddd"
punchstunthreshold = 9 //60% chance, from 40%
meat = /obj/item/stack/ore/silver
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks are heavier and have a higher chance of stunning."
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks have a higher chance of stunning. Being made of silver, your body is immune to most types of magic."
prefix = "Silver"
special_names = list("Surfer", "Chariot", "Lining")
@@ -194,6 +196,7 @@
attack_verb = "smash"
attack_sound = 'sound/effects/meteorimpact.ogg' //hits pretty hard
prefix = "Plasteel"
special_names = null
//Immune to ash storms
/datum/species/golem/titanium
@@ -204,6 +207,7 @@
info_text = "As a <span class='danger'>Titanium Golem</span>, you are immune to ash storms, and slightly more resistant to burn damage."
burnmod = 0.9
prefix = "Titanium"
special_names = list("Dioxide")
/datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -222,6 +226,7 @@
info_text = "As a <span class='danger'>Plastitanium Golem</span>, you are immune to both ash storms and lava, and slightly more resistant to burn damage."
burnmod = 0.8
prefix = "Plastitanium"
special_names = null
/datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -257,10 +262,10 @@
/datum/species/golem/wood
name = "Wood Golem"
id = "wood golem"
fixed_mut_color = "49311c"
fixed_mut_color = "9E704B"
meat = /obj/item/stack/sheet/mineral/wood
//Can burn and take damage from heat
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
armor = 30
burnmod = 1.25
heatmod = 1.5
@@ -315,6 +320,7 @@
var/last_event = 0
var/active = null
prefix = "Uranium"
special_names = list("Oxide", "Rod", "Meltdown")
/datum/species/golem/uranium/spec_life(mob/living/carbon/human/H)
if(!active)
@@ -334,9 +340,10 @@
armor = 0
burnmod = 3 //melts easily
brutemod = 0.25
info_text = "As a <span class='danger'>Sand Golem</span>, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage. You will also turn to sand when dying, preventing any form of recovery."
info_text = "As a <span class='danger'>Sand Golem</span>, you are immune to physical bullets and take very little brute damage, but are extremely vulnerable to burn damage and energy weapons. You will also turn to sand when dying, preventing any form of recovery."
attack_sound = 'sound/effects/shovel_dig.ogg'
prefix = "Sand"
special_names = list("Castle", "Bag", "Dune", "Worm", "Storm")
/datum/species/golem/sand/spec_death(gibbed, mob/living/carbon/human/H)
H.visible_message("<span class='danger'>[H] turns into a pile of sand!</span>")
@@ -364,9 +371,10 @@
armor = 0
brutemod = 3 //very fragile
burnmod = 0.25
info_text = "As a <span class='danger'>Glass Golem</span>, you reflect lasers and energy weapons, and are very resistant to burn damage, but you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery."
info_text = "As a <span class='danger'>Glass Golem</span>, you reflect lasers and energy weapons, and are very resistant to burn damage. However, you are extremely vulnerable to brute damage. On death, you'll shatter beyond any hope of recovery."
attack_sound = 'sound/effects/glassbr2.ogg'
prefix = "Glass"
special_names = list("Lens", "Prism", "Fiber", "Bead")
/datum/species/golem/glass/spec_death(gibbed, mob/living/carbon/human/H)
playsound(H, "shatter", 70, 1)
@@ -397,7 +405,7 @@
id = "bluespace golem"
fixed_mut_color = "33f"
meat = /obj/item/stack/ore/bluespace_crystal
info_text = "As a <span class='danger'>Bluespace Golem</span>, are spatially unstable: you will teleport when hit, and you can teleport manually at a long distance."
info_text = "As a <span class='danger'>Bluespace Golem</span>, you are spatially unstable: You will teleport when hit, and you can teleport manually at a long distance."
attack_verb = "bluespace punch"
attack_sound = 'sound/effects/phasein.ogg'
prefix = "Bluespace"
@@ -494,10 +502,11 @@
punchdamagehigh = 1
punchstunthreshold = 2 //Harmless and can't stun
meat = /obj/item/stack/ore/bananium
info_text = "As a <span class='danger'>Bananium Golem</span>, you are made for pranking. Your body emits natural honks, and you cannot hurt people when punching them. Your skin also emits bananas when damaged."
info_text = "As a <span class='danger'>Bananium Golem</span>, you are made for pranking. Your body emits natural honks, and you can barely even hurt people when punching them. Your skin also bleeds banana peels when damaged."
attack_verb = "honk"
attack_sound = 'sound/items/airhorn2.ogg'
prefix = "Bananium"
special_names = null
var/last_honk = 0
var/honkooldown = 0
@@ -566,16 +575,17 @@
id = "runic golem"
limbs_id = "cultgolem"
sexes = FALSE
info_text = "As a <span class='danger'>Runic Golem</span>, you possess eldritch powers granted by the Elder God Nar'Sie."
info_text = "As a <span class='danger'>Runic Golem</span>, you possess eldritch powers granted by the Elder Goddess Nar'Sie."
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES) //no mutcolors
prefix = "Runic"
special_names = null
var/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/golem/phase_shift
var/obj/effect/proc_holder/spell/targeted/abyssal_gaze/abyssal_gaze
var/obj/effect/proc_holder/spell/targeted/dominate/dominate
/datum/species/golem/runic/random_name(gender,unique,lastname)
var/edgy_first_name = pick("Razor","Blood","Dark","Evil","Cold","Pale","Black","Silent","Chaos","Deadly")
var/edgy_first_name = pick("Razor","Blood","Dark","Evil","Cold","Pale","Black","Silent","Chaos","Deadly","Coldsteel")
var/edgy_last_name = pick("Edge","Night","Death","Razor","Blade","Steel","Calamity","Twilight","Shadow","Nightmare") //dammit Razor Razor
var/golem_name = "[edgy_first_name] [edgy_last_name]"
return golem_name
@@ -619,8 +629,7 @@
id = "clockwork golem"
say_mod = "clicks"
limbs_id = "clockgolem"
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>clockwork golem</span><span class='bold alloy'>, you are faster than \
other types of golem (being a machine), and are immune to electric shocks.</span>"
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>Clockwork Golem</span><span class='bold alloy'>, you are faster than other types of golems. On death, you will break down into scrap.</span>"
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES)
inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID)
armor = 20 //Reinforced, but much less so to allow for fast movement
@@ -628,9 +637,9 @@
attack_sound = 'sound/magic/clockwork/anima_fragment_attack.ogg'
sexes = FALSE
speedmod = 0
siemens_coeff = 0
damage_overlay_type = "synth"
prefix = "Clockwork"
special_names = list("Remnant", "Relic", "Scrap", "Vestige") //RIP Ratvar
var/has_corpse
/datum/species/golem/clockwork/on_species_gain(mob/living/carbon/human/H)
@@ -666,14 +675,15 @@
blacklisted = TRUE
dangerous_existence = TRUE
random_eligible = FALSE
info_text = "<span class='bold alloy'>As a </span><span class='bold brass'>Clockwork Golem Servant</span><span class='bold alloy'>, you are faster than other types of golems.</span>" //warcult golems leave a corpse
/datum/species/golem/cloth
name = "Cloth Golem"
id = "cloth golem"
limbs_id = "clothgolem"
sexes = FALSE
info_text = "As a <span class='danger'>Cloth Golem</span>, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable."
info_text = "As a <span class='danger'>Cloth Golem</span>, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable. \
Being made of cloth, your body is magic resistant and faster than that of other golems, but weaker and less resilient."
species_traits = list(NOBLOOD,NO_UNDERWEAR) //no mutcolors, and can burn
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOGUNS)
inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
@@ -684,6 +694,7 @@
punchstunthreshold = 7
punchdamagehigh = 8 // not as heavy as stone
prefix = "Cloth"
special_names = null
/datum/species/golem/cloth/on_species_gain(mob/living/carbon/C, datum/species/old_species)
..()
@@ -734,6 +745,7 @@
var/mob/living/carbon/human/cloth_golem
/obj/structure/cloth_pile/Initialize(mapload, mob/living/carbon/human/H)
. = ..()
if(!QDELETED(H) && is_species(H, /datum/species/golem/cloth))
H.unequip_everything()
H.forceMove(src)
@@ -781,11 +793,12 @@
fire_act()
/datum/species/golem/plastic
name = "Plastic"
name = "Plastic Golem"
id = "plastic golem"
prefix = "Plastic"
special_names = null
fixed_mut_color = "fff"
info_text = "As a <span class='danger'>Plastic Golem</span>, you are capable of ventcrawling, and passing through plastic flaps."
info_text = "As a <span class='danger'>Plastic Golem</span>, you are capable of ventcrawling and passing through plastic flaps as long as you are naked."
/datum/species/golem/plastic/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -10,23 +10,32 @@
disliked_food = GROSS | RAW
liked_food = JUNKFOOD | FRIED
/datum/species/human/qualifies_for_rank(rank, list/features)
return TRUE //Pure humans are always allowed in all roles.
//Curiosity killed the cat's wagging tail.
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
stop_wagging_tail(H)
/datum/species/human/spec_stun(mob/living/carbon/human/H,amount)
if(H)
H.endTailWag()
stop_wagging_tail(H)
. = ..()
/datum/species/human/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
if(H.dna.features["ears"] == "Cat")
mutantears = /obj/item/organ/ears/cat
if(H.dna.features["tail_human"] == "Cat")
mutanttail = /obj/item/organ/tail/cat
..()
/datum/species/human/can_wag_tail(mob/living/carbon/human/H)
return ("mam_tail" in mutant_bodyparts) || ("mam_waggingtail" in mutant_bodyparts)
/datum/species/human/is_wagging_tail(mob/living/carbon/human/H)
return ("mam_waggingtail" in mutant_bodyparts)
/datum/species/human/start_wagging_tail(mob/living/carbon/human/H)
if("tail_human" in mutant_bodyparts)
mutant_bodyparts -= "mam_tail"
mutant_bodyparts |= "mam_waggingtail"
H.update_body()
/datum/species/human/stop_wagging_tail(mob/living/carbon/human/H)
if("mam_waggingtail" in mutant_bodyparts)
mutant_bodyparts -= "mam_waggingtail"
mutant_bodyparts |= "mam_tail"
H.update_body()
@@ -5,9 +5,9 @@
default_color = "00FF90"
say_mod = "chirps"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,NOBLOOD)
inherent_traits = list(TRAIT_TOXINLOVER)
mutant_bodyparts = list("mam_tail", "mam_ears", "taur") //CIT CHANGE
default_features = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None") //CIT CHANGE
inherent_traits = list(TRAIT_TOXINLOVER)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
exotic_blood = "slimejelly"
damage_overlay_type = ""
@@ -64,7 +64,7 @@
if(!limbs_to_consume.len)
H.losebreath++
return
if(H.get_num_legs()) //Legs go before arms
if(H.get_num_legs(FALSE)) //Legs go before arms
limbs_to_consume -= list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM)
consumed_limb = H.get_bodypart(pick(limbs_to_consume))
consumed_limb.drop_limb()
@@ -647,7 +647,7 @@
if(message)
var/msg = "<i><font color=#008CA2>\[[species.slimelink_owner.real_name]'s Slime Link\] <b>[H]:</b> [message]</font></i>"
log_talk(H,"SlimeLink: [key_name(H)] : [msg]",LOGSAY)
log_directed_talk(H, species.slimelink_owner, msg, LOG_SAY, "slime link")
for(var/X in species.linked_mobs)
var/mob/living/M = X
if(QDELETED(M) || M.stat == DEAD)
@@ -684,7 +684,7 @@
var/msg = sanitize(input("Message:", "Telepathy") as text|null)
if(msg)
log_talk(H,"SlimeTelepathy: [key_name(H)]->[key_name(M)] : [msg]",LOGSAY)
log_directed_talk(H, M, msg, LOG_SAY, "slime telepathy")
to_chat(M, "<span class='notice'>You hear an alien voice in your head... </span><font color=#008CA2>[msg]</font>")
to_chat(H, "<span class='notice'>You telepathically said: \"[msg]\" to [M]</span>")
for(var/dead in GLOB.dead_mob_list)
@@ -37,17 +37,39 @@
/datum/species/lizard/qualifies_for_rank(rank, list/features)
return TRUE
//I wag in death
/datum/species/lizard/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
stop_wagging_tail(H)
/datum/species/lizard/spec_stun(mob/living/carbon/human/H,amount)
if(H)
H.endTailWag()
stop_wagging_tail(H)
. = ..()
/datum/species/lizard/can_wag_tail(mob/living/carbon/human/H)
return ("tail_lizard" in mutant_bodyparts) || ("waggingtail_lizard" in mutant_bodyparts)
/datum/species/lizard/is_wagging_tail(mob/living/carbon/human/H)
return ("waggingtail_lizard" in mutant_bodyparts)
/datum/species/lizard/start_wagging_tail(mob/living/carbon/human/H)
if("tail_lizard" in mutant_bodyparts)
mutant_bodyparts -= "tail_lizard"
mutant_bodyparts -= "spines"
mutant_bodyparts |= "waggingtail_lizard"
mutant_bodyparts |= "waggingspines"
H.update_body()
/datum/species/lizard/stop_wagging_tail(mob/living/carbon/human/H)
if("waggingtail_lizard" in mutant_bodyparts)
mutant_bodyparts -= "waggingtail_lizard"
mutant_bodyparts -= "waggingspines"
mutant_bodyparts |= "tail_lizard"
mutant_bodyparts |= "spines"
H.update_body()
/*
Lizard subspecies: ASHWALKERS
*/
@@ -1,5 +1,5 @@
/datum/species/moth
name = "Mothmen"
name = "Mothman"
id = "moth"
say_mod = "flutters"
default_color = "00FF00"
@@ -180,6 +180,7 @@
AddComponent(/datum/component/butchering, 80, 70)
/obj/item/light_eater/afterattack(atom/movable/AM, mob/user, proximity)
. = ..()
if(!proximity)
return
if(isopenturf(AM)) //So you can actually melee with it
@@ -7,7 +7,7 @@
sexes = 0
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
species_traits = list(NOBLOOD)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH)
inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
mutanttongue = /obj/item/organ/tongue/bone
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
@@ -1,5 +1,5 @@
/datum/species/vampire
name = "vampire"
name = "Vampire"
id = "vampire"
default_color = "FFFFFF"
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD)
@@ -2,14 +2,14 @@
/datum/species/zombie
// 1spooky
name = "High Functioning Zombie"
name = "High-Functioning Zombie"
id = "zombie"
say_mod = "moans"
sexes = 0
blacklisted = 1
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH)
inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
mutanttongue = /obj/item/organ/tongue/zombie
var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
@@ -29,6 +29,7 @@
armor = 20 // 120 damage to KO a zombie, which kills it
speedmod = 1.6
mutanteyes = /obj/item/organ/eyes/night_vision/zombie
var/heal_rate = 1
var/regen_cooldown = 0
/datum/species/zombie/infectious/check_roundstart_eligible()
@@ -46,15 +47,25 @@
/datum/species/zombie/infectious/spec_life(mob/living/carbon/C)
. = ..()
C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
//Zombies never actually die, they just fall down until they regenerate enough to rise back up.
//They must be restrained, beheaded or gibbed to stop being a threat.
if(regen_cooldown < world.time)
C.heal_overall_damage(4,4)
C.adjustToxLoss(-4)
if(prob(4))
var/heal_amt = heal_rate
if(C.InCritical())
heal_amt *= 2
C.heal_overall_damage(heal_amt,heal_amt)
C.adjustToxLoss(-heal_amt)
if(!C.InCritical() && prob(4))
playsound(C, pick(spooks), 50, TRUE, 10)
if(C.InCritical())
C.death()
// Zombies only move around when not in crit, they instantly
// succumb otherwise, and will standup again soon
//Congrats you somehow died so hard you stopped being a zombie
/datum/species/zombie/infectious/spec_death(mob/living/carbon/C)
. = ..()
var/obj/item/organ/zombie_infection/infection
infection = C.getorganslot(ORGAN_SLOT_ZOMBIE)
if(infection)
qdel(infection)
/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
+113 -12
View File
@@ -11,9 +11,20 @@
if(stat != DEAD) //Reagent processing needs to come before breathing, to prevent edge cases.
handle_organs()
if(..()) //not dead
. = ..()
if (QDELETED(src))
return
if(.) //not dead
handle_blood()
if(stat != DEAD)
var/bprv = handle_bodyparts()
if(bprv & BODYPART_LIFE_UPDATE_HEALTH)
updatehealth()
update_stamina()
if(stat != DEAD)
handle_brain_damage()
@@ -22,6 +33,7 @@
if(stat == DEAD)
stop_sound_channel(CHANNEL_HEARTBEAT)
rot()
//Updates the number of stored chemicals for powers
handle_changeling()
@@ -52,7 +64,7 @@
return
if(ismob(loc))
return
if(istype(loc, /obj/belly))
if(isbelly(loc))
return
var/datum/gas_mixture/environment
@@ -65,7 +77,7 @@
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL))
losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath
else if(health <= HEALTH_THRESHOLD_CRIT)
else if(health <= crit_threshold)
losebreath += 0.25 //You're having trouble breathing in soft crit, so you'll miss a breath one in four times
//Suffocate
@@ -160,7 +172,7 @@
else //Enough oxygen
failed_last_breath = 0
if(health >= HEALTH_THRESHOLD_CRIT)
if(health >= crit_threshold)
adjustOxyLoss(-5)
oxygen_used = breath_gases[/datum/gas/oxygen][MOLES]
clear_alert("not_enough_oxy")
@@ -210,15 +222,59 @@
hallucination += 10
else if(bz_partialpressure > 0.01)
hallucination += 5
//TRITIUM
if(breath_gases[/datum/gas/tritium])
var/tritium_partialpressure = (breath_gases[/datum/gas/tritium][MOLES]/breath.total_moles())*breath_pressure
radiation += tritium_partialpressure/10
//NITRYL
if (breath_gases[/datum/gas/nitryl])
if(breath_gases[/datum/gas/nitryl])
var/nitryl_partialpressure = (breath_gases[/datum/gas/nitryl][MOLES]/breath.total_moles())*breath_pressure
adjustFireLoss(nitryl_partialpressure/4)
//MIASMA
if(breath_gases[/datum/gas/miasma])
var/miasma_partialpressure = (breath_gases[/datum/gas/miasma][MOLES]/breath.total_moles())*breath_pressure
if(prob(1 * miasma_partialpressure))
var/datum/disease/advance/miasma_disease = new /datum/disease/advance/random(2,3)
miasma_disease.name = "Unknown"
ForceContractDisease(miasma_disease, TRUE, TRUE)
//Miasma side effects
switch(miasma_partialpressure)
if(1 to 5)
// At lower pp, give out a little warning
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
if(prob(5))
to_chat(src, "<span class='notice'>There is an unpleasant smell in the air.</span>")
if(5 to 20)
//At somewhat higher pp, warning becomes more obvious
if(prob(15))
to_chat(src, "<span class='warning'>You smell something horribly decayed inside this room.</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/bad_smell)
if(15 to 30)
//Small chance to vomit. By now, people have internals on anyway
if(prob(5))
to_chat(src, "<span class='warning'>The stench of rotting carcasses is unbearable!</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
vomit()
if(30 to INFINITY)
//Higher chance to vomit. Let the horror start
if(prob(25))
to_chat(src, "<span class='warning'>The stench of rotting carcasses is unbearable!</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "smell", /datum/mood_event/disgust/nauseating_stench)
vomit()
else
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
//Clear all moods if no miasma at all
else
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "smell")
breath.garbage_collect()
@@ -246,9 +302,46 @@
if(!.)
return FALSE //to differentiate between no internals and active, but empty internals
// Make corpses rot, emitting miasma
/mob/living/carbon/proc/rot()
// Properly stored corpses shouldn't create miasma
if(istype(loc, /obj/structure/closet/crate/coffin)|| istype(loc, /obj/structure/closet/body_bag) || istype(loc, /obj/structure/bodycontainer))
return
// No decay if formaldehyde in corpse or when the corpse is charred
if(reagents.has_reagent("formaldehyde", 15) || has_trait(TRAIT_HUSK))
return
// Also no decay if corpse chilled or not organic/undead
if(bodytemperature <= T0C-10 || (!(MOB_ORGANIC in mob_biotypes) && !(MOB_UNDEAD in mob_biotypes)))
return
// Wait a bit before decaying
if(world.time - timeofdeath < 1200)
return
var/deceasedturf = get_turf(src)
// Closed turfs don't have any air in them, so no gas building up
if(!istype(deceasedturf,/turf/open))
return
var/turf/open/miasma_turf = deceasedturf
var/list/cached_gases = miasma_turf.air.gases
ASSERT_GAS(/datum/gas/miasma, miasma_turf.air)
cached_gases[/datum/gas/miasma][MOLES] += 0.02
/mob/living/carbon/proc/handle_blood()
return
/mob/living/carbon/proc/handle_bodyparts()
for(var/I in bodyparts)
var/obj/item/bodypart/BP = I
if(BP.needs_processing)
. |= BP.on_life()
/mob/living/carbon/proc/handle_organs()
for(var/V in internal_organs)
var/obj/item/organ/O = V
@@ -437,6 +530,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
if(drunkenness)
drunkenness = max(drunkenness - (drunkenness * 0.04), 0)
if(drunkenness >= 6)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "drunk", /datum/mood_event/drunk)
if(prob(25))
slurring += 2
jitteriness = max(jitteriness - 3, 0)
@@ -457,12 +551,12 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
else
ballmer_percent = (-abs(drunkenness - 13.35) / 0.9) + 1
if(prob(5))
say(pick(GLOB.ballmer_good_msg))
say(pick(GLOB.ballmer_good_msg), forced = "ballmer")
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = BALLMER_POINTS * ballmer_percent))
if(drunkenness > 26) // by this point you're into windows ME territory
if(prob(5))
SSresearch.science_tech.remove_point_list(list(TECHWEB_POINT_TYPE_GENERIC = BALLMER_POINTS))
say(pick(GLOB.ballmer_windows_me_msg))
say(pick(GLOB.ballmer_windows_me_msg), forced = "ballmer")
if(drunkenness >= 41)
if(prob(25))
@@ -551,9 +645,9 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
reagents.metabolize(src, can_overdose=FALSE, liverless = TRUE)
if(has_trait(TRAIT_STABLEHEART))
return
adjustToxLoss(8, TRUE, TRUE)
adjustToxLoss(4, TRUE, TRUE)
if(prob(30))
to_chat(src, "<span class='notice'>You feel confused and nauseated...</span>")//actual symptoms of liver failure
to_chat(src, "<span class='warning'>You feel a stabbing pain in your abdomen!</span>")
////////////////
@@ -577,19 +671,26 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
/////////////////////////////////////
/mob/living/carbon/proc/can_heartattack()
if(dna && dna.species && (NOBLOOD in dna.species.species_traits)) //not all carbons have species!
if(!needs_heart())
return FALSE
var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART)
if(!heart || heart.synthetic)
return FALSE
return TRUE
/mob/living/carbon/proc/undergoing_cardiac_arrest()
if(!can_heartattack())
/mob/living/carbon/proc/needs_heart()
if(has_trait(TRAIT_STABLEHEART))
return FALSE
if(dna && dna.species && (NOBLOOD in dna.species.species_traits)) //not all carbons have species!
return FALSE
return TRUE
/mob/living/carbon/proc/undergoing_cardiac_arrest()
var/obj/item/organ/heart/heart = getorganslot(ORGAN_SLOT_HEART)
if(istype(heart) && heart.beating)
return FALSE
else if(!needs_heart())
return FALSE
return TRUE
/mob/living/carbon/proc/set_heartattack(status)
@@ -56,7 +56,7 @@
return 1
if(IsUnconscious())
return 1
if(IsStun())
if(IsStun() || IsKnockdown())
return 1
if(stat)
return 1
@@ -397,7 +397,7 @@
/mob/living/carbon/monkey/bullet_act(obj/item/projectile/Proj)
if(istype(Proj , /obj/item/projectile/beam)||istype(Proj, /obj/item/projectile/bullet))
if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
if(!Proj.nodamage && Proj.damage < src.health)
if(!Proj.nodamage && Proj.damage < src.health && isliving(Proj.firer))
retaliate(Proj.firer)
..()
@@ -12,8 +12,8 @@
if(..())
if(!client)
if(stat == CONSCIOUS)
if(on_fire || buckled || restrained() || (resting && canmove)) //CIT CHANGE - makes it so monkeys attempt to resist if they're resting
if(stat == CONSCIOUS)
if(on_fire || buckled || restrained() || (resting && canmove)) //CIT CHANGE - makes it so monkeys attempt to resist if they're resting)
if(!resisting && prob(MONKEY_RESIST_PROB))
resisting = TRUE
walk_to(src,0)
+21 -18
View File
@@ -14,8 +14,7 @@
unique_name = TRUE
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
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
verbs += /mob/living/proc/mob_sleep
@@ -27,7 +26,6 @@
//initialize limbs
create_bodyparts()
create_internal_organs()
. = ..()
@@ -59,26 +57,31 @@
internal_organs += new /obj/item/organ/stomach
..()
/mob/living/carbon/monkey/movement_delay()
if(reagents)
if(reagents.has_reagent("morphine"))
return -1
if(reagents.has_reagent("nuka_cola"))
return -1
/mob/living/carbon/monkey/on_reagent_change()
. = ..()
remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE)
var/amount
if(reagents.has_reagent("morphine"))
amount = -1
if(reagents.has_reagent("nuka_cola"))
amount = -1
if(amount)
add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
/mob/living/carbon/monkey/updatehealth()
. = ..()
var/slow = 0
var/health_deficiency = (100 - health)
if(health_deficiency >= 45)
. += (health_deficiency / 25)
slow += (health_deficiency / 25)
add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow)
/mob/living/carbon/monkey/adjust_bodytemperature(amount)
. = ..()
var/slow = 0
if (bodytemperature < 283.222)
. += (283.222 - bodytemperature) / 10 * 1.75
var/static/config_monkey_delay
if(isnull(config_monkey_delay))
config_monkey_delay = CONFIG_GET(number/monkey_delay)
. += config_monkey_delay
slow += (283.222 - bodytemperature) / 10 * 1.75
add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
/mob/living/carbon/monkey/Stat()
..()
@@ -54,7 +54,7 @@
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
apply_damage(damage, BRUTE, affecting)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
@@ -66,7 +66,7 @@
if (prob(25))
Knockdown(40)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
add_logs(M, src, "pushed")
log_combat(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>", null, COMBAT_MESSAGE_RANGE)
else if(dropItemToGround(get_active_held_item()))
@@ -90,7 +90,7 @@
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
@@ -115,7 +115,7 @@
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
I = null
add_logs(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
updatehealth()
+1 -1
View File
@@ -45,4 +45,4 @@
return
for(var/T in get_traumas())
var/datum/brain_trauma/trauma = T
message = trauma.on_hear(message, speaker, message_language, raw_message, radio_freq)
message = trauma.on_hear(message, speaker, message_language, raw_message, radio_freq)
@@ -45,7 +45,7 @@
if(druggy)
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/drugs/high)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/high)
else
clear_fullscreen("high")
clear_alert("high")
+6 -3
View File
@@ -26,14 +26,14 @@
/mob/living/proc/spread_bodyparts()
return
/mob/living/dust(just_ash = FALSE, drop_items = FALSE)
/mob/living/dust(just_ash, drop_items, force)
death(TRUE)
if(drop_items)
unequip_everything()
if(buckled)
buckled.unbuckle_mob(src,force=1)
buckled.unbuckle_mob(src, force = TRUE)
dust_animation()
spawn_dust(just_ash)
@@ -74,9 +74,12 @@
update_canmove()
med_hud_set_health()
med_hud_set_status()
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
if(!gibbed && !QDELETED(src))
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
stop_pulling()
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
if (client)
client.move_delay = initial(client.move_delay)
+2 -2
View File
@@ -1,7 +1,7 @@
/* EMOTE DATUMS */
/datum/emote/living
mob_type_allowed_typecache = list(/mob/living)
mob_type_allowed_typecache = /mob/living
mob_type_blacklist_typecache = list(/mob/living/simple_animal/slime, /mob/living/brain)
/datum/emote/living/blush
@@ -60,7 +60,7 @@
/datum/emote/living/cough/can_run_emote(mob/user, status_check = TRUE)
. = ..()
if(user.reagents.get_reagent("menthol") || user.reagents.get_reagent("peppermint_patty"))
if(user.reagents && (user.reagents.get_reagent("menthol") || user.reagents.get_reagent("peppermint_patty")))
return FALSE
/datum/emote/living/dance
+4 -1
View File
@@ -43,7 +43,10 @@
//Breathing, if applicable
handle_breathing(times_fired)
handle_diseases() // DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not.
handle_diseases()// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not.
if (QDELETED(src)) // diseases can qdel the mob via transformations
return
if(stat != DEAD)
//Random events (vomiting etc)
+41 -49
View File
@@ -9,6 +9,10 @@
diag_hud.add_to_hud(src)
faction += "[REF(src)]"
GLOB.mob_living_list += src
initialize_footstep()
/mob/living/proc/initialize_footstep()
AddComponent(/datum/component/footstep)
/mob/living/prepare_huds()
..()
@@ -39,31 +43,31 @@
/mob/living/proc/OpenCraftingMenu()
return
//Generic Collide(). Override MobCollide() and ObjCollide() instead of this.
/mob/living/Collide(atom/A)
//Generic Bump(). Override MobBump() and ObjBump() instead of this.
/mob/living/Bump(atom/A)
if(..()) //we are thrown onto something
return
if (buckled || now_pushing)
return
if(ismob(A))
var/mob/M = A
if(MobCollide(M))
if(MobBump(M))
return
if(isobj(A))
var/obj/O = A
if(ObjCollide(O))
if(ObjBump(O))
return
if(ismovableatom(A))
var/atom/movable/AM = A
if(PushAM(AM))
return
/mob/living/CollidedWith(atom/movable/AM)
/mob/living/Bumped(atom/movable/AM)
..()
last_bumped = world.time
//Called when we bump onto a mob
/mob/living/proc/MobCollide(mob/M)
/mob/living/proc/MobBump(mob/M)
//Even if we don't push/swap places, we "touched" them, so spread fire
spreadFire(M)
@@ -96,6 +100,7 @@
if(!(world.time % 5))
to_chat(src, "<span class='warning'>[L] is restraining [P], you cannot push past.</span>")
return 1
//CIT CHANGES START HERE - makes it so resting stops you from moving through standing folks without a short delay
if(resting && !L.resting)
if(attemptingcrawl)
@@ -116,6 +121,7 @@
attemptingcrawl = FALSE
return TRUE
//END OF CIT CHANGES
if(moving_diagonally)//no mob swap during diagonal moves.
return 1
@@ -170,8 +176,24 @@
if(prob(I.block_chance*2))
return 1
/mob/living/get_photo_description(obj/item/camera/camera)
var/list/mob_details = list()
var/list/holding = list()
var/len = length(held_items)
if(len)
for(var/obj/item/I in held_items)
if(!holding.len)
holding += "They are holding \a [I]"
else if(held_items.Find(I) == len)
holding += ", and \a [I]."
else
holding += ", \a [I]"
holding += "."
mob_details += "You can also see [src] on the photo[health < (maxHealth * 0.75) ? ", looking a bit hurt":""][holding ? ". [holding.Join("")]":"."]."
return mob_details.Join("")
//Called when we bump onto an obj
/mob/living/proc/ObjCollide(obj/O)
/mob/living/proc/ObjBump(obj/O)
return
//Called when we want to push an atom/movable
@@ -223,7 +245,7 @@
if(AM.pulledby)
if(!supress_message)
visible_message("<span class='danger'>[src] has pulled [AM] from [AM.pulledby]'s grip.</span>")
add_logs(AM, AM.pulledby, "pulled from", src)
log_combat(AM, AM.pulledby, "pulled from", src)
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
@@ -235,7 +257,7 @@
if(ismob(AM))
var/mob/M = AM
add_logs(src, M, "grabbed", addition="passive grab")
log_combat(src, M, "grabbed", addition="passive grab")
if(!supress_message)
visible_message("<span class='warning'>[src] has grabbed [M][(zone_selected == "l_arm" || zone_selected == "r_arm")? " by their hands":" passively"]!</span>") //Cit change - And they thought ERP was bad.
if(!iscarbon(src))
@@ -279,7 +301,7 @@
/mob/living/pointed(atom/A as mob|obj|turf in view())
if(incapacitated())
return FALSE
if(has_trait(TRAIT_FAKEDEATH))
if(has_trait(TRAIT_DEATHCOMA))
return FALSE
if(!..())
return FALSE
@@ -289,7 +311,7 @@
/mob/living/verb/succumb(whispered as null)
set hidden = TRUE
if (InCritical())
log_message("Has [whispered ? "whispered his final words" : "succumbed to death"] while in [InFullCritical() ? "hard":"soft"] critical with [round(health, 0.1)] points of health!", INDIVIDUAL_ATTACK_LOG)
log_message("Has [whispered ? "whispered his final words" : "succumbed to death"] while in [InFullCritical() ? "hard":"soft"] critical with [round(health, 0.1)] points of health!", LOG_ATTACK)
adjustOxyLoss(health - HEALTH_THRESHOLD_DEAD)
updatehealth()
if(!whispered)
@@ -301,7 +323,7 @@
return TRUE
/mob/living/proc/InCritical()
return (health <= HEALTH_THRESHOLD_CRIT && (stat == SOFT_CRIT || stat == UNCONSCIOUS))
return (health <= crit_threshold && (stat == SOFT_CRIT || stat == UNCONSCIOUS))
/mob/living/proc/InFullCritical()
return (health <= HEALTH_THRESHOLD_FULLCRIT && stat == UNCONSCIOUS)
@@ -363,6 +385,7 @@
to_chat(src, "<span class='notice'>You are now [resting ? "resting" : "getting up"].</span>")
update_canmove()
*/
//Recursive function to find everything a mob is holding. Really shitty proc tbh.
/mob/living/get_contents()
var/list/ret = list()
@@ -487,27 +510,6 @@
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
/mob/living/movement_delay(ignorewalk = 0)
. = 0
if(isopenturf(loc) && !is_flying())
var/turf/open/T = loc
. += T.slowdown
var/static/datum/config_entry/number/run_delay/config_run_delay
var/static/datum/config_entry/number/walk_delay/config_walk_delay
if(isnull(config_run_delay))
config_run_delay = CONFIG_GET(number/run_delay)
config_walk_delay = CONFIG_GET(number/walk_delay)
if(ignorewalk)
. += config_run_delay.value_cache
else
switch(m_intent)
if(MOVE_INTENT_RUN)
if(drowsyness > 0)
. += 6
. += config_run_delay.value_cache
if(MOVE_INTENT_WALK)
. += config_walk_delay.value_cache
/mob/living/proc/makeTrail(turf/target_turf, turf/start, direction)
if(!has_gravity())
return
@@ -594,8 +596,8 @@
//resisting grabs (as if it helps anyone...)
if(!restrained(ignore_grab = 1) && pulledby)
visible_message("<span class='danger'>[src] resists against [pulledby]'s grip!</span>")
log_combat(src, pulledby, "resisted grab")
resist_grab()
add_logs(pulledby, src, "resisted grab")
return
//unbuckling yourself
@@ -631,7 +633,7 @@
if(pulledby.grab_state)
if(prob(30/pulledby.grab_state))
visible_message("<span class='danger'>[src] has broken free of [pulledby]'s grip!</span>")
add_logs(pulledby, src, "broke grab")
log_combat(pulledby, src, "broke grab")
pulledby.stop_pulling()
return 0
if(moving_resist && client) //we resisted by trying to move
@@ -698,10 +700,10 @@
var/list/L = where
if(what == who.get_item_for_held_index(L[2]))
if(who.dropItemToGround(what))
add_logs(src, who, "stripped [what] off")
log_combat(src, who, "stripped [what] off")
if(what == who.get_item_by_slot(where))
if(who.dropItemToGround(what))
add_logs(src, who, "stripped [what] off")
log_combat(src, who, "stripped [what] off")
// The src mob is trying to place an item on someone
// Override if a certain mob should be behave differently when placing items (can't, for example)
@@ -822,16 +824,6 @@
/mob/living/proc/update_stamina()
return
/*
/mob/living/carbon/update_stamina()
var/stam = getStaminaLoss()
if(stam)
var/total_health = (health - stam)
if(total_health <= HEALTH_THRESHOLD_CRIT && !stat)
to_chat(src, "<span class='notice'>You're too exhausted to keep going...</span>")
Knockdown(100)
setStaminaLoss(health - 2, FALSE, FALSE)
update_health_hud() */ //CITADEL OVERRIDE
/mob/living/carbon/alien/update_stamina()
return
@@ -944,7 +936,7 @@
ExtinguishMob()
//Share fire evenly between the two mobs
//Called in MobCollide() and Crossed()
//Called in MobBump() and Crossed()
/mob/living/proc/spreadFire(mob/living/L)
if(!istype(L))
return
@@ -986,7 +978,7 @@
//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it.
//Robots, animals and brains have their own version so don't worry about them
/mob/living/proc/update_canmove()
var/ko = IsKnockdown() || IsUnconscious() || (stat && (stat != SOFT_CRIT || pulledby)) || (has_trait(TRAIT_FAKEDEATH))
var/ko = IsKnockdown() || IsUnconscious() || (stat && (stat != SOFT_CRIT || pulledby)) || (has_trait(TRAIT_DEATHCOMA))
var/move_and_fall = stat == SOFT_CRIT && !pulledby
var/chokehold = pulledby && pulledby.grab_state >= GRAB_NECK
var/buckle_lying = !(buckled && !buckled.buckle_lying)
+18 -14
View File
@@ -88,7 +88,7 @@
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor)
if(I.thrownby)
add_logs(I.thrownby, src, "threw and hit", I)
log_combat(I.thrownby, src, "threw and hit", I)
else
return 1
else
@@ -116,10 +116,10 @@
updatehealth()
visible_message("<span class='danger'>[M.name] has hit [src]!</span>", \
"<span class='userdanger'>[M.name] has hit [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
log_combat(M.occupant, src, "attacked", M, "(INTENT: [uppertext(M.occupant.a_intent)]) (DAMTYPE: [uppertext(M.damtype)])")
else
step_away(src,M)
add_logs(M.occupant, src, "pushed", M)
log_combat(M.occupant, src, "pushed", M)
visible_message("<span class='warning'>[M] pushes [src] out of the way.</span>", null, null, 5)
/mob/living/fire_act()
@@ -144,17 +144,21 @@
grippedby(user)
//proc to upgrade a simple pull into a more aggressive grab.
/mob/living/proc/grippedby(mob/living/carbon/user)
/mob/living/proc/grippedby(mob/living/carbon/user, instant = FALSE)
if(user.grab_state < GRAB_KILL)
user.changeNext_move(CLICK_CD_GRABBING)
playsound(src.loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(user.grab_state) //only the first upgrade is instantaneous
var/old_grab_state = user.grab_state
var/grab_upgrade_time = 30
var/grab_upgrade_time = instant ? 0 : 30
visible_message("<span class='danger'>[user] starts to tighten [user.p_their()] grip on [src]!</span>", \
"<span class='userdanger'>[user] starts to tighten [user.p_their()] grip on you!</span>")
add_logs(user, src, "attempted to strangle", addition="grab")
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
log_combat(user, src, "attempted to neck grab", addition="neck grab")
if(GRAB_NECK)
log_combat(user, src, "attempted to strangle", addition="kill grab")
if(!do_mob(user, src, grab_upgrade_time))
return 0
if(!user.pulling || user.pulling != src || user.grab_state != old_grab_state || user.a_intent != INTENT_GRAB)
@@ -162,20 +166,20 @@
user.grab_state++
switch(user.grab_state)
if(GRAB_AGGRESSIVE)
add_logs(user, src, "grabbed", addition="aggressive grab")
log_combat(user, src, "grabbed", addition="aggressive grab")
visible_message("<span class='danger'>[user] has grabbed [src] aggressively!</span>", \
"<span class='userdanger'>[user] has grabbed [src] aggressively!</span>")
drop_all_held_items()
stop_pulling()
if(GRAB_NECK)
add_logs(user, src, "grabbed", addition="neck grab")
log_combat(user, src, "grabbed", addition="neck grab")
visible_message("<span class='danger'>[user] has grabbed [src] by the neck!</span>",\
"<span class='userdanger'>[user] has grabbed you by the neck!</span>")
update_canmove() //we fall down
if(!buckled && !density)
Move(user.loc)
if(GRAB_KILL)
add_logs(user, src, "strangled", addition="grab")
log_combat(user, src, "strangled", addition="kill grab")
visible_message("<span class='danger'>[user] is strangling [src]!</span>", \
"<span class='userdanger'>[user] is strangling you!</span>")
update_canmove() //we fall down
@@ -199,7 +203,7 @@
return FALSE
if (stat != DEAD)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
M.do_attack_animation(src)
visible_message("<span class='danger'>The [M.name] glomps [src]!</span>", \
"<span class='userdanger'>The [M.name] glomps [src]!</span>", null, COMBAT_MESSAGE_RANGE)
@@ -220,7 +224,7 @@
M.do_attack_animation(src)
visible_message("<span class='danger'>\The [M] [M.attacktext] [src]!</span>", \
"<span class='userdanger'>\The [M] [M.attacktext] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
return TRUE
@@ -239,7 +243,7 @@
return FALSE
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
if (prob(75))
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M.name] bites [src]!</span>", \
"<span class='userdanger'>[M.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
@@ -262,7 +266,7 @@
L.do_attack_animation(src)
if(prob(90))
add_logs(L, src, "attacked")
log_combat(L, src, "attacked")
visible_message("<span class='danger'>[L.name] bites [src]!</span>", \
"<span class='userdanger'>[L.name] bites [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
@@ -335,7 +339,7 @@
return
if(is_servant_of_ratvar(src) && !stat)
to_chat(src, "<span class='userdanger'>You resist Nar-Sie's influence... but not all of it. <i>Run!</i></span>")
to_chat(src, "<span class='userdanger'>You resist Nar'Sie's influence... but not all of it. <i>Run!</i></span>")
adjustBruteLoss(35)
if(src && reagents)
reagents.add_reagent("heparin", 5)
+2 -2
View File
@@ -20,6 +20,7 @@
var/fireloss = 0 //Burn damage caused by being way too hot, too cold or burnt.
var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims
var/staminaloss = 0 //Stamina damage, or exhaustion. You recover it slowly naturally, and are knocked down if it gets too high. Holodeck and hallucinations deal this.
var/crit_threshold = HEALTH_THRESHOLD_CRIT // when the mob goes from "normal" to crit
var/confused = 0 //Makes the mob move in random directions.
@@ -38,7 +39,7 @@
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
var/now_pushing = null //used by living/Collide() and living/PushAM() to prevent potential infinite loop.
var/now_pushing = null //used by living/Bump() and living/PushAM() to prevent potential infinite loop.
var/cameraFollow = null
@@ -101,7 +102,6 @@
var/list/obj/effect/proc_holder/abilities = list()
var/registered_z
var/can_be_held = FALSE //whether this can be picked up and held.
var/radiation = 0 //If the mob is irradiated.
@@ -0,0 +1,27 @@
/mob/living/Moved()
. = ..()
update_turf_movespeed(loc)
/mob/living/toggle_move_intent()
. = ..()
update_move_intent_slowdown()
/mob/living/update_config_movespeed()
update_move_intent_slowdown()
return ..()
/mob/living/proc/update_move_intent_slowdown()
var/mod = 0
if(m_intent == MOVE_INTENT_WALK)
mod = CONFIG_GET(number/movedelay/walk_delay)
else
mod = CONFIG_GET(number/movedelay/run_delay)
if(!isnum(mod))
mod = 1
add_movespeed_modifier(MOVESPEED_ID_MOB_WALK_RUN_CONFIG_SPEED, TRUE, 100, override = TRUE, multiplicative_slowdown = mod)
/mob/living/proc/update_turf_movespeed(turf/open/T)
if(isopenturf(T) && !is_flying())
add_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = T.slowdown)
else
remove_movespeed_modifier(MOVESPEED_ID_LIVING_TURF_SPEEDMOD)
+18 -24
View File
@@ -60,29 +60,28 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
))
/mob/living/proc/Ellipsis(original_msg, chance = 50, keep_words)
if(chance <= 0)
return "..."
if(chance >= 100)
return original_msg
if(chance <= 0)
return "..."
if(chance >= 100)
return original_msg
var/list
words = splittext(original_msg," ")
new_words = list()
var/list/words = splittext(original_msg," ")
var/list/new_words = list()
var/new_msg = ""
var/new_msg = ""
for(var/w in words)
if(prob(chance))
new_words += "..."
if(!keep_words)
continue
new_words += w
for(var/w in words)
if(prob(chance))
new_words += "..."
if(!keep_words)
continue
new_words += w
new_msg = jointext(new_words," ")
new_msg = jointext(new_words," ")
return new_msg
return new_msg
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE)
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/talk_key = get_key(message)
@@ -164,7 +163,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
if((InCritical() && !fullcrit) || message_mode == MODE_WHISPER)
message_range = 1
message_mode = MODE_WHISPER
log_talk(src,"[key_name(src)] : [message]",LOGWHISPER)
src.log_talk(message, LOG_WHISPER)
if(fullcrit)
var/health_diff = round(-HEALTH_THRESHOLD_DEAD + health)
// If we cut our message short, abruptly end it with a-..
@@ -175,7 +174,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
message_mode = MODE_WHISPER_CRIT
succumbed = TRUE
else
log_talk(src,"[name]/[key] : [message]",LOGSAY)
src.log_talk(message, LOG_SAY, forced_by=forced)
message = treat_message(message)
if(!message)
@@ -187,9 +186,6 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/datum/language/L = GLOB.language_datum_instances[language]
spans |= L.spans
//Log what we've said with an associated timestamp, using the list's len for safety/to prevent overwriting messages
log_message(message, INDIVIDUAL_SAY_LOG)
var/radio_return = radio(message, message_mode, spans, language)
if(radio_return & ITALICS)
spans |= SPAN_ITALICS
@@ -242,11 +238,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
eavesdrop_range = EAVESDROP_EXTRA_RANGE
var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source)
var/list/the_dead = list()
var/list/yellareas //CIT CHANGE - adds the ability for yelling to penetrate walls and echo throughout areas
if(say_test(message) == "2") //CIT CHANGE - ditto
yellareas = get_areas_in_range(message_range*0.5,src) //CIT CHANGE - ditto
for(var/_M in GLOB.player_list)
var/mob/M = _M
if(M.stat != DEAD) //not dead, not important
+29 -15
View File
@@ -23,6 +23,7 @@
a_intent = INTENT_HARM //so we always get pushed instead of trying to swap
sight = SEE_TURFS | SEE_MOBS | SEE_OBJS
see_in_dark = 8
hud_type = /datum/hud/ai
med_hud = DATA_HUD_MEDICAL_BASIC
sec_hud = DATA_HUD_SECURITY_BASIC
d_hud = DATA_HUD_DIAGNOSTIC_ADVANCED
@@ -177,9 +178,11 @@
if(incapacitated())
return
var/icontype = input("Please, select a display!", "AI", null/*, null*/) in list("Clown", "Monochrome", "Blue", "Inverted", "Firewall", "Green", "Red", "Static", "Red October", "House", "Heartline", "Hades", "Helios", "President", "Syndicat Meow", "Alien", "Too Deep", "Triumvirate", "Triumvirate-M", "Text", "Matrix", "Dorf", "Bliss", "Not Malf", "Fuzzy", "Goon", "Database", "Glitchman", "Murica", "Nanotrasen", "Gentoo", "Angel", "TechDemon") //CIT CHANGE - adds 'TechDemon
var/icontype = input("Please, select a display!", "AI", null/*, null*/) in list("Clown", ":thinking:", "Monochrome", "Blue", "Inverted", "Firewall", "Green", "Red", "Static", "Red October", "House", "Heartline", "Hades", "Helios", "President", "Syndicat Meow", "Alien", "Too Deep", "Triumvirate", "Triumvirate-M", "Text", "Matrix", "Dorf", "Bliss", "Not Malf", "Fuzzy", "Goon", "Database", "Glitchman", "Murica", "Nanotrasen", "Gentoo", "Angel", "TechDemon") //CIT CHANGE - adds 'TechDemon
if(icontype == "Clown")
icon_state = "ai-clown2"
else if (icontype == ":thinking:")
icon_state = "ai-:thinking:"
else if(icontype == "Monochrome")
icon_state = "ai-mono"
else if(icontype == "Blue")
@@ -244,6 +247,7 @@
icon_state = "ai-angel"
else if(icontype == "TechDemon") //CIT CHANGE - adds 'TechDemon
icon_state = "ai-techdemon"
/mob/living/silicon/ai/Stat()
..()
if(statpanel("Status"))
@@ -328,7 +332,16 @@
/mob/living/silicon/ai/can_interact_with(atom/A)
. = ..()
return . || (istype(loc, /obj/item/aicard))? (ISINRANGE(A.x, x - interaction_range, x + interaction_range) && ISINRANGE(A.y, y - interaction_range, y + interaction_range)): GLOB.cameranet.checkTurfVis(get_turf(A))
if (.)
return
if (istype(loc, /obj/item/aicard))
var/turf/T0 = get_turf(src)
var/turf/T1 = get_turf(A)
if (!T0 || ! T1)
return FALSE
return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range)
else
return GLOB.cameranet.checkTurfVis(get_turf(A))
/mob/living/silicon/ai/cancel_camera()
view_core()
@@ -620,19 +633,20 @@
if(incapacitated())
return
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Thinking", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/M in GLOB.ai_status_displays) //change status of displays
if(istype(M, /obj/machinery/ai_status_display))
var/obj/machinery/ai_status_display/AISD = M
AISD.emotion = emote
//if Friend Computer, change ALL displays
else if(istype(M, /obj/machinery/status_display))
var/obj/machinery/status_display/SD = M
if(emote=="Friend Computer")
SD.friendc = 1
else
SD.friendc = 0
for (var/each in GLOB.ai_status_displays) //change status of displays
var/obj/machinery/status_display/ai/M = each
M.emotion = emote
M.update()
if (emote == "Friend Computer")
var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
if(!frequency)
return
var/datum/signal/status_signal = new(list("command" = "friendcomputer"))
frequency.post_signal(src, status_signal)
return
//I am the icon meister. Bow fefore me. //>fefore
@@ -1004,7 +1018,7 @@
target_ai = src //cheat! just give... ourselves as the spawned AI, because that's technically correct
/mob/living/silicon/ai/proc/camera_visibility(mob/camera/aiEye/moved_eye)
GLOB.cameranet.visibility(moved_eye, client, all_eyes)
GLOB.cameranet.visibility(moved_eye, client, all_eyes, USE_STATIC_OPAQUE)
/mob/living/silicon/ai/forceMove(atom/destination)
. = ..()
+9 -4
View File
@@ -25,11 +25,16 @@
spawn(10)
explosion(src.loc, 3, 6, 12, 15)
for(var/obj/machinery/ai_status_display/O in GLOB.ai_status_displays) //change status
if(src.key)
if(src.key)
for(var/each in GLOB.ai_status_displays) //change status
var/obj/machinery/status_display/ai/O = each
O.mode = 2
if(istype(loc, /obj/item/aicard))
loc.icon_state = "aicard-404"
O.update()
if(istype(loc, /obj/item/aicard/aitater))
loc.icon_state = "aitater-404"
else if(istype(loc, /obj/item/aicard))
loc.icon_state = "aicard-404"
/mob/living/silicon/ai/proc/ShutOffDoomsdayDevice()
if(nuking)
@@ -18,15 +18,24 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
// The object used for the clickable stat() button.
var/obj/effect/statclick/statclick
// The object used in vis_contents of obscured turfs
var/vis_contents
// The objects used in vis_contents of obscured turfs
var/list/vis_contents_objects
var/obj/effect/overlay/camera_static/vis_contents_opaque
var/obj/effect/overlay/camera_static/vis_contents_transparent
// The image given to the effect in vis_contents on AI clients
var/image/obscured
var/image/obscured_transparent
/datum/cameranet/New()
vis_contents = new /obj/effect/overlay/camera_static()
obscured = new('icons/effects/cameravis.dmi', vis_contents, null, BYOND_LIGHTING_LAYER + 0.1)
obscured.plane = BYOND_LIGHTING_PLANE + 1
vis_contents_opaque = new /obj/effect/overlay/camera_static()
vis_contents_transparent = new /obj/effect/overlay/camera_static/transparent()
vis_contents_objects = list(vis_contents_opaque, vis_contents_transparent)
obscured = new('icons/effects/cameravis.dmi', vis_contents_opaque, null, CAMERA_STATIC_LAYER)
obscured.plane = CAMERA_STATIC_PLANE
obscured_transparent = new('icons/effects/cameravis.dmi', vis_contents_transparent, null, CAMERA_STATIC_LAYER)
obscured_transparent.plane = CAMERA_STATIC_PLANE
// Checks if a chunk has been Generated in x, y, z.
/datum/cameranet/proc/chunkGenerated(x, y, z)
@@ -46,7 +55,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set.
/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes)
/datum/cameranet/proc/visibility(list/moved_eyes, client/C, list/other_eyes, use_static = USE_STATIC_OPAQUE)
if(!islist(moved_eyes))
moved_eyes = moved_eyes ? list(moved_eyes) : list()
if(islist(other_eyes))
@@ -54,33 +63,48 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
else
other_eyes = list()
if(C)
switch(use_static)
if(USE_STATIC_TRANSPARENT)
C.images += obscured_transparent
if(USE_STATIC_OPAQUE)
C.images += obscured
for(var/V in moved_eyes)
var/mob/camera/aiEye/eye = V
var/static_range = eye.static_visibility_range
var/x1 = max(0, eye.x - static_range) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, eye.y - static_range) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, eye.x + static_range) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, eye.y + static_range) & ~(CHUNK_SIZE - 1)
var/list/visibleChunks = list()
if(eye.loc)
// 0xf = 15
var/static_range = eye.static_visibility_range
var/x1 = max(0, eye.x - static_range) & ~(CHUNK_SIZE - 1)
var/y1 = max(0, eye.y - static_range) & ~(CHUNK_SIZE - 1)
var/x2 = min(world.maxx, eye.x + static_range) & ~(CHUNK_SIZE - 1)
var/y2 = min(world.maxy, eye.y + static_range) & ~(CHUNK_SIZE - 1)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
visibleChunks |= getCameraChunk(x, y, eye.z)
for(var/x = x1; x <= x2; x += CHUNK_SIZE)
for(var/y = y1; y <= y2; y += CHUNK_SIZE)
visibleChunks |= getCameraChunk(x, y, eye.z)
var/list/remove = eye.visibleCameraChunks - visibleChunks
var/list/add = visibleChunks - eye.visibleCameraChunks
for(var/chunk in remove)
var/datum/camerachunk/c = chunk
c.remove(eye)
c.remove(eye, FALSE)
for(var/chunk in add)
var/datum/camerachunk/c = chunk
c.add(eye)
if(C)
C.images += obscured
if(!eye.visibleCameraChunks.len)
var/client/client = eye.GetViewerClient()
if(client)
switch(eye.use_static)
if(USE_STATIC_TRANSPARENT)
client.images -= GLOB.cameranet.obscured_transparent
if(USE_STATIC_OPAQUE)
client.images -= GLOB.cameranet.obscured
// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open.
@@ -173,5 +197,8 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
mouse_opacity = MOUSE_OPACITY_ICON
invisibility = INVISIBILITY_ABSTRACT
layer = BYOND_LIGHTING_LAYER + 0.1
plane = BYOND_LIGHTING_PLANE + 1
layer = CAMERA_STATIC_LAYER
plane = CAMERA_STATIC_PLANE
/obj/effect/overlay/camera_static/transparent
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -26,9 +26,17 @@
// Remove an AI eye from the chunk, then update if changed.
/datum/camerachunk/proc/remove(mob/camera/aiEye/eye)
/datum/camerachunk/proc/remove(mob/camera/aiEye/eye, remove_static_with_last_chunk = TRUE)
eye.visibleCameraChunks -= src
seenby -= eye
if(remove_static_with_last_chunk && !eye.visibleCameraChunks.len)
var/client/client = eye.GetViewerClient()
if(client)
switch(eye.use_static)
if(USE_STATIC_TRANSPARENT)
client.images -= GLOB.cameranet.obscured_transparent
if(USE_STATIC_OPAQUE)
client.images -= GLOB.cameranet.obscured
// Called when a chunk has changed. I.E: A wall was deleted.
@@ -81,12 +89,12 @@
for(var/turf in visAdded)
var/turf/t = turf
t.vis_contents -= GLOB.cameranet.vis_contents
t.vis_contents -= GLOB.cameranet.vis_contents_objects
for(var/turf in visRemoved)
var/turf/t = turf
if(obscuredTurfs[t] && !istype(t, /turf/open/ai_visible))
t.vis_contents += GLOB.cameranet.vis_contents
t.vis_contents += GLOB.cameranet.vis_contents_objects
changed = 0
@@ -128,7 +136,7 @@
for(var/turf in obscuredTurfs)
var/turf/t = turf
t.vis_contents += GLOB.cameranet.vis_contents
t.vis_contents += GLOB.cameranet.vis_contents_objects
#undef UPDATE_BUFFER
#undef CHUNK_SIZE
@@ -7,28 +7,81 @@
name = "Inactive AI Eye"
invisibility = INVISIBILITY_MAXIMUM
hud_possible = list(ANTAG_HUD, AI_DETECT_HUD = HUD_LIST_LIST)
var/list/visibleCameraChunks = list()
var/mob/living/silicon/ai/ai = null
var/relay_speech = FALSE
var/use_static = TRUE
var/use_static = USE_STATIC_OPAQUE
var/static_visibility_range = 16
var/ai_detector_visible = TRUE
var/ai_detector_color = COLOR_RED
/mob/camera/aiEye/Initialize()
. = ..()
GLOB.aiEyes += src
update_ai_detect_hud()
setLoc(loc, TRUE)
/mob/camera/aiEye/proc/update_ai_detect_hud()
var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT]
var/list/old_images = hud_list[AI_DETECT_HUD]
if(!ai_detector_visible)
hud.remove_from_hud(src)
QDEL_LIST(old_images)
return
if(!hud.hudusers.len)
//no one is watching, do not bother updating anything
return
hud.remove_from_hud(src)
var/static/list/vis_contents_objects = list()
var/obj/effect/overlay/ai_detect_hud/hud_obj = vis_contents_objects[ai_detector_color]
if(!hud_obj)
hud_obj = new /obj/effect/overlay/ai_detect_hud()
hud_obj.color = ai_detector_color
vis_contents_objects[ai_detector_color] = hud_obj
var/list/new_images = list()
var/list/turfs = get_visible_turfs()
for(var/T in turfs)
var/image/I = (old_images.len > new_images.len) ? old_images[new_images.len + 1] : image(null, T)
I.loc = T
I.vis_contents += hud_obj
new_images += I
for(var/i in (new_images.len + 1) to old_images.len)
qdel(old_images[i])
hud_list[AI_DETECT_HUD] = new_images
hud.add_to_hud(src)
/mob/camera/aiEye/proc/get_visible_turfs()
if(!isturf(loc))
return list()
var/client/C = GetViewerClient()
var/view = C ? getviewsize(C.view) : getviewsize(world.view)
var/turf/lowerleft = locate(max(1, x - (view[1] - 1)/2), max(1, y - (view[2] - 1)/2), z)
var/turf/upperright = locate(min(world.maxx, lowerleft.x + (view[1] - 1)), min(world.maxy, lowerleft.y + (view[2] - 1)), lowerleft.z)
return block(lowerleft, upperright)
// Use this when setting the aiEye's location.
// It will also stream the chunk that the new loc is in.
/mob/camera/aiEye/proc/setLoc(T)
/mob/camera/aiEye/proc/setLoc(T, force_update = FALSE)
if(ai)
if(!isturf(ai.loc))
return
T = get_turf(T)
if(!force_update && (T == get_turf(src)) )
return //we are already here!
if (T)
forceMove(T)
else
moveToNullspace() // ????
if(use_static)
moveToNullspace()
if(use_static != USE_STATIC_NONE)
ai.camera_visibility(src)
if(ai.client && !ai.multicam_on)
ai.client.eye = src
update_ai_detect_hud()
update_parallax_contents()
//Holopad
if(istype(ai.current, /obj/machinery/holopad))
@@ -47,11 +100,6 @@
return ai.client
return null
/mob/camera/aiEye/proc/RemoveImages()
var/client/C = GetViewerClient()
if(C && use_static)
C.images -= GLOB.cameranet.obscured
/mob/camera/aiEye/Destroy()
if(ai)
ai.all_eyes -= src
@@ -59,6 +107,12 @@
for(var/V in visibleCameraChunks)
var/datum/camerachunk/c = V
c.remove(src)
GLOB.aiEyes -= src
if(ai_detector_visible)
var/datum/atom_hud/ai_detector/hud = GLOB.huds[DATA_HUD_AI_DETECT]
hud.remove_from_hud(src)
var/list/L = hud_list[AI_DETECT_HUD]
QDEL_LIST(L)
return ..()
/atom/proc/move_camera_by_click()
@@ -132,3 +186,12 @@
. = ..()
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker))
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
/obj/effect/overlay/ai_detect_hud
name = ""
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
icon = 'icons/effects/alphacolors.dmi'
icon_state = ""
alpha = 100
layer = ABOVE_ALL_MOB_LAYER
plane = GAME_PLANE
+3 -1
View File
@@ -1,9 +1,11 @@
/mob/living/silicon/ai/Login()
..()
if(stat != DEAD)
for(var/obj/machinery/ai_status_display/O in GLOB.ai_status_displays) //change status
for(var/each in GLOB.ai_status_displays) //change status
var/obj/machinery/status_display/ai/O = each
O.mode = 1
O.emotion = "Neutral"
O.update()
if(multicam_on)
end_multicam()
view_core()
+3 -1
View File
@@ -1,5 +1,7 @@
/mob/living/silicon/ai/Logout()
..()
for(var/obj/machinery/ai_status_display/O in GLOB.ai_status_displays) //change status
for(var/each in GLOB.ai_status_displays) //change status
var/obj/machinery/status_display/ai/O = each
O.mode = 0
O.update()
view_core()
@@ -124,6 +124,7 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
var/list/cameras_telegraphed = list()
var/telegraph_cameras = TRUE
var/telegraph_range = 7
ai_detector_color = COLOR_ORANGE
/mob/camera/aiEye/pic_in_pic/GetViewerClient()
if(screen && screen.ai)
@@ -139,6 +140,10 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
else
GLOB.cameranet.visibility(src)
update_camera_telegraphing()
update_ai_detect_hud()
/mob/camera/aiEye/pic_in_pic/get_visible_turfs()
return screen ? screen.get_visible_turfs() : list()
/mob/camera/aiEye/pic_in_pic/proc/update_camera_telegraphing()
if(!telegraph_cameras)
+2 -2
View File
@@ -1,4 +1,4 @@
/mob/living/silicon/ai/say(message, language)
/mob/living/silicon/ai/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
if(parent && istype(parent) && parent.stat != DEAD) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
parent.say(message, language)
return
@@ -48,7 +48,7 @@
padloc = AREACOORD(padturf)
else
padloc = "(UNKNOWN)"
log_talk(src,"HOLOPAD in [padloc]: [key_name(src)] : [message]", LOGSAY)
src.log_talk(message, LOG_SAY, tag="HOLOPAD in [padloc]")
send_speech(message, 7, T, "robot", get_spans(), language)
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> <span class='message robot'>\"[message]\"</span></span></i>")
else
+4 -12
View File
@@ -1,6 +1,6 @@
/mob/living/silicon/pai
name = "pAI"
icon = 'modular_citadel/icons/mob/pai.dmi' // CITADEL EDIT
icon = 'icons/mob/pai.dmi'
icon_state = "repairbot"
mouse_opacity = MOUSE_OPACITY_OPAQUE
density = FALSE
@@ -58,7 +58,7 @@
var/canholo = TRUE
var/obj/item/card/id/access_card = null
var/chassis = "repairbot"
var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE, "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE, "borgi" = FALSE , "parrot" = FALSE, "bear" = FALSE , "mushroom" = FALSE, "crow" = FALSE , "fairy" = FALSE , "spiderbot" = FALSE ) //assoc value is whether it can be picked up.-- borgi and on = // CITADEL EDIT
var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE, "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE) //assoc value is whether it can be picked up.
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'
@@ -75,13 +75,7 @@
var/overload_maxhealth = 0
canmove = FALSE
var/silent = FALSE
var/hit_slowdown = 0
var/brightness_power = 5
var/slowdown = 0
/mob/living/silicon/pai/movement_delay()
. = ..()
. += slowdown
/mob/living/silicon/pai/can_unbuckle()
return FALSE
@@ -266,9 +260,9 @@
/mob/living/silicon/pai/Process_Spacemove(movement_dir = 0)
. = ..()
if(!.)
slowdown = 2
add_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD, TRUE, 100, multiplicative_slowdown = 2)
return TRUE
slowdown = initial(slowdown)
remove_movespeed_modifier(MOVESPEED_ID_PAI_SPACEWALK_SPEEDMOD, TRUE)
return TRUE
/mob/living/silicon/pai/examine(mob/user)
@@ -293,7 +287,5 @@
health = maxHealth - getBruteLoss() - getFireLoss()
update_stat()
/mob/living/silicon/pai/process()
emitterhealth = CLAMP((emitterhealth + emitterregen), -50, emittermaxhealth)
hit_slowdown = CLAMP((hit_slowdown - 1), 0, 100)
@@ -64,7 +64,6 @@
if(emitterhealth < 0)
fold_in(force = TRUE)
to_chat(src, "<span class='userdanger'>The impact degrades your holochassis!</span>")
hit_slowdown += amount
return amount
/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
@@ -103,10 +103,6 @@
set_light(0)
to_chat(src, "<span class='notice'>You disable your integrated light.</span>")
/mob/living/silicon/pai/movement_delay()
. = ..()
. += 1 //A bit slower than humans, so they're easier to smash
/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))
+2 -2
View File
@@ -1,8 +1,8 @@
/mob/living/silicon/pai/say(msg)
/mob/living/silicon/pai/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
if(silent)
to_chat(src, "<span class='warning'>Communication circuits remain unitialized.</span>")
else
..(msg)
..(message)
/mob/living/silicon/pai/binarycheck()
return 0
@@ -2,7 +2,7 @@
/mob/living/silicon/robot/gib_animation()
new /obj/effect/temp_visual/gib_animation(loc, "gibbed-r")
/mob/living/silicon/robot/dust()
/mob/living/silicon/robot/dust(just_ash, drop_items, force)
if(mmi)
qdel(mmi)
..()
+15 -12
View File
@@ -8,6 +8,7 @@
bubble_icon = "robot"
designation = "Default" //used for displaying the prefix & getting the current module of cyborg
has_limbs = 1
hud_type = /datum/hud/robot
var/custom_name = ""
var/braintype = "Cyborg"
@@ -211,10 +212,6 @@
cell = null
return ..()
/mob/living/silicon/robot/can_interact_with(atom/A)
. = ..()
return . || in_view_range(src, A)
/mob/living/silicon/robot/proc/pick_module()
if(module.type != /obj/item/robot_module)
return
@@ -297,12 +294,12 @@
if(!ionpulse_on)
return
if(cell.charge <= 50)
if(cell.charge <= 10)
toggle_ionpulse()
return
cell.charge -= 50 // 500 steps on a default cell.
return 1
cell.charge -= 10
return TRUE
/mob/living/silicon/robot/proc/toggle_ionpulse()
if(!ionpulse)
@@ -381,7 +378,13 @@
return !cleared
/mob/living/silicon/robot/can_interact_with(atom/A)
return !low_power_mode && ISINRANGE(A.x, x - interaction_range, x + interaction_range) && ISINRANGE(A.y, y - interaction_range, y + interaction_range)
if (low_power_mode)
return FALSE
var/turf/T0 = get_turf(src)
var/turf/T1 = get_turf(A)
if (!T0 || ! T1)
return FALSE
return ISINRANGE(T1.x, T0.x - interaction_range, T0.x + interaction_range) && ISINRANGE(T1.y, T0.y - interaction_range, T0.y + interaction_range)
/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src))
@@ -1118,10 +1121,10 @@
undeployment_action.Grant(src)
/datum/action/innate/undeployment
name = "Disconnect from shell"
desc = "Stop controlling your shell and resume normal core operations."
icon_icon = 'icons/mob/actions/actions_AI.dmi'
button_icon_state = "ai_core"
name = "Disconnect from shell"
desc = "Stop controlling your shell and resume normal core operations."
icon_icon = 'icons/mob/actions/actions_AI.dmi'
button_icon_state = "ai_core"
/datum/action/innate/undeployment/Trigger()
if(!..())
@@ -22,11 +22,11 @@
uneq_active()
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disabled [src]'s active module!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
else
Stun(40)
step(src,get_dir(M,src))
add_logs(M, src, "pushed")
log_combat(M, src, "pushed")
visible_message("<span class='danger'>[M] has forced back [src]!</span>", \
"<span class='userdanger'>[M] has forced back [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1)
@@ -3,13 +3,6 @@
return 1
return ..()
/mob/living/silicon/robot/movement_delay()
. = ..()
var/static/config_robot_delay
if(isnull(config_robot_delay))
config_robot_delay = CONFIG_GET(number/robot_delay)
. += speed + config_robot_delay
/mob/living/silicon/robot/mob_negates_gravity()
return magpulse
+1 -2
View File
@@ -3,8 +3,7 @@
return ..() | SPAN_ROBOT
/mob/living/proc/robot_talk(message)
log_talk(src,"[key_name(src)] : [message]",LOGSAY)
log_message(message, INDIVIDUAL_SAY_LOG)
log_talk(message, LOG_SAY)
var/desig = "Default Cyborg" //ezmode for taters
if(issilicon(src))
var/mob/living/silicon/S = src
@@ -1,5 +1,5 @@
/mob/living/silicon/grippedby(mob/living/user)
/mob/living/silicon/grippedby(mob/living/user, instant = FALSE)
return //can't upgrade a simple pull into a more aggressive grab.
/mob/living/silicon/get_ear_protection()//no ears
@@ -9,13 +9,13 @@
if(..()) //if harm or disarm intent
var/damage = 20
if (prob(90))
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
if(prob(8))
flash_act(affect_silicon = 1)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
adjustBruteLoss(damage)
updatehealth()
else
@@ -23,7 +23,7 @@
"<span class='userdanger'>[M] [response_harm] [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, attacked_sound, 25, 1, -1)
attack_threshold_check(harm_intent_damage)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
updatehealth()
return TRUE
@@ -57,14 +57,14 @@
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(M, src, "disarmed")
log_combat(M, src, "disarmed")
else
var/damage = rand(15, 30)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
attack_threshold_check(damage)
add_logs(M, src, "attacked")
log_combat(M, src, "attacked")
return 1
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
@@ -0,0 +1,150 @@
/mob/living/simple_animal/bot/secbot/grievous //This bot is powerful. If you managed to get 4 eswords somehow, you deserve this horror. Emag him for best results.
name = "General Beepsky"
desc = "Is that a secbot with four eswords in its arms...?"
icon = 'icons/mob/aibots.dmi'
icon_state = "grievous"
health = 150
maxHealth = 150
baton_type = /obj/item/melee/transforming/energy/sword
base_speed = 4 //he's a fast fucker
var/obj/item/weapon
var/block_chance = 50
/mob/living/simple_animal/bot/secbot/grievous/toy //A toy version of general beepsky!
name = "Genewul Bweepskee"
desc = "An adorable looking secbot with four toy swords taped to its arms"
health = 50
maxHealth = 50
baton_type = /obj/item/toy/sword
/mob/living/simple_animal/bot/secbot/grievous/bullet_act(obj/item/projectile/P)
visible_message("[src] deflects [P] with its energy swords!")
playsound(src, 'sound/weapons/blade1.ogg', 50, TRUE)
return FALSE
/mob/living/simple_animal/bot/secbot/grievous/Crossed(atom/movable/AM)
..()
if(ismob(AM) && AM == target)
visible_message("[src] flails his swords and cuts [AM]!")
playsound(src,'sound/effects/beepskyspinsabre.ogg',100,TRUE,-1)
stun_attack(AM)
/mob/living/simple_animal/bot/secbot/grievous/Initialize()
. = ..()
weapon = new baton_type(src)
weapon.attack_self(src)
/mob/living/simple_animal/bot/secbot/grievous/Destroy()
QDEL_NULL(weapon)
return ..()
/mob/living/simple_animal/bot/secbot/grievous/special_retaliate_after_attack(mob/user)
if(mode != BOT_HUNT)
return
if(prob(block_chance))
visible_message("[src] deflects [user]'s attack with his energy swords!")
playsound(src, 'sound/weapons/blade1.ogg', 50, TRUE, -1)
return TRUE
/mob/living/simple_animal/bot/secbot/grievous/stun_attack(mob/living/carbon/C) //Criminals don't deserve to live
weapon.attack(C, src)
playsound(src, 'sound/weapons/blade1.ogg', 50, TRUE, -1)
if(C.stat == DEAD)
addtimer(CALLBACK(src, .proc/update_icon), 2)
back_to_idle()
/mob/living/simple_animal/bot/secbot/grievous/handle_automated_action()
if(!on)
return
switch(mode)
if(BOT_IDLE) // idle
update_icon()
walk_to(src,0)
look_for_perp() // see if any criminals are in range
if(!mode && auto_patrol) // still idle, and set to patrol
mode = BOT_START_PATROL // switch to patrol mode
if(BOT_HUNT) // hunting for perp
update_icon()
playsound(src,'sound/effects/beepskyspinsabre.ogg',100,TRUE,-1)
// general beepsky doesn't give up so easily, jedi scum
if(frustration >= 20)
walk_to(src,0)
back_to_idle()
return
if(target) // make sure target exists
if(Adjacent(target) && isturf(target.loc)) // if right next to perp
target_lastloc = target.loc //stun_attack() can clear the target if they're dead, so this needs to be set first
stun_attack(target)
anchored = TRUE
return
else // not next to perp
var/turf/olddist = get_dist(src, target)
walk_to(src, target,1,4)
if((get_dist(src, target)) >= (olddist))
frustration++
else
frustration = 0
else
back_to_idle()
if(BOT_START_PATROL)
look_for_perp()
start_patrol()
if(BOT_PATROL)
look_for_perp()
bot_patrol()
/mob/living/simple_animal/bot/secbot/grievous/look_for_perp()
anchored = FALSE
var/judgement_criteria = judgement_criteria()
for (var/mob/living/carbon/C in view(7,src)) //Let's find us a criminal
if((C.stat) || (C.handcuffed))
continue
if((C.name == oldtarget_name) && (world.time < last_found + 100))
continue
threatlevel = C.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
if(!threatlevel)
continue
else if(threatlevel >= 4)
target = C
oldtarget_name = C.name
speak("Level [threatlevel] infraction alert!")
playsound(src, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE)
playsound(src,'sound/weapons/saberon.ogg',50,TRUE,-1)
visible_message("[src] ignites his energy swords!")
icon_state = "grievous-c"
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
INVOKE_ASYNC(src, .proc/handle_automated_action)
break
else
continue
/mob/living/simple_animal/bot/secbot/grievous/explode()
walk_to(src,0)
visible_message("<span class='boldannounce'>[src] lets out a huge cough as it blows apart!</span>")
var/atom/Tsec = drop_location()
var/obj/item/bot_assembly/secbot/Sa = new (Tsec)
Sa.build_step = 1
Sa.add_overlay("hs_hole")
Sa.created_name = name
new /obj/item/assembly/prox_sensor(Tsec)
if(prob(50))
drop_part(robot_arm, Tsec)
do_sparks(3, TRUE, src)
for(var/IS = 0 to 4)
drop_part(baton_type, Tsec)
new /obj/effect/decal/cleanable/oil(Tsec)
qdel(src)
@@ -196,7 +196,7 @@
bot_reset()
turn_on() //The bot automatically turns on when emagged, unless recently hit with EMP.
to_chat(src, "<span class='userdanger'>(#$*#$^^( OVERRIDE DETECTED</span>")
add_logs(user, src, "emagged")
log_combat(user, src, "emagged")
return
else //Bot is unlocked, but the maint panel has not been opened with a screwdriver yet.
to_chat(user, "<span class='warning'>You need to open maintenance panel first!</span>")
@@ -762,7 +762,7 @@ Pass a positive integer as an argument to override a bot's default speed.
else // no path, so calculate new one
calc_summon_path()
/mob/living/simple_animal/bot/Collide(M as mob|obj) //Leave no door unopened!
/mob/living/simple_animal/bot/Bump(M as mob|obj) //Leave no door unopened!
. = ..()
if((istype(M, /obj/machinery/door/airlock) || istype(M, /obj/machinery/door/window)) && (!isnull(access_card)))
var/obj/machinery/door/D = M
@@ -900,7 +900,7 @@ Pass a positive integer as an argument to override a bot's default speed.
name = paicard.pai.name
faction = user.faction.Copy()
language_holder = paicard.pai.language_holder.copy(src)
add_logs(user, paicard.pai, "uploaded to [bot_name],")
log_combat(user, paicard.pai, "uploaded to [bot_name],")
return TRUE
else
to_chat(user, "<span class='warning'>[card] is inactive.</span>")
@@ -920,9 +920,9 @@ Pass a positive integer as an argument to override a bot's default speed.
key = null
paicard.forceMove(loc)
if(user)
add_logs(user, paicard.pai, "ejected from [src.bot_name],")
log_combat(user, paicard.pai, "ejected from [src.bot_name],")
else
add_logs(src, paicard.pai, "ejected")
log_combat(src, paicard.pai, "ejected")
if(announce)
to_chat(paicard.pai, "<span class='notice'>You feel your control fade as [paicard] ejects from [bot_name].</span>")
paicard = null
@@ -379,6 +379,8 @@
icon_state = "helmet_signaler"
item_state = "helmet"
created_name = "Securitron" //To preserve the name if it's a unique securitron I guess
var/swordamt = 0 //If you're converting it into a grievousbot, how many swords have you attached
var/toyswordamt = 0 //honk
/obj/item/bot_assembly/secbot/attackby(obj/item/I, mob/user, params)
..()
@@ -441,6 +443,29 @@
S.robot_arm = robot_arm
qdel(I)
qdel(src)
if(istype(I, /obj/item/wrench))
to_chat(user, "You adjust [src]'s arm slots to mount extra weapons")
build_step ++
return
if(istype(I, /obj/item/toy/sword))
if(toyswordamt < 3 && swordamt <= 0)
if(!user.temporarilyRemoveItemFromInventory(I))
return
created_name = "General Beepsky"
name = "helmet/signaler/prox sensor/robot arm/toy sword assembly"
icon_state = "grievous_assembly"
to_chat(user, "<span class='notice'>You superglue [I] onto one of [src]'s arm slots.</span>")
qdel(I)
toyswordamt ++
else
if(!can_finish_build(I, user))
return
to_chat(user, "<span class='notice'>You complete the Securitron!...Something seems a bit wrong with it..?</span>")
var/mob/living/simple_animal/bot/secbot/grievous/toy/S = new(Tsec)
S.name = created_name
S.robot_arm = robot_arm
qdel(I)
qdel(src)
else if(istype(I, /obj/item/screwdriver)) //deconstruct
cut_overlay("hs_arm")
@@ -448,3 +473,35 @@
robot_arm = null
to_chat(user, "<span class='notice'>You remove [dropped_arm] from [src].</span>")
build_step--
if(toyswordamt > 0 || toyswordamt)
icon_state = initial(icon_state)
to_chat(user, "<span class='notice'>The superglue binding [src]'s toy swords to its chassis snaps!</span>")
for(var/IS in 1 to toyswordamt)
new /obj/item/toy/sword(Tsec)
if(ASSEMBLY_FIFTH_STEP)
if(istype(I, /obj/item/melee/transforming/energy/sword/saber))
if(swordamt < 3)
if(!user.temporarilyRemoveItemFromInventory(I))
return
created_name = "General Beepsky"
name = "helmet/signaler/prox sensor/robot arm/energy sword assembly"
icon_state = "grievous_assembly"
to_chat(user, "<span class='notice'>You bolt [I] onto one of [src]'s arm slots.</span>")
qdel(I)
swordamt ++
else
if(!can_finish_build(I, user))
return
to_chat(user, "<span class='notice'>You complete the Securitron!...Something seems a bit wrong with it..?</span>")
var/mob/living/simple_animal/bot/secbot/grievous/S = new(Tsec)
S.name = created_name
S.robot_arm = robot_arm
qdel(I)
qdel(src)
else if(istype(I, /obj/item/screwdriver)) //deconstruct
build_step--
icon_state = initial(icon_state)
to_chat(user, "<span class='notice'>You unbolt [src]'s energy swords</span>")
for(var/IS in 1 to swordamt)
new /obj/item/melee/transforming/energy/sword/saber(Tsec)
@@ -26,7 +26,7 @@
var/lastfired = 0
var/shot_delay = 15
var/lasercolor = ""
var/disabled = 0//A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag
var/disabled = FALSE //A holder for if it needs to be disabled, if true it will not seach for targets, shoot at targets, or move, currently only used for lasertag
var/mob/living/carbon/target
@@ -34,16 +34,18 @@
var/threatlevel = 0
var/target_lastloc //Loc of target when arrested.
var/last_found //There's a delay
var/declare_arrests = 1 //When making an arrest, should it notify everyone wearing sechuds?
var/idcheck = 1 //If true, arrest people with no IDs
var/weaponscheck = 1 //If true, arrest people for weapons if they don't have access
var/check_records = 1 //Does it check security records?
var/arrest_type = 0 //If true, don't handcuff
var/declare_arrests = TRUE //When making an arrest, should it notify everyone wearing sechuds?
var/idcheck = TRUE //If true, arrest people with no IDs
var/weaponscheck = TRUE //If true, arrest people for weapons if they don't have access
var/check_records = TRUE //Does it check security records?
var/arrest_type = FALSE //If true, don't handcuff
var/projectile = /obj/item/projectile/energy/electrode //Holder for projectile type
var/shoot_sound = 'sound/weapons/taser.ogg'
var/cell_type = /obj/item/stock_parts/cell
var/vest_type = /obj/item/clothing/suit/armor/vest
do_footstep = TRUE
/mob/living/simple_animal/bot/ed209/Initialize(mapload,created_name,created_lasercolor)
. = ..()
@@ -199,14 +201,14 @@ Auto Patrol[]"},
to_chat(user, "<span class='warning'>You short out [src]'s target assessment circuits.</span>")
oldtarget_name = user.name
audible_message("<span class='danger'>[src] buzzes oddly!</span>")
declare_arrests = 0
declare_arrests = FALSE
icon_state = "[lasercolor]ed209[on]"
set_weapon()
/mob/living/simple_animal/bot/ed209/bullet_act(obj/item/projectile/Proj)
if(istype(Proj , /obj/item/projectile/beam/laser)||istype(Proj, /obj/item/projectile/bullet))
if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
if(!Proj.nodamage && Proj.damage < src.health)
if(!Proj.nodamage && Proj.damage < src.health && ishuman(Proj.firer))
retaliate(Proj.firer)
..()
@@ -357,7 +359,7 @@ Auto Patrol[]"},
target = C
oldtarget_name = C.name
speak("Level [threatlevel] infraction alert!")
playsound(loc, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/edplaceholder.ogg'), 50, 0)
playsound(src, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/edplaceholder.ogg'), 50, FALSE)
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
spawn(0)
@@ -447,7 +449,7 @@ Auto Patrol[]"},
return
var/obj/item/projectile/A = new projectile (loc)
playsound(loc, shoot_sound, 50, 1)
playsound(src, shoot_sound, 50, TRUE)
A.preparePixelProjectile(target, src)
A.fire()
@@ -538,7 +540,7 @@ Auto Patrol[]"},
shootAt(A)
/mob/living/simple_animal/bot/ed209/proc/stun_attack(mob/living/carbon/C)
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
icon_state = "[lasercolor]ed209-c"
spawn(2)
icon_state = "[lasercolor]ed209[on]"
@@ -549,7 +551,7 @@ Auto Patrol[]"},
var/mob/living/carbon/human/H = C
var/judgement_criteria = judgement_criteria()
threat = H.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
add_logs(src,C,"stunned")
log_combat(src,C,"stunned")
if(declare_arrests)
var/area/location = get_area(src)
speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag <b>[C]</b> in [location].", radio_channel)
@@ -558,12 +560,12 @@ Auto Patrol[]"},
/mob/living/simple_animal/bot/ed209/proc/cuff(mob/living/carbon/C)
mode = BOT_ARREST
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
spawn(60)
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
if( !on || !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
@@ -2,7 +2,7 @@
name = "\improper honkbot"
desc = "A little robot. It looks happy with its bike horn."
icon = 'icons/mob/aibots.dmi'
icon_state = "honkbot1"
icon_state = "honkbot"
density = FALSE
anchored = FALSE
health = 25
@@ -39,7 +39,7 @@
/mob/living/simple_animal/bot/honkbot/Initialize()
. = ..()
icon_state = "honkbot[on]"
update_icon()
auto_patrol = TRUE
var/datum/job/clown/J = new/datum/job/clown
access_card.access += J.get_access()
@@ -48,22 +48,19 @@
/mob/living/simple_animal/bot/honkbot/proc/spam_flag_false() //used for addtimer
spam_flag = FALSE
/mob/living/simple_animal/bot/honkbot/proc/blink_end() //used for addtimer
icon_state = "honkbot[on]"
/mob/living/simple_animal/bot/honkbot/proc/sensor_blink()
icon_state = "honkbot-c"
addtimer(CALLBACK(src, .proc/blink_end), 5)
addtimer(CALLBACK(src, .proc/update_icon), 5, TIMER_OVERRIDE|TIMER_UNIQUE)
//honkbots react with sounds.
/mob/living/simple_animal/bot/honkbot/proc/react_ping()
playsound(src, 'sound/machines/ping.ogg', 50, 1, -1) //the first sound upon creation!
playsound(src, 'sound/machines/ping.ogg', 50, TRUE, -1) //the first sound upon creation!
spam_flag = TRUE
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), 18) // calibrates before starting the honk
/mob/living/simple_animal/bot/honkbot/proc/react_buzz()
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, 1, -1)
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE, -1)
sensor_blink()
/mob/living/simple_animal/bot/honkbot/bot_reset()
@@ -123,7 +120,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
/mob/living/simple_animal/bot/honkbot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM).
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
return
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Check for welding tool to fix #2432.
retaliate(user)
@@ -138,10 +135,10 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
oldtarget_name = user.name
audible_message("<span class='danger'>[src] gives out an evil laugh!</span>")
playsound(src, 'sound/machines/honkbot_evil_laugh.ogg', 75, 1, -1) // evil laughter
icon_state = "honkbot[on]"
update_icon()
/mob/living/simple_animal/bot/honkbot/bullet_act(obj/item/projectile/Proj)
if((istype(Proj,/obj/item/projectile/beam)) || (istype(Proj,/obj/item/projectile/bullet) && (Proj.damage_type == BURN))||(Proj.damage_type == BRUTE) && (!Proj.nodamage && Proj.damage < health))
if((istype(Proj,/obj/item/projectile/beam)) || (istype(Proj,/obj/item/projectile/bullet) && (Proj.damage_type == BURN))||(Proj.damage_type == BRUTE) && (!Proj.nodamage && Proj.damage < health && ishuman(Proj.firer)))
retaliate(Proj.firer)
..()
@@ -162,7 +159,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
if(istype(AM, /obj/item))
playsound(src, honksound, 50, 1, -1)
playsound(src, honksound, 50, TRUE, -1)
var/obj/item/I = AM
if(I.throwforce < health && I.thrownby && (istype(I.thrownby, /mob/living/carbon/human)))
var/mob/living/carbon/human/H = I.thrownby
@@ -172,7 +169,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
/mob/living/simple_animal/bot/honkbot/proc/bike_horn() //use bike_horn
if (emagged <= 1)
if (!spam_flag)
playsound(src, honksound, 50, 1, -1)
playsound(src, honksound, 50, TRUE, -1)
spam_flag = TRUE //prevent spam
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
@@ -181,19 +178,19 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
playsound(src, "honkbot_e", 50, 0)
spam_flag = TRUE // prevent spam
icon_state = "honkbot-e"
addtimer(CALLBACK(src, .proc/blink_end), 30)
addtimer(CALLBACK(src, .proc/update_icon), 30, TIMER_OVERRIDE|TIMER_UNIQUE)
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
/mob/living/simple_animal/bot/honkbot/proc/honk_attack(mob/living/carbon/C) // horn attack
if(!spam_flag)
playsound(loc, honksound, 50, 1, -1)
playsound(loc, honksound, 50, TRUE, -1)
spam_flag = TRUE // prevent spam
sensor_blink()
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntimehorn)
/mob/living/simple_animal/bot/honkbot/proc/stun_attack(mob/living/carbon/C) // airhorn stun
if(!spam_flag)
playsound(loc, 'sound/items/AirHorn.ogg', 100, 1, -1) //HEEEEEEEEEEEENK!!
playsound(src, 'sound/items/AirHorn.ogg', 100, TRUE, -1) //HEEEEEEEEEEEENK!!
sensor_blink()
if(spam_flag == 0)
if(ishuman(C))
@@ -213,7 +210,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
threatlevel = 6 // will never let you go
addtimer(CALLBACK(src, .proc/spam_flag_false), cooldowntime)
add_logs(src,C,"honked")
log_combat(src,C,"honked")
C.visible_message("<span class='danger'>[src] has honked [C]!</span>",\
"<span class='userdanger'>[src] has honked you!</span>")
@@ -261,7 +261,7 @@
if(assess_patient(H))
last_found = world.time
if((last_newpatient_speak + 300) < world.time) //Don't spam these messages!
var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/mcoming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/mhelp.ogg',"[H.name], you appear to be injured!" = 'sound/voice/minjured.ogg')
var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg')
var/message = pick(messagevoice)
speak(message)
playsound(loc, messagevoice[message], 50, 0)
@@ -287,9 +287,9 @@
oldpatient = patient
soft_reset()
if(!patient)
if(QDELETED(patient))
if(!shut_up && prob(1))
var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/mradar.ogg',"There's always a catch, and I'm the best there is." = 'sound/voice/mcatch.ogg',"I knew it, I should've been a plastic surgeon." = 'sound/voice/msurgeon.ogg',"What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/mflies.ogg',"Delicious!" = 'sound/voice/mdelicious.ogg')
var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/medbot/radar.ogg',"There's always a catch, and I'm the best there is." = 'sound/voice/medbot/catch.ogg',"I knew it, I should've been a plastic surgeon." = 'sound/voice/medbot/surgeon.ogg',"What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/medbot/flies.ogg',"Delicious!" = 'sound/voice/medbot/delicious.ogg')
var/message = pick(messagevoice)
speak(message)
playsound(loc, messagevoice[message], 50, 0)
@@ -422,7 +422,7 @@
return
if(C.stat == DEAD || (C.has_trait(TRAIT_FAKEDEATH)))
var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/mno.ogg',"Live, damnit! LIVE!" = 'sound/voice/mlive.ogg',"I...I've never lost a patient before. Not today, I mean." = 'sound/voice/mlost.ogg')
var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/medbot/no.ogg',"Live, damnit! LIVE!" = 'sound/voice/medbot/live.ogg',"I...I've never lost a patient before. Not today, I mean." = 'sound/voice/medbot/lost.ogg')
var/message = pick(messagevoice)
speak(message)
playsound(loc, messagevoice[message], 50, 0)
@@ -476,7 +476,7 @@
if(!reagent_id) //If they don't need any of that they're probably cured!
if(C.maxHealth - C.health < heal_threshold)
to_chat(src, "<span class='notice'>[C] is healthy! Your programming prevents you from injecting anyone without at least [heal_threshold] damage of any one type ([heal_threshold + 15] for oxygen damage.)</span>")
var/list/messagevoice = list("All patched up!" = 'sound/voice/mpatchedup.ogg',"An apple a day keeps me away." = 'sound/voice/mapple.ogg',"Feel better soon!" = 'sound/voice/mfeelbetter.ogg')
var/list/messagevoice = list("All patched up!" = 'sound/voice/medbot/patchedup.ogg',"An apple a day keeps me away." = 'sound/voice/medbot/apple.ogg',"Feel better soon!" = 'sound/voice/medbot/feelbetter.ogg')
var/message = pick(messagevoice)
speak(message)
playsound(loc, messagevoice[message], 50, 0)
@@ -540,7 +540,7 @@
drop_part(robot_arm, Tsec)
if(emagged && prob(25))
playsound(loc, 'sound/voice/minsult.ogg', 50, 0)
playsound(loc, 'sound/voice/medbot/insult.ogg', 50, 0)
do_sparks(3, TRUE, src)
..()
@@ -623,7 +623,7 @@
return
// called when bot bumps into anything
/mob/living/simple_animal/bot/mulebot/Collide(atom/obs)
/mob/living/simple_animal/bot/mulebot/Bump(atom/obs)
if(wires.is_cut(WIRE_AVOIDANCE)) // usually just bumps, but if avoidance disabled knock over mobs
if(isliving(obs))
var/mob/living/L = obs
@@ -631,7 +631,7 @@
visible_message("<span class='danger'>[src] bumps into [L]!</span>")
else
if(!paicard)
add_logs(src, L, "knocked down")
log_combat(src, L, "knocked down")
visible_message("<span class='danger'>[src] knocks over [L]!</span>")
L.Knockdown(160)
return ..()
@@ -639,7 +639,7 @@
// called from mob/living/carbon/human/Crossed()
// when mulebot is in the same loc
/mob/living/simple_animal/bot/mulebot/proc/RunOver(mob/living/carbon/human/H)
add_logs(src, H, "run over", null, "(DAMTYPE: [uppertext(BRUTE)])")
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)
@@ -2,7 +2,7 @@
name = "\improper Securitron"
desc = "A little security robot. He looks less than thrilled."
icon = 'icons/mob/aibots.dmi'
icon_state = "secbot0"
icon_state = "secbot"
density = FALSE
anchored = FALSE
health = 25
@@ -24,21 +24,21 @@
var/baton_type = /obj/item/melee/baton
var/mob/living/carbon/target
var/oldtarget_name
var/threatlevel = 0
var/threatlevel = FALSE
var/target_lastloc //Loc of target when arrested.
var/last_found //There's a delay
var/declare_arrests = 1 //When making an arrest, should it notify everyone on the security channel?
var/idcheck = 0 //If true, arrest people with no IDs
var/weaponscheck = 0 //If true, arrest people for weapons if they lack access
var/check_records = 1 //Does it check security records?
var/arrest_type = 0 //If true, don't handcuff
var/declare_arrests = TRUE //When making an arrest, should it notify everyone on the security channel?
var/idcheck = FALSE //If true, arrest people with no IDs
var/weaponscheck = FALSE //If true, arrest people for weapons if they lack access
var/check_records = TRUE //Does it check security records?
var/arrest_type = FALSE //If true, don't handcuff
/mob/living/simple_animal/bot/secbot/beepsky
name = "Officer Beep O'sky"
desc = "It's Officer Beep O'sky! Powered by a potato and a shot of whiskey."
idcheck = 0
weaponscheck = 0
auto_patrol = 1
idcheck = FALSE
weaponscheck = FALSE
auto_patrol = TRUE
/mob/living/simple_animal/bot/secbot/beepsky/jr
name = "Officer Pipsqueak"
@@ -65,7 +65,7 @@
/mob/living/simple_animal/bot/secbot/Initialize()
. = ..()
icon_state = "secbot[on]"
update_icon()
var/datum/job/detective/J = new/datum/job/detective
access_card.access += J.get_access()
prev_access = access_card.access
@@ -74,13 +74,15 @@
var/datum/atom_hud/secsensor = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
secsensor.add_hud_to(src)
/mob/living/simple_animal/bot/secbot/turn_on()
/mob/living/simple_animal/bot/secbot/update_icon()
if(mode == BOT_HUNT)
icon_state = "[initial(icon_state)]-c"
return
..()
icon_state = "secbot[on]"
/mob/living/simple_animal/bot/secbot/turn_off()
..()
icon_state = "secbot[on]"
mode = BOT_IDLE
/mob/living/simple_animal/bot/secbot/bot_reset()
..()
@@ -167,9 +169,14 @@ Auto Patrol: []"},
final = final|JUDGE_EMAGGED
return final
/mob/living/simple_animal/bot/secbot/proc/special_retaliate_after_attack(mob/user) //allows special actions to take place after being attacked.
return
/mob/living/simple_animal/bot/secbot/attack_hand(mob/living/carbon/human/H)
if((H.a_intent == INTENT_HARM) || (H.a_intent == INTENT_DISARM))
retaliate(H)
if(special_retaliate_after_attack(H))
return
return ..()
@@ -179,6 +186,8 @@ Auto Patrol: []"},
return
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
retaliate(user)
if(special_retaliate_after_attack(user))
return
/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
..()
@@ -187,13 +196,13 @@ Auto Patrol: []"},
to_chat(user, "<span class='danger'>You short out [src]'s target assessment circuits.</span>")
oldtarget_name = user.name
audible_message("<span class='danger'>[src] buzzes oddly!</span>")
declare_arrests = 0
icon_state = "secbot[on]"
declare_arrests = FALSE
update_icon()
/mob/living/simple_animal/bot/secbot/bullet_act(obj/item/projectile/Proj)
if(istype(Proj , /obj/item/projectile/beam)||istype(Proj, /obj/item/projectile/bullet))
if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
if(!Proj.nodamage && Proj.damage < src.health)
if(!Proj.nodamage && Proj.damage < src.health && ishuman(Proj.firer))
retaliate(Proj.firer)
..()
@@ -222,13 +231,13 @@ Auto Patrol: []"},
/mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C)
mode = BOT_ARREST
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
addtimer(CALLBACK(src, .proc/attempt_handcuff, C), 60)
/mob/living/simple_animal/bot/secbot/proc/attempt_handcuff(mob/living/carbon/C)
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
if( !on || !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
@@ -236,14 +245,11 @@ Auto Patrol: []"},
playsound(src, "law", 50, 0)
back_to_idle()
/mob/living/simple_animal/bot/secbot/proc/update_onsprite()
icon_state = "secbot[on]"
/mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C)
var/judgement_criteria = judgement_criteria()
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
icon_state = "secbot-c"
addtimer(CALLBACK(src, .proc/update_onsprite), 2)
addtimer(CALLBACK(src, .proc/update_icon), 2)
var/threat = 5
if(ishuman(C))
C.stuttering = 5
@@ -255,7 +261,7 @@ Auto Patrol: []"},
C.stuttering = 5
threat = C.assess_threat(judgement_criteria, weaponcheck=CALLBACK(src, .proc/check_for_weapons))
add_logs(src,C,"stunned")
log_combat(src,C,"stunned")
if(declare_arrests)
var/area/location = get_area(src)
speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag <b>[C]</b> in [location].", radio_channel)
@@ -384,7 +390,7 @@ Auto Patrol: []"},
target = C
oldtarget_name = C.name
speak("Level [threatlevel] infraction alert!")
playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0)
playsound(loc, pick('sound/voice/beepsky/criminal.ogg', 'sound/voice/beepsky/justice.ogg', 'sound/voice/beepsky/freeze.ogg'), 50, FALSE)
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
INVOKE_ASYNC(src, .proc/handle_automated_action)
@@ -32,6 +32,7 @@
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
deathmessage = "collapses in a shattered heap."
hud_type = /datum/hud/constructs
var/list/construct_spells = list()
var/playstyle_string = "<span class='big bold'>You are a generic construct!</span><b> Your job is to not exist, and you should probably adminhelp this.</b>"
var/master = null
@@ -121,8 +122,8 @@
desc = "A massive, armored construct built to spearhead attacks and soak up enemy fire."
icon_state = "behemoth"
icon_living = "behemoth"
maxHealth = 200
health = 200
maxHealth = 150
health = 150
response_harm = "harmlessly punches"
harm_intent_damage = 0
obj_damage = 90
@@ -147,7 +148,7 @@
/mob/living/simple_animal/hostile/construct/armored/bullet_act(obj/item/projectile/P)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
var/reflectchance = 60 - round(P.damage/3)
var/reflectchance = 40 - round(P.damage/3)
if(prob(reflectchance))
apply_damage(P.damage * 0.5, P.damage_type)
visible_message("<span class='danger'>The [P.name] is reflected by [src]'s armored shell!</span>", \
@@ -227,7 +228,7 @@
/mob/living/simple_animal/hostile/construct/builder
name = "Artificer"
real_name = "Artificer"
desc = "A bulbous construct dedicated to building and maintaining the Cult of Nar-Sie's armies."
desc = "A bulbous construct dedicated to building and maintaining the Cult of Nar'Sie's armies."
icon_state = "artificer"
icon_living = "artificer"
maxHealth = 50
@@ -311,7 +312,7 @@
/mob/living/simple_animal/hostile/construct/harvester
name = "Harvester"
real_name = "Harvester"
desc = "A long, thin construct built to herald Nar-Sie's rise. It'll be all over soon."
desc = "A long, thin construct built to herald Nar'Sie's rise. It'll be all over soon."
icon_state = "chosen"
icon_living = "chosen"
maxHealth = 40
@@ -328,7 +329,7 @@
can_repair_constructs = TRUE
/mob/living/simple_animal/hostile/construct/harvester/Collide(atom/AM)
/mob/living/simple_animal/hostile/construct/harvester/Bump(atom/AM)
. = ..()
if(istype(AM, /turf/closed/wall/mineral/cult) && AM != loc) //we can go through cult walls
var/atom/movable/stored_pulling = pulling
@@ -27,7 +27,6 @@
back = /obj/item/storage/backpack
id = /obj/item/card/id/syndicate
/obj/effect/mob_spawn/human/corpse/syndicatecommando
name = "Syndicate Commando"
id_job = "Operative"
@@ -76,7 +75,7 @@
/obj/effect/mob_spawn/human/corpse/pirate
name = "Pirate"
skin_tone = "Caucasian1" //all pirates are white because it's easier that way
skin_tone = "caucasian1" //all pirates are white because it's easier that way
outfit = /datum/outfit/piratecorpse
hair_style = "Bald"
facial_hair_style = "Shaved"
@@ -155,7 +154,7 @@
outfit = /datum/outfit/wizardcorpse
hair_style = "Bald"
facial_hair_style = "Long Beard"
skin_tone = "Caucasian1"
skin_tone = "caucasian1"
/datum/outfit/wizardcorpse
name = "Space Wizard Corpse"
@@ -203,4 +202,20 @@
ears = /obj/item/radio/headset
back = /obj/item/storage/backpack/satchel/med
id = /obj/item/card/id
glasses = /obj/item/clothing/glasses/hud/health
glasses = /obj/item/clothing/glasses/hud/health
/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
suit = /obj/item/clothing/suit/hooded/bee_costume
shoes = /obj/item/clothing/shoes/sneakers/yellow
gloves = /obj/item/clothing/gloves/color/yellow
ears = /obj/item/radio/headset
belt = /obj/item/storage/belt/fannypack/yellow/bee_terrorist
id = /obj/item/card/id
l_pocket = /obj/item/paper/fluff/bee_objectives
mask = /obj/item/clothing/mask/rat/bee
@@ -2,7 +2,7 @@
/mob/living/simple_animal/proc/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(!forced && (status_flags & GODMODE))
return FALSE
bruteloss = CLAMP(bruteloss + amount, 0, maxHealth)
bruteloss = round(CLAMP(bruteloss + amount, 0, maxHealth),DAMAGE_PRECISION)
if(updating_health)
updatehealth()
return amount

Some files were not shown because too many files have changed in this diff Show More