module things, jfc
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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,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()
|
||||
|
||||
@@ -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]")
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,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,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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user