This commit is contained in:
SoundScopes
2014-11-06 12:46:38 +00:00
537 changed files with 29868 additions and 17588 deletions
+14 -40
View File
@@ -69,6 +69,7 @@
..()
/mob/dead/observer/Topic(href, href_list)
if (href_list["track"])
var/mob/target = locate(href_list["track"]) in mob_list
@@ -173,10 +174,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost, you won't be able to play this round for another 30 minutes! You can't change your mind so choose wisely!)","Are you sure you want to ghost?","Ghost","Stay in body")
if(response != "Ghost") return //didn't want to ghost after-all
resting = 1
var/turf/location = get_turf(src)
message_admins("[key_name_admin(usr)] has ghosted. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>JMP</a>)")
log_game("[key_name_admin(usr)] has ghosted.")
var/mob/dead/observer/ghost = ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
ghost.timeofdeath = world.time // Because the living mob won't have a time of death and we want the respawn timer to work properly.
if(istype(src, /mob/living/simple_animal/mouse))
ghost.client.time_died_as_mouse = world.time
return
@@ -185,7 +187,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(NewLoc)
loc = NewLoc
for(var/obj/effect/step_trigger/S in NewLoc)
S.HasEntered(src)
S.Crossed(src)
return
loc = get_turf(src) //Get out of closets and such as a ghost
@@ -199,7 +201,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
x--
for(var/obj/effect/step_trigger/S in locate(x, y, z)) //<-- this is dumb
S.HasEntered(src)
S.Crossed(src)
/mob/dead/observer/examine()
if(usr)
@@ -221,10 +223,9 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(ticker.mode:malf_mode_declared)
stat(null, "Time left: [max(ticker.mode:AI_win_timeleft/(ticker.mode:apcs/3), 0)]")
if(emergency_shuttle)
if(emergency_shuttle.online && emergency_shuttle.location < 2)
var/timeleft = emergency_shuttle.timeleft()
if (timeleft)
stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
/mob/dead/observer/verb/reenter_corpse()
set category = "Ghost"
@@ -262,16 +263,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set category = "Ghost"
set name = "Toggle AntagHUD"
set desc = "Toggles AntagHUD allowing you to see who is the antagonist"
if(!config.antag_hud_allowed && !client.holder)
src << "\red Admins have disabled this for this round."
return
if(!client)
return
var/mob/dead/observer/M = src
if(jobban_isbanned(M, "AntagHUD"))
src << "\red <B>You have been banned from using this feature</B>"
return
if(config.antag_hud_restricted && !M.has_enabled_antagHUD &&!client.holder)
if(config.antag_hud_restricted && !M.has_enabled_antagHUD && !client.holder)
var/response = alert(src, "If you turn this on, you will not be able to take any part in the round.","Are you sure you want to turn this feature on?","Yes","No")
if(response == "No") return
M.can_reenter_corpse = 0
@@ -401,7 +400,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
var/datum/gas_mixture/environment = usr.loc.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
var/total_moles = environment.total_moles
src << "\blue <B>Results:</B>"
if(abs(pressure - ONE_ATMOSPHERE) < 10)
@@ -409,33 +408,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
else
src << "\red Pressure: [round(pressure,0.1)] kPa"
if(total_moles)
var/o2_concentration = environment.oxygen/total_moles
var/n2_concentration = environment.nitrogen/total_moles
var/co2_concentration = environment.carbon_dioxide/total_moles
var/plasma_concentration = environment.toxins/total_moles
var/unknown_concentration = 1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration)
if(abs(n2_concentration - N2STANDARD) < 20)
src << "\blue Nitrogen: [round(n2_concentration*100)]% ([round(environment.nitrogen,0.01)] moles)"
else
src << "\red Nitrogen: [round(n2_concentration*100)]% ([round(environment.nitrogen,0.01)] moles)"
if(abs(o2_concentration - O2STANDARD) < 2)
src << "\blue Oxygen: [round(o2_concentration*100)]% ([round(environment.oxygen,0.01)] moles)"
else
src << "\red Oxygen: [round(o2_concentration*100)]% ([round(environment.oxygen,0.01)] moles)"
if(co2_concentration > 0.01)
src << "\red CO2: [round(co2_concentration*100)]% ([round(environment.carbon_dioxide,0.01)] moles)"
else
src << "\blue CO2: [round(co2_concentration*100)]% ([round(environment.carbon_dioxide,0.01)] moles)"
if(plasma_concentration > 0.01)
src << "\red Plasma: [round(plasma_concentration*100)]% ([round(environment.toxins,0.01)] moles)"
if(unknown_concentration > 0.01)
src << "\red Unknown: [round(unknown_concentration*100)]% ([round(unknown_concentration*total_moles,0.01)] moles)"
for(var/g in environment.gas)
src << "\blue [gas_data.name[g]]: [round((environment.gas[g] / total_moles) * 100)]% ([round(environment.gas[g], 0.01)] moles)"
src << "\blue Temperature: [round(environment.temperature-T0C,0.1)]&deg;C"
src << "\blue Heat Capacity: [round(environment.heat_capacity(),0.1)]"
+38 -51
View File
@@ -1,14 +1,25 @@
// At minimum every mob has a hear_say proc.
/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null)
/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
if(!client)
return
if(speaker && !speaker.client && istype(src,/mob/dead/observer) && client.prefs.toggles & CHAT_GHOSTEARS && !speaker in view(src))
//Does the speaker have a client? It's either random stuff that observers won't care about (Experiment 97B says, 'EHEHEHEHEHEHEHE')
//Or someone snoring. So we make it where they won't hear it.
return
if(sleeping || stat == 1)
hear_sleep(message)
return
var/style = "body"
//non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
if (language && (language.flags & NONVERBAL))
if (!speaker || (src.sdisabilities & BLIND || src.blinded) || !(speaker in view(src)))
message = stars(message)
if(!say_understands(speaker,language))
if(istype(speaker,/mob/living/simple_animal))
var/mob/living/simple_animal/S = speaker
@@ -17,7 +28,6 @@
message = stars(message)
if(language)
verb = language.speech_verb
style = language.colour
var/speaker_name = speaker.name
@@ -42,9 +52,12 @@
if(speaker == src)
src << "<span class='warning'>You cannot hear yourself speak!</span>"
else
src << "<span class='name'>[speaker_name]</span>[alt_name] talks but you cannot hear them."
src << "<span class='name'>[speaker_name]</span>[alt_name] talks but you cannot hear \him."
else
src << "<span class='game say'><span class='name'>[speaker_name]</span>[alt_name] [track][verb], <span class='message'><span class='[style]'>\"[message]\"</span></span></span>"
if (speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
src.playsound_local(source, speech_sound, sound_vol, 1)
/mob/proc/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
@@ -60,6 +73,11 @@
var/style = "body"
//non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
if (language && (language.flags & NONVERBAL))
if (!speaker || (src.sdisabilities & BLIND || src.blinded) || !(speaker in view(src)))
message = stars(message)
if(!say_understands(speaker,language))
if(istype(speaker,/mob/living/simple_animal))
var/mob/living/simple_animal/S = speaker
@@ -76,9 +94,7 @@
if(hard_to_hear)
message = stars(message)
var/speaker_name
if(speaker)
speaker_name = speaker.name
var/speaker_name = speaker.name
if(vname)
speaker_name = vname
@@ -145,6 +161,22 @@
else
src << "[part_a][speaker_name][part_b][verb], <span class=\"[style]\">\"[message]\"</span></span></span>"
/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null)
if(!client)
return
if(say_understands(speaker, language))
message = "<B>[src]</B> [verb], \"[message]\""
else
message = "<B>[src]</B> [verb]."
if(src.status_flags & PASSEMOTES)
for(var/obj/item/weapon/holder/H in src.contents)
H.show_message(message)
for(var/mob/living/M in src.contents)
M.show_message(message)
src.show_message(message)
/mob/proc/hear_sleep(var/message)
var/heard = ""
if(prob(15))
@@ -162,48 +194,3 @@
heard = "<span class = 'game_say'>...<i>You almost hear someone talking</i>...</span>"
src << heard
/mob/proc/see_say(var/message, var/verb = "signs", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/signer = null)
if(!client)
return
if(sleeping || stat == 1)
return
var/style = "body"
if(!say_understands(signer,language))
if(istype(signer,/mob/living/simple_animal))
var/mob/living/simple_animal/S = signer
message = pick(S.speak)
else
message = stars(message)
if(language)
verb = language.speech_verb
style = language.colour
var/signer_name = signer.name
if(istype(signer, /mob/living/carbon/human))
var/mob/living/carbon/human/H = signer
signer_name = H.GetVoice()
if(italics)
message = "<i>[message]</i>"
var/track = null
if(istype(src, /mob/dead/observer))
if(italics && client.prefs.toggles & CHAT_GHOSTRADIO)
return
if(signer_name != signer.real_name && signer.real_name)
signer_name = "[signer.real_name] ([signer_name])"
track = "(<a href='byond://?src=\ref[src];track=\ref[signer]'>follow</a>) "
if(client.prefs.toggles & CHAT_GHOSTEARS && signer in view(src))
message = "<b>[message]</b>"
if(sdisabilities & BLIND)
if(signer == src)
src << "<span class='warning'>You cannot see yourself sign!</span>"
else
if((signer_name != signer.name) || (istype(src.wear_mask, /obj/item/clothing/mask/gas)))
src << "<span class='game say'><span class='name'>[signer.name]</span>[track] [verb], <span class='message'><span class='[style]'>\"[message]\"</span></span></span>"
else
src << "<span class='game say'><span class='name'>[signer_name]</span>[alt_name]</span>[track] [verb], <span class='message'><span class='[style]'>\"[message]\"</span></span></span>"
+30 -3
View File
@@ -4,6 +4,7 @@
desc = "You shouldn't ever see this."
icon = 'icons/obj/objects.dmi'
slot_flags = SLOT_HEAD
sprite_sheets = list("Vox" = 'icons/mob/species/vox/head.dmi')
/obj/item/weapon/holder/New()
..()
@@ -34,18 +35,44 @@
for(var/mob/living/M in contents)
M.show_message(message,m_type)
//Mob procs and vars for scooping up
/mob/living/var/holder_type
/mob/living/proc/get_scooped(var/mob/living/carbon/grabber)
if(!holder_type)
return
var/obj/item/weapon/holder/H = new holder_type(loc)
src.loc = H
H.name = loc.name
H.attack_hand(grabber)
grabber << "You scoop up [src]."
src << "[grabber] scoops you up."
grabber.status_flags |= PASSEMOTES
return
//Mob specific holders.
/obj/item/weapon/holder/diona
name = "diona nymph"
desc = "It's a tiny plant critter."
icon_state = "nymph"
origin_tech = "magnets=3;biotech=5"
/obj/item/weapon/holder/drone
name = "maintenance drone"
desc = "It's a small maintenance robot."
icon_state = "drone"
origin_tech = "magnets=3;engineering=5"
origin_tech = "magnets=3;engineering=5"
/obj/item/weapon/holder/cat
name = "cat"
desc = "It's a cat. Meow."
icon_state = "cat"
origin_tech = null
/obj/item/weapon/holder/borer
name = "cortical borer"
desc = "It's a slimy brain slug. Gross."
icon_state = "borer"
origin_tech = "biotech=6"
+9 -4
View File
@@ -6,11 +6,11 @@
var/name = "an unknown language" // Fluff name of language if any.
var/desc = "A language." // Short description for 'Check Languages'.
var/speech_verb = "says" // 'says', 'hisses', 'farts'.
var/signlang_verb = list() // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
var/colour = "body" // CSS style to use for strings in this language.
var/key = "x" // Character used to speak in language eg. :o for Unathi.
var/flags = 0 // Various language flags.
var/native // If set, non-native speakers will have trouble speaking.
var/vocal = 1 // Is a spoken language
/datum/language/unathi
name = "Sinta'unathi"
@@ -82,13 +82,13 @@
key = "z"
flags = WHITELISTED
/datum/language/sign
/*/datum/language/sign
name = "Sign language"
desc = "A mixture of manual communication and body-languaged, used to communication with those who have impaired hearing."
speech_verb = "signs"
colour = "say_quote"
key = "4"
vocal = 0
vocal = 0*/
// Language handling.
/mob/proc/add_language(var/language)
@@ -107,6 +107,11 @@
return 0
// Can we speak this language, as opposed to just understanding it?
/mob/proc/can_speak(datum/language/speaking)
return (universal_speak || speaking in src.languages)
//TBD
/mob/verb/check_languages()
set name = "Check Known Languages"
@@ -119,4 +124,4 @@
dat += "<b>[L.name] (:[L.key])</b><br/>[L.desc]<br/><br/>"
src << browse(dat, "window=checklanguage")
return
return
+11 -13
View File
@@ -86,15 +86,14 @@
// Aliens are now weak to fire.
//After then, it reacts to the surrounding atmosphere based on your thermal protection
if(!on_fire) // If you're on fire, ignore local air temperature
if(loc_temp > bodytemperature)
//Place is hotter than we are
var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
else
bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
// bodytemperature -= max((loc_temp - bodytemperature / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
if(loc_temp > bodytemperature)
//Place is hotter than we are
var/thermal_protection = heat_protection //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
bodytemperature += (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
else
bodytemperature += 1 * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
// bodytemperature -= max((loc_temp - bodytemperature / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
// +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt.
if(bodytemperature > 360.15)
@@ -166,10 +165,9 @@
stat(null, "Plasma Stored: [getPlasma()]/[max_plasma]")
if(emergency_shuttle)
if(emergency_shuttle.online && emergency_shuttle.location < 2)
var/timeleft = emergency_shuttle.timeleft()
if (timeleft)
stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
/mob/living/carbon/alien/Stun(amount)
if(status_flags & CANSTUN)
@@ -177,7 +177,7 @@
var/damage = rand(1, 3)
if(istype(M, /mob/living/carbon/slime/adult))
if(M.is_adult)
damage = rand(10, 40)
else
damage = rand(5, 35)
@@ -125,7 +125,7 @@
breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature)
else*/
// Not enough air around, take a percentage of what's there to model this properly
breath_moles = environment.total_moles()*BREATH_PERCENTAGE
breath_moles = environment.total_moles*BREATH_PERCENTAGE
breath = loc.remove_air(breath_moles)
@@ -174,24 +174,24 @@
return 0
var/toxins_used = 0
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/breath_pressure = (breath.total_moles * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME
//Partial pressure of the toxins in our breath
var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure
var/Toxins_pp = (breath.gas["toxins"] / breath.total_moles) * breath_pressure
if(Toxins_pp) // Detect toxins in air
adjustToxLoss(breath.toxins*250)
adjustToxLoss(breath.gas["toxins"] *250)
toxins_alert = max(toxins_alert, 1)
toxins_used = breath.toxins
toxins_used = breath.gas["toxins"]
else
toxins_alert = 0
//Breathe in toxins and out oxygen
breath.toxins -= toxins_used
breath.oxygen += toxins_used
breath.adjust_gas("toxins", -toxins_used)
breath.adjust_gas("oxygen", toxins_used)
if(breath.temperature > (T0C+66) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :(
if(prob(20))
@@ -359,22 +359,7 @@
ear_damage = max(ear_damage-0.05, 0)
//Other
if(stunned)
AdjustStunned(-1)
if(!stunned)
update_icons()
if(weakened)
weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times
if(stuttering)
stuttering = max(stuttering-1, 0)
if(silent)
silent = max(silent-1, 0)
if(druggy)
druggy = max(druggy-1, 0)
handle_statuses()
return 1
@@ -463,3 +448,8 @@
if(!(status_flags & GODMODE))
M.adjustBruteLoss(5)
nutrition += 10
/mob/living/carbon/alien/humanoid/handle_stunned()
if(stunned && !..())
update_icons()
return stunned
@@ -198,7 +198,7 @@
var/damage = rand(1, 3)
if(istype(src, /mob/living/carbon/slime/adult))
if(M.is_adult)
damage = rand(20, 40)
else
damage = rand(5, 35)
@@ -98,7 +98,7 @@
breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature)
else*/
// Not enough air around, take a percentage of what's there to model this properly
breath_moles = environment.total_moles()*BREATH_PERCENTAGE
breath_moles = environment.total_moles*BREATH_PERCENTAGE
breath = loc.remove_air(breath_moles)
@@ -147,24 +147,24 @@
return 0
var/toxins_used = 0
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/breath_pressure = (breath.total_moles * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME
//Partial pressure of the toxins in our breath
var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure
//Partial pressure of the phoron in our breath
var/Toxins_pp = (breath.gas["toxins"] / breath.total_moles) * breath_pressure
if(Toxins_pp) // Detect toxins in air
adjustToxLoss(breath.toxins*250)
adjustToxLoss(breath.gas["toxins"] * 250)
toxins_alert = max(toxins_alert, 1)
toxins_used = breath.toxins
toxins_used = breath.gas["toxins"]
else
toxins_alert = 0
//Breathe in toxins and out oxygen
breath.toxins -= toxins_used
breath.oxygen += toxins_used
breath.adjust_gas("toxins", -toxins_used)
breath.adjust_gas("oxygen", toxins_used)
if(breath.temperature > (T0C+66) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :(
if(prob(20))
@@ -274,20 +274,7 @@ FUCK YOU MORE FAT CODE -Hawk*/
ear_damage = max(ear_damage-0.05, 0)
//Other
if(stunned)
AdjustStunned(-1)
if(weakened)
weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times
if(stuttering)
stuttering = max(stuttering-1, 0)
if(silent)
silent = max(silent-1, 0)
if(druggy)
druggy = max(druggy-1, 0)
handle_statuses()
return 1
@@ -379,4 +366,4 @@ FUCK YOU MORE FAT CODE -Hawk*/
if(air_master.current_cycle%3==1)
if(!(M.status_flags & GODMODE))
M.adjustBruteLoss(5)
nutrition += 10
nutrition += 10
@@ -16,6 +16,7 @@ var/const/MAX_ACTIVE_TIME = 400
item_state = "facehugger"
w_class = 1 //note: can be picked up by aliens unlike most other items of w_class below 4
flags = FPRINT | TABLEPASS | MASKCOVERSMOUTH | MASKCOVERSEYES | MASKINTERNALS
body_parts_covered = FACE|EYES
throw_range = 5
var/stat = CONSCIOUS //UNCONSCIOUS is the idle state in this case
@@ -80,7 +81,7 @@ var/const/MAX_ACTIVE_TIME = 400
/obj/item/clothing/mask/facehugger/equipped(mob/M)
Attach(M)
/obj/item/clothing/mask/facehugger/HasEntered(atom/target)
/obj/item/clothing/mask/facehugger/Crossed(atom/target)
HasProximity(target)
return
@@ -107,6 +108,7 @@ var/const/MAX_ACTIVE_TIME = 400
if(stat == CONSCIOUS)
icon_state = "[initial(icon_state)]"
Attach(hit_atom)
throwing = 0
/obj/item/clothing/mask/facehugger/proc/Attach(M as mob)
if( (!iscorgi(M) && !iscarbon(M)) || isalien(M))
@@ -32,8 +32,9 @@
brainmob.timeofhostdeath = H.timeofdeath
if(H.mind)
H.mind.transfer_to(brainmob)
brainmob << "\blue You feel slightly disoriented. That's normal when you're just a brain."
return
callHook("debrain", list(brainmob))
/obj/item/brain/examine() // -- TLE
set src in oview(12)
@@ -95,4 +96,4 @@
del(src)
else
..()
return
return
+1 -14
View File
@@ -186,20 +186,7 @@
emp_damage -= 1
//Other
if(stunned)
AdjustStunned(-1)
if(weakened)
weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times
if(stuttering)
stuttering = max(stuttering-1, 0)
if(silent)
silent = max(silent-1, 0)
if(druggy)
druggy = max(druggy-1, 0)
handle_statuses()
return 1
@@ -1,2 +1,3 @@
/mob/living/carbon/brain/Login()
return ..()
..()
sleeping = 0
@@ -16,80 +16,82 @@
mecha = null//This does not appear to be used outside of reference in mecha.dm.
attack_self(mob/user as mob)
if(brainmob && !brainmob.key && searching == 0)
//Start the process of searching for a new user.
user << "\blue You carefully locate the manual activation switch and start the positronic brain's boot process."
icon_state = "posibrain-searching"
src.searching = 1
src.request_player()
spawn(600) reset_search()
/obj/item/device/mmi/posibrain/attack_self(mob/user as mob)
if(brainmob && !brainmob.key && searching == 0)
//Start the process of searching for a new user.
user << "\blue You carefully locate the manual activation switch and start the positronic brain's boot process."
icon_state = "posibrain-searching"
src.searching = 1
src.request_player()
spawn(600) reset_search()
proc/request_player()
for(var/mob/dead/observer/O in player_list)
if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
continue
if(jobban_isbanned(O, "pAI"))
continue
if(O.client)
if(O.client.prefs.be_special & BE_PAI)
question(O.client)
/obj/item/device/mmi/posibrain/proc/request_player()
for(var/mob/dead/observer/O in player_list)
if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
continue
if(jobban_isbanned(O, "pAI"))
continue
if(O.client)
if(O.client.prefs.be_special & BE_PAI)
question(O.client)
proc/question(var/client/C)
spawn(0)
if(!C) return
var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round")
if(!C || brainmob.key || 0 == searching) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
if(response == "Yes")
transfer_personality(C.mob)
else if (response == "Never for this round")
C.prefs.be_special ^= BE_PAI
/obj/item/device/mmi/posibrain/proc/question(var/client/C)
spawn(0)
if(!C) return
var/response = alert(C, "Someone is requesting a personality for a positronic brain. Would you like to play as one?", "Positronic brain request", "Yes", "No", "Never for this round")
if(!C || brainmob.key || 0 == searching) return //handle logouts that happen whilst the alert is waiting for a response, and responses issued after a brain has been located.
if(response == "Yes")
transfer_personality(C.mob)
else if (response == "Never for this round")
C.prefs.be_special ^= BE_PAI
transfer_identity(var/mob/living/carbon/H)
name = "positronic brain ([H])"
brainmob.name = H.real_name
brainmob.real_name = H.real_name
brainmob.dna = H.dna
brainmob.timeofhostdeath = H.timeofdeath
brainmob.stat = 0
if(brainmob.mind)
brainmob.mind.assigned_role = "Positronic Brain"
if(H.mind)
H.mind.transfer_to(brainmob)
brainmob << "\blue You feel slightly disoriented. That's normal when you're just a metal cube."
icon_state = "posibrain-occupied"
return
/obj/item/device/mmi/posibrain/transfer_identity(var/mob/living/carbon/H)
/*
Positronic brains should have posibrain-like name, instead of human-MMIlike names. -- ATL
proc/transfer_personality(var/mob/candidate)
name = "positronic brain ([H])"
brainmob.name = H.real_name
brainmob.real_name = H.real_name
*/
brainmob.dna = H.dna
brainmob.timeofhostdeath = H.timeofdeath
brainmob.stat = 0
if(brainmob.mind)
brainmob.mind.assigned_role = "Positronic Brain"
if(H.mind)
H.mind.transfer_to(brainmob)
brainmob << "\blue You feel slightly disoriented. That's normal when you're just a metal cube."
icon_state = "posibrain-occupied"
return
src.searching = 0
src.brainmob.mind = candidate.mind
//src.brainmob.key = candidate.key
src.brainmob.ckey = candidate.ckey
src.name = "positronic brain ([src.brainmob.name])"
/obj/item/device/mmi/posibrain/proc/transfer_personality(var/mob/candidate)
src.brainmob << "<b>You are a positronic brain, brought into existence on [station_name()].</b>"
src.brainmob << "<b>As a synthetic intelligence, you answer to all crewmembers, as well as the AI.</b>"
src.brainmob << "<b>Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
src.brainmob << "<b>Use say :b to speak to other artificial intelligences.</b>"
src.brainmob.mind.assigned_role = "Positronic Brain"
src.searching = 0
src.brainmob.mind = candidate.mind
src.brainmob.ckey = candidate.ckey
src.name = "positronic brain ([src.brainmob.name])"
src.brainmob << "<b>You are a positronic brain, brought into existence on [station_name()].</b>"
src.brainmob << "<b>As a synthetic intelligence, you answer to all crewmembers, as well as the AI.</b>"
src.brainmob << "<b>Remember, the purpose of your existence is to serve the crew and the station. Above all else, do no harm.</b>"
src.brainmob << "<b>Use say :b to speak to other artificial intelligences.</b>"
src.brainmob.mind.assigned_role = "Positronic Brain"
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("\blue The positronic brain chimes quietly.")
icon_state = "posibrain-occupied"
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("\blue The positronic brain chimes quietly.")
icon_state = "posibrain-occupied"
proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
/obj/item/device/mmi/posibrain/proc/reset_search() //We give the players sixty seconds to decide, then reset the timer.
if(src.brainmob && src.brainmob.key) return
if(src.brainmob && src.brainmob.key) return
src.searching = 0
icon_state = "posibrain"
src.searching = 0
icon_state = "posibrain"
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("\blue The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?")
var/turf/T = get_turf_or_move(src.loc)
for (var/mob/M in viewers(T))
M.show_message("\blue The positronic brain buzzes quietly, and the golden lights fade away. Perhaps you could try again?")
/obj/item/device/mmi/posibrain/examine()
+50 -38
View File
@@ -1,7 +1,10 @@
/mob/living/carbon/Login()
/mob/living/carbon/Life()
..()
update_hud()
return
// Increase germ_level regularly
if(germ_level < GERM_LEVEL_AMBIENT && prob(30)) //if you're just standing there, you shouldn't get more germs beyond an ambient level
germ_level++
/mob/living/carbon/Move(NewLoc, direct)
. = ..()
if(.)
@@ -12,6 +15,10 @@
if((FAT in src.mutations) && src.m_intent == "run" && src.bodytemperature <= 360)
src.bodytemperature += 2
// Moving around increases germ_level faster
if(germ_level < GERM_LEVEL_MOVE_CAP && prob(8))
germ_level++
/mob/living/carbon/relaymove(var/mob/user, direction)
if(user in src.stomach_contents)
if(prob(40))
@@ -92,24 +99,34 @@
return
/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0)
/mob/living/carbon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/def_zone = null)
if(status_flags & GODMODE) return 0 //godmode
shock_damage *= siemens_coeff
if (shock_damage<1)
return 0
src.take_overall_damage(0,shock_damage,used_weapon="Electrocution")
//src.burn_skin(shock_damage)
//src.adjustFireLoss(shock_damage) //burn_skin will do this for us
//src.updatehealth()
src.visible_message(
"\red [src] was shocked by the [source]!", \
"\red <B>You feel a powerful shock course through your body!</B>", \
"\red You hear a heavy electrical crack." \
)
// if(src.stunned < shock_damage) src.stunned = shock_damage
Stun(10)//This should work for now, more is really silly and makes you lay there forever
// if(src.weakened < 20*siemens_coeff) src.weakened = 20*siemens_coeff
Weaken(10)
src.apply_damage(shock_damage, BURN, def_zone, used_weapon="Electrocution")
playsound(loc, "sparks", 50, 1, -1)
if (shock_damage > 10)
src.visible_message(
"\red [src] was shocked by the [source]!", \
"\red <B>You feel a powerful shock course through your body!</B>", \
"\red You hear a heavy electrical crack." \
)
Stun(10)//This should work for now, more is really silly and makes you lay there forever
Weaken(10)
else
src.visible_message(
"\red [src] was mildly shocked by the [source].", \
"\red You feel a mild shock course through your body.", \
"\red You hear a light zapping." \
)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, loc)
s.start()
return shock_damage
@@ -200,12 +217,12 @@
var/mob/living/carbon/human/H = src
H.w_uniform.add_fingerprint(M)
if(lying)
if(lying || src.sleeping)
src.sleeping = max(0,src.sleeping-5)
if(src.sleeping == 0)
src.resting = 0
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [t_him] up!</span>", \
"<span class='notice'>You shake [src] trying to wake [t_him] up!</span>")
M.visible_message("<span class='notice'>[M] shakes [src] trying to wake [t_him] up!", \
"<span class='notice'>You shake [src] trying to wake [t_him] up!")
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [t_him] feel better!</span>", \
"<span class='notice'>You hug [src] to make [t_him] feel better!</span>")
@@ -323,7 +340,7 @@
*/
item.throw_at(target, item.throw_range, item.throw_speed)
item.throw_at(target, item.throw_range, item.throw_speed, src)
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
@@ -416,23 +433,17 @@
var/mob/living/simple_animal/borer/B = has_brain_worms()
if(!B)
return
if(B.controlling)
if(B && B.host_brain)
src << "\red <B>You withdraw your probosci, releasing control of [B.host_brain]</B>"
B.host_brain << "\red <B>Your vision swims as the alien parasite releases control of your body.</B>"
B.ckey = ckey
B.controlling = 0
if(B.host_brain.ckey)
ckey = B.host_brain.ckey
B.host_brain.ckey = null
B.host_brain.name = "host brain"
B.host_brain.real_name = "host brain"
verbs -= /mob/living/carbon/proc/release_control
verbs -= /mob/living/carbon/proc/punish_host
verbs -= /mob/living/carbon/proc/spawn_larvae
B.detatch()
verbs -= /mob/living/carbon/proc/release_control
verbs -= /mob/living/carbon/proc/punish_host
verbs -= /mob/living/carbon/proc/spawn_larvae
else
src << "\red <B>ERROR NO BORER OR BRAINMOB DETECTED IN THIS MOB, THIS IS A BUG !</B>"
//Brain slug proc for tormenting the host.
/mob/living/carbon/proc/punish_host()
@@ -469,9 +480,10 @@
return
if(B.chemicals >= 100)
src << "\red <B>Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body.</B>"
src << "\red <B>Your host twitches and quivers as you rapidly excrete a larva from your sluglike body.</B>"
visible_message("\red <B>[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!</B>")
B.chemicals -= 100
B.has_reproduced = 1
new /obj/effect/decal/cleanable/vomit(get_turf(src))
playsound(loc, 'sound/effects/splat.ogg', 50, 1)
@@ -479,4 +491,4 @@
else
src << "You do not have enough chemicals stored to reproduce."
return
return
@@ -58,7 +58,6 @@
dizziness = 0
jitteriness = 0
hud_updateflag |= 1 << HEALTH_HUD
hud_updateflag |= 1 << STATUS_HUD
@@ -86,6 +85,8 @@
verbs -= /mob/living/carbon/proc/release_control
callHook("death", list(src, gibbed))
//Check for heist mode kill count.
if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist) ) )
//Check for last assailant's mutantrace.
@@ -106,7 +107,7 @@
update_canmove()
if(client) blind.layer = 0
worldtod = world.time
tod = worldtime2text() //weasellos time of death patch
if(mind) mind.store_memory("Time of death: [tod]", 0)
if(ticker && ticker.mode)
@@ -115,8 +116,6 @@
ticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
return ..(gibbed)
/mob/living/carbon/human/proc/makeSkeleton()
if(SKELETON in src.mutations) return
+39 -3
View File
@@ -66,8 +66,10 @@
return custom_emote(m_type, message)
if ("me")
if(silent)
return
//if(silent && silent > 0 && findtext(message,"\"",1, null) > 0)
// return //This check does not work and I have no idea why, I'm leaving it in for reference.
if (src.client)
if (client.prefs.muted & MUTE_IC)
src << "\red You cannot send IC messages (muted)."
@@ -582,4 +584,38 @@
set desc = "Sets an extended description of your character's features."
set category = "IC"
flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1)
var/HTML = "<body>"
HTML += "<tt><center>"
HTML += "<b>Update Flavour Text</b> <hr />"
HTML += "<br></center>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=general'>General:</a> "
HTML += TextPreview(flavor_texts["general"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=head'>Head:</a> "
HTML += TextPreview(flavor_texts["head"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=face'>Face:</a> "
HTML += TextPreview(flavor_texts["face"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=eyes'>Eyes:</a> "
HTML += TextPreview(flavor_texts["eyes"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=torso'>Body:</a> "
HTML += TextPreview(flavor_texts["torso"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=arms'>Arms:</a> "
HTML += TextPreview(flavor_texts["arms"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=hands'>Hands:</a> "
HTML += TextPreview(flavor_texts["hands"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=legs'>Legs:</a> "
HTML += TextPreview(flavor_texts["legs"])
HTML += "<br>"
HTML += "<a href='byond://?src=\ref[src];flavor_change=feet'>Feet:</a> "
HTML += TextPreview(flavor_texts["feet"])
HTML += "<br>"
HTML += "<hr />"
HTML +="<a href='?src=\ref[src];flavor_change=done'>\[Done\]</a>"
HTML += "<tt>"
src << browse(HTML, "window=flavor_changes;size=430x300")
+157 -38
View File
@@ -1,4 +1,3 @@
/mob/living/carbon/human
name = "unknown"
real_name = "unknown"
@@ -52,7 +51,7 @@
if(!species)
if(new_species)
set_species(new_species)
set_species(new_species,null,1)
else
set_species()
@@ -121,7 +120,7 @@
return
//BubbleWrap: people in handcuffs are always switched around as if they were on 'help' intent to prevent a person being pulled from being seperated from their puller
if((tmob.a_intent == "help" || tmob.restrained()) && (a_intent == "help" || src.restrained()) && tmob.canmove && canmove) // mutual brohugs all around!
if((tmob.a_intent == "help" || tmob.restrained()) && (a_intent == "help" || src.restrained()) && tmob.canmove && !tmob.buckled && canmove) // mutual brohugs all around!
var/turf/oldloc = loc
loc = tmob.loc
tmob.loc = oldloc
@@ -180,10 +179,9 @@
if(ticker.mode:malf_mode_declared)
stat(null, "Time left: [max(ticker.mode:AI_win_timeleft/(ticker.mode:apcs/3), 0)]")
if(emergency_shuttle)
if(emergency_shuttle.online && emergency_shuttle.location < 2)
var/timeleft = emergency_shuttle.timeleft()
if (timeleft)
stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
if (client.statpanel == "Status")
if (internal)
@@ -326,7 +324,6 @@
apply_damage(damage, BRUTE, affecting, armor)
if(armor >= 2) return
/mob/living/carbon/human/proc/is_loyalty_implanted(mob/living/carbon/human/M)
for(var/L in M.contents)
if(istype(L, /obj/item/weapon/implant/loyalty))
@@ -346,7 +343,7 @@
var/damage = rand(1, 3)
if(istype(M, /mob/living/carbon/slime/adult))
if(M.is_adult)
damage = rand(10, 35)
else
damage = rand(5, 25)
@@ -449,12 +446,17 @@
return
// called when something steps onto a human
// this could be made more general, but for now just handle mulebot
/mob/living/carbon/human/HasEntered(var/atom/movable/AM)
var/obj/machinery/bot/mulebot/MB = AM
if(istype(MB))
// this handles mulebots and vehicles
/mob/living/carbon/human/Crossed(var/atom/movable/AM)
if(istype(AM, /obj/machinery/bot/mulebot))
var/obj/machinery/bot/mulebot/MB = AM
MB.RunOver(src)
/* if(istype(AM, /obj/vehicle))
var/obj/vehicle/V = AM
V.RunOver(src)
*/
//gets assignment from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_assignment(var/if_no_id = "No id", var/if_no_job = "No job")
@@ -526,13 +528,18 @@
if(wear_id)
return wear_id.GetID()
//Added a safety check in case you want to shock a human mob directly through electrocute_act.
/mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0, var/safety = 0)
if(!safety)
if(gloves)
var/obj/item/clothing/gloves/G = gloves
siemens_coeff = G.siemens_coefficient
return ..(shock_damage,source,siemens_coeff)
//Removed the horrible safety parameter. It was only being used by ninja code anyways.
//Now checks siemens_coefficient of the affected area by default
/mob/living/carbon/human/electrocute_act(var/shock_damage, var/obj/source, var/base_siemens_coeff = 1.0, var/def_zone = null)
if(status_flags & GODMODE) return 0 //godmode
if (!def_zone)
def_zone = pick("l_hand", "r_hand")
var/datum/organ/external/affected_organ = get_organ(check_zone(def_zone))
var/siemens_coeff = base_siemens_coeff * get_siemens_coefficient_organ(affected_organ)
return ..(shock_damage, source, siemens_coeff, def_zone)
/mob/living/carbon/human/Topic(href, href_list)
@@ -822,6 +829,27 @@
if (href_list["lookmob"])
var/mob/M = locate(href_list["lookmob"])
M.examine()
if (href_list["flavor_change"])
switch(href_list["flavor_change"])
if("done")
src << browse(null, "window=flavor_changes")
return
if("general")
var/msg = input(usr,"Update the general description of your character. This will be shown regardless of clothing, and may include OOC notes and preferences.","Flavor Text",html_decode(flavor_texts[href_list["flavor_change"]])) as message
if(msg != null)
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
msg = html_encode(msg)
flavor_texts[href_list["flavor_change"]] = msg
return
else
var/msg = input(usr,"Update the flavor text for your [href_list["flavor_change"]].","Flavor Text",html_decode(flavor_texts[href_list["flavor_change"]])) as message
if(msg != null)
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
msg = html_encode(msg)
flavor_texts[href_list["flavor_change"]] = msg
set_flavor()
return
..()
return
@@ -1091,8 +1119,7 @@
H.brainmob.mind.transfer_to(src)
del(H)
for(var/E in internal_organs)
var/datum/organ/internal/I = internal_organs[E]
for(var/datum/organ/internal/I in internal_organs)
I.damage = 0
for (var/datum/disease/virus in viruses)
@@ -1104,11 +1131,11 @@
..()
/mob/living/carbon/human/proc/is_lung_ruptured()
var/datum/organ/internal/lungs/L = internal_organs["lungs"]
var/datum/organ/internal/lungs/L = internal_organs_by_name["lungs"]
return L.is_bruised()
/mob/living/carbon/human/proc/rupture_lung()
var/datum/organ/internal/lungs/L = internal_organs["lungs"]
var/datum/organ/internal/lungs/L = internal_organs_by_name["lungs"]
if(!L.is_bruised())
src.custom_pain("You feel a stabbing pain in your chest!", 1)
@@ -1171,16 +1198,11 @@
var/list/visible_implants = list()
for(var/datum/organ/external/organ in src.organs)
for(var/obj/item/weapon/O in organ.implants)
if(!istype(O,/obj/item/weapon/implant) && O.w_class > class)
if(!istype(O,/obj/item/weapon/implant) && (O.w_class > class) && !istype(O,/obj/item/weapon/shard/shrapnel))
visible_implants += O
return(visible_implants)
/*
/mob/living/carbon/human/generate_name()
name = species.makeName(gender,src)
real_name = name
return name
*/
/mob/living/carbon/human/proc/handle_embedded_objects()
for(var/datum/organ/external/organ in src.organs)
@@ -1229,14 +1251,14 @@
return
usr << "Don't move until counting is finished."
var/time = world.timeofday
var/time = world.time
sleep(60)
if(usr.l_move_time >= time) //checks if our mob has moved during the sleep()
usr << "You moved while counting. Try again."
else
usr << "\blue [self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)]."
/mob/living/carbon/human/proc/set_species(var/new_species, var/force_organs)
/mob/living/carbon/human/proc/set_species(var/new_species, var/force_organs, var/default_colour)
if(!dna)
if(!new_species)
@@ -1261,11 +1283,22 @@
if(species.language)
add_language(species.language)
if(species.base_color && default_colour)
//Apply colour.
r_skin = hex2num(copytext(species.base_color,2,4))
g_skin = hex2num(copytext(species.base_color,4,6))
b_skin = hex2num(copytext(species.base_color,6,8))
else
r_skin = 0
g_skin = 0
b_skin = 0
species.handle_post_spawn(src)
spawn(0)
update_icons()
if(species)
species.handle_post_spawn(src)
return 1
else
return 0
@@ -1356,7 +1389,7 @@
if(last_special > world.time)
return
if(stat || paralysis || stunned || weakened || lying)
if(stat || paralysis || stunned || weakened || lying || restrained() || buckled)
src << "You cannot leap in your current state."
return
@@ -1366,17 +1399,24 @@
choices += M
choices -= src
var/mob/living/T = input(src,"Who do you wish to leap at?") in null|choices
var/mob/living/T = input(src,"Who do you wish to leap at?") as null|anything in choices
if(!T || !src || src.stat) return
if(get_dist(get_turf(T), get_turf(src)) > 6) return
last_special = world.time + 100
if(last_special > world.time)
return
if(stat || paralysis || stunned || weakened || lying || restrained() || buckled)
src << "You cannot leap in your current state."
return
last_special = world.time + 75
status_flags |= LEAPING
src.visible_message("<span class='warning'><b>\The [src]</b> leaps at [T]!</span>")
src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1)
src.throw_at(get_step(get_turf(T),get_turf(src)), 5, 1, src)
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
sleep(5)
@@ -1389,6 +1429,11 @@
T.Weaken(5)
//Only official raider vox get the grab and no self-prone."
if(src.mind && src.mind.special_role != "Vox Raider")
src.Weaken(5)
return
var/use_hand = "left"
if(l_hand)
if(r_hand)
@@ -1445,3 +1490,77 @@
M.apply_damage(50,BRUTE)
if(M.stat == 2)
M.gib()
/mob/living/carbon/human/proc/commune()
set category = "IC"
set name = "Commune with creature"
set desc = "Send a telepathic message to an unlucky recipient."
var/list/targets = list()
var/target = null
var/text = null
targets += getmobs() //Fill list, prompt user with list
target = input("Select a creature!", "Speak to creature", null, null) as null|anything in targets
if(!target) return
text = input("What would you like to say?", "Speak to creature", null, null)
text = trim(copytext(sanitize(text), 1, MAX_MESSAGE_LEN))
if(!text) return
var/mob/M = targets[target]
if(istype(M, /mob/dead/observer) || M.stat == DEAD)
src << "Not even a [src.species.name] can speak to the dead."
return
log_say("[key_name(src)] communed to [key_name(M)]: [text]")
M << "\blue Like lead slabs crashing into the ocean, alien thoughts drop into your mind: [text]"
if(istype(M,/mob/living/carbon/human))
var/mob/living/carbon/human/H = M
if(H.species.name == src.species.name)
return
H << "\red Your nose begins to bleed..."
H.drip(1)
/mob/living/carbon/human/print_flavor_text()
var/list/equipment = list(src.head,src.wear_mask,src.glasses,src.w_uniform,src.wear_suit,src.gloves,src.shoes)
var/head_exposed = 1
var/face_exposed = 1
var/eyes_exposed = 1
var/torso_exposed = 1
var/arms_exposed = 1
var/legs_exposed = 1
var/hands_exposed = 1
var/feet_exposed = 1
for(var/obj/item/clothing/C in equipment)
if(C.body_parts_covered & HEAD)
head_exposed = 0
if(C.body_parts_covered & FACE)
face_exposed = 0
if(C.body_parts_covered & EYES)
eyes_exposed = 0
if(C.body_parts_covered & UPPER_TORSO)
torso_exposed = 0
if(C.body_parts_covered & ARMS)
arms_exposed = 0
if(C.body_parts_covered & HANDS)
hands_exposed = 0
if(C.body_parts_covered & LEGS)
legs_exposed = 0
if(C.body_parts_covered & FEET)
feet_exposed = 0
flavor_text = flavor_texts["general"]
flavor_text += "\n\n"
for (var/T in flavor_texts)
if(flavor_texts[T] && flavor_texts[T] != "")
if((T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
flavor_text += flavor_texts[T]
flavor_text += "\n\n"
return ..()
@@ -160,7 +160,7 @@
//Rearranged, so claws don't increase weaken chance.
if(damage >= 5 && prob(50))
visible_message("\red <B>[M] has weakened [src]!</B>")
apply_effect(2, WEAKEN, armor_block)
apply_effect(3, WEAKEN, armor_block)
damage += attack.damage
apply_damage(damage, BRUTE, affecting, armor_block, sharp=attack.sharp, edge=attack.edge)
@@ -198,7 +198,7 @@
var/randn = rand(1, 100)
if (randn <= 25)
apply_effect(4, WEAKEN, run_armor_check(affecting, "melee"))
apply_effect(3, WEAKEN, run_armor_check(affecting, "melee"))
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("\red <B>[M] has pushed [src]!</B>")
return
@@ -17,7 +17,7 @@
/mob/living/carbon/human/getBrainLoss()
var/res = brainloss
var/datum/organ/internal/brain/sponge = internal_organs["brain"]
var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"]
if (sponge.is_bruised())
res += 20
if (sponge.is_broken())
@@ -312,20 +312,4 @@ This function restores all organs.
// Will set our damageoverlay icon to the next level, which will then be set back to the normal level the next mob.Life().
updatehealth()
hud_updateflag |= 1 << HEALTH_HUD
//Embedded projectile code.
if(!organ) return
if(istype(used_weapon,/obj/item/weapon))
var/obj/item/weapon/W = used_weapon //Sharp objects will always embed if they do enough damage.
if( (damage > (10*W.w_class)) && ( (sharp && !ismob(W.loc)) || prob(damage/W.w_class) ) )
organ.implants += W
visible_message("<span class='danger'>\The [W] sticks in the wound!</span>")
embedded_flag = 1
src.verbs += /mob/proc/yank_out_object
W.add_blood(src)
if(ismob(W.loc))
var/mob/living/H = W.loc
H.drop_item()
W.loc = src
return 1
@@ -10,22 +10,12 @@ emp_act
/mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone)
// BEGIN TASER NERF
/* Commenting out new-old taser nerf.
if(C.siemens_coefficient == 0) //If so, is that clothing shock proof?
if(prob(deflectchance))
visible_message("\red <B>The [P.name] gets deflected by [src]'s [C.name]!</B>") //DEFLECT!
visible_message("\red <B> Taser hit for [P.damage] damage!</B>")
del P
*/
/* Commenting out old Taser nerf
if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/armor))
if(istype(P, /obj/item/projectile/energy/electrode))
visible_message("\red <B>The [P.name] gets deflected by [src]'s [wear_suit.name]!</B>")
del P
return -1
*/
// END TASER NERF
var/datum/organ/external/organ = get_organ(check_zone(def_zone))
//Shields
if(check_shields(P.damage, "the [P.name]"))
P.on_hit(src, 2, def_zone)
return 2
//Laserproof armour
if(wear_suit && istype(wear_suit, /obj/item/clothing/suit/armor/laserproof))
@@ -52,87 +42,88 @@ emp_act
return -1 // complete projectile permutation
if(check_shields(P.damage, "the [P.name]"))
P.on_hit(src, 2, def_zone)
return 2
//BEGIN BOOK'S TASER NERF.
if(istype(P, /obj/item/projectile/energy/electrode))
var/datum/organ/external/select_area = get_organ(def_zone) // We're checking the outside, buddy!
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking?
// var/deflectchance=90 //Is it a CRITICAL HIT with that taser?
for(var/bp in body_parts) //Make an unregulated var to pass around.
if(!bp)
continue //Does this thing we're shooting even exist?
if(bp && istype(bp ,/obj/item/clothing)) // If it exists, and it's clothed
var/obj/item/clothing/C = bp // Then call an argument C to be that clothing!
if(C.body_parts_covered & select_area.body_part) // Is that body part being targeted covered?
P.agony=P.agony*C.siemens_coefficient
apply_effect(P.agony,AGONY,0)
flash_pain()
src <<"\red You have been shot!"
del P
var/obj/item/weapon/cloaking_device/C = locate((/obj/item/weapon/cloaking_device) in src)
if(C && C.active)
C.attack_self(src)//Should shut it off
update_icons()
src << "\blue Your [C.name] was disrupted!"
Stun(2)
if(istype(equipped(),/obj/item/device/assembly/signaler))
var/obj/item/device/assembly/signaler/signaler = equipped()
if(signaler.deadman && prob(80))
src.visible_message("\red [src] triggers their deadman's switch!")
signaler.signal()
return
//END TASER NERF
var/datum/organ/external/organ = get_organ(check_zone(def_zone))
var/armor = checkarmor(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))) && P.damage_type == BRUTE)
var/obj/item/weapon/shard/shrapnel/SP = new()
(SP.name) = "[P.name] shrapnel"
(SP.desc) = "[SP.desc] It looks like it was fired from [P.shot_from]."
(SP.loc) = organ
organ.implants += SP
visible_message("<span class='danger'>The projectile sticks in the wound!</span>")
embedded_flag = 1
src.verbs += /mob/proc/yank_out_object
SP.add_blood(src)
//Shrapnel
if (P.damage_type == BRUTE)
var/armor = getarmor_organ(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))))
var/obj/item/weapon/shard/shrapnel/SP = new()
(SP.name) = "[P.name] shrapnel"
(SP.desc) = "[SP.desc] It looks like it was fired from [P.shot_from]."
(SP.loc) = organ
organ.embed(SP)
return (..(P , def_zone))
/mob/living/carbon/human/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone)
var/datum/organ/external/affected = get_organ(check_zone(def_zone))
var/siemens_coeff = get_siemens_coefficient_organ(affected)
stun_amount *= siemens_coeff
agony_amount *= siemens_coeff
switch (def_zone)
if("head")
agony_amount *= 1.50
if("l_hand", "r_hand")
var/c_hand
if (def_zone == "l_hand")
c_hand = l_hand
else
c_hand = r_hand
if(c_hand && (stun_amount || agony_amount > 10))
msg_admin_attack("[src.name] ([src.ckey]) was disarmed by a stun effect")
u_equip(c_hand)
if (affected.status & ORGAN_ROBOT)
emote("me", 1, "drops what they were holding, their [affected.display_name] malfunctioning!")
else
var/emote_scream = pick("screams in pain and", "lets out a sharp cry and", "cries out and")
emote("me", 1, "[(species && species.flags & NO_PAIN) ? "" : emote_scream ] drops what they were holding in their [affected.display_name]!")
..(stun_amount, agony_amount, def_zone)
/mob/living/carbon/human/getarmor(var/def_zone, var/type)
var/armorval = 0
var/organnum = 0
var/total = 0
if(def_zone)
if(isorgan(def_zone))
return checkarmor(def_zone, type)
var/datum/organ/external/affecting = get_organ(ran_zone(def_zone))
return checkarmor(affecting, type)
return getarmor_organ(def_zone, type)
var/datum/organ/external/affecting = get_organ(def_zone)
return getarmor_organ(affecting, type)
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
for(var/datum/organ/external/organ in organs)
armorval += checkarmor(organ, type)
organnum++
return (armorval/max(organnum, 1))
for(var/organ_name in organs_by_name)
if (organ_name in organ_rel_size)
var/datum/organ/external/organ = organs_by_name[organ_name]
var/weight = organ_rel_size[organ_name]
armorval += getarmor_organ(organ, type) * weight
total += weight
return (armorval/max(total, 1))
//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ.
/mob/living/carbon/human/proc/get_siemens_coefficient_organ(var/datum/organ/external/def_zone)
if (!def_zone)
return 1.0
/mob/living/carbon/human/proc/checkarmor(var/datum/organ/external/def_zone, var/type)
var/siemens_coefficient = 1.0
var/list/clothing_items = list(head, wear_mask, wear_suit, w_uniform, gloves, shoes) // What all are we checking?
for(var/obj/item/clothing/C in clothing_items)
if(istype(C) && (C.body_parts_covered & def_zone.body_part)) // Is that body part being targeted covered?
siemens_coefficient *= C.siemens_coefficient
return siemens_coefficient
//this proc returns the armour value for a particular external organ.
/mob/living/carbon/human/proc/getarmor_organ(var/datum/organ/external/def_zone, var/type)
if(!type) return 0
var/protection = 0
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform)
for(var/bp in body_parts)
if(!bp) continue
if(bp && istype(bp ,/obj/item/clothing))
var/obj/item/clothing/C = bp
var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform)
for(var/gear in protective_gear)
if(gear && istype(gear ,/obj/item/clothing))
var/obj/item/clothing/C = gear
if(C.body_parts_covered & def_zone.body_part)
protection += C.armor[type]
return protection
@@ -194,11 +185,12 @@ emp_act
/mob/living/carbon/human/proc/attacked_by(var/obj/item/I, var/mob/living/user, var/def_zone)
if(!I || !user) return 0
var/target_zone = get_zone_with_miss_chance(user.zone_sel.selecting, src)
var/target_zone = def_zone? check_zone(def_zone) : get_zone_with_miss_chance(user.zone_sel.selecting, src)
if(user == src) // Attacking yourself can't miss
target_zone = user.zone_sel.selecting
if(!target_zone)
visible_message("\red <B>[user] misses [src] with \the [I]!</B>")
visible_message("\red <B>[user] misses [src] with \the [I]!")
return 0
var/datum/organ/external/affecting = get_organ(target_zone)
@@ -231,10 +223,16 @@ emp_act
visible_message("\red <B>[src] has been attacked in the [hit_area] with [I.name] by [user]!</B>")
var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].")
var/weapon_sharp = is_sharp(I)
var/weapon_edge = has_edge(I)
if ((weapon_sharp || weapon_edge) && prob(getarmor(target_zone, "melee")))
weapon_sharp = 0
weapon_edge = 0
if(armor >= 2) return 0
if(!I.force) return 0
apply_damage(I.force, I.damtype, affecting, armor , is_sharp(I), has_edge(I), I)
apply_damage(I.force, I.damtype, affecting, armor, sharp=weapon_sharp, edge=weapon_edge, used_weapon=I)
var/bloody = 0
if(((I.damtype == BRUTE) || (I.damtype == HALLOSS)) && prob(25 + (I.force * 2)))
@@ -273,13 +271,117 @@ emp_act
if("chest")//Easier to score a stun but lasts less time
if(prob((I.force + 10)))
apply_effect(5, WEAKEN, armor)
apply_effect(6, WEAKEN, armor)
visible_message("\red <B>[src] has been knocked down!</B>")
if(bloody)
bloody_body(src)
//Melee weapon embedded object code.
if (I.damtype == BRUTE && !I.is_robot_module())
var/damage = I.force
if (armor)
damage /= armor+1
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/embed_chance = weapon_sharp? damage/I.w_class : damage/(I.w_class*3)
var/embed_threshold = weapon_sharp? 5*I.w_class : 15*I.w_class
//Sharp objects will always embed if they do enough damage.
if((weapon_sharp && damage > (10*I.w_class)) || (damage > embed_threshold && prob(embed_chance)))
affecting.embed(I)
return 1
//this proc handles being hit by a thrown atom
/mob/living/carbon/human/hitby(atom/movable/AM as mob|obj,var/speed = 5)
if(istype(AM,/obj/))
var/obj/O = AM
var/dtype = BRUTE
if(istype(O,/obj/item/weapon))
var/obj/item/weapon/W = O
dtype = W.damtype
var/throw_damage = O.throwforce*(speed/5)
var/zone
if (istype(O.thrower, /mob/living))
var/mob/living/L = O.thrower
zone = check_zone(L.zone_sel.selecting)
else
zone = ran_zone("chest",75) //Hits a random part of the body, geared towards the chest
//check if we hit
if (O.throw_source)
var/distance = get_dist(O.throw_source, loc)
zone = get_zone_with_miss_chance(zone, src, min(15*(distance-2), 0))
else
zone = get_zone_with_miss_chance(zone, src, 15)
if(!zone)
visible_message("\blue \The [O] misses [src] narrowly!")
return
O.throwing = 0 //it hit, so stop moving
if ((O.thrower != src) && check_shields(throw_damage, "[O]"))
return
var/datum/organ/external/affecting = get_organ(zone)
var/hit_area = affecting.display_name
src.visible_message("\red [src] has been hit in the [hit_area] by [O].")
var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here
if(armor < 2)
apply_damage(throw_damage, dtype, zone, armor, is_sharp(O), has_edge(O), O)
if(ismob(O.thrower))
var/mob/M = O.thrower
var/client/assailant = M.client
if(assailant)
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been hit with a [O], thrown by [M.name] ([assailant.ckey])</font>")
M.attack_log += text("\[[time_stamp()]\] <font color='red'>Hit [src.name] ([src.ckey]) with a thrown [O]</font>")
if(!istype(src,/mob/living/simple_animal/mouse))
msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)")
//thrown weapon embedded object code.
if(dtype == BRUTE && istype(O,/obj/item))
var/obj/item/I = O
if (!I.is_robot_module())
var/sharp = is_sharp(I)
var/damage = throw_damage
if (armor)
damage /= armor+1
//blunt objects should really not be embedding in things unless a huge amount of force is involved
var/embed_chance = sharp? damage/I.w_class : damage/(I.w_class*3)
var/embed_threshold = sharp? 5*I.w_class : 15*I.w_class
//Sharp objects will always embed if they do enough damage.
//Thrown sharp objects have some momentum already and have a small chance to embed even if the damage is below the threshold
if((sharp && prob(damage/(10*I.w_class)*100)) || (damage > embed_threshold && prob(embed_chance)))
affecting.embed(I)
// Begin BS12 momentum-transfer code.
if(O.throw_source && speed >= 15)
var/obj/item/weapon/W = O
var/momentum = speed/2
var/dir = get_dir(O.throw_source, src)
visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!")
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
if(!W || !src) return
if(W.loc == src && W.sharp) //Projectile is embedded and suitable for pinning.
var/turf/T = near_wall(dir,2)
if(T)
src.loc = T
visible_message("<span class='warning'>[src] is pinned to the wall by [O]!</span>","<span class='warning'>You are pinned to the wall by [O]!</span>")
src.anchored = 1
src.pinned += O
/mob/living/carbon/human/proc/bloody_hands(var/mob/living/source, var/amount = 2)
if (gloves)
gloves.add_blood(source)
@@ -70,3 +70,5 @@
var/mob/remoteview_target = null
var/hand_blood_color
var/list/flavor_texts = list()
@@ -13,16 +13,17 @@
if(reagents.has_reagent("nuka_cola")) return -1
var/health_deficiency = (100 - health + halloss)
var/health_deficiency = (100 - health)
if(health_deficiency >= 40) tally += (health_deficiency / 25)
if(halloss >= 10) tally += (halloss / 10)
var/hungry = (500 - nutrition)/5 // So overeat would be 100 and default level would be 80
if (hungry >= 70) tally += hungry/50
if(wear_suit)
tally += wear_suit.slowdown
if(!buckled || (buckled && !istype(buckled, /obj/structure/stool/bed/chair/wheelchair)))
if(shoes)
tally += shoes.slowdown
@@ -110,6 +110,7 @@
head = null
if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR))
update_hair(0) //rebuild hair
update_inv_ears(0)
success = 1
update_inv_head()
else if (W == l_ear)
@@ -133,6 +134,7 @@
success = 1
if((W.flags & BLOCKHAIR) || (W.flags & BLOCKHEADHAIR))
update_hair(0) //rebuild hair
update_inv_ears(0)
if(internal)
if(internals)
internals.icon_state = "internal0"
@@ -214,6 +216,7 @@
src.wear_mask = W
if((wear_mask.flags & BLOCKHAIR) || (wear_mask.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_inv_ears(0)
W.equipped(src, slot)
update_inv_wear_mask(redraw_mob)
if(slot_handcuffed)
@@ -269,6 +272,7 @@
src.head = W
if((head.flags & BLOCKHAIR) || (head.flags & BLOCKHEADHAIR))
update_hair(redraw_mob) //rebuild hair
update_inv_ears(0)
if(istype(W,/obj/item/clothing/head/kitty))
W.update_icon(src)
W.equipped(src, slot)
@@ -671,20 +675,38 @@ It can still be worn/put on as normal.
slot_to_process = slot_handcuffed
if (target.handcuffed)
strip_item = target.handcuffed
else if (source != target && ishuman(source))
//check that we are still grabbing them
var/grabbing = 0
for (var/obj/item/weapon/grab/G in target.grabbed_by)
if (G.loc == source && G.state >= GRAB_AGGRESSIVE)
grabbing = 1
if (!grabbing)
slot_to_process = null
source << "\red Your grasp was broken before you could restrain [target]!"
if("legcuff")
slot_to_process = slot_legcuffed
if (target.legcuffed)
strip_item = target.legcuffed
if("splints")
for(var/organ in list("l_leg","r_leg","l_arm","r_arm"))
var/datum/organ/external/o = target.get_organ(organ)
if (o && o.status & ORGAN_SPLINTED)
var/obj/item/W = new /obj/item/stack/medical/splint(amount=1)
o.status &= ~ORGAN_SPLINTED
if (W)
W.loc = target.loc
W.layer = initial(W.layer)
W.add_fingerprint(source)
var/can_reach_splints = 1
if(target.wear_suit && istype(target.wear_suit,/obj/item/clothing/suit/space))
var/obj/item/clothing/suit/space/suit = target.wear_suit
if(suit.supporting_limbs && suit.supporting_limbs.len)
source << "You cannot remove the splints - [target]'s [suit] is supporting some of the breaks."
can_reach_splints = 0
if(can_reach_splints)
for(var/organ in list("l_leg","r_leg","l_arm","r_arm"))
var/datum/organ/external/o = target.get_organ(organ)
if (o && o.status & ORGAN_SPLINTED)
var/obj/item/W = new /obj/item/stack/medical/splint(amount=1)
o.status &= ~ORGAN_SPLINTED
if (W)
W.loc = target.loc
W.layer = initial(W.layer)
W.add_fingerprint(source)
if("CPR")
if ((target.health > config.health_threshold_dead && target.health < config.health_threshold_crit))
var/suff = min(target.getOxyLoss(), 5) //Pre-merge level, less healing, more prevention of dieing.
+313 -310
View File
@@ -2,7 +2,7 @@
//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick!
#define HUMAN_MAX_OXYLOSS 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it.
#define HUMAN_CRIT_MAX_OXYLOSS ( (last_tick_duration) /5) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 100HP to get through, so (1/3)*last_tick_duration per second. Breaths however only happen every 4 ticks.
#define HUMAN_CRIT_MAX_OXYLOSS ( (last_tick_duration) /6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks.
#define HEAT_DAMAGE_LEVEL_1 2 //Amount of damage applied when your body temperature just passes the 360.15k safety point
#define HEAT_DAMAGE_LEVEL_2 4 //Amount of damage applied when your body temperature passes the 400K point
@@ -21,9 +21,12 @@
#define COLD_GAS_DAMAGE_LEVEL_2 1.5 //Amount of damage applied when the current breath's temperature passes the 200K point
#define COLD_GAS_DAMAGE_LEVEL_3 3 //Amount of damage applied when the current breath's temperature passes the 120K point
#define RADIATION_SPEED_COEFFICIENT 0.1
/mob/living/carbon/human
var/oxygen_alert = 0
var/toxins_alert = 0
var/co2_alert = 0
var/fire_alert = 0
var/pressure_alert = 0
var/prev_gender = null // Debug for plural genders
@@ -32,6 +35,8 @@
/mob/living/carbon/human/Life()
set invisibility = 0
set background = 1
@@ -70,7 +75,7 @@
//No need to update all of these procs if the guy is dead.
if(stat != DEAD && !in_stasis)
if(air_master.current_cycle%4==2 || failed_last_breath) //First, resolve location and get a breath
if(air_master.current_cycle%4==2 || failed_last_breath || (health < config.health_threshold_crit)) //First, resolve location and get a breath
breathe() //Only try to take a breath every 4 ticks, unless suffocating
else //Still give containing object the chance to interact
@@ -156,8 +161,6 @@
return pressure_adjustment_coefficient
// Calculate how much of the enviroment pressure-difference affects the human.
/mob/living/carbon/human/calculate_affecting_pressure(var/pressure)
var/pressure_difference
@@ -281,60 +284,54 @@
speech_problem_flag = 1
gene.OnMobLife(src)
radiation = Clamp(radiation,0,100)
if (radiation)
if (radiation > 100)
radiation = 100
Weaken(10)
src << "\red You feel weak."
emote("collapse")
if(species.flags & RAD_ABSORB)
var/rads = radiation/25
radiation -= rads
nutrition += rads
adjustBruteLoss(-(rads))
adjustOxyLoss(-(rads))
adjustToxLoss(-(rads))
updatehealth()
return
if (radiation < 0)
radiation = 0
var/damage = 0
radiation -= 1 * RADIATION_SPEED_COEFFICIENT
if(prob(25))
damage = 1
else
if (radiation > 50)
damage = 1
radiation -= 1 * RADIATION_SPEED_COEFFICIENT
if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT))
radiation -= 5 * RADIATION_SPEED_COEFFICIENT
src << "<span class='warning'>You feel weak.</span>"
Weaken(3)
if(!lying)
emote("collapse")
if(prob(5) && prob(100 * RADIATION_SPEED_COEFFICIENT) && species.name == "Human") //apes go bald
if((h_style != "Bald" || f_style != "Shaved" ))
src << "<span class='warning'>Your hair falls out.</span>"
h_style = "Bald"
f_style = "Shaved"
update_hair()
if(species.flags & RAD_ABSORB)
var/rads = radiation/25
radiation -= rads
nutrition += rads
adjustBruteLoss(-(rads))
adjustOxyLoss(-(rads))
adjustToxLoss(-(rads))
updatehealth()
return
if (radiation > 75)
radiation -= 1 * RADIATION_SPEED_COEFFICIENT
damage = 3
if(prob(5))
take_overall_damage(0, 5 * RADIATION_SPEED_COEFFICIENT, used_weapon = "Radiation Burns")
if(prob(1))
src << "<span class='warning'>You feel strange!</span>"
adjustCloneLoss(5 * RADIATION_SPEED_COEFFICIENT)
emote("gasp")
var/damage = 0
switch(radiation)
if(1 to 49)
radiation--
if(prob(25))
adjustToxLoss(1)
damage = 1
updatehealth()
if(50 to 74)
radiation -= 2
damage = 1
adjustToxLoss(1)
if(prob(5))
radiation -= 5
Weaken(3)
src << "\red You feel weak."
emote("collapse")
updatehealth()
if(75 to 100)
radiation -= 3
adjustToxLoss(3)
damage = 1
if(prob(1))
src << "\red You mutate!"
randmutb(src)
domutcheck(src,null)
emote("gasp")
updatehealth()
if(damage && organs.len)
if(damage)
adjustToxLoss(damage * RADIATION_SPEED_COEFFICIENT)
updatehealth()
if(organs.len)
var/datum/organ/external/O = pick(organs)
if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage)
@@ -343,9 +340,6 @@
if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return
if(species && (species.flags & NO_BREATHE || species.flags & IS_SYNTHETIC)) return
var/datum/organ/internal/lungs/L = internal_organs["lungs"]
L.process()
var/datum/gas_mixture/environment = loc.return_air()
var/datum/gas_mixture/breath
@@ -377,26 +371,15 @@
breath_moles = (ONE_ATMOSPHERE*BREATH_VOLUME/R_IDEAL_GAS_EQUATION*environment.temperature)
else*/
// Not enough air around, take a percentage of what's there to model this properly
breath_moles = environment.total_moles()*BREATH_PERCENTAGE
breath_moles = environment.total_moles*BREATH_PERCENTAGE
breath = loc.remove_air(breath_moles)
if(istype(wear_mask, /obj/item/clothing/mask/gas) && breath)
var/obj/item/clothing/mask/gas/G = wear_mask
var/datum/gas_mixture/filtered = new
filtered.copy_from(breath)
filtered.toxins *= G.gas_filter_strength
for(var/datum/gas/gas in filtered.trace_gases)
gas.moles *= G.gas_filter_strength
filtered.update_values()
if(istype(wear_mask, /obj/item/clothing/mask) && breath)
var/obj/item/clothing/mask/M = wear_mask
var/datum/gas_mixture/filtered = M.filter_air(breath)
loc.assume_air(filtered)
breath.toxins *= 1 - G.gas_filter_strength
for(var/datum/gas/gas in breath.trace_gases)
gas.moles *= 1 - G.gas_filter_strength
breath.update_values()
if(!is_lung_ruptured())
if(!breath || breath.total_moles < BREATH_MOLES / 5 || breath.total_moles > BREATH_MOLES * 5)
if(prob(5))
@@ -459,7 +442,7 @@
if(status_flags & GODMODE)
return
if(!breath || (breath.total_moles() == 0) || suiciding)
if(!breath || (breath.total_moles == 0) || suiciding)
if(suiciding)
adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster
failed_last_breath = 1
@@ -478,166 +461,147 @@
var/safe_pressure_min = 16 // Minimum safe partial pressure of breathable gas in kPa
//var/safe_pressure_max = 140 // Maximum safe partial pressure of breathable gas in kPa (Not used for now)
var/safe_exhaled_max = 10 // Yes it's an arbitrary value who cares?
var/safe_exhaled_max = 10
var/safe_toxins_max = 0.005
var/SA_para_min = 1
var/SA_sleep_min = 5
var/inhaled_gas_used = 0
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/inhaling
var/exhaling
var/poison
var/no_exhale
var/exhaling
switch(species.breath_type)
if("nitrogen")
inhaling = breath.nitrogen
if("plasma")
inhaling = breath.toxins
if("C02")
inhaling = breath.carbon_dioxide
else
inhaling = breath.oxygen
var/breath_type
var/poison_type
var/exhale_type
switch(species.poison_type)
if("oxygen")
poison = breath.oxygen
if("nitrogen")
poison = breath.nitrogen
if("C02")
poison = breath.carbon_dioxide
else
poison = breath.toxins
var/failed_inhale = 0
var/failed_exhale = 0
switch(species.exhale_type)
if("C02")
exhaling = breath.carbon_dioxide
if("oxygen")
exhaling = breath.oxygen
if("nitrogen")
exhaling = breath.nitrogen
if("plasma")
exhaling = breath.toxins
else
no_exhale = 1
if(species.breath_type)
breath_type = species.breath_type
else
breath_type = "oxygen"
inhaling = breath.gas[breath_type]
var/inhale_pp = (inhaling/breath.total_moles())*breath_pressure
var/toxins_pp = (poison/breath.total_moles())*breath_pressure
var/exhaled_pp = (exhaling/breath.total_moles())*breath_pressure
if(species.poison_type)
poison_type = species.poison_type
else
poison_type = "toxins"
poison = breath.gas[poison_type]
if(species.exhale_type)
exhale_type = species.exhale_type
exhaling = breath.gas[exhale_type]
else
exhaling = 0
var/inhale_pp = (inhaling/breath.total_moles)*breath_pressure
var/toxins_pp = (poison/breath.total_moles)*breath_pressure
var/exhaled_pp = (exhaling/breath.total_moles)*breath_pressure
// Not enough to breathe
if(inhale_pp < safe_pressure_min)
if(prob(20))
spawn(0) emote("gasp")
if(inhale_pp > 0)
var/ratio = inhale_pp/safe_pressure_min
// Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!)
adjustOxyLoss(min(5*(1 - ratio), HUMAN_MAX_OXYLOSS))
failed_last_breath = 1
inhaled_gas_used = inhaling*ratio/6
else
adjustOxyLoss(HUMAN_MAX_OXYLOSS)
failed_last_breath = 1
var/ratio = inhale_pp/safe_pressure_min
// Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS after all!)
adjustOxyLoss(max(HUMAN_MAX_OXYLOSS*(1-ratio), 0))
failed_inhale = 1
oxygen_alert = max(oxygen_alert, 1)
else
// We're in safe limits
failed_last_breath = 0
adjustOxyLoss(-5)
inhaled_gas_used = inhaling/6
oxygen_alert = 0
switch(species.breath_type)
if("nitrogen")
breath.nitrogen -= inhaled_gas_used
inhaled_gas_used = inhaling/6
breath.adjust_gas(breath_type, -inhaled_gas_used, update = 0) //update afterwards
if(exhale_type)
breath.adjust_gas_temp(exhale_type, inhaled_gas_used, bodytemperature, update = 0) //update afterwards
// Too much exhaled gas in the air
if(exhaled_pp > safe_exhaled_max)
if (!co2_alert|| prob(15))
var/word = pick("extremely dizzy","short of breath","faint","confused")
src << "<span class='danger'>You feel [word].</span>"
adjustOxyLoss(HUMAN_MAX_OXYLOSS)
co2_alert = 1
failed_exhale = 1
else if(exhaled_pp > safe_exhaled_max * 0.7)
if (!co2_alert || prob(1))
var/word = pick("dizzy","short of breath","faint","momentarily confused")
src << "<span class='warning>You feel [word].</span>"
//scale linearly from 0 to 1 between safe_exhaled_max and safe_exhaled_max*0.7
var/ratio = 1.0 - (safe_exhaled_max - exhaled_pp)/(safe_exhaled_max*0.3)
//give them some oxyloss, up to the limit - we don't want people falling unconcious due to CO2 alone until they're pretty close to safe_exhaled_max.
if (getOxyLoss() < 50*ratio)
adjustOxyLoss(HUMAN_MAX_OXYLOSS)
co2_alert = 1
failed_exhale = 1
else if(exhaled_pp > safe_exhaled_max * 0.6)
if (prob(0.3))
var/word = pick("a little dizzy","short of breath")
src << "<span class='warning>You feel [word].</span>"
else
breath.oxygen -= inhaled_gas_used
if(!no_exhale)
switch(species.exhale_type)
if("oxygen")
breath.oxygen += inhaled_gas_used
if("nitrogen")
breath.nitrogen += inhaled_gas_used
if("plasma")
breath.toxins += inhaled_gas_used
if("C02")
breath.carbon_dioxide += inhaled_gas_used
// CO2 does not affect failed_last_breath. So if there was enough oxygen in the air but too much co2,
// this will hurt you, but only once per 4 ticks, instead of once per tick.
if(exhaled_pp > safe_exhaled_max)
// If it's the first breath with too much CO2 in it, lets start a counter,
// then have them pass out after 12s or so.
if(!co2overloadtime)
co2overloadtime = world.time
else if(world.time - co2overloadtime > 120)
// Lets hurt em a little, let them know we mean business
Paralyse(3)
adjustOxyLoss(3)
// They've been in here 30s now, lets start to kill them for their own good!
if(world.time - co2overloadtime > 300)
adjustOxyLoss(8)
// Lets give them some chance to know somethings not right though I guess.
if(prob(20))
spawn(0) emote("cough")
else
co2overloadtime = 0
co2_alert = 0
// Too much poison in the air.
if(toxins_pp > safe_toxins_max)
var/ratio = (poison/safe_toxins_max) * 10
if(reagents)
//TODO: Fix Ravensdale's shit, make toxins toxins again instead of phoron.
reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE))
breath.adjust_gas(poison_type, -poison/6, update = 0) //update after
toxins_alert = max(toxins_alert, 1)
else
toxins_alert = 0
// If there's some other shit in the air lets deal with it here.
if(breath.trace_gases.len)
for(var/datum/gas/sleeping_agent/SA in breath.trace_gases)
var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure
if(breath.gas["sleeping_agent"])
var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure
// Enough to make us paralysed for a bit
if(SA_pp > SA_para_min)
// Enough to make us paralysed for a bit
if(SA_pp > SA_para_min)
// 3 gives them one second to wake up and run away a bit!
Paralyse(3)
// 3 gives them one second to wake up and run away a bit!
Paralyse(3)
// Enough to make us sleep as well
if(SA_pp > SA_sleep_min)
sleeping = min(sleeping+2, 10)
// Enough to make us sleep as well
if(SA_pp > SA_sleep_min)
sleeping = min(sleeping+2, 10)
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
else if(SA_pp > 0.15)
if(prob(20))
spawn(0) emote(pick("giggle", "laugh"))
SA.moles = 0
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
else if(SA_pp > 0.15)
if(prob(20))
spawn(0) emote(pick("giggle", "laugh"))
breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"]/6, update = 0) //update after
if( (abs(310.15 - breath.temperature) > 50) && !(COLD_RESISTANCE in mutations)) // Hot air hurts :(
// Were we able to breathe?
if (failed_inhale || failed_exhale)
failed_last_breath = 1
else
failed_last_breath = 0
adjustOxyLoss(-5)
if(status_flags & GODMODE)
return 1
// Hot air hurts :(
if( (breath.temperature < species.cold_level_1 || breath.temperature > species.heat_level_1) && !(COLD_RESISTANCE in mutations))
if(breath.temperature < species.cold_level_1)
if(prob(20))
src << "\red You feel your face freezing and an icicle forming in your lungs!"
src << "<span class='danger'>You feel your face freezing and icicles forming in your lungs!</span>"
else if(breath.temperature > species.heat_level_1)
if(prob(20))
src << "\red You feel your face burning and a searing heat in your lungs!"
src << "<span class='danger'>You feel your face burning and a searing heat in your lungs!</span>"
switch(breath.temperature)
if(-INFINITY to species.cold_level_3)
@@ -659,8 +623,23 @@
apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
fire_alert = max(fire_alert, 2)
//Temporary fixes to the alerts.
//breathing in hot/cold air also heats/cools you a bit
var/temp_adj = breath.temperature - bodytemperature
if (temp_adj < 0)
temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
else
temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE)
temp_adj *= relative_density
if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX
if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX
//world << "Breath: [breath.temperature], [src]: [bodytemperature], Adjusting: [temp_adj]"
bodytemperature += temp_adj
breath.update_values()
return 1
proc/handle_environment(datum/gas_mixture/environment)
@@ -671,68 +650,75 @@
var/pressure = environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure)
//Check for contaminants before anything else because we don't want to skip it.
for(var/g in environment.gas)
if(gas_data.flags[g] & XGM_GAS_CONTAMINANT && environment.gas[g] > gas_data.overlay_limit[g] + 1)
pl_effects()
break
if(!istype(get_turf(src), /turf/space)) //space is not meant to change your body temperature.
var/loc_temp = T0C
if(istype(loc, /obj/mecha))
var/obj/mecha/M = loc
loc_temp = M.return_temperature()
else if(istype(get_turf(src), /turf/space))
else if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
loc_temp = loc:air_contents.temperature
else
loc_temp = environment.temperature
if(adjusted_pressure < species.warning_low_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5 && environment.toxins < MOLES_PLASMA_VISIBLE)
if(adjusted_pressure < species.warning_high_pressure && adjusted_pressure > species.warning_low_pressure && abs(loc_temp - bodytemperature) < 20 && bodytemperature < species.heat_level_1 && bodytemperature > species.cold_level_1)
pressure_alert = 0
return // Temperatures are within normal ranges, fuck all this processing. ~Ccomp
//Body temperature is adjusted in two steps. Firstly your body tries to stabilize itself a bit.
if(stat != 2)
stabilize_temperature_from_calories()
//Body temperature adjusts depending on surrounding atmosphere based on your thermal protection
var/temp_adj = 0
if(loc_temp < bodytemperature) //Place is colder than we are
var/thermal_protection = get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR) //this will be negative
else if (loc_temp > bodytemperature) //Place is hotter than we are
var/thermal_protection = get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
temp_adj = (1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR)
//After then, it reacts to the surrounding atmosphere based on your thermal protection
if(!on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases
if(loc_temp < BODYTEMP_COLD_DAMAGE_LIMIT) //Place is colder than we are
var/thermal_protection = get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
var/amt = min((1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR), BODYTEMP_COOLING_MAX)
// log_debug("[loc_temp] is Cold. Cooling by [amt]")
bodytemperature += amt
else if (loc_temp > BODYTEMP_HEAT_DAMAGE_LIMIT) //Place is hotter than we are
var/thermal_protection = get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(thermal_protection < 1)
var/amt = min((1-thermal_protection) * ((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX)
// log_debug("[loc_temp] is Heat. Heating up by [amt]")
bodytemperature += amt
//Use heat transfer as proportional to the gas density. However, we only care about the relative density vs standard 101 kPa/20 C air. Therefore we can use mole ratios
var/relative_density = environment.total_moles / MOLES_CELLSTANDARD
temp_adj *= relative_density
if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX
if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX
//world << "Environment: [loc_temp], [src]: [bodytemperature], Adjusting: [temp_adj]"
bodytemperature += temp_adj
// +/- 50 degrees from 310.15K is the 'safe' zone, where no damage is dealt.
if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT)
if(bodytemperature > species.heat_level_1)
//Body temperature is too hot.
fire_alert = max(fire_alert, 1)
if(status_flags & GODMODE) return 1 //godmode
switch(bodytemperature)
if(360 to 400)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN, used_weapon = "High Body Temperature")
if(species.heat_level_1 to species.heat_level_2)
take_overall_damage(burn=HEAT_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature")
fire_alert = max(fire_alert, 2)
if(400 to 1000)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN, used_weapon = "High Body Temperature")
if(species.heat_level_2 to species.heat_level_3)
take_overall_damage(burn=HEAT_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature")
fire_alert = max(fire_alert, 2)
if(1000 to INFINITY)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN, used_weapon = "High Body Temperature")
if(species.heat_level_3 to INFINITY)
take_overall_damage(burn=HEAT_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature")
fire_alert = max(fire_alert, 2)
else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
else if(bodytemperature < species.cold_level_1)
fire_alert = max(fire_alert, 1)
if(status_flags & GODMODE) return 1 //godmode
if(!istype(loc, /obj/machinery/atmospherics/unary/cryo_cell))
switch(bodytemperature)
if(200 to 260)
apply_damage(COLD_DAMAGE_LEVEL_1, BURN, used_weapon = "Low Body Temperature")
if(species.cold_level_2 to species.cold_level_1)
take_overall_damage(burn=COLD_DAMAGE_LEVEL_1, used_weapon = "High Body Temperature")
fire_alert = max(fire_alert, 1)
if(120 to 200)
apply_damage(COLD_DAMAGE_LEVEL_2, BURN, used_weapon = "Low Body Temperature")
if(species.cold_level_3 to species.cold_level_2)
take_overall_damage(burn=COLD_DAMAGE_LEVEL_2, used_weapon = "High Body Temperature")
fire_alert = max(fire_alert, 1)
if(-INFINITY to 120)
apply_damage(COLD_DAMAGE_LEVEL_3, BURN, used_weapon = "Low Body Temperature")
if(-INFINITY to species.cold_level_3)
take_overall_damage(burn=COLD_DAMAGE_LEVEL_3, used_weapon = "High Body Temperature")
fire_alert = max(fire_alert, 1)
// Account for massive pressure differences. Done by Polymorph
@@ -740,7 +726,8 @@
if(status_flags & GODMODE) return 1 //godmode
if(adjusted_pressure >= species.hazard_high_pressure)
adjustBruteLoss( min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
var/pressure_damage = min( ( (adjusted_pressure / species.hazard_high_pressure) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE)
take_overall_damage(brute=pressure_damage, used_weapon = "High Pressure")
pressure_alert = 2
else if(adjusted_pressure >= species.warning_high_pressure)
pressure_alert = 1
@@ -748,24 +735,13 @@
pressure_alert = 0
else if(adjusted_pressure >= species.hazard_low_pressure)
pressure_alert = -1
if(species && species.flags & IS_SYNTHETIC)
bodytemperature += 0.5 * TEMPERATURE_DAMAGE_COEFFICIENT //Synthetics suffer overheating in a vaccuum. ~Z
else
if(species && species.flags & IS_SYNTHETIC)
bodytemperature += 1 * TEMPERATURE_DAMAGE_COEFFICIENT
if( !(COLD_RESISTANCE in mutations))
adjustBruteLoss( LOW_PRESSURE_DAMAGE )
take_overall_damage(brute=LOW_PRESSURE_DAMAGE, used_weapon = "Low Pressure")
pressure_alert = -2
else
pressure_alert = -1
if(environment.toxins > MOLES_PLASMA_VISIBLE)
pl_effects()
return
///FIRE CODE
handle_fire()
@@ -796,26 +772,34 @@
return temp_change
*/
proc/stabilize_temperature_from_calories()
var/body_temperature_difference = 310.15 - bodytemperature
proc/stabilize_body_temperature()
if (species.flags & IS_SYNTHETIC)
bodytemperature += species.synth_temp_gain //just keep putting out heat.
return
var/body_temperature_difference = species.body_temperature - bodytemperature
if (abs(body_temperature_difference) < 0.5)
return //fuck this precision
switch(bodytemperature)
if(-INFINITY to 260.15) //260.15 is 310.15 - 50, the temperature where you start to feel effects.
if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up.
nutrition -= 2
var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
if(bodytemperature < species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects.
if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up.
nutrition -= 2
var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
//world << "Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]"
// log_debug("Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]")
bodytemperature += recovery_amt
if(260.15 to 360.15)
var/recovery_amt = body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR
bodytemperature += recovery_amt
else if(species.cold_level_1 <= bodytemperature && bodytemperature <= species.heat_level_1)
var/recovery_amt = body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR
//world << "Norm. Difference = [body_temperature_difference]. Recovering [recovery_amt]"
// log_debug("Norm. Difference = [body_temperature_difference]. Recovering [recovery_amt]")
bodytemperature += recovery_amt
if(360.15 to INFINITY) //360.15 is 310.15 + 50, the temperature where you start to feel effects.
//We totally need a sweat system cause it totally makes sense...~
var/recovery_amt = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers
bodytemperature += recovery_amt
else if(bodytemperature > species.heat_level_1) //360.15 is 310.15 + 50, the temperature where you start to feel effects.
//We totally need a sweat system cause it totally makes sense...~
var/recovery_amt = min((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), -BODYTEMP_AUTORECOVERY_MINIMUM) //We're dealing with negative numbers
//world << "Hot. Difference = [body_temperature_difference]. Recovering [recovery_amt]"
// log_debug("Hot. Difference = [body_temperature_difference]. Recovering [recovery_amt]")
bodytemperature += recovery_amt
bodytemperature += recovery_amt
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, UPPER_TORSO, LOWER_TORSO, etc. See setup.dm for the full list)
proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
@@ -995,19 +979,18 @@
proc/handle_chemicals_in_body()
if(reagents && !(species.flags & IS_SYNTHETIC)) //Synths don't process reagents.
var/alien = 0 //Not the best way to handle it, but neater than checking this for every single reagent proc.
if(species && species.name == "Diona")
alien = 1
else if(species && species.name == "Vox")
alien = 2
var/alien = 0
if(species && species.reagent_tag)
alien = species.reagent_tag
reagents.metabolize(src,alien)
var/total_plasmaloss = 0
for(var/obj/item/I in src)
if(I.contaminated)
total_plasmaloss += vsc.plc.CONTAMINATION_LOSS
var/total_plasmaloss = 0
for(var/obj/item/I in src)
if(I.contaminated)
total_plasmaloss += vsc.plc.CONTAMINATION_LOSS
if(!(status_flags & GODMODE)) adjustToxLoss(total_plasmaloss)
if(status_flags & GODMODE) return 0 //godmode
adjustToxLoss(total_plasmaloss)
if(species.flags & REQUIRE_LIGHT)
var/light_amount = 0 //how much light there is in the place, affects receiving nutrition and healing
@@ -1095,23 +1078,21 @@
if(!(species.flags & IS_SYNTHETIC)) handle_trace_chems()
var/datum/organ/internal/liver/liver = internal_organs["liver"]
liver.process()
var/datum/organ/internal/eyes/eyes = internal_organs["eyes"]
eyes.process()
updatehealth()
return //TODO: DEFERRED
proc/handle_regular_status_updates()
if(status_flags & GODMODE) return 0
if(stat == DEAD) //DEAD. BROWN BREAD. SWIMMING WITH THE SPESS CARP
blinded = 1
silent = 0
else //ALIVE. LIGHTS ARE ON
updatehealth() //TODO
if(!in_stasis)
stabilize_body_temperature() //Body temperature adjusts itself
handle_organs() //Optimized.
handle_blood()
@@ -1223,33 +1204,12 @@
ear_damage = max(ear_damage-0.05, 0)
//Other
if(stunned)
speech_problem_flag = 1
AdjustStunned(-1)
handle_statuses()
if(weakened)
weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times
if(stuttering)
speech_problem_flag = 1
stuttering = max(stuttering-1, 0)
if (slurring)
speech_problem_flag = 1
slurring = max(slurring-1, 0)
if(silent)
speech_problem_flag = 1
silent = max(silent-1, 0)
if(druggy)
druggy = max(druggy-1, 0)
/*
// Increase germ_level regularly
if(prob(40))
germ_level += 1
// If you're dirty, your gloves will become dirty, too.
if(gloves && germ_level > gloves.germ_level && prob(10))
gloves.germ_level += 1
*/
return 1
proc/handle_regular_hud_updates()
@@ -1267,7 +1227,7 @@
if(copytext(hud.icon_state,1,4) == "hud") //ugly, but icon comparison is worse, I believe
client.images.Remove(hud)
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg, global_hud.lum)
client.screen.Remove(global_hud.blurry, global_hud.druggy, global_hud.vimpaired, global_hud.darkMask, global_hud.nvg)
update_action_buttons()
@@ -1381,7 +1341,7 @@
if(XRAY in mutations)
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(seer==1)
var/obj/effect/rune/R = locate() in loc
@@ -1391,7 +1351,9 @@
see_invisible = SEE_INVISIBLE_LIVING
seer = 0
var/tmp/has_ninja_mask = 0
if(istype(wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja))
has_ninja_mask = 1
var/obj/item/clothing/mask/gas/voice/space_ninja/O = wear_mask
switch(O.mode)
if(0)
@@ -1440,7 +1402,7 @@
if(!druggy)
see_invisible = SEE_INVISIBLE_LIVING
else if(!seer)
else if(!seer && !has_ninja_mask)
see_invisible = SEE_INVISIBLE_LIVING
@@ -1491,17 +1453,46 @@
else fire.icon_state = "fire0"
if(bodytemp)
switch(bodytemperature) //310.055 optimal body temp
if(370 to INFINITY) bodytemp.icon_state = "temp4"
if(350 to 370) bodytemp.icon_state = "temp3"
if(335 to 350) bodytemp.icon_state = "temp2"
if(320 to 335) bodytemp.icon_state = "temp1"
if(300 to 320) bodytemp.icon_state = "temp0"
if(295 to 300) bodytemp.icon_state = "temp-1"
if(280 to 295) bodytemp.icon_state = "temp-2"
if(260 to 280) bodytemp.icon_state = "temp-3"
else bodytemp.icon_state = "temp-4"
if (!species)
switch(bodytemperature) //310.055 optimal body temp
if(370 to INFINITY) bodytemp.icon_state = "temp4"
if(350 to 370) bodytemp.icon_state = "temp3"
if(335 to 350) bodytemp.icon_state = "temp2"
if(320 to 335) bodytemp.icon_state = "temp1"
if(300 to 320) bodytemp.icon_state = "temp0"
if(295 to 300) bodytemp.icon_state = "temp-1"
if(280 to 295) bodytemp.icon_state = "temp-2"
if(260 to 280) bodytemp.icon_state = "temp-3"
else bodytemp.icon_state = "temp-4"
else
var/temp_step
if (bodytemperature >= species.body_temperature)
temp_step = (species.heat_level_1 - species.body_temperature)/4
if (bodytemperature >= species.heat_level_1)
bodytemp.icon_state = "temp4"
else if (bodytemperature >= species.body_temperature + temp_step*3)
bodytemp.icon_state = "temp3"
else if (bodytemperature >= species.body_temperature + temp_step*2)
bodytemp.icon_state = "temp2"
else if (bodytemperature >= species.body_temperature + temp_step*1)
bodytemp.icon_state = "temp1"
else
bodytemp.icon_state = "temp0"
else if (bodytemperature < species.body_temperature)
temp_step = (species.body_temperature - species.cold_level_1)/4
if (bodytemperature <= species.cold_level_1)
bodytemp.icon_state = "temp-4"
else if (bodytemperature <= species.body_temperature - temp_step*3)
bodytemp.icon_state = "temp-3"
else if (bodytemperature <= species.body_temperature - temp_step*2)
bodytemp.icon_state = "temp-2"
else if (bodytemperature <= species.body_temperature - temp_step*1)
bodytemp.icon_state = "temp-1"
else
bodytemp.icon_state = "temp0"
if(blind)
if(blinded) blind.layer = 18
else blind.layer = 0
@@ -1684,26 +1675,19 @@
if(status_flags & FAKEDEATH)
temp = PULSE_NONE //pretend that we're dead. unlike actual death, can be inflienced by meds
//handles different chems' influence on pulse
for(var/datum/reagent/R in reagents.reagent_list)
if(R.id in bradycardics)
if(temp <= PULSE_THREADY && temp >= PULSE_NORM)
temp--
break //one reagent is enough
//comment out the breaks to make med effects stack
for(var/datum/reagent/R in reagents.reagent_list) //handles different chems' influence on pulse
if(R.id in tachycardics)
if(temp <= PULSE_FAST && temp >= PULSE_NONE)
temp++
break
for(var/datum/reagent/R in reagents.reagent_list) //To avoid using fakedeath
if(R.id in heartstopper)
if(R.id in heartstopper) //To avoid using fakedeath
temp = PULSE_NONE
break
for(var/datum/reagent/R in reagents.reagent_list) //Conditional heart-stoppage
if(R.id in cheartstopper)
if(R.id in cheartstopper) //Conditional heart-stoppage
if(R.volume >= R.overdose)
temp = PULSE_NONE
break
return temp
@@ -1852,6 +1836,25 @@
hud_list[SPECIALROLE_HUD] = holder
hud_updateflag = 0
/mob/living/carbon/human/handle_silent()
if(..())
speech_problem_flag = 1
return silent
/mob/living/carbon/human/handle_slurring()
if(..())
speech_problem_flag = 1
return slurring
/mob/living/carbon/human/handle_stunned()
if(..())
speech_problem_flag = 1
return stunned
/mob/living/carbon/human/handle_stuttering()
if(..())
speech_problem_flag = 1
return stuttering
#undef HUMAN_MAX_OXYLOSS
#undef HUMAN_CRIT_MAX_OXYLOSS
+77 -90
View File
@@ -1,4 +1,5 @@
/mob/living/carbon/human/say(var/message, var/verb = "says")
/mob/living/carbon/human/say(var/message)
var/verb = "says"
var/alt_name = ""
var/message_range = world.view
var/italics = 0
@@ -13,7 +14,9 @@
if(stat == 2)
return say_dead(message)
if (istype(wear_mask, /obj/item/clothing/mask/muzzle)) //Todo: Add this to speech_problem_flag checks.
var/message_mode = parse_message_mode(message, "headset")
if (istype(wear_mask, /obj/item/clothing/mask/muzzle) && message_mode != "changeling") //Todo: Add this to speech_problem_flag checks.
return
if(copytext(message,1,2) == "*")
@@ -23,10 +26,9 @@
alt_name = "(as [get_id_name("Unknown")])"
//parse the radio code and consume it
var/message_mode = parse_message_mode(message)
if (message_mode)
if (message_mode == "headset")
message = copytext(message,2)
message = copytext(message,2) //it would be really nice if the parse procs could do this for us.
else
message = copytext(message,3)
@@ -35,6 +37,7 @@
if (speaking)
verb = speaking.speech_verb
message = copytext(message,3)
message = capitalize(trim(message))
if(speech_problem_flag)
@@ -46,72 +49,59 @@
if(!message || stat)
return
var/ending = copytext(message, length(message))
if(verb == "says")
if(ending == "!")
verb = pick("exclaims","shouts","yells")
if(ending == "?")
verb = "asks"
else
if(ending == "!")
verb = "orders"
if(ending == "?")
verb = "requests"
if(speaking) //speaking = null if used through say without a language
if(!speaking.vocal)
sign(message, verb, speaking, alt_name, italics, message_range)
return
if (!speaking)
var/ending = copytext(message, length(message))
if(ending=="!")
verb=pick("exclaims","shouts","yells")
if(ending=="?")
verb="asks"
var/list/obj/item/used_radios = new
switch (message_mode)
if("headset")
if(!(stunned >= 4))
if(l_ear && istype(l_ear,/obj/item/device/radio))
var/obj/item/device/radio/R = l_ear
R.talk_into(src,message,null,verb,speaking)
used_radios += l_ear
else if(r_ear && istype(r_ear,/obj/item/device/radio))
var/obj/item/device/radio/R = r_ear
R.talk_into(src,message,null,verb,speaking)
used_radios += r_ear
if(l_ear && istype(l_ear,/obj/item/device/radio))
var/obj/item/device/radio/R = l_ear
R.talk_into(src,message,null,verb,speaking)
used_radios += l_ear
else if(r_ear && istype(r_ear,/obj/item/device/radio))
var/obj/item/device/radio/R = r_ear
R.talk_into(src,message,null,verb,speaking)
used_radios += r_ear
if("right ear")
if(!(stunned >= 4))
var/obj/item/device/radio/R
var/has_radio = 0
if(r_ear && istype(r_ear,/obj/item/device/radio))
R = r_ear
has_radio = 1
if(r_hand && istype(r_hand, /obj/item/device/radio))
R = r_hand
has_radio = 1
if(has_radio)
R.talk_into(src,message,null,verb,speaking)
used_radios += R
var/obj/item/device/radio/R
var/has_radio = 0
if(r_ear && istype(r_ear,/obj/item/device/radio))
R = r_ear
has_radio = 1
if(r_hand && istype(r_hand, /obj/item/device/radio))
R = r_hand
has_radio = 1
if(has_radio)
R.talk_into(src,message,null,verb,speaking)
used_radios += R
if("left ear")
if(!(stunned >= 4))
var/obj/item/device/radio/R
var/has_radio = 0
if(l_ear && istype(l_ear,/obj/item/device/radio))
R = l_ear
has_radio = 1
if(l_hand && istype(l_hand,/obj/item/device/radio))
R = l_hand
has_radio = 1
if(has_radio)
R.talk_into(src,message,null,verb,speaking)
used_radios += R
var/obj/item/device/radio/R
var/has_radio = 0
if(l_ear && istype(l_ear,/obj/item/device/radio))
R = l_ear
has_radio = 1
if(l_hand && istype(l_hand,/obj/item/device/radio))
R = l_hand
has_radio = 1
if(has_radio)
R.talk_into(src,message,null,verb,speaking)
used_radios += R
if("intercom")
for(var/obj/item/device/radio/intercom/I in view(1, null))
I.talk_into(src, message, verb, speaking)
used_radios += I
if("whisper")
whisper(message)
whisper_say(message, speaking, alt_name)
return
if("binary")
if(robot_talk_understand || binarycheck())
@@ -124,51 +114,45 @@
Changeling << "<i><font color=#800080><b>[mind.changeling.changelingID]:</b> [message]</font></i>"
return
else
if(!(stunned >= 4))
if(message_mode)
if(message_mode in (radiochannels | "department"))
if(l_ear && istype(l_ear,/obj/item/device/radio))
l_ear.talk_into(src,message, message_mode, verb, speaking)
used_radios += l_ear
else if(r_ear && istype(r_ear,/obj/item/device/radio))
r_ear.talk_into(src,message, message_mode, verb, speaking)
used_radios += r_ear
if(used_radios.len)
italics = 1
message_range = 1
var/datum/gas_mixture/environment = loc.return_air()
if(environment)
var/pressure = environment.return_pressure()
if(pressure < SAY_MINIMUM_PRESSURE)
italics = 1
message_range =1
if(message_mode)
if(message_mode in (radiochannels | "department"))
if(l_ear && istype(l_ear,/obj/item/device/radio))
l_ear.talk_into(src,message, message_mode, verb, speaking)
used_radios += l_ear
else if(r_ear && istype(r_ear,/obj/item/device/radio))
r_ear.talk_into(src,message, message_mode, verb, speaking)
used_radios += r_ear
var/sound/speech_sound
var/sound_vol
if((species.name == "Vox" || species.name == "Vox Armalis") && prob(20))
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
speech_sound = sound('sound/voice/shriek1.ogg')
sound_vol = 50
..(message, speaking, verb, alt_name, italics, message_range, used_radios)
..(message, speaking, verb, alt_name, italics, message_range, used_radios, speech_sound, sound_vol) //ohgod we should really be passing a datum here.
/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null)
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
return 1
if (istype(other, /mob/living/carbon/monkey/diona) && !speaking)
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
//These only pertain to common. Languages are handled by mob/say_understands()
if (!speaking)
if (istype(other, /mob/living/carbon/monkey/diona))
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
return 1
if (istype(other, /mob/living/silicon))
return 1
if (istype(other, /mob/living/carbon/brain))
return 1
if (istype(other, /mob/living/carbon/slime))
return 1
if (istype(other, /mob/living/silicon))
return 1
if (istype(other, /mob/living/carbon/brain))
return 1
if (istype(other, /mob/living/carbon/slime))
return 1
if (istype(other, /mob/living/simple_animal))
if(other.universal_speak || src.universal_speak || src.universal_understand)
return 1
return 0
//This is already covered by mob/say_understands()
//if (istype(other, /mob/living/simple_animal))
// if((other.universal_speak && !speaking) || src.universal_speak || src.universal_understand)
// return 1
// return 0
return ..()
@@ -217,6 +201,9 @@
return verb
/mob/living/carbon/human/proc/handle_speech_problems(var/message)
var/list/returns[3]
var/verb = "says"
@@ -237,7 +224,7 @@
handled = 1
if((HULK in mutations) && health >= 25 && length(message))
//message = "[uppertext(message)]!!!" //this is really irritating. let's not.
message = "[uppertext(message)]!!!"
verb = pick("yells","roars","hollers")
handled = 1
if(slurring)
@@ -113,13 +113,13 @@ Please contact me on #coderbus IRC. ~Carn x
#define ID_LAYER 6
#define SHOES_LAYER 7
#define GLOVES_LAYER 8
#define EARS_LAYER 9
#define SUIT_LAYER 10
#define GLASSES_LAYER 11
#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 13
#define BACK_LAYER 14
#define HAIR_LAYER 15 //TODO: make part of head layer?
#define SUIT_LAYER 9
#define GLASSES_LAYER 10
#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 12
#define BACK_LAYER 13
#define HAIR_LAYER 14 //TODO: make part of head layer?
#define EARS_LAYER 15
#define FACEMASK_LAYER 16
#define HEAD_LAYER 17
#define COLLAR_LAYER 18
@@ -128,8 +128,8 @@ Please contact me on #coderbus IRC. ~Carn x
#define L_HAND_LAYER 21
#define R_HAND_LAYER 22
#define TARGETED_LAYER 23 //BS12: Layer for the target overlay from weapon targeting system
#define FIRE_LAYER 23 //If you're on fire
#define TOTAL_LAYERS 23
#define FIRE_LAYER 24 //If you're on fire
#define TOTAL_LAYERS 24
//////////////////////////////////
/mob/living/carbon/human
@@ -137,7 +137,6 @@ Please contact me on #coderbus IRC. ~Carn x
var/list/overlays_lying[TOTAL_LAYERS]
var/previous_damage_appearance // store what the body last looked like, so we only have to update it if something changed
/mob/living/carbon/human/proc/apply_overlay(cache_index)
var/image/I = lying ? overlays_lying[cache_index] : overlays_standing[cache_index]
if(I)
@@ -265,7 +264,7 @@ proc/get_damage_icon_part(damage_state, body_part)
icon_key = "[icon_key]0"
else if(part.status & ORGAN_ROBOT)
icon_key = "[icon_key]2"
else if(part.status & ORGAN_DEAD) //Do we even have necrosis in our current code? ~Z
else if(part.status & ORGAN_DEAD)
icon_key = "[icon_key]3"
else
icon_key = "[icon_key]1"
@@ -292,6 +291,10 @@ proc/get_damage_icon_part(damage_state, body_part)
var/datum/organ/external/chest = get_organ("chest")
base_icon = chest.get_icon(race_icon,deform_icon,g)
if(chest.status & ORGAN_DEAD)
base_icon.ColorTone(necrosis_color_mod)
base_icon.SetIntensity(0.7)
for(var/datum/organ/external/part in organs)
var/icon/temp //Hold the bodypart icon for processing.
@@ -385,11 +388,11 @@ proc/get_damage_icon_part(damage_state, body_part)
stand_icon.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_s"), ICON_OVERLAY)
//Underwear
if(underwear >0 && underwear < 7 && species.flags & HAS_UNDERWEAR)
if(underwear >0 && underwear < 12 && species.flags & HAS_UNDERWEAR)
if(!fat && !skeleton)
stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY)
if(undershirt > 0 && undershirt < 16 && species.flags & HAS_UNDERWEAR)
if(undershirt>0 && undershirt < 5 && species.flags & HAS_UNDERWEAR)
stand_icon.Blend(new /icon('icons/mob/human.dmi', "undershirt[undershirt]_s"), ICON_OVERLAY)
if(update_icons)
@@ -672,6 +675,7 @@ proc/get_damage_icon_part(damage_state, body_part)
if(l_ear || r_ear)
if(l_ear)
var/t_type = l_ear.icon_state
if(l_ear.icon_override)
t_type = "[t_type]_l"
@@ -683,6 +687,7 @@ proc/get_damage_icon_part(damage_state, body_part)
overlays_standing[EARS_LAYER] = image("icon" = 'icons/mob/ears.dmi', "icon_state" = "[t_type]")
if(r_ear)
var/t_type = r_ear.icon_state
if(r_ear.icon_override)
t_type = "[t_type]_r"
+69 -82
View File
@@ -1,15 +1,11 @@
//Lallander was here
/mob/living/carbon/human/whisper(message as text)
var/alt_name = ""
if(say_disabled) //This is here to try to identify lag problems
usr << "\red Speech is currently admin-disabled."
return
message = trim(copytext(strip_html_simple(message), 1, MAX_MESSAGE_LEN))
if (!message || silent || miming)
return
log_whisper("[src.name]/[src.key] : [message]")
if (src.client)
@@ -20,27 +16,51 @@
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (src.stat == 2)
return src.say_dead(message)
if (src.stat)
return
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //made consistent with say
var/alt_name = ""
if (istype(src, /mob/living/carbon/human) && src.name != GetVoice())
var/mob/living/carbon/human/H = src
alt_name = " (as [H.get_id_name("Unknown")])"
if(name != GetVoice())
alt_name = "(as [get_id_name("Unknown")])"
//parse the language code and consume it
var/datum/language/speaking = parse_language(message)
if (speaking)
message = copytext(message,3)
whisper_say(message, speaking, alt_name)
//This is used by both the whisper verb and human/say() to handle whispering
/mob/living/carbon/human/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/verb="whispers")
var/message_range = 1
var/eavesdropping_range = 2
var/watching_range = 5
var/italics = 1
if (speaking)
verb = speaking.speech_verb + pick(" quietly", " softly")
message = capitalize(trim(message))
//TODO: handle_speech_problems for silent
if (!message || silent || miming)
return
// Mute disability
//TODO: handle_speech_problems
if (src.sdisabilities & MUTE)
return
//TODO: handle_speech_problems
if (istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
return
var/italics = 1
var/message_range = 1
//looks like this only appears in whisper. Should it be elsewhere as well? Maybe handle_speech_problems?
if(istype(src.wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja)&&src.wear_mask:voice=="Unknown")
if(copytext(message, 1, 2) != "*")
var/list/temp_message = text2list(message, " ")
@@ -60,90 +80,57 @@
message = replacetext(message, "u", "µ")
message = replacetext(message, "b", "ß")
//TODO: handle_speech_problems
if (src.stuttering)
message = stutter(message)
for (var/obj/O in view(message_range, src))
spawn (0)
if (O)
O.hear_talk(src, message)
var/list/listening = hearers(message_range, src)
listening |= src
//ghosts
for (var/mob/M in dead_mob_list) //does this include players who joined as observers as well?
if (!(M.client))
continue
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
listening |= M
//Pass whispers on to anything inside the immediate listeners.
for(var/mob/L in listening)
for(var/mob/C in L.contents)
if(istype(C,/mob/living))
listening += C
//pass on the message to objects that can hear us.
for (var/obj/O in view(message_range, src))
spawn (0)
if (O)
O.hear_talk(src, message) //O.hear_talk(src, message, verb, speaking)
var/list/eavesdropping = hearers(2, src)
var/list/eavesdropping = hearers(eavesdropping_range, src)
eavesdropping -= src
eavesdropping -= listening
var/list/watching = hearers(5, src)
var/list/watching = hearers(watching_range, src)
watching -= src
watching -= listening
watching -= eavesdropping
var/list/heard_a = list() // understood us
var/list/heard_b = list() // didn't understand us
for (var/mob/M in listening)
if (M.say_understands(src))
heard_a += M
else
heard_b += M
var/rendered = null
for (var/mob/M in watching)
if (M.say_understands(src))
rendered = "<span class='game say'><span class='name'>[src.name]</span> whispers something.</span>"
else
rendered = "<span class='game say'><span class='name'>[src.voice_name]</span> whispers something.</span>"
M.show_message(rendered, 2)
if (length(heard_a))
var/message_a = message
if (italics)
message_a = "<i>[message_a]</i>"
//This appears copied from carbon/living say.dm so the istype check for mob is probably not needed. Appending for src is also not needed as the game will check that automatically.
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] whispers, <span class='message'>\"[message_a]\"</span></span>"
for (var/mob/M in heard_a)
M.show_message(rendered, 2)
if (length(heard_b))
var/message_b
message_b = stars(message)
if (italics)
message_b = "<i>[message_b]</i>"
rendered = "<span class='game say'><span class='name'>[src.voice_name]</span> whispers, <span class='message'>\"[message_b]\"</span></span>"
for (var/mob/M in heard_b)
M.show_message(rendered, 2)
for (var/mob/M in eavesdropping)
if (M.say_understands(src))
var/message_c
message_c = stars(message)
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] whispers, <span class='message'>\"[message_c]\"</span></span>"
M.show_message(rendered, 2)
else
rendered = "<span class='game say'><span class='name'>[src.voice_name]</span> whispers something.</span>"
M.show_message(rendered, 2)
if (italics)
message = "<i>[message]</i>"
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] whispers, <span class='message'>\"[message]\"</span></span>"
for (var/mob/M in dead_mob_list)
if (!(M.client))
continue
if (M.stat > 1 && !(M in heard_a) && (M.client.prefs.toggles & CHAT_GHOSTEARS))
//now mobs
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
spawn(30) del(speech_bubble)
for(var/mob/M in listening)
M << speech_bubble
M.hear_say(message, verb, speaking, alt_name, italics, src)
if (eavesdropping.len)
var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
for(var/mob/M in eavesdropping)
M << speech_bubble
M.hear_say(new_message, verb, speaking, alt_name, italics, src)
if (watching.len)
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> whispers something.</span>"
for (var/mob/M in watching)
M.show_message(rendered, 2)
+18 -13
View File
@@ -1,23 +1,28 @@
/mob/living/carbon/slime/death(gibbed)
if(!gibbed)
if(is_adult)
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime(loc)
M.colour = colour
M.rabid = 1
is_adult = 0
maxHealth = 150
revive()
regenerate_icons()
number = rand(1, 1000)
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
return
if(stat == DEAD) return
stat = DEAD
icon_state = "[colour] baby slime dead"
if(!gibbed)
if(istype(src, /mob/living/carbon/slime/adult))
ghostize()
var/mob/living/carbon/slime/M1 = new primarytype(loc)
M1.rabid = 1
var/mob/living/carbon/slime/M2 = new primarytype(loc)
M2.rabid = 1
if(src) del(src)
else
for(var/mob/O in viewers(src, null))
O.show_message("<b>The [name]</b> seizes up and falls limp...", 1) //ded -- Urist
overlays.len = 0
for(var/mob/O in viewers(src, null))
O.show_message("<b>The [name]</b> seizes up and falls limp...", 1) //ded -- Urist
update_canmove()
if(blind) blind.layer = 0
ticker.mode.check_win()
if(ticker && ticker.mode)
ticker.mode.check_win()
return ..(gibbed)
+43 -32
View File
@@ -1,4 +1,4 @@
/mob/living/carbon/slime/emote(var/act,var/m_type=1,var/message = null)
/mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null)
if (findtext(act, "-", 1, null))
@@ -9,7 +9,7 @@
if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
act = copytext(act,1,length(act))
switch(act)
switch(act) //Alphabetical please
if ("me")
if(silent)
return
@@ -19,40 +19,51 @@
return
if (src.client.handle_spam_prevention(message,MUTE_IC))
return
if (stat)
return
if(!(message))
return
return custom_emote(m_type, message)
if ("custom")
return custom_emote(m_type, message)
if("moan")
message = "<B>The [src.name]</B> moans."
m_type = 2
if("shiver")
message = "<B>The [src.name]</B> shivers."
m_type = 2
if("sway")
message = "<B>The [src.name]</B> sways around dizzily."
m_type = 1
if("twitch")
message = "<B>The [src.name]</B> twitches."
m_type = 1
if("vibrate")
message = "<B>The [src.name]</B> vibrates!"
m_type = 1
if("light")
message = "<B>The [src.name]</B> lights up for a bit, then stops."
m_type = 1
if("jiggle")
message = "<B>The [src.name]</B> jiggles!"
m_type = 1
if (stat)
return
if(!(message))
return
return custom_emote(m_type, message)
if("bounce")
message = "<B>The [src.name]</B> bounces in place."
m_type = 1
if ("custom")
return custom_emote(m_type, message)
if("jiggle")
message = "<B>The [src.name]</B> jiggles!"
m_type = 1
if("light")
message = "<B>The [src.name]</B> lights up for a bit, then stops."
m_type = 1
if("moan")
message = "<B>The [src.name]</B> moans."
m_type = 2
if("shiver")
message = "<B>The [src.name]</B> shivers."
m_type = 2
if("sway")
message = "<B>The [src.name]</B> sways around dizzily."
m_type = 1
if("twitch")
message = "<B>The [src.name]</B> twitches."
m_type = 1
if("vibrate")
message = "<B>The [src.name]</B> vibrates!"
m_type = 1
if ("help") //This is an exception
src << "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, custom, jiggle, light, moan, shiver, sway, twitch, vibrate"
else
src << text("Invalid Emote: []", act)
src << "\blue Unusable emote '[act]'. Say *help for a list."
if ((message && src.stat == 0))
if (m_type & 1)
for(var/mob/O in viewers(src, null))
@@ -1,4 +1,2 @@
/mob/living/carbon/slime/proc/regular_hud_updates()
return
return
+277 -264
View File
@@ -1,3 +1,10 @@
/mob/living/carbon/slime
var/AIproc = 0 // determines if the AI loop is activated
var/Atkcool = 0 // attack cooldown
var/Tempstun = 0 // temporary temperature stuns
var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
var/SStun = 0 // stun variable
/mob/living/carbon/slime/Life()
set invisibility = 0
set background = 1
@@ -15,114 +22,80 @@
handle_targets()
if (!ckey)
handle_speech_and_mood()
var/datum/gas_mixture/environment // Added to prevent null location errors-- TLE
var/datum/gas_mixture/environment
if(src.loc)
environment = loc.return_air()
//Apparently, the person who wrote this code designed it so that
//blinded get reset each cycle and then get activated later in the
//code. Very ugly. I dont care. Moving this stuff here so its easy
//to find it.
src.blinded = null
// Basically just deletes any screen objects :<
regular_hud_updates()
regular_hud_updates() // Basically just deletes any screen objects :<
//Handle temperature/pressure differences between body and environment
if(environment)
handle_environment(environment)
handle_environment(environment) // Handle temperature/pressure differences between body and environment
//Status updates, death etc.
handle_regular_status_updates()
/mob/living/carbon/slime
var/AIproc = 0 // determines if the AI loop is activated
var/Atkcool = 0 // attack cooldown
var/Tempstun = 0 // temporary temperature stuns
var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
var/SStun = 0 // stun variable
handle_regular_status_updates() // Status updates, death etc.
/mob/living/carbon/slime/proc/AIprocess() // the master AI process
//world << "AI proc started."
if(AIproc || stat == DEAD || client) return
var/hungry = 0
var/starving = 0
if(istype(src, /mob/living/carbon/slime/adult))
switch(nutrition)
if(400 to 1100) hungry = 1
if(0 to 399)
starving = 1
else
switch(nutrition)
if(150 to 900) hungry = 1
if(0 to 149) starving = 1
if (nutrition < get_starve_nutrition())
hungry = 2
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
hungry = 1
AIproc = 1
//world << "AIproc [AIproc] && stat != 2 [stat] && (attacked > 0 [attacked] || starving [starving] || hungry [hungry] || rabid [rabid] || Victim [Victim] || Target [Target]"
while(AIproc && stat != 2 && (attacked > 0 || starving || hungry || rabid || Victim))
while(AIproc && stat != 2 && (attacked || hungry || rabid || Victim))
if(Victim) // can't eat AND have this little process at the same time
//world << "break 1"
break
if(!Target || client)
//world << "break 2"
break
if(Target.health <= -70 || Target.stat == 2)
Target = null
AIproc = 0
//world << "break 3"
break
if(Target)
//world << "[Target] Target Found"
for(var/mob/living/carbon/slime/M in view(1,Target))
if(M.Victim == Target)
Target = null
AIproc = 0
//world << "break 4"
break
if(!AIproc)
//world << "break 5"
break
if(Target in view(1,src))
if(istype(Target, /mob/living/silicon))
if(!Atkcool)
spawn()
Atkcool = 1
sleep(15)
Atkcool = 1
spawn(45)
Atkcool = 0
if(Target.Adjacent(src))
Target.attack_slime(src)
//world << "retrun 1"
return
if(!Target.lying && prob(80))
if(Target.client && Target.health >= 20)
if(!Atkcool)
spawn()
Atkcool = 1
sleep(25)
Atkcool = 1
spawn(45)
Atkcool = 0
if(Target.Adjacent(src))
Target.attack_slime(src)
if(prob(30))
step_to(src, Target)
else
if(!Atkcool && Target.Adjacent(src))
Feedon(Target)
@@ -133,13 +106,13 @@
else
if(Target in view(7, src))
if(Target.Adjacent(src))
if(!Target.Adjacent(src)) // Bug of the month candidate: slimes were attempting to move to target only if it was directly next to them, which caused them to target things, but not approach them
step_to(src, Target)
sleep(5)
else
Target = null
AIproc = 0
//world << "break 6"
break
var/sleeptime = movement_delay()
@@ -148,7 +121,6 @@
sleep(sleeptime + 2) // this is about as fast as a player slime can go
AIproc = 0
//world << "AI proc ended."
/mob/living/carbon/slime/proc/handle_environment(datum/gas_mixture/environment)
if(!environment)
@@ -166,28 +138,11 @@
else
loc_temp = environment.temperature
/*
if((environment.temperature > (T0C + 50)) || (environment.temperature < (T0C + 10)))
var/transfer_coefficient
transfer_coefficient = 1
if(wear_mask && (wear_mask.body_parts_covered & HEAD) && (environment.temperature < wear_mask.protective_temperature))
transfer_coefficient *= wear_mask.heat_transfer_coefficient
// handle_temperature_damage(HEAD, environment.temperature, environment_heat_capacity*transfer_coefficient)
*/
if(loc_temp < 310.15) // a cold place
bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1)
else // a hot place
bodytemperature += adjust_body_temperature(bodytemperature, loc_temp, 1)
/*
if(stat==2)
bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000)
*/
//Account for massive pressure differences
if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc
@@ -207,7 +162,6 @@
return //TODO: DEFERRED
/mob/living/carbon/slime/proc/adjust_body_temperature(current, loc_temp, boost)
var/temperature = current
var/difference = abs(current-loc_temp) //get difference
@@ -229,33 +183,28 @@
if(reagents) reagents.metabolize(src)
src.updatehealth()
return //TODO: DEFERRED
/mob/living/carbon/slime/proc/handle_regular_status_updates()
if(istype(src, /mob/living/carbon/slime/adult))
if(is_adult)
health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
else
health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
if(health < config.health_threshold_dead && stat != 2)
death()
return
else if(src.health < config.health_threshold_crit)
// if(src.health <= 20 && prob(1)) spawn(0) emote("gasp")
//if(!src.rejuv) src.oxyloss++
if(!src.reagents.has_reagent("inaprovaline")) src.adjustOxyLoss(10)
if(!src.reagents.has_reagent("inaprovaline"))
src.adjustOxyLoss(10)
if(src.stat != DEAD) src.stat = UNCONSCIOUS
if(src.stat != DEAD)
src.stat = UNCONSCIOUS
if(prob(30))
adjustOxyLoss(-1)
@@ -264,12 +213,9 @@
adjustCloneLoss(-1)
adjustBruteLoss(-1)
if (src.stat == DEAD)
src.lying = 1
src.blinded = 1
else
if (src.paralysis || src.stunned || src.weakened || (status_flags && FAKEDEATH)) //Stunned etc.
if (src.stunned > 0)
@@ -314,99 +260,25 @@
return 1
/mob/living/carbon/slime/proc/handle_nutrition()
if(prob(20))
if(istype(src, /mob/living/carbon/slime/adult)) nutrition-=rand(4,6)
else nutrition-=rand(2,3)
if (prob(15))
nutrition -= 1 + is_adult
if(nutrition <= 0)
nutrition = 0
if(prob(75))
adjustToxLoss(rand(0,5))
else
if(istype(src, /mob/living/carbon/slime/adult))
if(nutrition >= 1000)
if(prob(40)) amount_grown++
else if (nutrition >= get_grow_nutrition() && amount_grown < 10)
nutrition -= 20
amount_grown++
if(amount_grown >= 10 && !Victim && !Target && !ckey)
if(is_adult)
Reproduce()
else
if(nutrition >= 800)
if(prob(40)) amount_grown++
if(amount_grown >= 10 && !Victim && !Target)
if(istype(src, /mob/living/carbon/slime/adult))
if(!client)
for(var/i=1,i<=4,i++)
if(catalyst == 0)
if(prob(70))
var/mob/living/carbon/slime/M = new primarytype(loc)
M.powerlevel = round(powerlevel/4)
M.Friends = Friends
M.tame = tame
M.rabid = rabid
M.Discipline = Discipline
if(i != 1) step_away(M,src)
else
var/mutations = pick("one","two","three","four")
switch(mutations)
if("one")
var/mob/living/carbon/slime/M = new mutationone(loc)
M.powerlevel = round(powerlevel/4)
M.Friends = Friends
M.tame = tame
M.rabid = rabid
M.Discipline = Discipline
if(i != 1) step_away(M,src)
if("two")
var/mob/living/carbon/slime/M = new mutationtwo(loc)
M.powerlevel = round(powerlevel/4)
M.Friends = Friends
M.tame = tame
M.rabid = rabid
M.Discipline = Discipline
if(i != 1) step_away(M,src)
if("three")
var/mob/living/carbon/slime/M = new mutationthree(loc)
M.powerlevel = round(powerlevel/4)
M.Friends = Friends
M.tame = tame
M.rabid = rabid
M.Discipline = Discipline
if(i != 1) step_away(M,src)
if("four")
var/mob/living/carbon/slime/M = new mutationfour(loc)
M.powerlevel = round(powerlevel/4)
M.Friends = Friends
M.tame = tame
M.rabid = rabid
M.Discipline = Discipline
if(i != 1) step_away(M,src)
else
var/mob/living/carbon/slime/M = new primarytype(loc)
M.powerlevel = round(powerlevel/4)
M.Friends = Friends
M.tame = tame
M.rabid = rabid
M.Discipline = Discipline
if(i != 1) step_away(M,src)
del(src)
else
if(!client)
var/mob/living/carbon/slime/adult/A = new adulttype(src.loc)
A.nutrition = nutrition
// A.nutrition += 100
A.powerlevel = max(0, powerlevel-1)
A.Friends = Friends
A.tame = tame
A.rabid = rabid
A.catalyst = catalyst
del(src)
Evolve()
/mob/living/carbon/slime/proc/handle_targets()
if(Tempstun)
@@ -418,8 +290,7 @@
if(attacked > 50) attacked = 50
if(attacked > 0)
if(prob(85))
attacked--
attacked--
if(Discipline > 0)
@@ -429,136 +300,278 @@
if(prob(10))
Discipline--
if(!client)
if(!canmove) return
// DO AI STUFF HERE
if(Target)
if(attacked <= 0)
Target = null
if(Victim) return // if it's eating someone already, continue eating!
if(prob(1))
emote(pick("bounce","sway","light","vibrate","jiggle"))
if(Target)
--target_patience
if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention
target_patience = 0
Target = null
if(AIproc && SStun) return
var/hungry = 0 // determines if the slime is hungry
var/starving = 0 // determines if the slime is starving-hungry
if(istype(src, /mob/living/carbon/slime/adult)) // 1200 max nutrition
switch(nutrition)
if(601 to 900)
if(prob(25)) hungry = 1//Ensures they continue eating, but aren't as aggressive at the same time
if(301 to 600) hungry = 1
if(0 to 300)
starving = 1
else
switch(nutrition) // 1000 max nutrition
if(501 to 700)
if(prob(25)) hungry = 1
if(201 to 500) hungry = 1
if(0 to 200) starving = 1
if (nutrition < get_starve_nutrition())
hungry = 2
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
hungry = 1
if(starving && !client) // if a slime is starving, it starts losing its friends
if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
if(Friends.len > 0 && prob(1))
var/mob/nofriend = pick(Friends)
Friends -= nofriend
--Friends[nofriend]
if(!Target)
var/list/targets = list()
if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to
var/list/targets = list()
if(hungry || starving) //Only add to the list if we need to
for(var/mob/living/L in view(7,src))
//Ignore other slimes, dead mobs and simple_animals
if(isslime(L) || L.stat != CONSCIOUS || isanimal(L))
if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
continue
if(issilicon(L))
if(!istype(src, /mob/living/carbon/slime/adult)) //Non-starving diciplined adult slimes wont eat things
if(!starving && Discipline > 0)
if(L in Friends) // No eating friends!
continue
if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence
targets += L // Possible target found!
if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men
var/mob/living/carbon/human/H = L
if(H.dna)
if(H.dna.mutantrace == "slime")
continue
if(tame) //Tame slimes ignore electronic life
if(!L.canmove) // Only one slime can latch on at a time.
var/notarget = 0
for(var/mob/living/carbon/slime/M in view(1,L))
if(M.Victim == L)
notarget = 1
if(notarget)
continue
targets += L //Possible target found!
targets += L // Possible target found!
else if(iscarbon(L))
if(istype(L, /mob/living/carbon/human)) //Ignore slime(wo)men
var/mob/living/carbon/human/H = L
if(H.dna)
if(H.dna.mutantrace == "slime")
continue
if(!istype(src, /mob/living/carbon/slime/adult)) //Non-starving diciplined adult slimes wont eat things
if(!starving && Discipline > 0)
continue
if(L in Friends) //No eating friends!
continue
if(tame && ishuman(L)) //Tame slimes dont eat people.
continue
if(!L.canmove) //Only one slime can latch on at a time.
var/notarget = 0
for(var/mob/living/carbon/slime/M in view(1,L))
if(M.Victim == L)
notarget = 1
if(notarget)
continue
targets += L //Possible target found!
if((hungry || starving) && targets.len > 0)
if(!istype(src, /mob/living/carbon/slime/adult))
if(!starving)
if(targets.len > 0)
if(attacked || rabid || hungry == 2)
Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care
else
for(var/mob/living/carbon/C in targets)
if(!Discipline && prob(5))
if(ishuman(C))
Target = C
break
if(isalienadult(C))
if(ishuman(C) || isalienadult(C))
Target = C
break
if(islarva(C))
if(islarva(C) || ismonkey(C))
Target = C
break
if(ismonkey(C))
Target = C
break
else
Target = targets[1]
else
Target = targets[1] // closest target
if(targets.len > 0)
if(attacked > 0 || rabid)
Target = targets[1] //closest mob probably attacked it, so override Target and attack the nearest!
if (Target)
target_patience = rand(5,7)
if (is_adult)
target_patience += 3
if(!Target) // If we have no target, we are wandering or following orders
if (Leader)
if (holding_still)
holding_still = max(holding_still - 1, 0)
else if(canmove && isturf(loc))
step_to(src, Leader)
if(!Target)
if(hungry || starving)
if(canmove && isturf(loc) && prob(50))
else if(hungry)
if (holding_still)
holding_still = max(holding_still - hungry, 0)
else if(canmove && isturf(loc) && prob(50))
step(src, pick(cardinal))
else
if(canmove && isturf(loc) && prob(33))
if (holding_still)
holding_still = max(holding_still - 1, 0)
else if(canmove && isturf(loc) && prob(33))
step(src, pick(cardinal))
else
if(!AIproc)
spawn() AIprocess()
else if(!AIproc)
spawn()
AIprocess()
/mob/living/carbon/slime/proc/handle_speech_and_mood()
//Mood starts here
var/newmood = ""
if (rabid || attacked) newmood = "angry"
else if (Target) newmood = "mischevous"
if (!newmood)
if (Discipline && prob(25))
newmood = "pout"
else if (prob(1))
newmood = pick("sad", ":3", "pout")
if ((mood == "sad" || mood == ":3" || mood == "pout") && !newmood)
if (prob(75)) newmood = mood
if (newmood != mood) // This is so we don't redraw them every time
mood = newmood
regenerate_icons()
//Speech understanding starts here
var/to_say
if (speech_buffer.len > 0)
var/who = speech_buffer[1] // Who said it?
var/phrase = speech_buffer[2] // What did they say?
if ((findtext(phrase, num2text(number)) || findtext(phrase, "slimes"))) // Talking to us
if (findtext(phrase, "hello") || findtext(phrase, "hi"))
to_say = pick("Hello...", "Hi...")
else if (findtext(phrase, "follow"))
if (Leader)
if (Leader == who) // Already following him
to_say = pick("Yes...", "Lead...", "Following...")
else if (Friends[who] > Friends[Leader]) // VIVA
Leader = who
to_say = "Yes... I follow [who]..."
else
to_say = "No... I follow [Leader]..."
else
if (Friends[who] > 2)
Leader = who
to_say = "I follow..."
else // Not friendly enough
to_say = pick("No...", "I won't follow...")
else if (findtext(phrase, "stop"))
if (Victim) // We are asked to stop feeding
if (Friends[who] > 4)
Victim = null
Target = null
if (Friends[who] < 7)
--Friends[who]
to_say = "Grrr..." // I'm angry but I do it
else
to_say = "Fine..."
else if (Target) // We are asked to stop chasing
if (Friends[who] > 3)
Target = null
if (Friends[who] < 6)
--Friends[who]
to_say = "Grrr..." // I'm angry but I do it
else
to_say = "Fine..."
else if (Leader) // We are asked to stop following
if (Leader == who)
to_say = "Yes... I'll stay..."
Leader = null
else
if (Friends[who] > Friends[Leader])
Leader = null
to_say = "Yes... I'll stop..."
else
to_say = "No... I'll keep following..."
else if (findtext(phrase, "stay"))
if (Leader)
if (Leader == who)
holding_still = Friends[who] * 10
to_say = "Yes... Staying..."
else if (Friends[who] > Friends[Leader])
holding_still = (Friends[who] - Friends[Leader]) * 10
to_say = "Yes... Staying..."
else
to_say = "No... I'll keep following..."
else
if (Friends[who] > 2)
holding_still = Friends[who] * 10
to_say = "Yes... Staying..."
else
to_say = "No... I won't stay..."
speech_buffer = list()
//Speech starts here
if (to_say)
say (to_say)
else if(prob(1))
emote(pick("bounce","sway","light","vibrate","jiggle"))
else
var/t = 10
var/slimes_near = -1 // Don't count myself
var/dead_slimes = 0
var/friends_near = list()
for (var/mob/living/carbon/M in view(7,src))
if (isslime(M))
++slimes_near
if (M.stat == DEAD)
++dead_slimes
if (M in Friends)
t += 20
friends_near += M
if (nutrition < get_hunger_nutrition()) t += 10
if (nutrition < get_starve_nutrition()) t += 10
if (prob(2) && prob(t))
var/phrases = list()
if (Target) phrases += "[Target]... looks tasty..."
if (nutrition < get_starve_nutrition())
phrases += "So... hungry..."
phrases += "Very... hungry..."
phrases += "Need... food..."
phrases += "Must... eat..."
else if (nutrition < get_hunger_nutrition())
phrases += "Hungry..."
phrases += "Where is the food?"
phrases += "I want to eat..."
phrases += "Rawr..."
phrases += "Blop..."
phrases += "Blorble..."
if (rabid || attacked)
phrases += "Hrr..."
phrases += "Nhuu..."
phrases += "Unn..."
if (mood == ":3")
phrases += "Purr..."
if (attacked)
phrases += "Grrr..."
if (getToxLoss() > 30)
phrases += "Cold..."
if (getToxLoss() > 60)
phrases += "So... cold..."
phrases += "Very... cold..."
if (getToxLoss() > 90)
phrases += "..."
phrases += "C... c..."
if (Victim)
phrases += "Nom..."
phrases += "Tasty..."
if (powerlevel > 3) phrases += "Bzzz..."
if (powerlevel > 5) phrases += "Zap..."
if (powerlevel > 8) phrases += "Zap... Bzz..."
if (mood == "sad") phrases += "Bored..."
if (slimes_near) phrases += "Brother..."
if (slimes_near > 1) phrases += "Brothers..."
if (dead_slimes) phrases += "What happened?"
if (!slimes_near)
phrases += "Lonely..."
for (var/M in friends_near)
phrases += "[M]... friend..."
if (nutrition < get_hunger_nutrition())
phrases += "[M]... feed me..."
say (pick(phrases))
/mob/living/carbon/slime/proc/get_max_nutrition() // Can't go above it
if (is_adult) return 1200
else return 1000
/mob/living/carbon/slime/proc/get_grow_nutrition() // Above it we grow, below it we can eat
if (is_adult) return 1000
else return 800
/mob/living/carbon/slime/proc/get_hunger_nutrition() // Below it we will always eat
if (is_adult) return 600
else return 500
/mob/living/carbon/slime/proc/get_starve_nutrition() // Below it we will eat before everything else
if (is_adult) return 300
else return 200
/mob/living/carbon/slime/proc/will_hunt(var/hunger = -1) // Check for being stopped from feeding and chasing
if (hunger == 2 || rabid || attacked) return 1
if (Leader) return 0
if (holding_still) return 0
return 1
+268 -236
View File
@@ -3,6 +3,7 @@
icon = 'icons/mob/slimes.dmi'
icon_state = "grey baby slime"
pass_flags = PASSTABLE
var/is_adult = 0
speak_emote = list("hums")
layer = 5
@@ -22,23 +23,27 @@
status_flags = CANPARALYSE|CANPUSH
var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside
var/mutation_chance = 30 // Chance of mutating, should be between 25 and 35
var/powerlevel = 0 // 1-10 controls how much electricity they are generating
var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows into an adult
// if adult: if 10: reproduces
var/powerlevel = 0 // 1-10 controls how much electricity they are generating
var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows or reproduces
var/number = 0 // Used to understand when someone is talking to it
var/mob/living/Victim = null // the person the slime is currently feeding on
var/mob/living/Target = null // AI variable - tells the slime to hunt this down
var/mob/living/Leader = null // AI variable - tells the slime to follow this person
var/attacked = 0 // determines if it's been attacked recently. Can be any number, is a cooloff-ish variable
var/tame = 0 // if set to 1, the slime will not eat humans ever, or attack them
var/rabid = 0 // if set to 1, the slime will attack and eat anything it comes in contact with
var/attacked = 0 // Determines if it's been attacked recently. Can be any number, is a cooloff-ish variable
var/rabid = 0 // If set to 1, the slime will attack and eat anything it comes in contact with
var/holding_still = 0 // AI variable, cooloff-ish for how long it's going to stay in one place
var/target_patience = 0 // AI variable, cooloff-ish for how long it's going to follow its target
var/list/Friends = list() // A list of potential friends
var/list/FriendsWeight = list() // A list containing values respective to Friends. This determines how many times a slime "likes" something. If the slime likes it more than 2 times, it becomes a friend
var/list/Friends = list() // A list of friends; they are not considered targets for feeding; passed down after splitting
// slimes pass on genetic data, so all their offspring have the same "Friends",
var/list/speech_buffer = list() // Last phrase said near it and person who said it
var/mood = "" // To show its face
///////////TIME FOR SUBSPECIES
@@ -68,24 +73,29 @@
/mob/living/carbon/slime/New()
var/datum/reagents/R = new/datum/reagents(100)
reagents = R
R.my_atom = src
if(name == "baby slime")
name = text("[colour] baby slime ([rand(1, 1000)])")
else
name = text("[colour] adult slime ([rand(1,1000)])")
real_name = name
spawn (1)
regenerate_icons()
src << "\blue Your icons have been generated!"
create_reagents(100)
spawn (0)
number = rand(1, 1000)
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
real_name = name
// slime_mutation = mutation_table(colour)
mutation_chance = rand(25, 35)
var/sanitizedcolour = replacetext(colour, " ", "")
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
..()
/mob/living/carbon/slime/adult/New()
//verbs.Remove(/mob/living/carbon/slime/verb/ventcrawl)
/mob/living/carbon/slime/regenerate_icons()
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
overlays.len = 0
if (mood)
overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
..()
/mob/living/carbon/slime/movement_delay()
if (bodytemperature >= 330.23) // 135 F
return -1 // slimes become supercharged at high temperatures
var/tally = 0
var/health_deficiency = (100 - health)
@@ -95,8 +105,8 @@
tally += (283.222 - bodytemperature) / 10 * 1.75
if(reagents)
if(reagents.has_reagent("hyperzine")) // hyperzine slows slimes down
tally *= 2 // moves twice as slow
if(reagents.has_reagent("hyperzine")) // Hyperzine slows slimes down
tally *= 2
if(reagents.has_reagent("frostoil")) // frostoil also makes them move VEEERRYYYYY slow
tally *= 5
@@ -104,106 +114,84 @@
if(health <= 0) // if damaged, the slime moves twice as slow
tally *= 2
if (bodytemperature >= 330.23) // 135 F
return -1 // slimes become supercharged at high temperatures
return tally+config.slime_delay
return tally + config.slime_delay
/mob/living/carbon/slime/Bump(atom/movable/AM as mob|obj, yes)
spawn( 0 )
if ((!( yes ) || now_pushing))
return
now_pushing = 1
if ((!(yes) || now_pushing))
return
now_pushing = 1
if(isobj(AM))
if(!client && powerlevel > 0)
var/probab = 10
switch(powerlevel)
if(1 to 2) probab = 20
if(3 to 4) probab = 30
if(5 to 6) probab = 40
if(7 to 8) probab = 60
if(9) probab = 70
if(10) probab = 95
if(prob(probab))
if(isobj(AM))
if(!client && powerlevel > 0)
var/probab = 10
switch(powerlevel)
if(1 to 2) probab = 20
if(3 to 4) probab = 30
if(5 to 6) probab = 40
if(7 to 8) probab = 60
if(9) probab = 70
if(10) probab = 95
if(prob(probab))
if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
if(nutrition <= get_hunger_nutrition() && !Atkcool)
if (is_adult || prob(5))
AM.attack_slime(src)
spawn()
Atkcool = 1
sleep(45)
Atkcool = 0
if(ismob(AM))
var/mob/tmob = AM
if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
if(istype(src, /mob/living/carbon/slime/adult))
if(nutrition <= 600 && !Atkcool)
AM.attack_slime(src)
spawn()
Atkcool = 1
sleep(15)
Atkcool = 0
else
if(nutrition <= 500 && !Atkcool)
if(prob(5))
AM.attack_slime(src)
spawn()
Atkcool = 1
sleep(15)
Atkcool = 0
if(ismob(AM))
var/mob/tmob = AM
if(istype(src, /mob/living/carbon/slime/adult))
if(istype(tmob, /mob/living/carbon/human))
if(prob(90))
now_pushing = 0
return
else
if(istype(tmob, /mob/living/carbon/human))
if(is_adult)
if(istype(tmob, /mob/living/carbon/human))
if(prob(90))
now_pushing = 0
return
else
if(istype(tmob, /mob/living/carbon/human))
now_pushing = 0
return
now_pushing = 0
..()
if (!( istype(AM, /atom/movable) ))
return
if (!( now_pushing ))
now_pushing = 1
if (!( AM.anchored ))
var/t = get_dir(src, AM)
if (istype(AM, /obj/structure/window))
if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST)
for(var/obj/structure/window/win in get_step(AM,t))
now_pushing = 0
return
step(AM, t)
now_pushing = null
now_pushing = 0
..()
if (!istype(AM, /atom/movable))
return
return
if (!( now_pushing ))
now_pushing = 1
if (!( AM.anchored ))
var/t = get_dir(src, AM)
if (istype(AM, /obj/structure/window))
if(AM:ini_dir == NORTHWEST || AM:ini_dir == NORTHEAST || AM:ini_dir == SOUTHWEST || AM:ini_dir == SOUTHEAST)
for(var/obj/structure/window/win in get_step(AM,t))
now_pushing = 0
return
step(AM, t)
now_pushing = null
/mob/living/carbon/slime/Process_Spacemove()
return 2
/mob/living/carbon/slime/Stat()
..()
statpanel("Status")
if(istype(src, /mob/living/carbon/slime/adult))
if(is_adult)
stat(null, "Health: [round((health / 200) * 100)]%")
else
stat(null, "Health: [round((health / 150) * 100)]%")
if (client.statpanel == "Status")
if(istype(src,/mob/living/carbon/slime/adult))
stat(null, "Nutrition: [nutrition]/1200")
if(amount_grown >= 10)
stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]")
if(amount_grown >= 10)
if(is_adult)
stat(null, "You can reproduce!")
else
stat(null, "Nutrition: [nutrition]/1000")
if(amount_grown >= 10)
else
stat(null, "You can evolve!")
stat(null,"Power Level: [powerlevel]")
/mob/living/carbon/slime/adjustFireLoss(amount)
..(-abs(amount)) // Heals them
return
@@ -213,25 +201,18 @@
..(Proj)
return 0
/mob/living/carbon/slime/emp_act(severity)
powerlevel = 0 // oh no, the power!
..()
/mob/living/carbon/slime/ex_act(severity)
if (stat == 2 && client)
return
else if (stat == 2 && !client)
del(src)
return
..()
var/b_loss = null
var/f_loss = null
switch (severity)
if (1.0)
b_loss += 500
del(src)
return
if (2.0)
@@ -263,7 +244,7 @@
//paralysis += 1
show_message("\red The blob attacks you!")
show_message("<span class='userdanger'> The blob attacks you!</span>")
adjustFireLoss(damage)
@@ -274,7 +255,6 @@
/mob/living/carbon/slime/u_equip(obj/item/W as obj)
return
/mob/living/carbon/slime/attack_ui(slot)
return
@@ -289,52 +269,48 @@
updatehealth()
return
/mob/living/carbon/slime/attack_slime(mob/living/carbon/slime/M as mob)
if (!ticker)
M << "You cannot attack people before the game has started."
return
if(Victim) return // can't attack while eating!
if (Victim) return // can't attack while eating!
if (health > -100)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>The [M.name] has glomped []!</B>", src), 1)
visible_message("<span class='danger'> The [M.name] has glomped [src]!</span>", \
"<span class='userdanger'> The [M.name] has glomped [src]!</span>")
var/damage = rand(1, 3)
attacked += 5
if(istype(src, /mob/living/carbon/slime/adult))
if(M.is_adult)
damage = rand(1, 6)
else
damage = rand(1, 3)
adjustBruteLoss(damage)
updatehealth()
return
/mob/living/carbon/slime/attack_animal(mob/living/simple_animal/M as mob)
if(M.melee_damage_upper == 0)
M.emote("[M.friendly] [src]")
else
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
for(var/mob/O in viewers(src, null))
O.show_message("\red <B>[M]</B> [M.attacktext] [src]!", 1)
visible_message("<span class='danger'>[M] [M.attacktext] [src]!</span>", \
"<span class='userdanger'>[M] [M.attacktext] [src]!</span>")
M.attack_log += text("\[[time_stamp()]\] <font color='red'>attacked [src.name] ([src.ckey])</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>was attacked by [M.name] ([M.ckey])</font>")
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
attacked += 10
adjustBruteLoss(damage)
updatehealth()
/mob/living/carbon/slime/attack_paw(mob/living/carbon/monkey/M as mob)
if(!(istype(M, /mob/living/carbon/monkey))) return//Fix for aliens receiving double messages when attacking other aliens.
if(!(istype(M, /mob/living/carbon/monkey)))
return // Fix for aliens receiving double messages when attacking other aliens.
if (!ticker)
M << "You cannot attack people before the game has started."
@@ -343,6 +319,7 @@
if (istype(loc, /turf) && istype(loc.loc, /area/start))
M << "No attacking people at spawn, you jackass."
return
..()
switch(M.a_intent)
@@ -355,9 +332,8 @@
if (health > 0)
attacked += 10
//playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[M.name] has attacked [src]!</B>"), 1)
visible_message("<span class='danger'>[M.name] has attacked [src]!</span>", \
"<span class='userdanger'>[M.name] has attacked [src]!</span>")
adjustBruteLoss(rand(1, 3))
updatehealth()
return
@@ -377,15 +353,11 @@
if(Victim)
if(Victim == M)
if(prob(60))
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\red [M] attempts to wrestle \the [name] off!", 1)
visible_message("<span class='warning'>[M] attempts to wrestle \the [name] off!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
else
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\red [M] manages to wrestle \the [name] off!", 1)
visible_message("<span class='warning'> [M] manages to wrestle \the [name] off!</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(prob(90) && !client)
@@ -405,21 +377,17 @@
else
if(prob(30))
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\red [M] attempts to wrestle \the [name] off of [Victim]!", 1)
visible_message("<span class='warning'>[M] attempts to wrestle \the [name] off of [Victim]!</span>")
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
else
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\red [M] manages to wrestle \the [name] off of [Victim]!", 1)
visible_message("<span class='warning'> [M] manages to wrestle \the [name] off of [Victim]!</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if(prob(80) && !client)
Discipline++
if(!istype(src, /mob/living/carbon/slime/adult))
if(!is_adult)
if(Discipline == 1)
attacked = 0
@@ -435,18 +403,13 @@
return
if(M.gloves && istype(M.gloves,/obj/item/clothing/gloves))
var/obj/item/clothing/gloves/G = M.gloves
if(G.cell)
if(M.a_intent == "hurt")//Stungloves. Any contact will stun the alien.
if(G.cell.charge >= 2500)
G.cell.use(2500)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message("\red <B>[src] has been touched with the stun gloves by [M]!</B>", 1, "\red You hear someone fall.", 2)
visible_message("<span class='warning'>[src] has been touched with the stun gloves by [M]!</span>")
return
else
M << "\red Not enough charge! "
@@ -458,21 +421,18 @@
help_shake_act(M)
if ("grab")
if (M == src)
if (M == src || anchored)
return
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, src )
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src)
M.put_in_active_hand(G)
grabbed_by += G
G.synch()
LAssailant = M
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red [] has grabbed [] passively!", M, src), 1)
visible_message("<span class='warning'>[M] has grabbed [src] passively!</span>")
else
@@ -482,8 +442,9 @@
if (prob(90))
if (HULK in M.mutations)
damage += 5
if(Victim)
if(Victim || Target)
Victim = null
Target = null
anchored = 0
if(prob(80) && !client)
Discipline++
@@ -495,17 +456,14 @@
playsound(loc, "punch", 25, 1, -1)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has punched []!</B>", M, src), 1)
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='userdanger'>[M] has punched [src]!</span>")
adjustBruteLoss(damage)
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has attempted to punch []!</B>", M, src), 1)
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>")
return
@@ -521,48 +479,41 @@
switch(M.a_intent)
if ("help")
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\blue [M] caresses [src] with its scythe like arm."), 1)
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
if ("hurt")
if ((prob(95) && health > 0))
if (prob(95))
attacked += 10
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
var/damage = rand(15, 30)
if (damage >= 25)
damage = rand(20, 40)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has attacked [name]!</B>", M), 1)
visible_message("<span class='danger'>[M] has attacked [name]!</span>", \
"<span class='userdanger'>[M] has attacked [name]!</span>")
else
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has wounded [name]!</B>", M), 1)
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
"<span class='userdanger'>)[M] has wounded [name]!</span>")
adjustBruteLoss(damage)
updatehealth()
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has attempted to lunge at [name]!</B>", M), 1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>")
if ("grab")
if (M == src)
if (M == src || anchored)
return
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab( M, M, src )
var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src )
M.put_in_active_hand(G)
grabbed_by += G
G.synch()
LAssailant = M
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
for(var/mob/O in viewers(src, null))
O.show_message(text("\red [] has grabbed [name] passively!", M), 1)
visible_message("<span class='warning'> [M] has grabbed [name] passively!</span>")
if ("disarm")
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
@@ -570,12 +521,12 @@
attacked += 10
if(prob(95))
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has tackled [name]!</B>", M), 1)
visible_message("<span class='danger'>[M] has tackled [name]!</span>", \
"<span class='userdanger'>[M] has tackled [name]!</span>")
if(Victim)
if(Victim || Target)
Victim = null
Target = null
anchored = 0
if(prob(80) && !client)
Discipline++
@@ -596,68 +547,123 @@
else
drop_item()
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has disarmed [name]!</B>", M), 1)
visible_message("<span class='danger'>[M] has disarmed [name]!</span>",
"<span class='userdanger'>[M] has disarmed [name]!</span>")
adjustBruteLoss(damage)
updatehealth()
return
/mob/living/carbon/slime/attackby(obj/item/W, mob/user)
if(W.force > 0)
attacked += 10
if(prob(25))
user << "<span class='danger'>[W] passes right through [src]!</span>"
return
if(Discipline && prob(50)) // wow, buddy, why am I getting attacked??
Discipline = 0
if(W.force >= 3)
if(is_adult)
if(prob(5 + round(W.force/2)))
if(Victim || Target)
if(prob(80) && !client)
Discipline++
Victim = null
Target = null
anchored = 0
spawn()
SStun = 1
sleep(rand(5,20))
SStun = 0
spawn(0)
if(user)
canmove = 0
step_away(src, user)
if(prob(25 + W.force))
sleep(2)
if(user)
step_away(src, user)
canmove = 1
else
if(prob(10 + W.force*2))
if(Victim || Target)
if(prob(80) && !client)
Discipline++
if(Discipline == 1)
attacked = 0
spawn()
SStun = 1
sleep(rand(5,20))
SStun = 0
Victim = null
Target = null
anchored = 0
spawn(0)
if(user)
canmove = 0
step_away(src, user)
if(prob(25 + W.force*4))
sleep(2)
if(user)
step_away(src, user)
canmove = 1
..()
/mob/living/carbon/slime/restrained()
return 0
mob/living/carbon/slime/var/co2overloadtime = null
mob/living/carbon/slime/var/temperature_resistance = T0C+75
/mob/living/carbon/slime/show_inv(mob/user as mob)
user.set_machine(src)
var/dat = {"
<B><HR><FONT size=3>[name]</FONT></B>
<BR><HR><BR>
<BR><A href='?src=\ref[user];mach_close=mob[name]'>Close</A>
<BR>"}
user << browse(dat, text("window=mob[name];size=340x480"))
onclose(user, "mob[name]")
/mob/living/carbon/slime/show_inv(mob/user)
return
/mob/living/carbon/slime/updatehealth()
if(status_flags & GODMODE)
if(istype(src, /mob/living/carbon/slime/adult))
health = 200
else
health = 150
stat = CONSCIOUS
else
// slimes can't suffocate unless they suicide. They are also not harmed by fire
if(istype(src, /mob/living/carbon/slime/adult))
health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
else
health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
/mob/living/carbon/slime/toggle_throw_mode()
return
/mob/living/carbon/slime/proc/apply_water()
adjustToxLoss(rand(15,20))
if (!client)
if (Target) // Like cats
Target = null
++Discipline
return
/obj/item/slime_extract
name = "slime extract"
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
icon = 'icons/mob/slimes.dmi'
icon_state = "grey slime extract"
flags = TABLEPASS
force = 1.0
w_class = 1.0
throwforce = 1.0
throwforce = 0
throw_speed = 3
throw_range = 6
origin_tech = "biotech=4"
var/Uses = 1 // uses before it goes inert
var/enhanced = 0 //has it been enhanced before?
/* attackby(obj/item/O as obj, mob/user as mob)
if(istype(O, /obj/item/weapon/slimesteroid2))
if(enhanced == 1)
user << "<span class='warning'> This extract has already been enhanced!</span>"
return ..()
if(Uses == 0)
user << "<span class='warning'> You can't enhance a used extract!</span>"
return ..()
user <<"You apply the enhancer. It now has triple the amount of uses."
Uses = 3
enhanced = 1
del(O)
*/
/obj/item/slime_extract/New()
..()
var/datum/reagents/R = new/datum/reagents(100)
reagents = R
R.my_atom = src
create_reagents(100)
/obj/item/slime_extract/grey
name = "grey slime extract"
@@ -727,6 +733,26 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
name = "adamantine slime extract"
icon_state = "adamantine slime extract"
/obj/item/slime_extract/bluespace
name = "bluespace slime extract"
icon_state = "bluespace slime extract"
/obj/item/slime_extract/pyrite
name = "pyrite slime extract"
icon_state = "pyrite slime extract"
/obj/item/slime_extract/cerulean
name = "cerulean slime extract"
icon_state = "cerulean slime extract"
/obj/item/slime_extract/sepia
name = "sepia slime extract"
icon_state = "sepia slime extract"
/obj/item/slime_extract/rainbow
name = "rainbow slime extract"
icon_state = "rainbow slime extract"
////Pet Slime Creation///
/obj/item/weapon/slimepotion
@@ -737,28 +763,31 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
user << "\red The potion only works on baby slimes!"
user << "<span class='warning'> The potion only works on baby slimes!</span>"
return ..()
if(istype(M, /mob/living/carbon/slime/adult)) //Can't tame adults
user << "\red Only baby slimes can be tamed!"
if(M.is_adult) //Can't tame adults
user << "<span class='warning'> Only baby slimes can be tamed!</span>"
return..()
if(M.stat)
user << "\red The slime is dead!"
user << "<span class='warning'> The slime is dead!</span>"
return..()
if(M.mind)
user << "<span class='warning'> The slime resists!</span>"
return ..()
var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
pet.icon_state = "[M.colour] baby slime"
pet.icon_living = "[M.colour] baby slime"
pet.icon_dead = "[M.colour] baby slime dead"
pet.colour = "[M.colour]"
user <<"You feed the slime the potion, removing it's powers and calming it."
del (M)
del(M)
var/newname = copytext(sanitize(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text),1,MAX_NAME_LEN)
if (!newname)
newname = "pet slime"
pet.name = newname
pet.real_name = newname
del (src)
del(src)
/obj/item/weapon/slimepotion2
name = "advanced docility potion"
@@ -766,27 +795,30 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
icon = 'icons/obj/chemical.dmi'
icon_state = "bottle19"
attack(mob/living/carbon/slime/adult/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime/adult))//If target is not a slime.
user << "\red The potion only works on adult slimes!"
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
user << "<span class='warning'> The potion only works on slimes!</span>"
return ..()
if(M.stat)
user << "\red The slime is dead!"
user << "<span class='warning'> The slime is dead!</span>"
return..()
if(M.mind)
user << "<span class='warning'> The slime resists!</span>"
return ..()
var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc)
pet.icon_state = "[M.colour] adult slime"
pet.icon_living = "[M.colour] adult slime"
pet.icon_dead = "[M.colour] baby slime dead"
pet.colour = "[M.colour]"
user <<"You feed the slime the potion, removing it's powers and calming it."
del (M)
del(M)
var/newname = copytext(sanitize(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text),1,MAX_NAME_LEN)
if (!newname)
newname = "pet slime"
pet.name = newname
pet.real_name = newname
del (src)
del(src)
/obj/item/weapon/slimesteroid
@@ -797,16 +829,16 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
user << "\red The steroid only works on baby slimes!"
user << "<span class='warning'> The steroid only works on baby slimes!</span>"
return ..()
if(istype(M, /mob/living/carbon/slime/adult)) //Can't tame adults
user << "\red Only baby slimes can use the steroid!"
if(M.is_adult) //Can't tame adults
user << "<span class='warning'> Only baby slimes can use the steroid!</span>"
return..()
if(M.stat)
user << "\red The slime is dead!"
user << "<span class='warning'> The slime is dead!</span>"
return..()
if(M.cores == 3)
user <<"\red The slime already has the maximum amount of extract!"
user <<"<span class='warning'> The slime already has the maximum amount of extract!</span>"
return..()
user <<"You feed the slime the steroid. It now has triple the amount of extract."
@@ -842,6 +874,8 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
////////Adamantine Golem stuff I dunno where else to put it
// This will eventually be removed.
/obj/item/clothing/under/golem
name = "adamantine skin"
desc = "a golem's skin"
@@ -978,6 +1012,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
var/area/A = get_area(src)
if(A)
G << "Golem rune created in [A.name]."
//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
/*
@@ -987,11 +1022,10 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
icon = 'icons/mob/slimes.dmi'
icon_state = "slime extract"
flags = TABLEPASS
force = 1.0
w_class = 1.0
throwforce = 1.0
throw_speed = 3
throw_speed = 2
throw_range = 6
origin_tech = "biotech=4"
var/POWERFLAG = 0 // sshhhhhhh
@@ -1000,9 +1034,7 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
/obj/item/slime_core/New()
..()
var/datum/reagents/R = new/datum/reagents(100)
reagents = R
R.my_atom = src
create_reagents(100)
POWERFLAG = rand(1,10)
Uses = rand(7, 25)
//flags |= NOREACT
@@ -1046,9 +1078,9 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
processing_objects.Remove(src)
var/turf/T = get_turf(src)
src.visible_message("\blue The [name] pulsates and quivers!")
src.visible_message("<span class='warning'> The [name] pulsates and quivers!</span>")
spawn(rand(50,100))
src.visible_message("\blue The [name] bursts open!")
src.visible_message("<span class='warning'> The [name] bursts open!</span>")
new/mob/living/carbon/slime(T)
del(src)
@@ -1064,4 +1096,4 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
return
else
..()
*/
*/
@@ -11,12 +11,12 @@
var/list/choices = list()
for(var/mob/living/C in view(1,src))
if(C!=src && !istype(C,/mob/living/carbon/slime))
if(C!=src && !istype(C,/mob/living/carbon/slime) && Adjacent(C))
choices += C
var/mob/living/carbon/M = input(src,"Who do you wish to feed on?") in null|choices
var/mob/living/M = input(src,"Who do you wish to feed on?") in null|choices
if(!M) return
if(M in view(1, src))
if(Adjacent(M))
if(!istype(src, /mob/living/carbon/brain))
if(!istype(M, /mob/living/carbon/slime))
@@ -42,76 +42,72 @@
/mob/living/carbon/slime/proc/Feedon(var/mob/living/carbon/M)
/mob/living/carbon/slime/proc/Feedon(var/mob/living/M)
Victim = M
src.loc = M.loc
canmove = 0
anchored = 1
var/lastnut = nutrition
//if(M.client) M << "\red You legs become paralyzed!"
if(istype(src, /mob/living/carbon/slime/adult))
var/fed_succesfully = 0
if(is_adult)
icon_state = "[colour] adult slime eat"
else
icon_state = "[colour] baby slime eat"
while(Victim && M.health > -70 && stat != 2)
// M.canmove = 0
canmove = 0
if(M in view(1, src))
if(Adjacent(M))
loc = M.loc
if(prob(15) && M.client && istype(M, /mob/living/carbon))
M << "\red [pick("You can feel your body becoming weak!", \
M << "<span class='danger'>[pick("You can feel your body becoming weak!", \
"You feel like you're about to die!", \
"You feel every part of your body screaming in agony!", \
"A low, rolling pain passes through your body!", \
"Your body feels as if it's falling apart!", \
"You feel extremely weak!", \
"A sharp, deep pain bathes every inch of your body!")]"
"A sharp, deep pain bathes every inch of your body!")]</span>"
if(istype(M, /mob/living/carbon))
Victim.adjustCloneLoss(rand(1,10))
Victim.adjustCloneLoss(rand(5,6))
Victim.adjustToxLoss(rand(1,2))
if(Victim.health <= 0)
Victim.adjustToxLoss(rand(2,4))
// Heal yourself
adjustToxLoss(-10)
adjustOxyLoss(-10)
adjustBruteLoss(-10)
adjustFireLoss(-10)
adjustCloneLoss(-10)
fed_succesfully = 1
if(Victim)
for(var/mob/living/carbon/slime/slime in view(1,M))
if(slime.Victim == M && slime != src)
slime.Feedstop()
else if(istype(M, /mob/living/simple_animal))
Victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12))
fed_succesfully = 1
nutrition += rand(10,25)
else
if(prob(25))
src << "<span class='warning'>[pick("This subject is incompatable", \
"This subject does not have a life energy", "This subject is empty", \
"I am not satisified", "I can not feed from this subject", \
"I do not feel nourished", "This subject is not food")]...</span>"
if(fed_succesfully)
//I have no idea why this is not in handle_nutrition()
nutrition += rand(15,30)
if(nutrition >= lastnut + 50)
if(prob(80))
lastnut = nutrition
powerlevel++
if(powerlevel > 10)
powerlevel = 10
adjustToxLoss(-10)
if(istype(src, /mob/living/carbon/slime/adult))
if(nutrition > 1200)
nutrition = 1200
else
if(nutrition > 1000)
nutrition = 1000
//Heal yourself.
adjustOxyLoss(-10)
adjustBruteLoss(-10)
adjustFireLoss(-10)
adjustCloneLoss(-10)
Victim.updatehealth()
updatehealth()
else
if(prob(25))
src << "\red <i>[pick("This subject is incompatable", \
"This subject does not have a life energy", "This subject is empty", \
"I am not satisified", "I can not feed from this subject", \
"I do not feel nourished", "This subject is not food")]...</i>"
if(Victim)
Victim.updatehealth()
sleep(rand(15,45))
@@ -119,11 +115,11 @@
break
if(stat == 2)
if(!istype(src, /mob/living/carbon/slime/adult))
if(!is_adult)
icon_state = "[colour] baby slime dead"
else
if(istype(src, /mob/living/carbon/slime/adult))
if(is_adult)
icon_state = "[colour] adult slime"
else
icon_state = "[colour] baby slime"
@@ -139,7 +135,11 @@
if(Victim.LAssailant && Victim.LAssailant != Victim)
if(prob(50))
if(!(Victim.LAssailant in Friends))
Friends.Add(Victim.LAssailant) // no idea why i was using the |= operator
Friends[Victim.LAssailant] = 1
//Friends.Add(Victim.LAssailant) // no idea why i was using the |= operator
else
++Friends[Victim.LAssailant]
if(M.client && istype(src, /mob/living/carbon/human))
if(prob(85))
@@ -173,16 +173,13 @@
if(stat)
src << "<i>I must be conscious to do this...</i>"
return
if(!istype(src, /mob/living/carbon/slime/adult))
if(!is_adult)
if(amount_grown >= 10)
var/mob/living/carbon/slime/adult/new_slime = new adulttype(loc)
new_slime.nutrition = nutrition
new_slime.powerlevel = max(0, powerlevel-1)
new_slime.a_intent = "hurt"
new_slime.key = key
new_slime.universal_speak = universal_speak
new_slime << "<B>You are now an adult slime.</B>"
del(src)
is_adult = 1
maxHealth = 200
amount_grown = 0
regenerate_icons()
name = text("[colour] [is_adult ? "adult" : "baby"] slime ([number])")
else
src << "<i>I am not ready to evolve yet...</i>"
else
@@ -190,15 +187,14 @@
/mob/living/carbon/slime/verb/Reproduce()
set category = "Slime"
set desc = "This will make you split into four Slimes. NOTE: this will KILL you, but you will be transferred into one of the babies."
set desc = "This will make you split into four Slimes."
if(stat)
src << "<i>I must be conscious to do this...</i>"
return
if(istype(src, /mob/living/carbon/slime/adult))
if(is_adult)
if(amount_grown >= 10)
//if(input("Are you absolutely sure you want to reproduce? Your current body will cease to be, but your consciousness will be transferred into a produced slime.") in list("Yes","No")=="Yes")
if(stat)
src << "<i>I must be conscious to do this...</i>"
return
@@ -207,54 +203,49 @@
var/new_nutrition = round(nutrition * 0.9)
var/new_powerlevel = round(powerlevel / 4)
for(var/i=1,i<=4,i++)
if(prob(80))
var/mob/living/carbon/slime/M = new primarytype(loc)
M.nutrition = new_nutrition
M.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += M
else
var/mutations = pick("one","two","three","four")
switch(mutations)
if("one")
var/mob/living/carbon/slime/M = new mutationone(loc)
M.nutrition = new_nutrition
M.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += M
if("two")
var/mob/living/carbon/slime/M = new mutationtwo(loc)
M.nutrition = new_nutrition
M.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += M
if("three")
var/mob/living/carbon/slime/M = new mutationthree(loc)
M.nutrition = new_nutrition
M.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += M
if("four")
var/mob/living/carbon/slime/M = new mutationfour(loc)
M.nutrition = new_nutrition
M.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += M
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime/(loc)
// if(prob(mutation_chance))
// M.colour = slime_mutation[rand(1,4)]
// else
var/mutations = pick("one","two","three","four")
switch(mutations)
if("one")
var/mob/living/carbon/slime/O = new mutationone(loc)
O.nutrition = new_nutrition
O.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += O
if("two")
var/mob/living/carbon/slime/K = new mutationtwo(loc)
K.nutrition = new_nutrition
K.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += K
if("three")
var/mob/living/carbon/slime/L = new mutationthree(loc)
L.nutrition = new_nutrition
L.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += L
if("four")
var/mob/living/carbon/slime/N = new mutationfour(loc)
N.nutrition = new_nutrition
N.powerlevel = new_powerlevel
if(i != 1) step_away(M,src)
babies += N
var/mob/living/carbon/slime/new_slime = pick(babies)
new_slime.a_intent = "hurt"
new_slime.universal_speak = universal_speak
new_slime.key = key
new_slime << "<B>You are now a slime!</B>"
if(src.mind)
src.mind.transfer_to(new_slime)
else
new_slime.key = src.key
del(src)
else
src << "<i>I am not ready to reproduce yet...</i>"
else
src << "<i>I am not old enough to reproduce yet...</i>"
/mob/living/carbon/slime/verb/ventcrawl()
set name = "Crawl through Vent"
set desc = "Enter an air vent and crawl through the pipe system."
@@ -0,0 +1,23 @@
/mob/living/carbon/slime/say(var/message)
var/verb = say_quote(message)
if(copytext(message,1,2) == "*")
return emote(copytext(message,2))
return ..(message, null, verb)
/mob/living/carbon/slime/say_quote(var/text)
var/ending = copytext(text, length(text))
if (ending == "?")
return "telepathically asks";
else if (ending == "!")
return "telepathically cries";
return "telepathically chirps";
/mob/living/carbon/slime/say_understands(var/other)
if (istype(other, /mob/living/carbon/slime))
return 1
return ..()
+6 -11
View File
@@ -12,6 +12,7 @@
var/ready_evolve = 0
universal_understand = 0 // Dionaea do not need to speak to people
universal_speak = 0 // before becoming an adult. Use *chirp.
holder_type = /obj/item/weapon/holder/diona
/mob/living/carbon/monkey/diona/attack_hand(mob/living/carbon/human/M as mob)
@@ -24,14 +25,7 @@
src.verbs -= /mob/living/carbon/monkey/diona/proc/merge
src.loc = M
else
var/obj/item/weapon/holder/diona/D = new(loc)
src.loc = D
D.name = loc.name
D.attack_hand(M)
M << "You scoop up [src]."
src << "[M] scoops you up."
M.status_flags |= PASSEMOTES
return
get_scooped(M)
..()
@@ -114,7 +108,7 @@
var/list/trays = list()
for(var/obj/machinery/hydroponics/tray in range(1))
if(tray.nutrilevel < 10)
if(tray.nutrilevel < 10 && src.Adjacent(tray))
trays += tray
var/obj/machinery/hydroponics/target = input("Select a tray:") as null|anything in trays
@@ -133,7 +127,7 @@
var/list/trays = list()
for(var/obj/machinery/hydroponics/tray in range(1))
if(tray.weedlevel > 0)
if(tray.weedlevel > 0 && src.Adjacent(tray))
trays += tray
var/obj/machinery/hydroponics/target = input("Select a tray:") as null|anything in trays
@@ -192,7 +186,8 @@
var/list/choices = list()
for(var/mob/living/carbon/human/H in oview(1,src))
choices += H
if(src.Adjacent(H))
choices += H
var/mob/living/carbon/human/M = input(src,"Who do you wish to take a sample from?") in null|choices
+32 -61
View File
@@ -83,11 +83,6 @@
emote(pick("scratch","jump","roll","tail"))
updatehealth()
/mob/living/carbon/monkey/calculate_affecting_pressure(var/pressure)
..()
return pressure
/mob/living/carbon/monkey
proc/handle_disabilities()
@@ -142,8 +137,9 @@
if (radiation > 100)
radiation = 100
Weaken(10)
src << "\red You feel weak."
emote("collapse")
if(!lying)
src << "\red You feel weak."
emote("collapse")
switch(radiation)
if(1 to 49)
@@ -157,8 +153,9 @@
if(prob(5))
radiation -= 5
Weaken(3)
src << "\red You feel weak."
emote("collapse")
if(!lying)
src << "\red You feel weak."
emote("collapse")
if(75 to 100)
radiation -= 3
@@ -238,25 +235,14 @@
var/obj/location_as_object = loc
breath = location_as_object.handle_internal_lifeform(src, BREATH_VOLUME)
else if(istype(loc, /turf/))
var/breath_moles = environment.total_moles()*BREATH_PERCENTAGE
var/breath_moles = environment.total_moles*BREATH_PERCENTAGE
breath = loc.remove_air(breath_moles)
if(istype(wear_mask, /obj/item/clothing/mask/gas))
var/obj/item/clothing/mask/gas/G = wear_mask
var/datum/gas_mixture/filtered = new
filtered.copy_from(breath)
filtered.toxins *= G.gas_filter_strength
for(var/datum/gas/gas in filtered.trace_gases)
gas.moles *= G.gas_filter_strength
filtered.update_values()
if(istype(wear_mask, /obj/item/clothing/mask) && breath)
var/obj/item/clothing/mask/M = wear_mask
var/datum/gas_mixture/filtered = M.filter_air(breath)
loc.assume_air(filtered)
breath.toxins *= 1 - G.gas_filter_strength
for(var/datum/gas/gas in breath.trace_gases)
gas.moles *= 1 - G.gas_filter_strength
breath.update_values()
// Handle chem smoke effect -- Doohl
var/block = 0
if(wear_mask)
@@ -317,14 +303,14 @@
var/SA_para_min = 0.5
var/SA_sleep_min = 5
var/oxygen_used = 0
var/breath_pressure = (breath.total_moles()*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
var/breath_pressure = (breath.total_moles * R_IDEAL_GAS_EQUATION * breath.temperature) / BREATH_VOLUME
//Partial pressure of the O2 in our breath
var/O2_pp = (breath.oxygen/breath.total_moles())*breath_pressure
var/O2_pp = (breath.gas["oxygen"] / breath.total_moles) * breath_pressure
// Same, but for the toxins
var/Toxins_pp = (breath.toxins/breath.total_moles())*breath_pressure
var/Toxins_pp = (breath.gas["toxins"] / breath.total_moles) * breath_pressure
// And CO2, lets say a PP of more than 10 will be bad (It's a little less really, but eh, being passed out all round aint no fun)
var/CO2_pp = (breath.carbon_dioxide/breath.total_moles())*breath_pressure
var/CO2_pp = (breath.gas["carbon_dioxide"] / breath.total_moles) * breath_pressure
if(O2_pp < safe_oxygen_min) // Too little oxygen
if(prob(20))
@@ -333,7 +319,7 @@
O2_pp = 0.01
var/ratio = safe_oxygen_min/O2_pp
adjustOxyLoss(min(5*ratio, 7)) // Don't fuck them up too fast (space only does 7 after all!)
oxygen_used = breath.oxygen*ratio/6
oxygen_used = breath.gas["oxygen"] * ratio / 6
oxygen_alert = max(oxygen_alert, 1)
/*else if (O2_pp > safe_oxygen_max) // Too much oxygen (commented this out for now, I'll deal with pressure damage elsewhere I suppose)
spawn(0) emote("cough")
@@ -343,11 +329,11 @@
oxygen_alert = max(oxygen_alert, 1)*/
else // We're in safe limits
adjustOxyLoss(-5)
oxygen_used = breath.oxygen/6
oxygen_used = breath.gas["oxygen"] / 6
oxygen_alert = 0
breath.oxygen -= oxygen_used
breath.carbon_dioxide += oxygen_used
breath.adjust_gas("oxygen", -oxygen_used)
breath.adjust_gas("carbon_dioxide", oxygen_used)
if(CO2_pp > safe_co2_max)
if(!co2overloadtime) // If it's the first breath with too much CO2 in it, lets start a counter, then have them pass out after 12s or so.
@@ -364,7 +350,7 @@
co2overloadtime = 0
if(Toxins_pp > safe_toxins_max) // Too much toxins
var/ratio = (breath.toxins/safe_toxins_max) * 10
var/ratio = (breath.gas["toxins"] / safe_toxins_max) * 10
//adjustToxLoss(Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE)) //Limit amount of damage toxin exposure can do per second
if(reagents)
reagents.add_reagent("plasma", Clamp(ratio, MIN_PLASMA_DAMAGE, MAX_PLASMA_DAMAGE))
@@ -372,16 +358,15 @@
else
toxins_alert = 0
if(breath.trace_gases.len) // If there's some other shit in the air lets deal with it here.
for(var/datum/gas/sleeping_agent/SA in breath.trace_gases)
var/SA_pp = (SA.moles/breath.total_moles())*breath_pressure
if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit
Paralyse(3) // 3 gives them one second to wake up and run away a bit!
if(SA_pp > SA_sleep_min) // Enough to make us sleep as well
sleeping = max(sleeping+2, 10)
else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
if(prob(20))
spawn(0) emote(pick("giggle", "laugh"))
if(breath.gas["sleeping_agent"])
var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure
if(SA_pp > SA_para_min) // Enough to make us paralysed for a bit
Paralyse(3) // 3 gives them one second to wake up and run away a bit!
if(SA_pp > SA_sleep_min) // Enough to make us sleep as well
sleeping = max(sleeping+2, 10)
else if(SA_pp > 0.01) // There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
if(prob(20))
spawn(0) emote(pick("giggle", "laugh"))
if(breath.temperature > (T0C+66)) // Hot air hurts :(
@@ -402,9 +387,8 @@
//Moved these vars here for use in the fuck-it-skip-processing check.
var/pressure = environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob.
if(pressure < WARNING_HIGH_PRESSURE && pressure > WARNING_LOW_PRESSURE && abs(environment.temperature - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5 && environment.gas["toxins"] < MOLES_PLASMA_VISIBLE)
if(adjusted_pressure < WARNING_HIGH_PRESSURE && adjusted_pressure > WARNING_LOW_PRESSURE && abs(environment.temperature - 293.15) < 20 && abs(bodytemperature - 310.14) < 0.5 && environment.toxins < MOLES_PLASMA_VISIBLE)
//Hopefully should fix the walk-inside-still-pressure-warning issue.
if(pressure_alert)
@@ -427,9 +411,9 @@
bodytemperature += 0.1*(environment.temperature - bodytemperature)*environment_heat_capacity/(environment_heat_capacity + 270000)
//Account for massive pressure differences
switch(adjusted_pressure)
switch(pressure)
if(HAZARD_HIGH_PRESSURE to INFINITY)
adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
adjustBruteLoss( min( ( (pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
pressure_alert = 2
if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
pressure_alert = 1
@@ -569,20 +553,7 @@
ear_damage = max(ear_damage-0.05, 0)
//Other
if(stunned)
AdjustStunned(-1)
if(weakened)
weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times
if(stuttering)
stuttering = max(stuttering-1, 0)
if(silent)
silent = max(silent-1, 0)
if(druggy)
druggy = max(druggy-1, 0)
handle_statuses()
return 1
+11 -12
View File
@@ -246,10 +246,9 @@
help_shake_act(M)
else
if (M.a_intent == "hurt")
var/datum/unarmed_attack/attack = M.species.unarmed
if ((prob(75) && health > 0))
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has punched [name]!</B>", M), 1)
visible_message("\red <B>[M] [pick(attack.attack_verb)]ed [src]!</B>")
playsound(loc, "punch", 25, 1, -1)
var/damage = rand(5, 10)
@@ -257,18 +256,18 @@
damage = rand(10, 15)
if (paralysis < 5)
Paralyse(rand(10, 15))
spawn( 0 )
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has knocked out [name]!</B>", M), 1)
return
visible_message("\red <B>[M] has knocked out [src]!</B>")
adjustBruteLoss(damage)
M.attack_log += text("\[[time_stamp()]\] <font color='red'>[pick(attack.attack_verb)]ed [src.name] ([src.ckey])</font>")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [pick(attack.attack_verb)]ed by [M.name] ([M.ckey])</font>")
msg_admin_attack("[key_name(M)] [pick(attack.attack_verb)]ed [key_name(src)]")
updatehealth()
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
for(var/mob/O in viewers(src, null))
if ((O.client && !( O.blinded )))
O.show_message(text("\red <B>[] has attempted to punch [name]!</B>", M), 1)
visible_message("\red <B>[M] tried to [pick(attack.attack_verb)] [src]!</B>")
else
if (M.a_intent == "grab")
if (M == src || anchored)
@@ -403,7 +402,7 @@
var/damage = rand(1, 3)
if(istype(src, /mob/living/carbon/slime/adult))
if(M.is_adult)
damage = rand(20, 40)
else
damage = rand(5, 35)
+28 -78
View File
@@ -14,11 +14,12 @@
var/language // Default racial language, if any.
var/unarmed //For empty hand harm-intent attack
var/unarmed_type = /datum/unarmed_attack
var/secondary_langs = list() // The names of secondary languages that are available to this species.
var/mutantrace // Safeguard due to old code.
var/breath_type = "oxygen" // Non-oxygen gas breathed, if any.
var/poison_type = "plasma" // Poisonous air.
var/exhale_type = "C02" // Exhaled gas type.
var/exhale_type = "carbon_dioxide" // Exhaled gas type.
var/cold_level_1 = 260 // Cold damage level 1 below this point.
var/cold_level_2 = 200 // Cold damage level 2 below this point.
@@ -28,6 +29,10 @@
var/heat_level_2 = 400 // Heat damage level 2 above this point.
var/heat_level_3 = 1000 // Heat damage level 2 above this point.
var/body_temperature = 310.15 //non-IS_SYNTHETIC species will try to stabilize at this temperature. (also affects temperature processing)
var/synth_temp_gain = 0 //IS_SYNTHETIC species will gain this much temperature every second
var/reagent_tag //Used for metabolizing reagents.
var/darksight = 2
var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure.
var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning.
@@ -43,34 +48,12 @@
var/blood_color = "#A10808" //Red.
var/flesh_color = "#FFC896" //Pink.
var/base_color //Used when setting species.
//Used in icon caching.
var/race_key = 0
var/icon/icon_template
//Used for character generation fluff items.
var/list/custom_gear_options
/* Species-specific sprites, concept stolen from Paradise//vg/.
ex:
sprite_sheets = list(
"held" = 'icons/mob/path',
"uniform" = 'icons/mob/path',
"suit" = 'icons/mob/path',
"belt" = 'icons/mob/path'
"head" = 'icons/mob/path',
"back" = 'icons/mob/path',
"mask" = 'icons/mob/path',
"ears" = 'icons/mob/path',
"eyes" = 'icons/mob/path',
"feet" = 'icons/mob/path',
"gloves" = 'icons/mob/path'
)
If index term exists and icon_override is not set, this sprite sheet will be used.
*/
var/list/sprite_sheets = list()
/datum/species/New()
unarmed = new unarmed_type()
@@ -156,10 +139,8 @@
flesh_color = "#34AF10"
custom_gear_options = list(
"Unathi robe" = /obj/item/clothing/suit/unathi/robe,
"Unathi mantle" = /obj/item/clothing/suit/unathi/mantle
)
reagent_tag = IS_UNATHI
base_color = "#066000"
/datum/species/tajaran
name = "Tajaran"
@@ -183,11 +164,7 @@
flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_TAIL | HAS_SKIN_COLOR
flesh_color = "#AFA59E"
custom_gear_options = list(
/obj/item/clothing/head/tajaran/scarf,
/obj/item/clothing/suit/tajaran/furs
)
base_color = "#333333"
/datum/species/skrell
name = "Skrell"
@@ -201,6 +178,8 @@
flesh_color = "#8CD7A3"
reagent_tag = IS_SKRELL
/datum/species/vox
name = "Vox"
icobase = 'icons/mob/human_races/r_vox.dmi'
@@ -220,27 +199,22 @@
breath_type = "nitrogen"
poison_type = "oxygen"
flags = NO_SCAN | NO_BLOOD
flags = NO_SCAN
blood_color = "#2299FC"
flesh_color = "#808D11"
sprite_sheets = list(
"suit" = 'icons/mob/species/vox/suit.dmi',
"head" = 'icons/mob/species/vox/head.dmi',
"mask" = 'icons/mob/species/vox/mask.dmi',
"feet" = 'icons/mob/species/vox/feet.dmi',
"gloves" = 'icons/mob/species/vox/gloves.dmi'
)
/* NO MORE LEAPS. NO MORE.
reagent_tag = IS_VOX
/datum/species/vox/handle_post_spawn(var/mob/living/carbon/human/H)
H.verbs += /mob/living/carbon/human/proc/leap
..()
*/
/datum/species/vox/armalis/handle_post_spawn(var/mob/living/carbon/human/H)
H.verbs += /mob/living/carbon/human/proc/gut
H.verbs += /mob/living/carbon/human/proc/commune
..()
/datum/species/vox/armalis
@@ -276,36 +250,7 @@
tail = "armalis_tail"
icon_template = 'icons/mob/human_races/r_armalis.dmi'
sprite_sheets = list(
"suit" = 'icons/mob/species/armalis/suit.dmi',
"gloves" = 'icons/mob/species/armalis/gloves.dmi',
"feet" = 'icons/mob/species/armalis/feet.dmi',
"head" = 'icons/mob/species/armalis/head.dmi',
"held" = 'icons/mob/species/armalis/held.dmi'
)
/datum/species/vox/create_organs(var/mob/living/carbon/human/H)
..() //create organs first.
//Now apply cortical stack.
var/datum/organ/external/affected = H.get_organ("head")
//To avoid duplicates.
for(var/obj/item/weapon/implant/cortical/imp in H.contents)
affected.implants -= imp
del(imp)
var/obj/item/weapon/implant/cortical/I = new(H)
I.imp_in = H
I.implanted = 1
affected.implants += I
I.part = affected
if(ticker.mode && ( istype( ticker.mode,/datum/game_mode/heist ) ) )
var/datum/game_mode/heist/M = ticker.mode
M.cortical_stacks += I
M.raiders[H.mind] = I
reagent_tag = IS_VOX
/datum/species/diona
name = "Diona"
@@ -326,11 +271,15 @@
heat_level_2 = 3000
heat_level_3 = 4000
body_temperature = T0C + 15 //make the plant people have a bit lower body temperature, why not
flags = IS_WHITELISTED | NO_BREATHE | REQUIRE_LIGHT | NO_SCAN | IS_PLANT | RAD_ABSORB | NO_BLOOD | IS_SLOW | NO_PAIN
blood_color = "#004400"
flesh_color = "#907E4A"
reagent_tag = IS_DIONA
/datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H)
H.gender = NEUTER
@@ -342,7 +291,6 @@
if(H.mind)
H.mind.transfer_to(S)
S.key = H
for(var/mob/living/carbon/monkey/diona/D in H.contents)
if(D.client)
@@ -364,15 +312,17 @@
burn_mod = 1
warning_low_pressure = 50
hazard_low_pressure = 10
hazard_low_pressure = 0
cold_level_1 = 50
cold_level_2 = -1
cold_level_3 = -1
heat_level_1 = 2000
heat_level_2 = 3000
heat_level_3 = 4000
heat_level_1 = 500 //gives them about 25 seconds in space before taking damage
heat_level_2 = 1000
heat_level_3 = 2000
synth_temp_gain = 10 //this should cause IPCs to stabilize at ~80 C in a 20 C environment.
flags = IS_WHITELISTED | NO_BREATHE | NO_SCAN | NO_BLOOD | NO_PAIN | IS_SYNTHETIC
+2 -1
View File
@@ -52,7 +52,8 @@
if(AGONY)
adjustHalLoss(effect) // Useful for objects that cause "subdual" damage. PAIN! //ducknote: tasers did not previously care about armor. i assume this was deliberate and am leaving it alone since taserdamage is mitigated by siemens
if(IRRADIATE)
radiation += max((((effect - (effect*(getarmor(null, "rad")/100))))/(blocked+1)),0)//Rads auto check armor
var/rad_protection = getarmor(null, "rad")/100
radiation += max((1-rad_protection)*effect/(blocked+1),0)//Rads auto check armor
if(STUTTER)
if(status_flags & CANSTUN) // stun is usually associated with stutter
stuttering = max(stuttering,(effect/(blocked+1)))
+5 -19
View File
@@ -18,7 +18,7 @@
//This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually
//affects them once clothing is factored in. ~Errorage
/mob/living/proc/calculate_affecting_pressure(var/pressure)
return 0
return
//sort of a legacy burn method for /electrocute, /shock, and the e_chair
@@ -202,15 +202,6 @@
return 0
/mob/living/proc/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0)
return 0 //only carbon liveforms have this proc
/mob/living/emp_act(severity)
var/list/L = src.get_contents()
for(var/obj/O in L)
O.emp_act(severity)
..()
/mob/living/proc/can_inject()
return 1
@@ -311,6 +302,7 @@
dead_mob_list -= src
living_mob_list += src
tod = null
timeofdeath = 0
// restore us to conciousness
stat = CONSCIOUS
@@ -483,7 +475,7 @@
H << "\red <B>You begin doggedly resisting the parasite's control (this will take approximately sixty seconds).</B>"
B.host << "\red <B>You feel the captive mind of [src] begin to resist your control.</B>"
spawn(rand(350,450)+B.host.brainloss)
spawn(rand(400,500)+B.host.brainloss)
if(!B || !B.controlling)
return
@@ -491,14 +483,8 @@
B.host.adjustBrainLoss(rand(5,10))
H << "\red <B>With an immense exertion of will, you regain control of your body!</B>"
B.host << "\red <B>You feel control of the host brain ripped from your grasp, and retract your probosci before the wild neural impulses can damage you.</b>"
B.controlling = 0
B.ckey = B.host.ckey
B.host.ckey = H.ckey
H.ckey = null
H.name = "host brain"
H.real_name = "host brain"
B.detatch()
verbs -= /mob/living/carbon/proc/release_control
verbs -= /mob/living/carbon/proc/punish_host
@@ -624,7 +610,7 @@
BD.attack_hand(usr)
C.open()
//breaking out of handcuffs and stop, drop, and roll
//breaking out of handcuffs
else if(iscarbon(L))
var/mob/living/carbon/CM = L
if(CM.on_fire && CM.canmove)
+83 -34
View File
@@ -32,11 +32,15 @@
return 0
//if null is passed for def_zone, then this should return something appropriate for all zones (e.g. area effect damage)
/mob/living/proc/getarmor(var/def_zone, var/type)
return 0
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone)
flash_weak_pain()
//Being hit while using a cloaking device
var/obj/item/weapon/cloaking_device/C = locate((/obj/item/weapon/cloaking_device) in src)
if(C && C.active)
C.attack_self(src)//Should shut it off
@@ -44,8 +48,7 @@
src << "\blue Your [C.name] was disrupted!"
Stun(2)
flash_weak_pain()
//Being hit while using a deadman switch
if(istype(equipped(),/obj/item/device/assembly/signaler))
var/obj/item/device/assembly/signaler/signaler = equipped()
if(signaler.deadman && prob(80))
@@ -53,60 +56,105 @@
signaler.signal()
var/absorb = run_armor_check(def_zone, P.flag)
var/proj_sharp = is_sharp(P)
var/proj_edge = has_edge(P)
if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.flag)))
proj_sharp = 0
proj_edge = 0
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, absorb, 0, P, sharp=is_sharp(P), edge=has_edge(P))
apply_damage(P.damage, P.damage_type, def_zone, absorb, 0, P, sharp=proj_sharp, edge=proj_edge)
P.on_hit(src, absorb, def_zone)
return absorb
//Handles the effects of "stun" weapons
/mob/living/proc/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null)
flash_pain()
if (stun_amount)
Stun(stun_amount)
Weaken(stun_amount)
apply_effect(STUTTER, stun_amount)
apply_effect(EYE_BLUR, stun_amount)
if (agony_amount)
apply_damage(agony_amount, HALLOSS, def_zone, 0, used_weapon)
apply_effect(STUTTER, agony_amount/10)
apply_effect(EYE_BLUR, agony_amount/10)
/mob/living/proc/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0)
return 0 //only carbon liveforms have this proc
/mob/living/emp_act(severity)
var/list/L = src.get_contents()
for(var/obj/O in L)
O.emp_act(severity)
..()
//this proc handles being hit by a thrown atom
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve
if(istype(AM,/obj/))
var/obj/O = AM
var/zone = ran_zone("chest",75)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
if(istype(O,/obj/item/weapon))
var/obj/item/weapon/W = O
dtype = W.damtype
src.visible_message("\red [src] has been hit by [O].")
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [zone].", "Your armor has softened hit to your [zone].")
if(armor < 2)
apply_damage(O.throwforce*(speed/5), dtype, zone, armor, O, sharp=is_sharp(O), edge=has_edge(O))
var/throw_damage = O.throwforce*(speed/5)
if(!O.fingerprintslast)
var/miss_chance = 15
if (O.throw_source)
var/distance = get_dist(O.throw_source, loc)
miss_chance = min(15*(distance-2), 0)
if (prob(miss_chance))
visible_message("\blue \The [O] misses [src] narrowly!")
return
var/client/assailant = directory[ckey(O.fingerprintslast)]
if(assailant && assailant.mob && istype(assailant.mob,/mob))
var/mob/M = assailant.mob
src.visible_message("\red [src] has been hit by [O].")
var/armor = run_armor_check(null, "melee")
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been hit with a thrown [O], last touched by [M.name] ([assailant.ckey])</font>")
M.attack_log += text("\[[time_stamp()]\] <font color='red'>Hit [src.name] ([src.ckey]) with a thrown [O]</font>")
if(!istype(src,/mob/living/simple_animal/mouse))
msg_admin_attack("[src.name] ([src.ckey]) was hit by a thrown [O], last touched by [M.name] ([assailant.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)")
if(armor < 2)
apply_damage(throw_damage, dtype, null, armor, is_sharp(O), has_edge(O), O)
// Begin BS12 momentum-transfer code.
O.throwing = 0 //it hit, so stop moving
if(speed >= 20)
var/obj/item/weapon/W = O
var/momentum = speed/2
var/dir = get_dir(M,src)
if(ismob(O.thrower))
var/mob/M = O.thrower
var/client/assailant = M.client
if(assailant)
src.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been hit with a [O], thrown by [M.name] ([assailant.ckey])</font>")
M.attack_log += text("\[[time_stamp()]\] <font color='red'>Hit [src.name] ([src.ckey]) with a thrown [O]</font>")
if(!istype(src,/mob/living/simple_animal/mouse))
msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)")
visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!")
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
// Begin BS12 momentum-transfer code.
if(O.throw_source && speed >= 15)
var/obj/item/weapon/W = O
var/momentum = speed/2
var/dir = get_dir(O.throw_source, src)
if(istype(W.loc,/mob/living) && W.sharp) //Projectile is embedded and suitable for pinning.
visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!")
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
if(!istype(src,/mob/living/carbon/human)) //Handles embedding for non-humans and simple_animals.
O.loc = src
src.embedded += O
if(!W || !src) return
var/turf/T = near_wall(dir,2)
if(W.sharp) //Projectile is suitable for pinning.
//Handles embedding for non-humans and simple_animals.
O.loc = src
src.embedded += O
if(T)
src.loc = T
visible_message("<span class='warning'>[src] is pinned to the wall by [O]!</span>","<span class='warning'>You are pinned to the wall by [O]!</span>")
src.anchored = 1
src.pinned += O
var/turf/T = near_wall(dir,2)
if(T)
src.loc = T
visible_message("<span class='warning'>[src] is pinned to the wall by [O]!</span>","<span class='warning'>You are pinned to the wall by [O]!</span>")
src.anchored = 1
src.pinned += O
src.verbs += /mob/proc/yank_out_object
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
src.take_organ_damage(speed*5)
/mob/living/proc/near_wall(var/direction,var/distance=1)
var/turf/T = get_step(get_turf(src),direction)
@@ -149,7 +197,8 @@
if(!on_fire)
return 1
var/datum/gas_mixture/G = loc.return_air() // Check if we're standing in an oxygenless environment
if(G.oxygen < 1)
if(!G.gas["oxygen"])
// if(G.oxygen < 1) //Investigate this when it's NOT 2332hrs local, K? - Skull132
ExtinguishMob() //If there's no oxygen in the tile we're on, put out the fire
return
var/turf/location = get_turf(src)
+60 -65
View File
@@ -1,4 +1,3 @@
#define SAY_MINIMUM_PRESSURE 10
var/list/department_radio_keys = list(
":r" = "right ear", "#r" = "right ear", ".r" = "right ear",
":l" = "left ear", "#l" = "left ear", ".l" = "left ear",
@@ -15,6 +14,7 @@ var/list/department_radio_keys = list(
":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
":g" = "changeling", "#g" = "changeling", ".g" = "changeling",
":d" = "dronechat", "#d" = "dronechat", ".d" = "dronechat",
":R" = "right ear", "#R" = "right ear", ".R" = "right ear",
":L" = "left ear", "#L" = "left ear", ".L" = "left ear",
@@ -31,6 +31,7 @@ var/list/department_radio_keys = list(
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
":G" = "changeling", "#G" = "changeling", ".G" = "changeling",
":D" = "dronechat", "#D" = "dronechat", ".D" = "dronechat",
//kinda localization -- rastaf0
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
@@ -81,14 +82,49 @@ var/list/department_radio_keys = list(
if(!istype(dongle)) return
if(dongle.translate_binary) return 1
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/list/used_radios = list())
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/list/used_radios = list(), var/sound/speech_sound, var/sound_vol)
var/turf/T = get_turf(src)
var/list/listening = list()
if(T)
//handle nonverbal and sign languages here
if (speaking)
if (speaking.flags & NONVERBAL)
if (prob(30))
src.custom_emote(1, "[pick(speaking.signlang_verb)].")
var/list/objects = list()
if (speaking.flags & SIGNLANG)
say_signlang(message, pick(speaking.signlang_verb), speaking)
return 1
//speaking into radios
if(used_radios.len)
italics = 1
message_range = 1
if (!istype(src, /mob/living/silicon/ai)) // Atlantis: Prevents nearby people from hearing the AI when it talks using it's integrated radio.
for(var/mob/living/M in hearers(5, src))
if(M != src)
M.show_message("<span class='notice'>[src] talks into [used_radios.len ? used_radios[1] : "the radio."]</span>")
if (speech_sound)
src.playsound_local(get_turf(src), speech_sound, sound_vol * 0.5, 1)
speech_sound = null //so we don't play it twice.
//make sure the air can transmit speech
var/datum/gas_mixture/environment = T.return_air()
if(environment)
var/pressure = environment.return_pressure()
if(pressure < SOUND_MINIMUM_PRESSURE)
italics = 1
message_range = 1
if (speech_sound)
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
var/list/listening = list()
var/list/listening_obj = list()
if(T)
var/list/hear = hear(message_range, T)
var/list/hearturfs = list()
@@ -98,11 +134,18 @@ var/list/department_radio_keys = list(
listening += M
hearturfs += M.locs[1]
for(var/obj/O in M.contents)
objects |= O
listening_obj |= O
if (isslime(I))
var/mob/living/carbon/slime/S = I
if (src in S.Friends)
S.speech_buffer = list()
S.speech_buffer.Add(src)
S.speech_buffer.Add(lowertext(html_decode(message)))
else if(istype(I, /obj/))
var/obj/O = I
hearturfs += O.locs[1]
objects |= O
listening_obj |= O
for(var/mob/M in player_list)
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
@@ -111,76 +154,28 @@ var/list/department_radio_keys = list(
if(M.loc && M.locs[1] in hearturfs)
listening |= M
for(var/obj/O in objects)
spawn(0)
if(O) //It's possible that it could be deleted in the meantime.
O.hear_talk(src, message, verb, speaking)
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
spawn(30) del(speech_bubble)
if(used_radios.len)
for(var/mob/living/M in hearers(5, src))
if(M != src)
M.show_message("<span class='notice'>[src] talks into [used_radios.len ? used_radios[1] : "radio"]</span>")
for(var/mob/M in listening)
M << speech_bubble
M.hear_say(message,verb,speaking,alt_name, italics, src)
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
for(var/obj/O in listening_obj)
spawn(0)
if(O) //It's possible that it could be deleted in the meantime.
O.hear_talk(src, message, verb, speaking)
log_say("[name]/[key] : [message]")
return 1
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)
for (var/mob/O in viewers(src, null))
O.hear_signlang(message, verb, language, src)
/obj/effect/speech_bubble
var/mob/parent
/mob/living/proc/GetVoice()
return name
/mob/living/sign(var/message, var/verb="signs", var/datum/language/speaking = null, var/alt_name="", var/italics=0, var/message_range = world.view)
var/turf/T = get_turf(src)
var/list/listening = list()
if(T)
var/list/objects = list()
var/list/hear = hear(message_range, T)
var/list/hearturfs = list()
for(var/I in hear)
if(istype(I, /mob/))
var/mob/M = I
listening += M
hearturfs += M.locs[1]
for(var/obj/O in M.contents)
objects |= O
else if(istype(I, /obj/))
var/obj/O = I
hearturfs += O.locs[1]
objects |= O
for(var/mob/M in player_list)
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
listening |= M
continue
if(M.loc && M.locs[1] in hearturfs)
listening |= M
// Can object see signing?
// Only if they have cameras.
// Do any objects currently have cameras? -- SoundScopes
// for(var/obj/O in objects)
// spawn(0)
// if(O) //It's possible that it could be deleted in the meantime.
// O.hear_talk(src, message, verb, speaking)
for(var/mob/M in listening)
if(istype(M, /mob/new_player)) // for some reason this didn't work like say() this fixes it
continue
M.see_say(message,verb,speaking,alt_name, italics, src)
log_say("[name]/[key] : [message]")
+152 -59
View File
@@ -1,4 +1,29 @@
#define AI_CHECK_WIRELESS 1
#define AI_CHECK_RADIO 2
var/list/ai_list = list()
var/list/ai_verbs_default = list(
/mob/living/silicon/ai/proc/ai_alerts,
/mob/living/silicon/ai/proc/ai_announcement,
/mob/living/silicon/ai/proc/ai_call_shuttle,
// /mob/living/silicon/ai/proc/ai_recall_shuttle,
/mob/living/silicon/ai/proc/ai_camera_track,
/mob/living/silicon/ai/proc/ai_camera_list,
/mob/living/silicon/ai/proc/ai_goto_location,
/mob/living/silicon/ai/proc/ai_remove_location,
/mob/living/silicon/ai/proc/ai_hologram_change,
/mob/living/silicon/ai/proc/ai_network_change,
/mob/living/silicon/ai/proc/pick_icon,
/mob/living/silicon/ai/proc/ai_roster,
/mob/living/silicon/ai/proc/ai_statuschange,
/mob/living/silicon/ai/proc/ai_store_location,
/mob/living/silicon/ai/proc/checklaws,
/mob/living/silicon/ai/proc/control_integrated_radio,
/mob/living/silicon/ai/proc/core,
/mob/living/silicon/ai/proc/show_laws_verb,
/mob/living/silicon/ai/proc/toggle_acceleration,
/mob/living/silicon/ai/proc/toggle_camera_light
)
//Not sure why this is necessary...
/proc/AutoUpdateAI(obj/subject)
@@ -20,16 +45,18 @@ var/list/ai_list = list()
density = 1
status_flags = CANSTUN|CANPARALYSE
var/list/network = list("SS13")
var/obj/machinery/camera/current = null
var/obj/machinery/camera/camera = null
var/list/connected_robots = list()
var/aiRestorePowerRoutine = 0
//var/list/laws = list()
var/viewalerts = 0
var/lawcheck[1]
var/ioncheck[1]
var/lawchannel = "Common" // Default channel on which to state laws
var/icon/holo_icon//Default is assigned when AI is created.
var/obj/item/device/pda/ai/aiPDA = null
var/obj/item/device/multitool/aiMulti = null
var/obj/item/device/radio/headset/heads/ai_integrated/aiRadio = null
var/custom_sprite = 0 //For our custom sprites
//Hud stuff
@@ -53,6 +80,13 @@ var/list/ai_list = list()
var/centcomm_message_cooldown = 0
/mob/living/silicon/ai/proc/add_ai_verbs()
src.verbs += ai_verbs_default
/mob/living/silicon/ai/proc/remove_ai_verbs()
src.verbs -= ai_verbs_default
/mob/living/silicon/ai/New(loc, var/datum/ai_laws/L, var/obj/item/device/mmi/B, var/safety = 0)
var/list/possibleNames = ai_names
@@ -81,21 +115,26 @@ var/list/ai_list = list()
else
laws = new base_law_type
verbs += /mob/living/silicon/ai/proc/show_laws_verb
aiPDA = new/obj/item/device/pda/ai(src)
aiPDA.owner = name
aiPDA.ownjob = "AI"
aiPDA.name = name + " (" + aiPDA.ownjob + ")"
aiMulti = new(src)
aiRadio = new(src)
aiRadio.myAi = src
aiCamera = new/obj/item/device/camera/siliconcam/ai_camera(src)
if (istype(loc, /turf))
verbs.Add(/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \
/mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/MessageCentcomm)
add_ai_verbs(src)
//Languages
add_language("Sol Common", 0)
add_language("Sinta'unathi", 0)
add_language("Siik'tajr", 0)
add_language("Skrellian", 0)
add_language("Tradeband", 1)
add_language("Gutter", 0)
if(!safety)//Only used by AIize() to successfully spawn an AI.
if (!B)//If there is no player/brain inside.
@@ -171,7 +210,7 @@ var/list/ai_list = list()
if(powered_ai.anchored)
use_power = 2
/mob/living/silicon/ai/verb/pick_icon()
/mob/living/silicon/ai/proc/pick_icon()
set category = "AI Commands"
set name = "Set AI Core Display"
if(stat || aiRestorePowerRoutine)
@@ -266,48 +305,70 @@ var/list/ai_list = list()
set name = "Show Crew Manifest"
show_station_manifest()
/mob/living/silicon/ai/var/message_cooldown = 0
/mob/living/silicon/ai/proc/ai_announcement()
set category = "AI Commands"
set name = "Make Station Announcement"
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
if(message_cooldown)
src << "Please allow one minute to pass between announcements."
return
var/input = stripped_input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement")
if(!input)
return
if(check_unable(AI_CHECK_WIRELESS | AI_CHECK_RADIO))
return
captain_announce(input, "A.I. Announcement", src.name)
log_say("[key_name(usr)] has made an AI announcement: [input]")
message_admins("[key_name_admin(usr)] has made an AI announcement.", 1)
message_cooldown = 1
spawn(600)//One minute cooldown
message_cooldown = 0
/mob/living/silicon/ai/proc/ai_call_shuttle()
set category = "AI Commands"
set name = "Call Emergency Shuttle"
if(src.stat == 2)
src << "You can't call the shuttle because you are dead!"
if(check_unable(AI_CHECK_WIRELESS))
return
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
usr << "Wireless control is disabled!"
return
var/confirm = alert("Are you sure you want to call the shuttle?", "Confirm Shuttle Call", "Yes", "No")
if(check_unable(AI_CHECK_WIRELESS))
return
if(confirm == "Yes")
call_shuttle_proc(src)
// hack to display shuttle timer
if(emergency_shuttle.online)
if(emergency_shuttle.online())
var/obj/machinery/computer/communications/C = locate() in machines
if(C)
C.post_status("shuttle")
return
/mob/living/silicon/ai/proc/ai_cancel_call()
/mob/living/silicon/ai/proc/ai_recall_shuttle()
set category = "AI Commands"
if(src.stat == 2)
src << "You can't send the shuttle back because you are dead!"
set name = "Recall Emergency Shuttle"
if(check_unable(AI_CHECK_WIRELESS))
return
if(istype(usr,/mob/living/silicon/ai))
var/mob/living/silicon/ai/AI = src
if(AI.control_disabled)
src << "Wireless control is disabled!"
return
cancel_call_proc(src)
return
var/confirm = alert("Are you sure you want to recall the shuttle?", "Confirm Shuttle Recall", "Yes", "No")
if(check_unable(AI_CHECK_WIRELESS))
return
if(confirm == "Yes")
cancel_call_proc(src)
/mob/living/silicon/ai/check_eye(var/mob/user as mob)
if (!current)
if (!camera)
return null
user.reset_view(current)
user.reset_view(camera)
return 1
/mob/living/silicon/ai/blob_act()
@@ -380,12 +441,12 @@ var/list/ai_list = list()
// src << text ("Switching Law [L]'s report status to []", lawcheck[L+1])
checklaws()
//Uncomment this line of code if you are enabling the AI Vocal (VOX) announcements.
/*
if(href_list["say_word"])
play_vox_word(href_list["say_word"], null, src)
return
*/
if (href_list["lawr"]) // Selects on which channel to state laws
var/setchannel = input(usr, "Specify channel.", "Channel selection") in list("State","Common","Science","Command","Medical","Engineering","Security","Supply","Binary","Holopad", "Cancel")
if(setchannel == "Cancel")
return
lawchannel = setchannel
checklaws()
if (href_list["lawi"]) // Toggling whether or not a law gets stated by the State Laws verb --NeoFite
var/L = text2num(href_list["lawi"])
@@ -403,7 +464,7 @@ var/list/ai_list = list()
if(target && (!istype(target, /mob/living/carbon/human) || html_decode(href_list["trackname"]) == target:get_face_name()))
ai_actual_track(target)
else // who forgot this?
else
src << "\red System error. Cannot locate [html_decode(href_list["trackname"])]."
return
@@ -491,10 +552,10 @@ var/list/ai_list = list()
updatehealth()
/mob/living/silicon/ai/reset_view(atom/A)
if(current)
current.SetLuminosity(0)
if(camera)
camera.SetLuminosity(0)
if(istype(A,/obj/machinery/camera))
current = A
camera = A
..()
if(istype(A,/obj/machinery/camera))
if(camera_light_on) A.SetLuminosity(AI_CAMERA_LUMINOSITY)
@@ -505,7 +566,7 @@ var/list/ai_list = list()
src.cameraFollow = null
if (!C || stat == 2) //C.can_use())
if (!C || stat == DEAD) //C.can_use())
return 0
if(!src.eyeobj)
@@ -558,8 +619,7 @@ var/list/ai_list = list()
src.cameraFollow = null
var/cameralist[0]
if(usr.stat == 2)
usr << "You can't change your camera network because you are dead!"
if(check_unable())
return
var/mob/living/silicon/ai/U = usr
@@ -602,10 +662,10 @@ var/list/ai_list = list()
set category = "AI Commands"
set name = "AI Status"
if(usr.stat == 2)
usr <<"You cannot change your emotional status because you are dead!"
if(check_unable(AI_CHECK_WIRELESS))
return
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Friend Computer")
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Surprised", "Sad", "Upset", "Angry", "Awesome", "BSOD", "Blank", "Problems?", "Facepalm", "Friend Computer")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
for (var/obj/machinery/M in machines) //change status
if(istype(M, /obj/machinery/ai_status_display))
@@ -627,6 +687,9 @@ var/list/ai_list = list()
set desc = "Change the default hologram available to AI to something else."
set category = "AI Commands"
if(check_unable())
return
var/input
if(alert("Would you like to select a hologram based on a crew member or switch to unique avatar?",,"Crew Member","Unique")=="Crew Member")
@@ -675,12 +738,15 @@ var/list/ai_list = list()
set desc = "Toggles the light on the camera the AI is looking through."
set category = "AI Commands"
if(check_unable())
return
camera_light_on = !camera_light_on
src << "Camera lights [camera_light_on ? "activated" : "deactivated"]."
if(!camera_light_on)
if(current)
current.SetLuminosity(0)
current = null
if(camera)
camera.SetLuminosity(0)
camera = null
else
lightNearbyCamera()
@@ -691,23 +757,23 @@ var/list/ai_list = list()
/mob/living/silicon/ai/proc/lightNearbyCamera()
if(camera_light_on && camera_light_on < world.timeofday)
if(src.current)
if(src.camera)
var/obj/machinery/camera/camera = near_range_camera(src.eyeobj)
if(camera && src.current != camera)
src.current.SetLuminosity(0)
if(camera && src.camera != camera)
src.camera.SetLuminosity(0)
if(!camera.light_disabled)
src.current = camera
src.current.SetLuminosity(AI_CAMERA_LUMINOSITY)
src.camera = camera
src.camera.SetLuminosity(AI_CAMERA_LUMINOSITY)
else
src.current = null
src.camera = null
else if(isnull(camera))
src.current.SetLuminosity(0)
src.current = null
src.camera.SetLuminosity(0)
src.camera = null
else
var/obj/machinery/camera/camera = near_range_camera(src.eyeobj)
if(camera && !camera.light_disabled)
src.current = camera
src.current.SetLuminosity(AI_CAMERA_LUMINOSITY)
src.camera = camera
src.camera.SetLuminosity(AI_CAMERA_LUMINOSITY)
camera_light_on = world.timeofday + 1 * 20 // Update the light every 2 seconds.
@@ -756,3 +822,30 @@ var/list/ai_list = list()
centcomm_message_cooldown = 1
spawn(6000)//10 minute cooldown
centcomm_message_cooldown = 0
/mob/living/silicon/ai/proc/control_integrated_radio()
set name = "Radio Settings"
set desc = "Allows you to change settings of your radio."
set category = "AI Commands"
if(check_unable(AI_CHECK_RADIO))
return
src << "Accessing Subspace Transceiver control..."
if (src.aiRadio)
src.aiRadio.interact(src)
/mob/living/silicon/ai/proc/check_unable(var/flags = 0)
if(stat == DEAD)
usr << "\red You are dead!"
return 1
if((flags & AI_CHECK_WIRELESS) && src.control_disabled)
usr << "\red Wireless control is disabled!"
return 1
if((flags & AI_CHECK_RADIO) && src.aiRadio.disabledAi)
src << "\red System Error - Transceiver Disabled!"
return 1
return 0
#undef AI_CHECK_WIRELESS
#undef AI_CHECK_RADIO
+3 -2
View File
@@ -11,6 +11,7 @@
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
see_in_dark = 8
see_invisible = SEE_INVISIBLE_LEVEL_TWO
remove_ai_verbs(src)
var/callshuttle = 0
@@ -39,11 +40,11 @@
callshuttle = 0
if(callshuttle == 3) //if all three conditions are met
emergency_shuttle.incall(2)
emergency_shuttle.call_evac()
log_game("All the AIs, comm consoles and boards are destroyed. Shuttle called.")
message_admins("All the AIs, comm consoles and boards are destroyed. Shuttle called.", 1)
message_mods("All the AIs, comm consoles and boards are destroyed. Shuttle called.")
captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.")
// captain_announce("The emergency shuttle has been called. It will arrive in [round(emergency_shuttle.timeleft()/60)] minutes.")
world << sound('sound/AI/shuttlecalled.ogg')
if(explosive)
@@ -128,6 +128,9 @@ var/datum/cameranet/cameranet = new()
// 0xf = 15
var/turf/position = get_turf(target)
return checkTurfVis(position)
/datum/cameranet/proc/checkTurfVis(var/turf/position)
var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z)
if(chunk)
if(chunk.changed)
@@ -136,7 +139,6 @@ var/datum/cameranet/cameranet = new()
return 1
return 0
// Debug verb for VVing the chunk that the turf is in.
/*
/turf/verb/view_chunk()
@@ -51,10 +51,15 @@
if(ai.client)
ai.client.eye = src
//Holopad
if(istype(ai.current, /obj/machinery/hologram/holopad))
var/obj/machinery/hologram/holopad/H = ai.current
H.move_hologram()
if(ai.holo)
ai.holo.move_hologram()
/mob/aiEye/proc/getLoc()
if(ai)
if(!isturf(ai.loc) || !ai.client)
return
return ai.eyeobj.loc
// AI MOVEMENT
@@ -65,7 +70,7 @@
var/sprint = 10
var/cooldown = 0
var/acceleration = 1
var/obj/machinery/hologram/holopad/holo = null
// Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us.
/mob/living/silicon/ai/New()
@@ -117,7 +122,7 @@
// Return to the Core.
/mob/living/silicon/ai/verb/core()
/mob/living/silicon/ai/proc/core()
set category = "AI Commands"
set name = "AI Core"
@@ -125,8 +130,7 @@
/mob/living/silicon/ai/proc/view_core()
current = null
camera = null
cameraFollow = null
unset_machine()
@@ -143,7 +147,7 @@
for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks)
c.remove(eyeobj)
/mob/living/silicon/ai/verb/toggle_acceleration()
/mob/living/silicon/ai/proc/toggle_acceleration()
set category = "AI Commands"
set name = "Toggle Camera Acceleration"
+24 -16
View File
@@ -1,4 +1,3 @@
/mob/living/silicon/ai/proc/show_laws_verb()
set category = "AI Commands"
set name = "Show Laws"
@@ -51,24 +50,33 @@
src.laws_sanity_check()
src.laws.clear_supplied_laws()
/mob/living/silicon/ai/proc/statelaws() // -- TLE
// set category = "AI Commands"
// set name = "State Laws"
src.say("Current Active Laws:")
/var/prefix = ""
switch(lawchannel)
if("Common") prefix = ";"
if("Science") prefix = ":n "
if("Command") prefix = ":c "
if("Medical") prefix = ":m "
if("Engineering") prefix = ":e "
if("Security") prefix = ":s "
if("Supply") prefix = ":u "
if("Binary") prefix = ":b "
if("Holopad") prefix = ":h "
else prefix = ""
if(src.say("[prefix]Current Active Laws:") != 1)
return
//src.laws_sanity_check()
//src.laws.show_laws(world)
var/number = 1
sleep(10)
if (src.laws.zeroth)
if (src.lawcheck[1] == "Yes") //This line and the similar lines below make sure you don't state a law unless you want to. --NeoFite
src.say("0. [src.laws.zeroth]")
src.say("[prefix]0. [src.laws.zeroth]")
sleep(10)
for (var/index = 1, index <= src.laws.ion.len, index++)
@@ -76,7 +84,7 @@
var/num = ionnum()
if (length(law) > 0)
if (src.ioncheck[index] == "Yes")
src.say("[num]. [law]")
src.say("[prefix][num]. [law]")
sleep(10)
for (var/index = 1, index <= src.laws.inherent.len, index++)
@@ -84,23 +92,21 @@
if (length(law) > 0)
if (src.lawcheck[index+1] == "Yes")
src.say("[number]. [law]")
src.say("[prefix][number]. [law]")
sleep(10)
number++
for (var/index = 1, index <= src.laws.supplied.len, index++)
var/law = src.laws.supplied[index]
if (length(law) > 0)
if(src.lawcheck.len >= number+1)
if (src.lawcheck[number+1] == "Yes")
src.say("[number]. [law]")
src.say("[prefix][number]. [law]")
sleep(10)
number++
/mob/living/silicon/ai/verb/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite
/mob/living/silicon/ai/proc/checklaws() //Gives you a link-driven interface for deciding what laws the statelaws() proc will share with the crew. --NeoFite
set category = "AI Commands"
set name = "State Laws"
@@ -144,6 +150,8 @@
src.lawcheck[number+1] = "Yes"
list += {"<A href='byond://?src=\ref[src];lawc=[number]'>[src.lawcheck[number+1]] [number]:</A> [law]<BR>"}
number++
list += {"<br><br><A href='byond://?src=\ref[src];laws=1'>State Laws</A>"}
list += {"<br><A href='byond://?src=\ref[src];lawr=1'>Channel: [src.lawchannel]</A><br>"}
list += {"<A href='byond://?src=\ref[src];laws=1'>State Laws</A>"}
usr << browse(list, "window=laws")
@@ -35,6 +35,9 @@
// Gain Power
adjustOxyLoss(-1)
// Handle EMP-stun
handle_stunned()
//stage = 1
//if (istype(src, /mob/living/silicon/ai)) // Are we not sure what we are?
var/blind = 0
@@ -179,3 +182,7 @@
health = 100 - getOxyLoss() - getToxLoss() - getBruteLoss()
else
health = 100 - getOxyLoss() - getToxLoss() - getFireLoss() - getBruteLoss()
/mob/living/silicon/ai/rejuvenate()
..()
add_ai_verbs(src)
+2 -137
View File
@@ -1,140 +1,5 @@
/mob/living/silicon/ai/say(var/message)
if(parent && istype(parent) && parent.stat != 2)
parent.say(message)
return
return parent.say(message)
//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.
..(message)
/mob/living/silicon/say_understands(var/other)
if (istype(other, /mob/living/carbon/human))
return 1
if (istype(other, /mob/living/silicon))
return 1
if (istype(other, /mob/living/carbon/brain))
return 1
return ..()
// These Verbs are commented out since we've disabled the AI vocal (VOX) announcements.
// If you re-enable them there is 3 lines in ai.dm Topic() that you need to uncomment as well.
// just search for VOX in there.
/*
var/announcing_vox = 0 // Stores the time of the last announcement
var/const/VOX_CHANNEL = 200
var/const/VOX_DELAY = 100 // 10 seconds
var/const/VOX_PATH = "sound/vox/"
/mob/living/silicon/ai/verb/announcement_help()
set name = "Announcement Help"
set desc = "Display a list of vocal words to announce to the crew."
set category = "AI Commands"
var/dat = "Here is a list of words you can type into the 'Announcement' button to create sentences to vocally announce to everyone on the same level at you.<BR> \
<UL><LI>You can also click on the word to preview it.</LI>\
<LI>You can only say 30 words for every announcement.</LI>\
<LI>Do not use punctuation as you would normally, if you want a pause you can use the full stop and comma characters by separating them with spaces, like so: 'Alpha . Test , Bravo'.</LI></UL>\
<font class='bad'>WARNING:</font><BR>Misuse of the announcement system will get you job banned.<HR>"
var/index = 0
var/list/vox_words = flist(VOX_PATH) // flist will return a list of strings with all the files in the path
for(var/word in vox_words)
index++
var/stripped_word = copytext(word, 1, length(word) - 3) // Remove the .wav
dat += "<A href='?src=\ref[src];say_word=[stripped_word]'>[capitalize(stripped_word)]</A>"
if(index != vox_words.len)
dat += " / "
src << browse(dat, "window=announce_help;size=500x400")
/mob/living/silicon/ai/verb/announcement()
set name = "Announcement"
set desc = "Create a vocal announcement by typing in the available words to create a sentence."
set category = "AI Commands"
if(announcing_vox > world.time)
src << "<span class='notice'>Please wait [round((announcing_vox - world.time) / 10)] seconds.</span>"
return
var/message = input(src, "WARNING: Misuse of this verb can result in you being job banned. More help is available in 'Announcement Help'", "Announcement", src.last_announcement) as text
last_announcement = message
if(!message || announcing_vox > world.time)
return
var/list/words = text2list(trim(message), " ")
var/list/incorrect_words = list()
if(words.len > 30)
words.len = 30
// Detect incorrect words which aren't .wav files.
for(var/word in words)
word = trim(word)
if(!word)
words -= word
continue
if(!vox_word_exists(word))
incorrect_words += word
if(incorrect_words.len)
src << "<span class='notice'>These words are not available on the announcement system: [english_list(incorrect_words)].</span>"
return
announcing_vox = world.time + VOX_DELAY
log_game("[key_name_admin(src)] made a vocal announcement with the following message: [message].")
for(var/word in words)
play_vox_word(word, src.z, null)
/proc/play_vox_word(var/word, var/z_level, var/mob/only_listener)
word = lowertext(word)
if(vox_word_exists(word))
var/sound_file = get_vox_file(word)
var/sound/voice = sound(sound_file, wait = 1, channel = VOX_CHANNEL)
voice.status = SOUND_STREAM
// If there is no single listener, broadcast to everyone in the same z level
if(!only_listener)
// Play voice for all mobs in the z level
for(var/mob/M in player_list)
if(M.client)
var/turf/T = get_turf(M)
if(T.z == z_level)
M << voice
else
only_listener << voice
return 1
return 0
/proc/vox_word_exists(var/word)
return fexists("[VOX_PATH][word].wav")
/proc/get_vox_file(var/word)
if(vox_word_exists(word))
return file("[VOX_PATH][word].wav")
// Dynamically loading it has bad results with sounds overtaking each other, even with the wait variable.
// We send the file to the user when they login.
/client/proc/preload_vox()
var/list/vox_files = flist(VOX_PATH)
for(var/file in vox_files)
// src << "Downloading [file]"
var/sound/S = sound("[VOX_PATH][file]")
src << browse_rsc(S)
*/
return ..(message)
+1
View File
@@ -1,4 +1,5 @@
/mob/living/silicon/Login()
sleeping = 0
if(mind && ticker && ticker.mode)
ticker.mode.remove_cultist(mind, 1)
ticker.mode.remove_revolutionary(mind, 1)
@@ -17,6 +17,7 @@
if(world.timeofday >= silence_time)
silence_time = null
src << "<font color=green>Communication circuit reinitialized. Speech and messaging functionality restored.</font>"
handle_statuses()
/mob/living/silicon/pai/updatehealth()
if(status_flags & GODMODE)
+210 -15
View File
@@ -1,12 +1,12 @@
/mob/living/silicon/pai
name = "pAI"
icon = 'icons/mob/mob.dmi'//
icon_state = "shadow"
icon = 'icons/mob/pai.dmi'
icon_state = "repairbot"
robot_talk_understand = 0
// Good roleplayers can emote well, why not let them.
// emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person)
emote_type = 2 // pAIs emotes are heard, not seen, so they can be seen through a container (eg. person)
small = 1
pass_flags = 1
var/network = "SS13"
var/obj/machinery/camera/current = null
@@ -17,10 +17,21 @@
var/obj/item/device/paicard/card // The card we inhabit
var/obj/item/device/radio/radio // Our primary radio
var/speakStatement = "states"
var/speakExclamation = "declares"
var/speakQuery = "queries"
var/chassis = "repairbot" // A record of your chosen chassis.
var/global/list/possible_chassis = list(
"Drone" = "repairbot",
"Cat" = "cat",
"Mouse" = "mouse",
"Monkey" = "monkey"
)
var/global/list/possible_say_verbs = list(
"Robotic" = list("states","declares","queries"),
"Natural" = list("says","yells","asks"),
"Beep" = list("beeps","beeps loudly","boops"),
"Chirp" = list("chirps","chirrups","cheeps"),
"Feline" = list("purrs","yowls","meows")
)
var/obj/item/weapon/pai_cable/cable // The cable we produce and use when door or camera jacking
@@ -54,8 +65,11 @@
var/obj/item/radio/integrated/signal/sradio // AI's signaller
var/translator_on = 0 // keeps track of the translator module
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
canmove = 0
src.loc = paicard
card = paicard
@@ -65,6 +79,14 @@
card.radio = new /obj/item/device/radio(src.card)
radio = card.radio
//Default languages without universal translator software
add_language("Sol Common", 1)
add_language("Tradeband", 1)
add_language("Gutter", 1)
verbs += /mob/living/silicon/pai/proc/choose_chassis
verbs += /mob/living/silicon/pai/proc/choose_verbs
//PDA
pda = new(src)
spawn(5)
@@ -110,7 +132,12 @@
return 0
/mob/living/silicon/pai/restrained()
return 0
if(istype(src.loc,/obj/item/device/paicard))
return 0
..()
/mob/living/silicon/pai/MouseDrop(atom/over_object)
return
/mob/living/silicon/pai/emp_act(severity)
// Silence for 2 minutes
@@ -228,7 +255,6 @@
src.reset_view(C)
return 1
/mob/living/silicon/pai/cancel_camera()
set category = "pAI Commands"
set name = "Cancel Camera View"
@@ -236,10 +262,6 @@
src.unset_machine()
src:cameraFollow = null
/mob/living/silicon/pai/float(var/on) //No, just no floating for these - SoundScopes
return
//Addition by Mord_Sith to define AI's network change ability
/*
/mob/living/silicon/pai/proc/pai_network_change()
@@ -258,7 +280,7 @@
if(!C.status)
continue
else
if(C.network != "CREED" && C.network != "thunder" && C.network != "RD" && C.network != "toxins" && C.network != "Prison") COMPILE ERROR! This will have to be updated as camera.network is no longer a string, but a list instead
if(C.network != "CREED" && C.network != "thunder" && C.network != "RD" && C.network != "phoron" && C.network != "Prison") COMPILE ERROR! This will have to be updated as camera.network is no longer a string, but a list instead
cameralist[C.network] = C.network
src.network = input(usr, "Which network would you like to view?") as null|anything in cameralist
@@ -276,3 +298,176 @@
card.setPersonality(pai)
*/
// Procs/code after this point is used to convert the stationary pai item into a
// mobile pai mob. This also includes handling some of the general shit that can occur
// to it. Really this deserves its own file, but for the moment it can sit here. ~ Z
/mob/living/silicon/pai/verb/fold_out()
set category = "pAI Commands"
set name = "Unfold Chassis"
if(stat || sleeping || paralysis || weakened)
return
if(src.loc != card)
return
if(world.time <= last_special)
return
last_special = world.time + 100
canmove = 1
//I'm not sure how much of this is necessary, but I would rather avoid issues.
if(istype(card.loc,/mob))
var/mob/holder = card.loc
holder.drop_from_inventory(card)
else if(istype(card.loc,/obj/item/clothing/suit/space/space_ninja))
var/obj/item/clothing/suit/space/space_ninja/holder = card.loc
holder.pai = null
else if(istype(card.loc,/obj/item/device/pda))
var/obj/item/device/pda/holder = card.loc
holder.pai = null
src.client.perspective = EYE_PERSPECTIVE
src.client.eye = src
src.forceMove(get_turf(card))
card.forceMove(src)
card.screen_loc = null
var/turf/T = get_turf(src)
if(istype(T)) T.visible_message("<b>[src]</b> folds outwards, expanding into a mobile form.")
/mob/living/silicon/pai/verb/fold_up()
set category = "pAI Commands"
set name = "Collapse Chassis"
if(stat || sleeping || paralysis || weakened)
return
if(src.loc == card)
return
if(world.time <= last_special)
return
close_up()
/mob/living/silicon/pai/proc/choose_chassis()
set category = "pAI Commands"
set name = "Choose Chassis"
var/choice
var/finalized = "No"
while(finalized == "No" && src.client)
choice = input(usr,"What would you like to use for your mobile chassis icon? This decision can only be made once.") as null|anything in possible_chassis
if(!choice) return
icon_state = possible_chassis[choice]
finalized = alert("Look at your sprite. Is this what you wish to use?",,"No","Yes")
chassis = possible_chassis[choice]
verbs -= /mob/living/silicon/pai/proc/choose_chassis
/mob/living/silicon/pai/proc/choose_verbs()
set category = "pAI Commands"
set name = "Choose Speech Verbs"
var/choice = input(usr,"What theme would you like to use for your speech verbs? This decision can only be made once.") as null|anything in possible_say_verbs
if(!choice) return
var/list/sayverbs = possible_say_verbs[choice]
speak_statement = sayverbs[1]
speak_exclamation = sayverbs[(sayverbs.len>1 ? 2 : sayverbs.len)]
speak_query = sayverbs[(sayverbs.len>2 ? 3 : sayverbs.len)]
verbs -= /mob/living/silicon/pai/proc/choose_verbs
/mob/living/silicon/pai/lay_down()
set name = "Rest"
set category = "IC"
if(istype(src.loc,/obj/item/device/paicard))
resting = 0
else
resting = !resting
icon_state = resting ? "[chassis]_rest" : "[chassis]"
src << "\blue You are now [resting ? "resting" : "getting up"]"
canmove = !resting
//Overriding this will stop a number of headaches down the track.
/mob/living/silicon/pai/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(W.force)
visible_message("<span class='danger'>[user.name] attacks [src] with [W]!</span>")
src.adjustBruteLoss(W.force)
src.updatehealth()
else
visible_message("<span class='warning'>[user.name] bonks [src] harmlessly with [W].</span>")
if(stat != 2) close_up()
return
/mob/living/silicon/pai/attack_hand(mob/user as mob)
visible_message("<span class='danger'>[user.name] boops [src] on the head.</span>")
close_up()
//I'm not sure how much of this is necessary, but I would rather avoid issues.
/mob/living/silicon/pai/proc/close_up()
last_special = world.time + 100
if(src.loc == card)
return
var/turf/T = get_turf(src)
if(istype(T)) T.visible_message("<b>[src]</b> neatly folds inwards, compacting down to a rectangular card.")
src.stop_pulling()
src.client.perspective = EYE_PERSPECTIVE
src.client.eye = card
//This seems redundant but not including the forced loc setting messes the behavior up.
src.loc = card
card.loc = get_turf(card)
src.forceMove(card)
card.forceMove(card.loc)
canmove = 0
/mob/living/silicon/pai/start_pulling(var/atom/movable/AM)
if(istype(AM,/obj/item))
var/obj/item/O = AM
if(O.w_class == 1)
..()
else
src << "<span class='warning'>You are too small to pull that.</span>"
/mob/living/silicon/pai/examine()
set src in oview()
if(!usr || !src) return
if( (usr.sdisabilities & BLIND || usr.blinded || usr.stat) && !istype(usr,/mob/dead/observer) )
usr << "<span class='notice'>Something is there but you can't see it.</span>"
return
var/msg = "<span class='info'>*---------*\nThis is \icon[src][name], a personal AI!"
switch(src.stat)
if(CONSCIOUS)
if(!src.client) msg += "\nIt appears to be in stand-by mode." //afk
if(UNCONSCIOUS) msg += "\n<span class='warning'>It doesn't seem to be responding.</span>"
if(DEAD) msg += "\n<span class='deadsay'>It looks completely unsalvageable.</span>"
msg += "\n*---------*</span>"
if(print_flavor_text()) msg += "\n[print_flavor_text()]\n"
if (pose)
if( findtext(pose,".",lentext(pose)) == 0 && findtext(pose,"!",lentext(pose)) == 0 && findtext(pose,"?",lentext(pose)) == 0 )
pose = addtext(pose,".") //Makes sure all emotes end with a period.
msg += "\nIt is [pose]"
usr << msg
+305 -303
View File
@@ -19,97 +19,233 @@ var/datum/paiController/paiController // Global handler for pAI candidates
/datum/paiController
var/inquirer = null
var/list/pai_candidates = list()
var/list/asked = list()
var/askDelay = 10 * 60 * 1 // One minute [ms * sec * min]
Topic(href, href_list[])
if(href_list["download"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/obj/item/device/paicard/card = locate(href_list["device"])
if(card.pai)
/datum/paiController/Topic(href, href_list[])
if(href_list["download"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/obj/item/device/paicard/card = locate(href_list["device"])
if(card.pai)
return
if(istype(card,/obj/item/device/paicard) && istype(candidate,/datum/paiCandidate))
var/mob/living/silicon/pai/pai = new(card)
if(!candidate.name)
pai.name = pick(ninja_names)
else
pai.name = candidate.name
pai.real_name = pai.name
pai.key = candidate.key
card.setPersonality(pai)
card.looking_for_personality = 0
ticker.mode.update_cult_icons_removed(card.pai.mind)
ticker.mode.update_rev_icons_removed(card.pai.mind)
pai_candidates -= candidate
usr << browse(null, "window=findPai")
if(href_list["new"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/option = href_list["option"]
var/t = ""
switch(option)
if("name")
t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text
if(t)
candidate.name = copytext(sanitize(t),1,MAX_NAME_LEN)
if("desc")
t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message
if(t)
candidate.description = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if("role")
t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text
if(t)
candidate.role = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if("ooc")
t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message
if(t)
candidate.comments = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if("save")
candidate.savefile_save(usr)
if("load")
candidate.savefile_load(usr)
//In case people have saved unsanitized stuff.
if(candidate.name)
candidate.name = copytext(sanitize(candidate.name),1,MAX_NAME_LEN)
if(candidate.description)
candidate.description = copytext(sanitize(candidate.description),1,MAX_MESSAGE_LEN)
if(candidate.role)
candidate.role = copytext(sanitize(candidate.role),1,MAX_MESSAGE_LEN)
if(candidate.comments)
candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN)
if("submit")
if(candidate)
candidate.ready = 1
for(var/obj/item/device/paicard/p in world)
if(p.looking_for_personality == 1)
p.alertUpdate()
usr << browse(null, "window=paiRecruit")
return
if(istype(card,/obj/item/device/paicard) && istype(candidate,/datum/paiCandidate))
var/mob/living/silicon/pai/pai = new(card)
if(!candidate.name)
pai.name = pick(ninja_names)
else
pai.name = candidate.name
pai.real_name = pai.name
pai.key = candidate.key
card.setPersonality(pai)
card.looking_for_personality = 0
recruitWindow(usr, href_list["allow_submit"] != "0")
ticker.mode.update_cult_icons_removed(card.pai.mind)
ticker.mode.update_rev_icons_removed(card.pai.mind)
/datum/paiController/proc/recruitWindow(var/mob/M as mob, allowSubmit = 1)
var/datum/paiCandidate/candidate
for(var/datum/paiCandidate/c in pai_candidates)
if(!istype(c) || !istype(M))
break
if(c.key == M.key)
candidate = c
if(!candidate)
candidate = new /datum/paiCandidate()
candidate.key = M.key
pai_candidates.Add(candidate)
pai_candidates -= candidate
usr << browse(null, "window=findPai")
var/dat = ""
dat += {"
<style type="text/css">
body {
margin-top:5px;
font-family:Verdana;
color:white;
font-size:13px;
background-image:url('uiBackground.png');
background-repeat:repeat-x;
background-color:#272727;
background-position:center top;
}
table {
border-collapse:collapse;
font-size:13px;
}
th, td {
border: 1px solid #333333;
}
p.top {
background-color: none;
color: white;
}
tr.d0 td {
background-color: #c0c0c0;
color: black;
border:0px;
border: 1px solid #333333;
}
tr.d0 th {
background-color: none;
color: #4477E0;
text-align:right;
vertical-align:top;
width:120px;
border:0px;
}
tr.d1 td {
background-color: #555555;
color: white;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
}
td.desc {
font-weight:bold;
}
a {
color:#4477E0;
}
a.button {
color:white;
text-decoration: none;
}
</style>
"}
if(href_list["new"])
var/datum/paiCandidate/candidate = locate(href_list["candidate"])
var/option = href_list["option"]
var/t = ""
dat += {"
<body>
<b><font size="3px">pAI Personality Configuration</font></b>
<p class="top">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>
switch(option)
if("name")
t = input("Enter a name for your pAI", "pAI Name", candidate.name) as text
if(t)
candidate.name = copytext(sanitize(t),1,MAX_NAME_LEN)
if("desc")
t = input("Enter a description for your pAI", "pAI Description", candidate.description) as message
if(t)
candidate.description = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if("role")
t = input("Enter a role for your pAI", "pAI Role", candidate.role) as text
if(t)
candidate.role = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if("ooc")
t = input("Enter any OOC comments", "pAI OOC Comments", candidate.comments) as message
if(t)
candidate.comments = copytext(sanitize(t),1,MAX_MESSAGE_LEN)
if("save")
candidate.savefile_save(usr)
if("load")
candidate.savefile_load(usr)
//In case people have saved unsanitized stuff.
if(candidate.name)
candidate.name = copytext(sanitize(candidate.name),1,MAX_NAME_LEN)
if(candidate.description)
candidate.description = copytext(sanitize(candidate.description),1,MAX_MESSAGE_LEN)
if(candidate.role)
candidate.role = copytext(sanitize(candidate.role),1,MAX_MESSAGE_LEN)
if(candidate.comments)
candidate.comments = copytext(sanitize(candidate.comments),1,MAX_MESSAGE_LEN)
if("submit")
if(candidate)
candidate.ready = 1
for(var/obj/item/device/paicard/p in world)
if(p.looking_for_personality == 1)
p.alertUpdate()
usr << browse(null, "window=paiRecruit")
return
recruitWindow(usr)
proc/recruitWindow(var/mob/M as mob)
var/datum/paiCandidate/candidate
for(var/datum/paiCandidate/c in pai_candidates)
if(!istype(c) || !istype(M))
break
if(c.key == M.key)
candidate = c
if(!candidate)
candidate = new /datum/paiCandidate()
candidate.key = M.key
pai_candidates.Add(candidate)
var/dat = ""
<table>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=name;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>Name</a>:</th>
<td class="desc">[candidate.name]&nbsp;</td>
</tr>
<tr class="d1">
<td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=desc;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>Description</a>:</th>
<td class="desc">[candidate.description]&nbsp;</td>
</tr>
<tr class="d1">
<td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=role;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>Preferred Role</a>:</th>
<td class="desc">[candidate.role]&nbsp;</td>
</tr>
<tr class="d1">
<td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=ooc;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]'>OOC Comments</a>:</th>
<td class="desc">[candidate.comments]&nbsp;</td>
</tr>
<tr class="d1">
<td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td>
</tr>
</table>
<br>
<table>
<tr>
<td class="button">
<a href='byond://?src=\ref[src];option=save;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]' class="button">Save Personality</a>
</td>
</tr>
<tr>
<td class="button">
<a href='byond://?src=\ref[src];option=load;new=1;allow_submit=[allowSubmit];candidate=\ref[candidate]' class="button">Load Personality</a>
</td>
</tr>
</table><br>
"}
if(allowSubmit)
dat += {"
<style type="text/css">
<table>
<td class="button"><a href='byond://?src=\ref[src];option=submit;new=1;candidate=\ref[candidate]' class="button"><b><font size="4px">Submit Personality</font></b></a></td>
</table><br>
"}
dat += {"
<body>
"}
M << browse(dat, "window=paiRecruit;size=580x580;")
/datum/paiController/proc/findPAI(var/obj/item/device/paicard/p, var/mob/user)
requestRecruits()
var/list/available = list()
for(var/datum/paiCandidate/c in paiController.pai_candidates)
if(c.ready)
var/found = 0
for(var/mob/dead/observer/o in player_list)
if(o.key == c.key)
found = 1
if(found)
available.Add(c)
var/dat = ""
dat += {"
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">
<html>
<head>
<style>
body {
margin-top:5px;
font-family:Verdana;
@@ -121,255 +257,121 @@ var/datum/paiController/paiController // Global handler for pAI candidates
background-position:center top;
}
table {
border-collapse:collapse;
font-size:13px;
}
th, td {
border: 1px solid #333333;
table.desc {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
p.top {
background-color: none;
table.download {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
tr.d0 td, tr.d0 th {
background-color: #506070;
color: white;
}
tr.d0 td {
background-color: #c0c0c0;
color: black;
border:0px;
border: 1px solid #333333;
}
tr.d0 th {
background-color: none;
color: #4477E0;
text-align:right;
vertical-align:top;
width:120px;
border:0px;
}
tr.d1 td {
background-color: #555555;
tr.d1 td, tr.d1 th {
background-color: #708090;
color: white;
}
tr.d2 td {
background-color: #00FF00;
color: white;
text-align:center;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
td.desc {
font-weight:bold;
td.download {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
a {
color:#4477E0;
th {
text-align:left;
width:125px;
vertical-align:top;
}
a.button {
color:white;
text-decoration: none;
}
</style>
"}
</head>
<body>
<b><font size='3px'>pAI Availability List</font></b><br><br>
"}
dat += "<p>Displaying available AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>"
for(var/datum/paiCandidate/c in available)
dat += {"
<body>
<b><font size="3px">pAI Personality Configuration</font></b>
<p class="top">Please configure your pAI personality's options. Remember, what you enter here could determine whether or not the user requesting a personality chooses you!</p>
<table>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=name;new=1;candidate=\ref[candidate]'>Name</a>:</th>
<td class="desc">[candidate.name]&nbsp;</td>
</tr>
<tr class="d1">
<td>What you plan to call yourself. Suggestions: Any character name you would choose for a station character OR an AI.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=desc;new=1;candidate=\ref[candidate]'>Description</a>:</th>
<td class="desc">[candidate.description]&nbsp;</td>
</tr>
<tr class="d1">
<td>What sort of pAI you typically play; your mannerisms, your quirks, etc. This can be as sparse or as detailed as you like.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=role;new=1;candidate=\ref[candidate]'>Preferred Role</a>:</th>
<td class="desc">[candidate.role]&nbsp;</td>
</tr>
<tr class="d1">
<td>Do you like to partner with sneaky social ninjas? Like to help security hunt down thugs? Enjoy watching an engineer's back while he saves the station yet again? This doesn't have to be limited to just station jobs. Pretty much any general descriptor for what you'd like to be doing works here.</td>
</tr>
<tr class="d0">
<th rowspan="2"><a href='byond://?src=\ref[src];option=ooc;new=1;candidate=\ref[candidate]'>OOC Comments</a>:</th>
<td class="desc">[candidate.comments]&nbsp;</td>
</tr>
<tr class="d1">
<td>Anything you'd like to address specifically to the player reading this in an OOC manner. \"I prefer more serious RP.\", \"I'm still learning the interface!\", etc. Feel free to leave this blank if you want.</td>
</tr>
</table>
<br>
<table>
<tr>
<td class="button">
<a href='byond://?src=\ref[src];option=save;new=1;candidate=\ref[candidate]' class="button">Save Personality</a>
<table class="desc">
<tr class="d0">
<th>Name:</th>
<td>[c.name]</td>
</tr>
<tr class="d1">
<th>Description:</th>
<td>[c.description]</td>
</tr>
<tr class="d0">
<th>Preferred Role:</th>
<td>[c.role]</td>
</tr>
<tr class="d1">
<th>OOC Comments:</th>
<td>[c.comments]</td>
</tr>
</table>
<table class="download">
<td class="download"><a href='byond://?src=\ref[src];download=1;candidate=\ref[c];device=\ref[p]' class="button"><b>Download [c.name]</b></a>
</td>
</tr>
<tr>
<td class="button">
<a href='byond://?src=\ref[src];option=load;new=1;candidate=\ref[candidate]' class="button">Load Personality</a>
</td>
</tr>
</table><br>
<table>
<td class="button"><a href='byond://?src=\ref[src];option=submit;new=1;candidate=\ref[candidate]' class="button"><b><font size="4px">Submit Personality</font></b></a></td>
</table><br>
<body>
</table>
<br>
"}
M << browse(dat, "window=paiRecruit;size=580x580;")
dat += {"
</body>
</html>
"}
proc/findPAI(var/obj/item/device/paicard/p, var/mob/user)
requestRecruits()
var/list/available = list()
for(var/datum/paiCandidate/c in paiController.pai_candidates)
if(c.ready)
var/found = 0
for(var/mob/dead/observer/o in player_list)
if(o.key == c.key)
found = 1
if(found)
available.Add(c)
var/dat = ""
user << browse(dat, "window=findPai")
dat += {"
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">
<html>
<head>
<style>
body {
margin-top:5px;
font-family:Verdana;
color:white;
font-size:13px;
background-image:url('uiBackground.png');
background-repeat:repeat-x;
background-color:#272727;
background-position:center top;
}
table {
font-size:13px;
}
table.desc {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
table.download {
border-collapse:collapse;
font-size:13px;
border: 1px solid #161616;
width:100%;
}
tr.d0 td, tr.d0 th {
background-color: #506070;
color: white;
}
tr.d1 td, tr.d1 th {
background-color: #708090;
color: white;
}
tr.d2 td {
background-color: #00FF00;
color: white;
text-align:center;
}
td.button {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
td.download {
border: 1px solid #161616;
background-color: #40628a;
text-align: center;
}
th {
text-align:left;
width:125px;
vertical-align:top;
}
a.button {
color:white;
text-decoration: none;
}
</style>
</head>
<body>
<b><font size='3px'>pAI Availability List</font></b><br><br>
"}
dat += "<p>Displaying available AI personalities from central database... If there are no entries, or if a suitable entry is not listed, check again later as more personalities may be added.</p>"
for(var/datum/paiCandidate/c in available)
dat += {"
<table class="desc">
<tr class="d0">
<th>Name:</th>
<td>[c.name]</td>
</tr>
<tr class="d1">
<th>Description:</th>
<td>[c.description]</td>
</tr>
<tr class="d0">
<th>Preferred Role:</th>
<td>[c.role]</td>
</tr>
<tr class="d1">
<th>OOC Comments:</th>
<td>[c.comments]</td>
</tr>
</table>
<table class="download">
<td class="download"><a href='byond://?src=\ref[src];download=1;candidate=\ref[c];device=\ref[p]' class="button"><b>Download [c.name]</b></a>
</td>
</table>
<br>
"}
dat += {"
</body>
</html>
"}
user << browse(dat, "window=findPai")
proc/requestRecruits()
for(var/mob/dead/observer/O in player_list)
if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
/datum/paiController/proc/requestRecruits()
for(var/mob/dead/observer/O in player_list)
if(O.has_enabled_antagHUD == 1 && config.antag_hud_restricted)
continue
if(jobban_isbanned(O, "pAI"))
continue
if(asked.Find(O.key))
if(world.time < asked[O.key] + askDelay)
continue
if(jobban_isbanned(O, "pAI"))
continue
if(asked.Find(O.key))
if(world.time < asked[O.key] + askDelay)
continue
else
asked.Remove(O.key)
if(O.client)
var/hasSubmitted = 0
for(var/datum/paiCandidate/c in paiController.pai_candidates)
if(c.key == O.key)
hasSubmitted = 1
if(!hasSubmitted && (O.client.prefs.be_special & BE_PAI))
question(O.client)
else
asked.Remove(O.key)
if(O.client)
if(O.client.prefs.be_special & BE_PAI)
question(O.client)
proc/question(var/client/C)
spawn(0)
if(!C) return
asked.Add(C.key)
asked[C.key] = world.time
var/response = alert(C, "Someone is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round")
if(!C) return //handle logouts that happen whilst the alert is waiting for a response.
if(response == "Yes")
recruitWindow(C.mob)
else if (response == "Never for this round")
var/warning = alert(C, "Are you sure? This action will be undoable and you will need to wait until next round.", "You sure?", "Yes", "No")
if(warning == "Yes")
asked[C.key] = INFINITY
else
question(C)
/datum/paiController/proc/question(var/client/C)
spawn(0)
if(!C) return
asked.Add(C.key)
asked[C.key] = world.time
var/response = alert(C, "[inquirer] is requesting a pAI personality. Would you like to play as a personal AI?", "pAI Request", "Yes", "No", "Never for this round")
if(!C) return //handle logouts that happen whilst the alert is waiting for a response.
if(response == "Yes")
recruitWindow(C.mob)
else if (response == "Never for this round")
var/warning = alert(C, "Are you sure? This action will be undoable and you will need to wait until next round.", "You sure?", "Yes", "No")
if(warning == "Yes")
asked[C.key] = INFINITY
else
question(C)
+50 -29
View File
@@ -266,7 +266,7 @@
src.medHUD = !src.medHUD
if("translator")
if(href_list["toggle"])
src.universal_speak = !src.universal_speak
src.translator_toggle()
if("doorjack")
if(href_list["jack"])
if(src.cable && src.cable.machine)
@@ -325,7 +325,7 @@
if(s == "medical HUD") //This file has to be saved as ANSI or this will not display correctly
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a> [(src.medHUD) ? "<font color=#55FF55>•</font>" : "<font color=#FF5555>•</font>"] <br>"
if(s == "universal translator") //This file has to be saved as ANSI or this will not display correctly
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a> [(src.universal_speak) ? "<font color=#55FF55>•</font>" : "<font color=#FF5555>•</font>"] <br>"
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a> [(src.translator_on) ? "<font color=#55FF55>•</font>" : "<font color=#FF5555>•</font>"] <br>"
if(s == "projection array")
dat += "<a href='byond://?src=\ref[src];software=projectionarray;sub=0'>Projection Array</a> <br>"
if(s == "camera jack")
@@ -438,9 +438,9 @@
for (var/ch_name in radio.channels)
dat+=radio.text_sec_channel(ch_name, radio.channels[ch_name])
dat+={"[radio.text_wires()]</TT></body></html>"}
return dat
// Crew Manifest
/mob/living/silicon/pai/proc/softwareManifest()
var/dat = ""
@@ -497,8 +497,8 @@
// Universal Translator
/mob/living/silicon/pai/proc/softwareTranslator()
var/dat = {"<h2>Universal Translator</h2><hr>
When enabled, this device will automatically convert all spoken and written language into a format that any known recipient can understand.<br><br>
The device is currently [ (src.universal_speak) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled</font>.<br>
When enabled, this device will automatically convert all spoken and written languages into a format that any known recipient can understand.<br><br>
The device is currently [ (src.translator_on) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled</font>.<br>
<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Toggle Device</a><br>
"}
return dat
@@ -528,17 +528,25 @@
dat += {"<h2>Medical Analysis Suite</h2><hr>
<h4>Host Bioscan</h4>
"}
var/mob/living/M = src.loc
if(!istype(M, /mob/living))
while (!istype(M, /mob/living))
M = M.loc
if(istype(M, /turf))
src.temp = "Error: No biological host found. <br>"
src.subscreen = 0
return dat
var/mob/living/M
//If we are not deployed, check the holder of the card.
if(src.loc == card)
M = card.loc
//If we are deployed or the card is not held, check the first living mob in our turf.
if(!M || !istype(M))
var/turf/T = get_turf(src)
M = locate(/mob/living/) in T.contents
if(!M || !istype(M))
src.temp = "Error: No biological host found. <br>"
src.subscreen = 0
return dat
dat += {"<b>Bioscan Results for [M]</b>: <br>
Overall Status: [M.stat > 1 ? "dead" : "[M.health]% healthy"] <br><br>
<b>Scan Breakdown</b>: <br>
Respiratory: [M.getOxyLoss() > 50 ? "<font color=#FF5555>" : "<font color=#55FF55>"][M.getOxyLoss()]</font><br>
Toxicology: [M.getToxLoss() > 50 ? "<font color=#FF5555>" : "<font color=#55FF55>"][M.getToxLoss()]</font><br>
@@ -568,22 +576,13 @@
var/datum/gas_mixture/environment = T.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
var/total_moles = environment.total_moles
dat += "Air Pressure: [round(pressure,0.1)] kPa<br>"
if (total_moles)
var/o2_level = environment.oxygen/total_moles
var/n2_level = environment.nitrogen/total_moles
var/co2_level = environment.carbon_dioxide/total_moles
var/plasma_level = environment.toxins/total_moles
var/unknown_level = 1-(o2_level+n2_level+co2_level+plasma_level)
dat += "Nitrogen: [round(n2_level*100)]%<br>"
dat += "Oxygen: [round(o2_level*100)]%<br>"
dat += "Carbon Dioxide: [round(co2_level*100)]%<br>"
dat += "Plasma: [round(plasma_level*100)]%<br>"
if(unknown_level > 0.01)
dat += "OTHER: [round(unknown_level)]%<br>"
if(total_moles)
for(var/g in environment.gas)
dat += "[gas_data.name[g]]: [round((environment.gas[g] / total_moles) * 100)]%<br>"
dat += "Temperature: [round(environment.temperature-T0C)]&deg;C<br>"
dat += "<br><a href='byond://?src=\ref[src];software=atmosensor;sub=0'>Refresh Reading</a>"
return dat
@@ -676,7 +675,7 @@
dat += "</li>"
dat += "</ul>"
dat += "Messages: <hr>"
dat += "<style>td.a { vertical-align:top; }</style>"
dat += "<table>"
for(var/index in pda.tnote)
@@ -686,3 +685,25 @@
dat += addtext("<tr><td class='a'><i><b>From</b></i></td><td class='a'><i><b>&rarr;</b></i></td><td><i><b><a href='byond://?src=\ref[src];software=pdamessage;target=",index["target"],"'>", index["owner"],"</a>: </b></i>", index["message"], "<br></td></tr>")
dat += "</table>"
return dat
/mob/living/silicon/pai/proc/translator_toggle()
// Sol Common, Tradeband and Gutter are added with New() and are therefore the current default, always active languages
if(translator_on)
translator_on = 0
remove_language("Sinta'unathi")
remove_language("Siik'tajr")
remove_language("Skrellian")
src << "\blue Translator Module toggled OFF."
else
translator_on = 1
add_language("Sinta'unathi")
add_language("Siik'tajr")
add_language("Skrellian")
src << "\blue Translator Module toggled ON."
@@ -23,11 +23,16 @@
/datum/robot_component/proc/uninstall()
/datum/robot_component/proc/destroy()
var/brokenstate = "broken" // Generic icon
if (istype(wrapped, /obj/item/robot_parts/robot_component))
var/obj/item/robot_parts/robot_component/comp = wrapped
brokenstate = comp.icon_state_broken
if(wrapped)
del wrapped
wrapped = new/obj/item/broken_device
wrapped.icon_state = brokenstate // Module-specific broken icons! Yay!
// The thing itself isn't there anymore, but some fried remains are.
installed = -1
@@ -137,25 +142,38 @@
construction_cost = list("metal"=5000)
var/brute = 0
var/burn = 0
var/icon_state_broken = "broken"
// TODO: actual icons ;)
/obj/item/robot_parts/robot_component/binary_communication_device
name = "binary communication device"
icon_state = "binradio"
icon_state_broken = "binradio_broken"
/obj/item/robot_parts/robot_component/actuator
name = "actuator"
icon_state = "motor"
icon_state_broken = "motor_broken"
/obj/item/robot_parts/robot_component/armour
name = "armour plating"
icon_state = "armor"
icon_state_broken = "armor_broken"
/obj/item/robot_parts/robot_component/camera
name = "camera"
icon_state = "camera"
icon_state_broken = "camera_broken"
/obj/item/robot_parts/robot_component/diagnosis_unit
name = "diagnosis unit"
icon_state = "analyser"
icon_state_broken = "analyser_broken"
/obj/item/robot_parts/robot_component/radio
name = "radio"
icon_state = "radio"
icon_state_broken = "radio_broken"
//
//Robotic Component Analyser, basically a health analyser for robots
@@ -171,7 +189,7 @@
w_class = 2.0
throw_speed = 5
throw_range = 10
m_amt = 200
matter = list("metal" = 200)
origin_tech = "magnets=1;biotech=1"
var/mode = 1;
@@ -188,7 +206,7 @@
if(!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
user << "\red You don't have the dexterity to do this!"
return
if(!istype(M, /mob/living/silicon/robot))
if(!istype(M, /mob/living/silicon/robot) && !(ishuman(M) && (M:species.flags & IS_SYNTHETIC)))
user << "\red You can't analyze non-robotic things!"
return
@@ -200,22 +218,39 @@
user.show_message("\t Damage Specifics: <font color='#FFA500'>[BU]</font> - <font color='red'>[BR]</font>")
if(M.tod && M.stat == DEAD)
user.show_message("\blue Time of Disable: [M.tod]")
var/mob/living/silicon/robot/H = M
var/list/damaged = H.get_damaged_components(1,1,1)
user.show_message("\blue Localized Damage:",1)
if(length(damaged)>0)
for(var/datum/robot_component/org in damaged)
user.show_message(text("\blue \t []: [][] - [] - [] - []", \
capitalize(org.name), \
(org.installed == -1) ? "<font color='red'><b>DESTROYED</b></font> " :"",\
(org.electronics_damage > 0) ? "<font color='#FFA500'>[org.electronics_damage]</font>" :0, \
(org.brute_damage > 0) ? "<font color='red'>[org.brute_damage]</font>" :0, \
(org.toggled) ? "Toggled ON" : "<font color='red'>Toggled OFF</font>",\
(org.powered) ? "Power ON" : "<font color='red'>Power OFF</font>"),1)
else
user.show_message("\blue \t Components are OK.",1)
if(H.emagged && prob(5))
user.show_message("\red \t ERROR: INTERNAL SYSTEMS COMPROMISED",1)
if (istype(M, /mob/living/silicon/robot))
var/mob/living/silicon/robot/H = M
var/list/damaged = H.get_damaged_components(1,1,1)
user.show_message("\blue Localized Damage:",1)
if(length(damaged)>0)
for(var/datum/robot_component/org in damaged)
user.show_message(text("\blue \t []: [][] - [] - [] - []", \
capitalize(org.name), \
(org.installed == -1) ? "<font color='red'><b>DESTROYED</b></font> " :"",\
(org.electronics_damage > 0) ? "<font color='#FFA500'>[org.electronics_damage]</font>" :0, \
(org.brute_damage > 0) ? "<font color='red'>[org.brute_damage]</font>" :0, \
(org.toggled) ? "Toggled ON" : "<font color='red'>Toggled OFF</font>",\
(org.powered) ? "Power ON" : "<font color='red'>Power OFF</font>"),1)
else
user.show_message("\blue \t Components are OK.",1)
if(H.emagged && prob(5))
user.show_message("\red \t ERROR: INTERNAL SYSTEMS COMPROMISED",1)
if (ishuman(M) && (M:species.flags & IS_SYNTHETIC))
var/mob/living/carbon/human/H = M
var/list/damaged = H.get_damaged_organs(1,1)
user.show_message("\blue Localized Damage, Brute/Electronics:",1)
if(length(damaged)>0)
for(var/datum/organ/external/org in damaged)
user.show_message(text("\blue \t []: [] - []", \
capitalize(org.display_name), \
(org.brute_dam > 0) ? "\red [org.brute_dam]" :0, \
(org.burn_dam > 0) ? "<font color='#FFA500'>[org.burn_dam]</font>" :0),1)
else
user.show_message("\blue \t Components are OK.",1)
user.show_message("\blue Operating Temperature: [M.bodytemperature-T0C]&deg;C ([M.bodytemperature*1.8-459.67]&deg;F)", 1)
src.add_fingerprint(user)
return
@@ -25,8 +25,7 @@
//Used for self-mailing.
var/mail_destination = ""
//Used for pulling.
holder_type = /obj/item/weapon/holder/drone
/mob/living/silicon/robot/drone/New()
..()
@@ -62,6 +61,13 @@
flavor_text = "It's a tiny little repair drone. The casing is stamped with an NT logo and the subscript: 'NanoTrasen Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
updateicon()
/mob/living/silicon/robot/drone/init()
laws = new /datum/ai_laws/drone()
connected_ai = null
aiCamera = new/obj/item/device/camera/siliconcam/drone_camera(src)
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
//Redefining some robot procs...
/mob/living/silicon/robot/drone/updatename()
real_name = "maintenance drone ([rand(100,999)])"
@@ -104,7 +110,7 @@
return emote(copytext(message,2))
else if(length(message) >= 2)
if(copytext(message, 1 ,3) == ":d" || copytext(message, 1 ,3) == ":D")
if(parse_message_mode(message, "NONE") == "dronechat")
if(!is_component_functioning("radio"))
src << "\red Your radio transmitter isn't functional."
@@ -132,18 +138,6 @@
else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
if(M.client) M << "<b>[src]</b> transmits, \"[message]\""
//Sick of trying to get this to display properly without redefining it.
/mob/living/silicon/robot/drone/show_system_integrity()
if(!src.stat)
var/temphealth = health+35 //Brings it to 0.
if(temphealth<0) temphealth = 0
//Convert to percentage.
temphealth = (temphealth / (maxHealth*2)) * 100
stat(null, text("System integrity: [temphealth]%"))
else
stat(null, text("Systems nonfunctional"))
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
/mob/living/silicon/robot/drone/attackby(obj/item/weapon/W as obj, mob/user as mob)
@@ -327,7 +321,13 @@
src << "<b>If a crewmember has noticed you, <i>you are probably breaking your third law</i></b>."
/mob/living/silicon/robot/drone/Bump(atom/movable/AM as mob|obj, yes)
if (!yes || ( !istype(AM,/obj/machinery/door) && !istype(AM,/obj/machinery/recharge_station) && !istype(AM,/obj/machinery/disposal/deliveryChute) ) ) return
if (!yes || ( \
!istype(AM,/obj/machinery/door) && \
!istype(AM,/obj/machinery/recharge_station) && \
!istype(AM,/obj/machinery/disposal/deliveryChute) && \
!istype(AM,/obj/machinery/teleport/hub) && \
!istype(AM,/obj/effect/portal)
)) return
..()
return
@@ -33,16 +33,19 @@
layer = MOB_LAYER
src << text("\blue You have stopped hiding.")
/mob/living/silicon/robot/drone/verb/light()
set name = "Light On/Off"
set desc = "Activate a low power omnidirectional LED. Toggled on or off."
set category = "Drone"
if(luminosity)
SetLuminosity(0)
return
SetLuminosity(2)
//Actual picking-up event.
/mob/living/silicon/robot/drone/attack_hand(mob/living/carbon/human/M as mob)
if(M.a_intent == "help")
var/obj/item/weapon/holder/drone/D = new(loc)
src.loc = D
D.attack_hand(M)
M << "You scoop up [src]."
src << "[M] scoops you up."
M.status_flags |= PASSEMOTES
return
get_scooped(M)
..()
@@ -28,6 +28,19 @@
//Item currently being held.
var/obj/item/wrapped = null
/obj/item/weapon/gripper/paperwork
name = "paperwork gripper"
desc = "A simple grasping tool for clerical work."
icon = 'icons/obj/device.dmi'
icon_state = "gripper"
can_hold = list(
/obj/item/weapon/clipboard,
/obj/item/weapon/paper,
/obj/item/weapon/paper_bundle,
/obj/item/weapon/card/id
)
/obj/item/weapon/gripper/attack_self(mob/user as mob)
if(wrapped)
wrapped.attack_self(user)
@@ -56,9 +69,9 @@
/obj/item/weapon/gripper/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
/obj/item/weapon/gripper/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
/obj/item/weapon/gripper/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
if(!target || !flag) //Target is invalid or we are not adjacent.
if(!target || !proximity) //Target is invalid or we are not adjacent.
return
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
@@ -67,25 +80,22 @@
wrapped = thing
break
if(wrapped) //Already have an item.
if(wrapped) //Already have an item.
//Temporary put wrapped into user so target's attackby() checks pass.
wrapped.loc = user
//Pass the attack on to the target.
//Pass the attack on to the target. This might delete/relocate wrapped.
target.attackby(wrapped,user)
if(wrapped && src && wrapped.loc == user)
//If wrapped did neither get deleted nor put into target, put it back into the gripper.
if(wrapped && user && (wrapped.loc == user))
wrapped.loc = src
//Sanity/item use checks.
if(!wrapped || !user)
return
if(wrapped.loc != src.loc)
else
wrapped = null
return
if(istype(target,/obj/item)) //Check that we're not pocketing a mob.
else if(istype(target,/obj/item)) //Check that we're not pocketing a mob.
//...and that the item is not in a container.
if(!isturf(target.loc))
@@ -145,9 +155,9 @@
/obj/item/weapon/matter_decompiler/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
/obj/item/weapon/matter_decompiler/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
/obj/item/weapon/matter_decompiler/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
if(!flag) return //Not adjacent.
if(!proximity) return //Not adjacent.
//We only want to deal with using this on turfs. Specific items aren't important.
var/turf/T = get_turf(target)
@@ -344,4 +354,4 @@
stack = stack_plastic
stack.amount++
decompiler.stored_comms[type]--;
decompiler.stored_comms[type]--;
@@ -19,11 +19,9 @@
..()
/obj/machinery/drone_fabricator/power_change()
if (powered())
stat &= ~NOPOWER
else
..()
if (stat & NOPOWER)
icon_state = "drone_fab_nopower"
stat |= NOPOWER
/obj/machinery/drone_fabricator/process()
@@ -18,6 +18,7 @@
else
lawsync()
photosync()
src << "<b>Laws synced with AI, be sure to note any changes.</b>"
if(mind && mind.special_role == "traitor" && mind.original == src)
src << "<b>Remember, your AI does NOT share or know about your law 0."
@@ -133,10 +133,6 @@
else
src.blinded = 1
if(!is_component_functioning("actuator"))
src.Paralyse(3)
return 1
/mob/living/silicon/robot/proc/handle_regular_hud_updates()
@@ -322,7 +318,7 @@
weaponlock_time = 120
/mob/living/silicon/robot/update_canmove()
if(paralysis || stunned || weakened || buckled || lockcharge) canmove = 0
if(paralysis || stunned || weakened || buckled || lockcharge || !is_component_functioning("actuator")) canmove = 0
else canmove = 1
return canmove
@@ -0,0 +1,13 @@
/mob/living/silicon/robot/proc/photosync()
var/obj/item/device/camera/siliconcam/master_cam = connected_ai ? connected_ai.aiCamera : null
if (!master_cam)
return
var/synced
synced = 0
for(var/datum/picture/z in aiCamera.aipictures)
if (!(master_cam.aipictures.Find(z)))
aiCamera.printpicture(null, z)
synced = 1
if(synced)
src << "<span class='notice'>Locally saved images synced with AI. Images were retained in local database in case of loss of connection with the AI.</span>"
+72 -46
View File
@@ -5,12 +5,12 @@
icon_state = "robot"
maxHealth = 200
health = 200
universal_speak = 1
var/sight_mode = 0
var/custom_name = ""
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
var/crisis //Admin-settable for combat module use.
var/crisis_override = 0
//Hud stuff
@@ -65,7 +65,6 @@
var/speed = 0 //Cause sec borgs gotta go fast //No they dont!
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
var/braintype = "Cyborg"
var/pose
/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0)
spark_system = new /datum/effect/effect/system/spark_spread()
@@ -89,18 +88,7 @@
hands.icon_state = "standard"
icon_state = "secborg"
modtype = "Security"
else if(istype(src,/mob/living/silicon/robot/drone))
laws = new /datum/ai_laws/drone()
connected_ai = null
else
laws = new /datum/ai_laws/nanotrasen()
connected_ai = select_active_ai_with_fewest_borgs()
if(connected_ai)
connected_ai.connected_robots += src
lawsync()
lawupdate = 1
else
lawupdate = 0
init()
radio = new /obj/item/device/radio/borg(src)
if(!scrambledcodes && !camera)
@@ -139,11 +127,19 @@
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
if(istype(src,/mob/living/silicon/robot/drone))
playsound(src.loc, 'sound/machines/twobeep.ogg', 50, 0)
/mob/living/silicon/robot/proc/init()
aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src)
laws = new /datum/ai_laws/nanotrasen()
connected_ai = select_active_ai_with_fewest_borgs()
if(connected_ai)
connected_ai.connected_robots += src
lawsync()
photosync()
lawupdate = 1
else
playsound(loc, 'sound/voice/liveagain.ogg', 75, 1)
lawupdate = 0
playsound(loc, 'sound/voice/liveagain.ogg', 75, 1)
// setup the PDA and its name
/mob/living/silicon/robot/proc/setup_PDA()
@@ -164,8 +160,8 @@
/mob/living/silicon/robot/proc/pick_module()
if(module)
return
var/list/modules = list("Standard", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
if(crisis && security_level == SEC_LEVEL_RED) //Leaving this in until it's balanced appropriately.
var/list/modules = list("Standard", "Engineering", "Construction", "Surgeon", "Crisis", "Miner", "Janitor", "Service", "Clerical", "Security")
if((crisis && security_level == SEC_LEVEL_RED) || crisis_override) //Leaving this in until it's balanced appropriately.
src << "\red Crisis mode active. Combat module available."
modules+="Combat"
modtype = input("Please, select a module!", "Robot", null, null) in modules
@@ -190,6 +186,14 @@
module_sprites["Rich"] = "maximillion"
module_sprites["Default"] = "Service2"
if("Clerical")
module = new /obj/item/weapon/robot_module/clerical(src)
module_sprites["Waitress"] = "Service"
module_sprites["Kent"] = "toiletbot"
module_sprites["Bro"] = "Brobot"
module_sprites["Rich"] = "maximillion"
module_sprites["Default"] = "Service2"
if("Miner")
module = new /obj/item/weapon/robot_module/miner(src)
module.channels = list("Supply" = 1)
@@ -199,15 +203,26 @@
module_sprites["Advanced Droid"] = "droid-miner"
module_sprites["Treadhead"] = "Miner"
if("Medical")
module = new /obj/item/weapon/robot_module/medical(src)
if("Crisis")
module = new /obj/item/weapon/robot_module/crisis(src)
module.channels = list("Medical" = 1)
if(camera && "Robots" in camera.network)
camera.network.Add("Medical")
module_sprites["Basic"] = "Medbot"
module_sprites["Standard"] = "surgeon"
module_sprites["Advanced Droid"] = "droid-medical"
module_sprites["Needles"] = "medicalrobot"
if("Surgeon")
module = new /obj/item/weapon/robot_module/surgeon(src)
module.channels = list("Medical" = 1)
if(camera && "Robots" in camera.network)
camera.network.Add("Medical")
module_sprites["Basic"] = "Medbot"
module_sprites["Standard"] = "surgeon"
module_sprites["Advanced Droid"] = "droid-medical"
module_sprites["Needles"] = "medicalrobot"
if("Security")
module = new /obj/item/weapon/robot_module/security(src)
@@ -226,6 +241,15 @@
module_sprites["Antique"] = "engineerrobot"
module_sprites["Landmate"] = "landmate"
if("Construction")
module = new /obj/item/weapon/robot_module/construction(src)
module.channels = list("Engineering" = 1)
if(camera && "Robots" in camera.network)
camera.network.Add("Engineering")
module_sprites["Basic"] = "Engineering"
module_sprites["Antique"] = "engineerrobot"
module_sprites["Landmate"] = "landmate"
if("Janitor")
module = new /obj/item/weapon/robot_module/janitor(src)
module_sprites["Basic"] = "JanBot2"
@@ -237,6 +261,9 @@
module_sprites["Combat Android"] = "droid-combat"
module.channels = list("Security" = 1)
//languages
module.add_languages(src)
//Custom_sprite check and entry
if (custom_sprite == 1)
module_sprites["Custom"] = "[src.ckey]-[modtype]"
@@ -254,10 +281,13 @@
/mob/living/silicon/robot/proc/updatename(var/prefix as text)
if(prefix)
modtype = prefix
if(istype(mmi, /obj/item/device/mmi/posibrain))
braintype = "Android"
if(mmi)
if(istype(mmi, /obj/item/device/mmi/posibrain))
braintype = "Android"
else
braintype = "Cyborg"
else
braintype = "Cyborg"
braintype = "Robot"
var/changed_name = ""
if(custom_name)
@@ -315,7 +345,7 @@
// this verb lets cyborgs see the stations manifest
/mob/living/silicon/robot/verb/cmd_station_manifest()
set category = "Robot Commands"
set name = "Show Station Manifest"
set name = "Show Crew Manifest"
show_station_manifest()
@@ -566,6 +596,10 @@
return
if (istype(W, /obj/item/weapon/weldingtool))
if (src == user)
user << "<span class='warning'>You lack the reach to be able to repair yourself.</span>"
return
if (!getBruteLoss())
user << "Nothing to fix here!"
return
@@ -870,7 +904,7 @@
var/damage = rand(1, 3)
if(istype(src, /mob/living/carbon/slime/adult))
if(M.is_adult)
damage = rand(20, 40)
else
damage = rand(5, 35)
@@ -1017,10 +1051,7 @@
else
icon_state = base_icon
return
/*
/mob/living/silicon/robot/proc/updatefire()
return
*/
//Call when target overlay should be added/removed
/mob/living/silicon/robot/update_targeted()
if(!targeted_by && target_locked)
@@ -1072,17 +1103,26 @@
/mob/living/silicon/robot/Topic(href, href_list)
..()
if(usr != src)
return
if (href_list["showalerts"])
robot_alerts()
return
if (href_list["mod"])
var/obj/item/O = locate(href_list["mod"])
if (O)
if (istype(O) && (O.loc == src))
O.attack_self(src)
if (href_list["act"])
var/obj/item/O = locate(href_list["act"])
if (!istype(O))
return
if(!((O in src.module.modules) || (O == src.module.emag)))
return
if(activated(O))
src << "Already activated"
return
@@ -1228,20 +1268,6 @@
return
/mob/living/silicon/robot/verb/pose()
set name = "Set Pose"
set desc = "Sets a description which will be shown when someone examines you."
set category = "IC"
pose = copytext(sanitize(input(usr, "This is [src]. It is...", "Pose", null) as text), 1, MAX_MESSAGE_LEN)
/mob/living/silicon/robot/verb/set_flavor()
set name = "Set Flavour Text"
set desc = "Sets an extended description of your character's features."
set category = "IC"
flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1)
/mob/living/silicon/robot/proc/choose_icon(var/triesleft, var/list/module_sprites)
if(triesleft<1 || !module_sprites.len)
@@ -1,9 +1,9 @@
/mob/living/silicon/robot/updatehealth()
if(status_flags & GODMODE)
health = 200
health = maxHealth
stat = CONSCIOUS
return
health = 200 - (getBruteLoss() + getFireLoss())
health = maxHealth - (getBruteLoss() + getFireLoss())
return
/mob/living/silicon/robot/getBruteLoss()
@@ -145,4 +145,4 @@
brute -= (picked.brute_damage - brute_was)
burn -= (picked.electronics_damage - burn_was)
parts -= picked
parts -= picked
@@ -6,7 +6,9 @@
name = "RoboTray"
desc = "An autoloading tray specialized for carrying refreshments."
/obj/item/weapon/tray/robotray/afterattack(atom/target, mob/user as mob)
/obj/item/weapon/tray/robotray/afterattack(atom/target, mob/user as mob, proximity)
if(!proximity)
return
if ( !target )
return
// pick up items, mostly copied from base tray pickup proc
@@ -95,14 +97,26 @@
var/mode = 1
/obj/item/weapon/pen/robopen/attack_self(mob/user as mob)
var/choice = input("Would you like to change colour or mode?") as null|anything in list("Colour","Mode")
if(!choice) return
playsound(src.loc, 'sound/effects/pop.ogg', 50, 0)
if (mode == 1)
mode = 2
user << "Changed printing mode to 'Rename Paper'"
return
if (mode == 2)
mode = 1
user << "Changed printing mode to 'Write Paper'"
switch(choice)
if("Colour")
var/newcolour = input("Which colour would you like to use?") as null|anything in list("black","blue","red","green","yellow")
if(newcolour) colour = newcolour
if("Mode")
if (mode == 1)
mode = 2
else
mode = 1
user << "Changed printing mode to '[mode == 2 ? "Rename Paper" : "Write Paper"]'"
return
// Copied over from paper's rename verb
// see code\modules\paperwork\paper.dm line 62
@@ -120,6 +134,33 @@
add_fingerprint(user)
return
//TODO: Add prewritten forms to dispense when you work out a good way to store the strings.
/obj/item/weapon/form_printer
//name = "paperwork printer"
name = "paper dispenser"
icon = 'icons/obj/bureaucracy.dmi'
icon_state = "paper_bin1"
item_state = "sheet-metal"
/obj/item/weapon/form_printer/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
/obj/item/weapon/form_printer/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
if(!target || !flag)
return
if(istype(target,/obj/structure/table))
deploy_paper(get_turf(target))
/obj/item/weapon/form_printer/attack_self(mob/user as mob)
deploy_paper(get_turf(src))
/obj/item/weapon/form_printer/proc/deploy_paper(var/turf/T)
T.visible_message("\blue \The [src.loc] dispenses a sheet of crisp white paper.")
new /obj/item/weapon/paper(T)
//Personal shielding for the combat module.
/obj/item/borg/combat/shield
name = "personal shielding"
@@ -9,7 +9,7 @@
var/list/modules = list()
var/obj/item/emag = null
var/obj/item/borg/upgrade/jetpack = null
var/list/stacktypes
emp_act(severity)
if(modules)
@@ -32,7 +32,21 @@
/obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R)
return
if(!stacktypes || !stacktypes.len) return
for(var/T in stacktypes)
var/O = locate(T) in src.modules
var/obj/item/stack/S = O
if(!S)
src.modules -= null
S = new T(src)
src.modules += S
S.amount = 1
if(S && S.amount < stacktypes[T])
S.amount++
/obj/item/weapon/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module
var/list/temp_list = modules
@@ -41,6 +55,16 @@
if(O)
modules += O
/obj/item/weapon/robot_module/proc/add_languages(var/mob/living/silicon/robot/R)
//full set of languages
R.add_language("Sol Common", 1)
R.add_language("Tradeband", 1)
R.add_language("Sinta'unathi", 0)
R.add_language("Siik'tajr", 0)
R.add_language("Skrellian", 0)
R.add_language("Gutter", 0)
/obj/item/weapon/robot_module/standard
name = "standard robot module"
@@ -55,13 +79,50 @@
src.emag = new /obj/item/weapon/melee/energy/sword(src)
return
/obj/item/weapon/robot_module/standard/respawn_consumable(var/mob/living/silicon/robot/R)
var/obj/item/weapon/melee/baton/B = locate() in src.modules
if(B.charges < 10)
B.charges += 1
/obj/item/weapon/robot_module/surgeon
name = "surgeon robot module"
stacktypes = list(
/obj/item/stack/medical/advanced/bruise_pack = 5,
/obj/item/stack/nanopaste = 5
)
/obj/item/weapon/robot_module/medical
name = "medical robot module"
New()
src.modules += new /obj/item/device/flashlight(src)
src.modules += new /obj/item/device/flash(src)
src.modules += new /obj/item/device/healthanalyzer(src)
src.modules += new /obj/item/weapon/reagent_containers/borghypo/surgeon(src)
src.modules += new /obj/item/weapon/scalpel(src)
src.modules += new /obj/item/weapon/hemostat(src)
src.modules += new /obj/item/weapon/retractor(src)
src.modules += new /obj/item/weapon/cautery(src)
src.modules += new /obj/item/weapon/bonegel(src)
src.modules += new /obj/item/weapon/FixOVein(src)
src.modules += new /obj/item/weapon/bonesetter(src)
src.modules += new /obj/item/weapon/circular_saw(src)
src.modules += new /obj/item/weapon/surgicaldrill(src)
src.modules += new /obj/item/weapon/extinguisher/mini(src)
src.modules += new /obj/item/stack/medical/advanced/bruise_pack(src)
src.modules += new /obj/item/stack/nanopaste(src)
src.emag = new /obj/item/weapon/reagent_containers/spray(src)
src.emag.reagents.add_reagent("pacid", 250)
src.emag.name = "Polyacid spray"
return
/obj/item/weapon/robot_module/surgeon/respawn_consumable(var/mob/living/silicon/robot/R)
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/PS = src.emag
PS.reagents.add_reagent("pacid", 2)
..()
/obj/item/weapon/robot_module/crisis
name = "crisis robot module"
stacktypes = list(
/obj/item/stack/medical/ointment = 5,
/obj/item/stack/medical/bruise_pack = 5,
/obj/item/stack/medical/splint = 5
)
New()
src.modules += new /obj/item/device/flashlight(src)
@@ -69,31 +130,69 @@
src.modules += new /obj/item/borg/sight/hud/med(src)
src.modules += new /obj/item/device/healthanalyzer(src)
src.modules += new /obj/item/device/reagent_scanner/adv(src)
src.modules += new /obj/item/weapon/reagent_containers/borghypo(src)
src.modules += new /obj/item/roller_holder(src)
src.modules += new /obj/item/stack/medical/ointment(src)
src.modules += new /obj/item/stack/medical/bruise_pack(src)
src.modules += new /obj/item/stack/medical/splint(src)
src.modules += new /obj/item/weapon/reagent_containers/borghypo/crisis(src)
src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
src.modules += new /obj/item/weapon/reagent_containers/robodropper(src)
src.modules += new /obj/item/weapon/reagent_containers/syringe(src)
src.modules += new /obj/item/weapon/extinguisher/mini(src)
src.emag = new /obj/item/weapon/reagent_containers/spray(src)
src.emag.reagents.add_reagent("pacid", 250)
src.emag.name = "Polyacid spray"
return
/obj/item/weapon/robot_module/medical/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/crisis/respawn_consumable(var/mob/living/silicon/robot/R)
var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules
if(S.mode == 2)//SYRINGE_BROKEN
if(S.mode == 2)
S.reagents.clear_reagents()
S.mode = initial(S.mode)
S.desc = initial(S.desc)
S.update_icon()
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/PS = src.emag
PS.reagents.add_reagent("pacid", 2)
..()
/obj/item/weapon/robot_module/construction
name = "construction robot module"
stacktypes = list(
/obj/item/stack/sheet/metal = 50,
/obj/item/stack/sheet/plasteel = 10,
/obj/item/stack/sheet/rglass = 50,
/obj/item/stack/rods = 50
)
New()
src.modules += new /obj/item/device/flashlight(src)
src.modules += new /obj/item/device/flash(src)
src.modules += new /obj/item/borg/sight/meson(src)
src.modules += new /obj/item/weapon/extinguisher(src)
src.modules += new /obj/item/weapon/rcd/borg(src)
src.modules += new /obj/item/weapon/screwdriver(src)
src.modules += new /obj/item/weapon/wrench(src)
src.modules += new /obj/item/weapon/crowbar(src)
src.modules += new /obj/item/weapon/pickaxe/plasmacutter(src)
/obj/item/weapon/robot_module/engineering
name = "engineering robot module"
stacktypes = list(
/obj/item/stack/sheet/metal = 50,
/obj/item/stack/sheet/glass = 50,
/obj/item/stack/sheet/rglass = 50,
/obj/item/weapon/cable_coil = 50,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15
)
New()
src.modules += new /obj/item/device/flashlight(src)
@@ -117,7 +216,11 @@
M.amount = 50
src.modules += M
var/obj/item/stack/sheet/rglass/cyborg/G = new /obj/item/stack/sheet/rglass/cyborg(src)
var/obj/item/stack/sheet/rglass/cyborg/R = new /obj/item/stack/sheet/rglass/cyborg(src)
R.amount = 50
src.modules += R
var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src)
G.amount = 50
src.modules += G
@@ -127,24 +230,6 @@
return
/obj/item/weapon/robot_module/engineering/respawn_consumable(var/mob/living/silicon/robot/R)
var/list/stacks = list (
/obj/item/stack/sheet/metal,
/obj/item/stack/sheet/rglass,
/obj/item/weapon/cable_coil,
)
for(var/T in stacks)
var/O = locate(T) in src.modules
if(O)
if(O:amount < 50)
O:amount++
else
src.modules -= null
O = new T(src)
src.modules += O
O:amount = 1
return
/obj/item/weapon/robot_module/security
name = "security robot module"
@@ -173,9 +258,6 @@
T.update_icon()
else
T.charge_tick = 0
var/obj/item/weapon/melee/baton/B = locate() in src.modules
if(B.charges < 10)
B.charges += 1
/obj/item/weapon/robot_module/janitor
name = "janitorial robot module"
@@ -211,7 +293,7 @@
src.modules += new /obj/item/weapon/pen/robopen(src)
var/obj/item/weapon/rsf/M = new /obj/item/weapon/rsf(src)
M.matter = 30
M.stored_matter = 30
src.modules += M
src.modules += new /obj/item/weapon/reagent_containers/robodropper(src)
@@ -231,6 +313,39 @@
src.emag.name = "Mickey Finn's Special Brew"
return
add_languages(var/mob/living/silicon/robot/R)
//full set of languages
R.add_language("Sol Common", 1)
R.add_language("Sinta'unathi", 1)
R.add_language("Siik'maas", 1)
R.add_language("Siik'tajr", 0)
R.add_language("Skrellian", 1)
R.add_language("Rootspeak", 1)
R.add_language("Tradeband", 1)
R.add_language("Gutter", 1)
/obj/item/weapon/robot_module/clerical
name = "clerical robot module"
New()
src.modules += new /obj/item/device/flashlight(src)
src.modules += new /obj/item/device/flash(src)
src.modules += new /obj/item/weapon/pen/robopen(src)
src.modules += new /obj/item/weapon/form_printer(src)
src.modules += new /obj/item/weapon/gripper/paperwork(src)
src.emag = new /obj/item/weapon/stamp/denied(src)
add_languages(var/mob/living/silicon/robot/R)
R.add_language("Sol Common", 1)
R.add_language("Sinta'unathi", 1)
R.add_language("Siik'maas", 1)
R.add_language("Siik'tajr", 0)
R.add_language("Skrellian", 1)
R.add_language("Rootspeak", 1)
R.add_language("Tradeband", 1)
R.add_language("Gutter", 1)
/obj/item/weapon/robot_module/butler/respawn_consumable(var/mob/living/silicon/robot/R)
var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules
E.reagents.add_reagent("enzyme", 2)
@@ -245,11 +360,12 @@
src.modules += new /obj/item/device/flashlight(src)
src.modules += new /obj/item/device/flash(src)
src.modules += new /obj/item/borg/sight/meson(src)
src.emag = new /obj/item/borg/stun(src)
src.modules += new /obj/item/weapon/wrench(src)
src.modules += new /obj/item/weapon/screwdriver(src)
src.modules += new /obj/item/weapon/storage/bag/ore(src)
src.modules += new /obj/item/weapon/pickaxe/borgdrill(src)
src.modules += new /obj/item/weapon/storage/bag/sheetsnatcher/borg(src)
// src.modules += new /obj/item/weapon/shovel(src) Uneeded due to buffed drill
src.emag = new /obj/item/weapon/pickaxe/plasmacutter(src)
return
/obj/item/weapon/robot_module/syndicate
@@ -281,20 +397,19 @@
/obj/item/weapon/robot_module/drone
name = "drone module"
var/list/stacktypes = list(
/obj/item/stack/sheet/wood/cyborg = 1,
/obj/item/stack/sheet/mineral/plastic/cyborg = 1,
/obj/item/stack/sheet/rglass/cyborg = 5,
stacktypes = list(
/obj/item/stack/sheet/wood = 1,
/obj/item/stack/sheet/mineral/plastic = 1,
/obj/item/stack/sheet/rglass = 5,
/obj/item/stack/tile/wood = 5,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15,
/obj/item/stack/sheet/metal/cyborg = 20,
/obj/item/stack/sheet/glass/cyborg = 20,
/obj/item/stack/sheet/metal = 20,
/obj/item/stack/sheet/glass = 20,
/obj/item/weapon/cable_coil = 30
)
New()
src.modules += new /obj/item/device/flashlight/drone(src)
src.modules += new /obj/item/weapon/weldingtool(src)
src.modules += new /obj/item/weapon/screwdriver(src)
src.modules += new /obj/item/weapon/wrench(src)
@@ -306,8 +421,8 @@
src.modules += new /obj/item/weapon/matter_decompiler(src)
src.modules += new /obj/item/weapon/reagent_containers/spray/cleaner/drone(src)
src.emag = new /obj/item/weapon/card/emag(src)
src.emag.name = "Cryptographic Sequencer"
src.emag = new /obj/item/weapon/pickaxe/plasmacutter(src)
src.emag.name = "Plasma Cutter"
for(var/T in stacktypes)
var/obj/item/stack/sheet/W = new T(src)
@@ -316,24 +431,24 @@
return
add_languages(var/mob/living/silicon/robot/R)
return //not much ROM to spare in that tiny microprocessor!
/obj/item/weapon/robot_module/drone/respawn_consumable(var/mob/living/silicon/robot/R)
var/obj/item/weapon/reagent_containers/spray/cleaner/C = locate() in src.modules
C.reagents.add_reagent("cleaner", 3)
for(var/T in stacktypes)
var/O = locate(T) in src.modules
var/obj/item/stack/sheet/S = O
if(!S)
src.modules -= null
S = new T(src)
src.modules += S
S.amount = 1
if(S && S.amount < stacktypes[T])
S.amount++
var/obj/item/device/lightreplacer/LR = locate() in src.modules
LR.Charge(R)
return
..()
return
//checks whether this item is a module of the robot it is located in.
/obj/item/proc/is_robot_module()
if (!istype(src.loc, /mob/living/silicon/robot))
return 0
var/mob/living/silicon/robot/R = src.loc
return (src in R.module.modules)
@@ -1,3 +1,8 @@
/mob/living/silicon/robot/Process_Spaceslipping(var/prob_slip)
if(module && (istype(module,/obj/item/weapon/robot_module/construction) || istype(module,/obj/item/weapon/robot_module/drone)))
return 0
..(prob_slip)
/mob/living/silicon/robot/Process_Spacemove()
if(module)
for(var/obj/item/weapon/tank/jetpack/J in module.modules)
@@ -34,6 +34,8 @@
R.base_icon = "robot"
R.icon_state = "robot"
R.updateicon()
R.languages = list()
R.speech_synthesizer_langs = list()
return 1
@@ -74,6 +74,7 @@
if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh
if (src.lawupdate)
src.lawsync()
src.photosync()
if (BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
if(!src.emagged)
+59 -39
View File
@@ -2,16 +2,27 @@
var/ending = copytext(text, length(text))
if (ending == "?")
return "queries"
return speak_query
else if (ending == "!")
return "declares"
return speak_exclamation
return "states"
return speak_statement
#define IS_AI 1
#define IS_ROBOT 2
#define IS_PAI 3
/mob/living/silicon/say_understands(var/other,var/datum/language/speaking = null)
//These only pertain to common. Languages are handled by mob/say_understands()
if (!speaking)
if (istype(other, /mob/living/carbon))
return 1
if (istype(other, /mob/living/silicon))
return 1
if (istype(other, /mob/living/carbon/brain))
return 1
return ..()
/mob/living/silicon/say(var/message)
if (!message)
return
@@ -49,39 +60,39 @@
return
var/verb = say_quote(message)
var/message_mode = null
//parse radio key and consume it
var/message_mode = parse_message_mode(message, "general")
if (message_mode)
if (message_mode == "general")
message = trim(copytext(message,2))
else
message = trim(copytext(message,3))
if(message_mode && bot_type == IS_ROBOT && message_mode != "binary" && !R.is_component_functioning("radio"))
src << "\red Your radio isn't functional at this time."
return
if(copytext(message,1,2) == ";")
message_mode = "general" // I don't know why but regular radio = fuck you we ain't broadcasting, pAI mode was what was in old say code.
message = trim(copytext(message,2))
//parse language key and consume it
var/datum/language/speaking = parse_language(message)
if (speaking)
verb = speaking.speech_verb
message = copytext(message,3)
else if(length(message) >= 2)
var/channel_prefix = copytext(message, 1 ,3)
if(!message_mode)
message_mode = department_radio_keys[channel_prefix]
if(message_mode && bot_type == IS_ROBOT)
if(message_mode != "binary" && !R.is_component_functioning("radio"))
src << "\red Your radio isn't functional at this time."
return
if(message_mode && message_mode != "general")
message = trim(copytext(message,3))
switch(message_mode)
if("department")
switch(bot_type)
if(IS_AI)
AI.holopad_talk(message)
return AI.holopad_talk(message)
if(IS_ROBOT)
log_say("[key_name(src)] : [message]")
R.radio.talk_into(src,message,message_mode,verb)
R.radio.talk_into(src,message,message_mode,verb,speaking)
if(IS_PAI)
log_say("[key_name(src)] : [message]")
P.radio.talk_into(src,message,message_mode,verb)
return
P.radio.talk_into(src,message,message_mode,verb,speaking)
return 1
if("binary")
switch(bot_type)
@@ -94,35 +105,43 @@
return
robot_talk(message)
return
return 1
if("general")
switch(bot_type)
if(IS_AI)
src << "Yeah, not yet, sorry"
if (AI.aiRadio.disabledAi)
src << "\red System Error - Transceiver Disabled"
return
else
log_say("[key_name(src)] : [message]")
AI.aiRadio.talk_into(src,message,null,verb,speaking)
if(IS_ROBOT)
log_say("[key_name(src)] : [message]")
R.radio.talk_into(src,message,null,verb)
R.radio.talk_into(src,message,null,verb,speaking)
if(IS_PAI)
log_say("[key_name(src)] : [message]")
P.radio.talk_into(src,message,null,verb)
return
P.radio.talk_into(src,message,null,verb,speaking)
return 1
else
if(message_mode && message_mode in radiochannels)
switch(bot_type)
if(IS_AI)
src << "You don't have this function yet, I'm working on it"
return
if (AI.aiRadio.disabledAi)
src << "\red System Error - Transceiver Disabled"
return
else
log_say("[key_name(src)] : [message]")
AI.aiRadio.talk_into(src,message,message_mode,verb,speaking)
if(IS_ROBOT)
log_say("[key_name(src)] : [message]")
R.radio.talk_into(src,message,message_mode,verb)
R.radio.talk_into(src,message,message_mode,verb,speaking)
if(IS_PAI)
log_say("[key_name(src)] : [message]")
P.radio.talk_into(src,message,message_mode,verb)
return
P.radio.talk_into(src,message,message_mode,verb,speaking)
return 1
return ..(message,null,verb)
return ..(message,speaking,verb)
//For holopads only. Usable by AI.
/mob/living/silicon/ai/proc/holopad_talk(var/message)
@@ -134,8 +153,8 @@
if (!message)
return
var/obj/machinery/hologram/holopad/T = src.current
if(istype(T) && T.hologram && T.master == src)//If there is a hologram and its master is the user.
var/obj/machinery/hologram/holopad/T = src.holo
if(T && T.hologram && T.master == src)//If there is a hologram and its master is the user.
var/verb = say_quote(message)
//Human-like, sorta, heard by those who understand humans.
@@ -155,7 +174,8 @@
This is another way of saying that we won't bother dealing with them.*/
else
src << "No holopad connected."
return
return
return 1
/mob/living/proc/robot_talk(var/message)
+76 -5
View File
@@ -6,6 +6,14 @@
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
immune_to_ssd = 1
var/list/hud_list[9]
var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer
//Used in say.dm.
var/speak_statement = "states"
var/speak_exclamation = "declares"
var/speak_query = "queries"
var/pose //Yes, now AIs can pose too.
var/obj/item/device/camera/siliconcam/aiCamera = null //photography
/mob/living/silicon/proc/show_laws()
return
@@ -26,6 +34,25 @@
src << "\red Warning: Electromagnetic pulse detected."
..()
/mob/living/silicon/stun_effect_act(var/stun_amount, var/agony_amount)
return //immune
/mob/living/silicon/electrocute_act(var/shock_damage, var/obj/source, var/siemens_coeff = 1.0)
if (istype(source, /obj/machinery/containment_field))
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, loc)
s.start()
shock_damage *= 0.75 //take reduced damage
take_overall_damage(0, shock_damage)
visible_message("\red [src] was shocked by \the [source]!", \
"\red <B>Energy pulse detected, system damaged!</B>", \
"\red You hear an electrical crack")
if(prob(20))
Stun(2)
return
/mob/living/silicon/proc/damage_mob(var/brute = 0, var/fire = 0, var/tox = 0)
return
@@ -79,7 +106,7 @@
// this function shows the health of the pAI in the Status panel
/mob/living/silicon/proc/show_system_integrity()
if(!src.stat)
stat(null, text("System integrity: [(src.health+100)/2]%"))
stat(null, text("System integrity: [round((health/maxHealth)*100)]%"))
else
stat(null, text("Systems nonfunctional"))
@@ -96,10 +123,10 @@
// this function displays the shuttles ETA in the status panel if the shuttle has been called
/mob/living/silicon/proc/show_emergency_shuttle_eta()
if(emergency_shuttle.online && emergency_shuttle.location < 2)
var/timeleft = emergency_shuttle.timeleft()
if (timeleft)
stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
// This adds the basic clock, shuttle recall timer, and malf_ai info to all silicon lifeforms
@@ -127,3 +154,47 @@
if(error_msg)
user << "<span class='alert'>The armoured plating is too tough.</span>"
return 0
//Silicon mob language procs
/mob/living/silicon/can_speak(datum/language/speaking)
return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language
/mob/living/silicon/add_language(var/language, var/can_speak=1)
if (..(language) && can_speak)
speech_synthesizer_langs.Add(all_languages[language])
/mob/living/silicon/remove_language(var/rem_language)
..(rem_language)
for (var/datum/language/L in speech_synthesizer_langs)
if (L.name == rem_language)
speech_synthesizer_langs -= L
/mob/living/silicon/check_languages()
set name = "Check Known Languages"
set category = "IC"
set src = usr
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>"
for(var/datum/language/L in languages)
dat += "<b>[L.name] (:[L.key])</b><br/>Speech Synthesizer: <i>[(L in speech_synthesizer_langs)? "YES":"NOT SUPPORTED"]</i><br/>[L.desc]<br/><br/>"
src << browse(dat, "window=checklanguage")
return
/mob/living/silicon/verb/pose()
set name = "Set Pose"
set desc = "Sets a description which will be shown when someone examines you."
set category = "IC"
pose = copytext(sanitize(input(usr, "This is [src]. It is...", "Pose", null) as text), 1, MAX_MESSAGE_LEN)
/mob/living/silicon/verb/set_flavor()
set name = "Set Flavour Text"
set desc = "Sets an extended description of your character's features."
set category = "IC"
flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1)
+121 -48
View File
@@ -1,6 +1,9 @@
/datum/game_mode/var/list/borers = list()
/mob/living/captive_brain
name = "host brain"
real_name = "host brain"
universal_understand = 1
/mob/living/captive_brain/say(var/message)
@@ -12,6 +15,14 @@
return
if(istype(src.loc,/mob/living/simple_animal/borer))
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
if (!message)
return
log_say("[key_name(src)] : [message]")
if (stat == 2)
return say_dead(message)
var/mob/living/simple_animal/borer/B = src.loc
src << "You whisper silently, \"[message]\""
B.host << "The captive mind of [src] whispers, \"[message]\""
@@ -31,7 +42,7 @@
desc = "A small, quivering sluglike creature."
speak_emote = list("chirrups")
emote_hear = list("chirrups")
response_help = "pokes the"
response_help = "pokes"
response_disarm = "prods the"
response_harm = "stomps on the"
icon_state = "brainslug"
@@ -45,6 +56,8 @@
friendly = "prods"
wander = 0
pass_flags = PASSTABLE
universal_understand = 1
holder_type = /obj/item/weapon/holder/borer
var/used_dominate
var/chemicals = 10 // Chemicals used for reproduction and spitting neurotoxin.
@@ -53,6 +66,11 @@
var/mob/living/captive_brain/host_brain // Used for swapping control of the body back and forth.
var/controlling // Used in human death check.
var/docile = 0 // Sugar can stop borers from acting.
var/has_reproduced
var/roundstart
/mob/living/simple_animal/borer/roundstart
roundstart = 1
/mob/living/simple_animal/borer/Life()
@@ -95,10 +113,7 @@
/mob/living/simple_animal/borer/New()
..()
truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
host_brain = new/mob/living/captive_brain(src)
request_player()
if(!roundstart) request_player()
/mob/living/simple_animal/borer/say(var/message)
@@ -128,6 +143,7 @@
return borer_speak(message)
if(!host)
//TODO: have this pick a random mob within 3 tiles to speak for the borer.
src << "You have no host to speak to."
return //No host, no audible speech.
@@ -140,16 +156,14 @@
else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
M << "[src.truename] whispers to [host], \"[message]\""
/mob/living/simple_animal/borer/Stat()
..()
statpanel("Status")
if(emergency_shuttle)
if(emergency_shuttle.online && emergency_shuttle.location < 2)
var/timeleft = emergency_shuttle.timeleft()
if (timeleft)
stat(null, "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]")
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
if (client.statpanel == "Status")
stat("Chemicals", chemicals)
@@ -166,10 +180,10 @@
/mob/living/simple_animal/borer/verb/dominate_victim()
set category = "Alien"
set name = "Dominate Victim"
set name = "Paralyze Victim"
set desc = "Freeze the limbs of a potential host with supernatural fear."
if(world.time - used_dominate < 300)
if(world.time - used_dominate < 150)
src << "You cannot use that ability again so soon."
return
@@ -186,7 +200,7 @@
if(C.stat != 2)
choices += C
if(world.time - used_dominate < 300)
if(world.time - used_dominate < 150)
src << "You cannot use that ability again so soon."
return
@@ -200,7 +214,7 @@
src << "\red You focus your psychic lance on [M] and freeze their limbs with a wave of terrible dread."
M << "\red You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing."
M.Weaken(3)
M.Weaken(10)
used_dominate = world.time
@@ -217,17 +231,13 @@
src << "You cannot do that in your current state."
return
if(!host.internal_organs_by_name["brain"]) //this should only run in admin-weirdness situations, but it's here non the less - RR
src << "<span class='warning'>There is no brain here for us to command!</span>"
return
if(docile)
src << "\blue You are feeling far too docile to do that."
return
src << "You begin delicately adjusting your connection to the host brain..."
spawn(300+(host.brainloss*5))
spawn(100+(host.brainloss*5))
if(!host || !src || controlling)
return
@@ -235,14 +245,47 @@
src << "\red <B>You plunge your probosci deep into the cortex of the host brain, interfacing directly with their nervous system.</B>"
host << "\red <B>You feel a strange shifting sensation behind your eyes as an alien consciousness displaces yours.</B>"
// host -> brain
var/h2b_id = host.computer_id
var/h2b_ip= host.lastKnownIP
host.computer_id = null
host.lastKnownIP = null
del(host_brain)
host_brain = new(src)
host_brain.ckey = host.ckey
host_brain.name = host.name
if(!host_brain.computer_id)
host_brain.computer_id = h2b_id
if(!host_brain.lastKnownIP)
host_brain.lastKnownIP = h2b_ip
// self -> host
var/s2h_id = src.computer_id
var/s2h_ip= src.lastKnownIP
src.computer_id = null
src.lastKnownIP = null
host.ckey = src.ckey
if(!host.computer_id)
host.computer_id = s2h_id
if(!host.lastKnownIP)
host.lastKnownIP = s2h_ip
controlling = 1
host.verbs += /mob/living/carbon/proc/release_control
host.verbs += /mob/living/carbon/proc/punish_host
host.verbs += /mob/living/carbon/proc/spawn_larvae
return
/mob/living/simple_animal/borer/verb/secrete_chemicals()
set category = "Alien"
set name = "Secrete Chemicals"
@@ -268,7 +311,7 @@
return
src << "\red <B>You squirt a measure of [chem] from your reservoirs into [host]'s bloodstream.</B>"
host.reagents.add_reagent(chem, 15)
host.reagents.add_reagent(chem, 10)
chemicals -= 50
/mob/living/simple_animal/borer/verb/release_host()
@@ -294,12 +337,12 @@
if(!host.stat)
host << "An odd, uncomfortable pressure begins to build inside your skull, behind your ear..."
spawn(200)
spawn(100)
if(!host || !src) return
if(src.stat)
src << "You cannot infest a target in your current state."
src << "You cannot release your host in your current state."
return
src << "You wiggle out of [host]'s ear and plop to the ground."
@@ -307,43 +350,74 @@
host << "Something slimy wiggles out of your ear and plops to the ground!"
detatch()
leave_host()
mob/living/simple_animal/borer/proc/detatch()
/mob/living/simple_animal/borer/proc/detatch()
if(!host) return
if(!host || !controlling) return
if(istype(host,/mob/living/carbon/human))
var/mob/living/carbon/human/H = host
var/datum/organ/external/head = H.get_organ("head")
head.implants -= src
src.loc = get_turf(host)
controlling = 0
host.verbs -= /mob/living/carbon/proc/release_control
host.verbs -= /mob/living/carbon/proc/punish_host
host.verbs -= /mob/living/carbon/proc/spawn_larvae
if(host_brain)
// these are here so bans and multikey warnings are not triggered on the wrong people when ckey is changed.
// computer_id and IP are not updated magically on their own in offline mobs -walter0o
// host -> self
var/h2s_id = host.computer_id
var/h2s_ip= host.lastKnownIP
host.computer_id = null
host.lastKnownIP = null
src.ckey = host.ckey
if(!src.computer_id)
src.computer_id = h2s_id
if(!host_brain.lastKnownIP)
src.lastKnownIP = h2s_ip
// brain -> host
var/b2h_id = host_brain.computer_id
var/b2h_ip= host_brain.lastKnownIP
host_brain.computer_id = null
host_brain.lastKnownIP = null
host.ckey = host_brain.ckey
if(!host.computer_id)
host.computer_id = b2h_id
if(!host.lastKnownIP)
host.lastKnownIP = b2h_ip
del(host_brain)
/mob/living/simple_animal/borer/proc/leave_host()
if(!host) return
src.loc = get_turf(host)
reset_view(null)
machine = null
host.reset_view(null)
host.machine = null
host.verbs -= /mob/living/carbon/proc/release_control
host.verbs -= /mob/living/carbon/proc/punish_host
host.verbs -= /mob/living/carbon/proc/spawn_larvae
if(host_brain.ckey)
src.ckey = host.ckey
host.ckey = host_brain.ckey
host_brain.ckey = null
host_brain.name = "host brain"
host_brain.real_name = "host brain"
var/mob/living/H = host
host = null
for(var/atom/A in H.contents)
if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder))
return
H.status_flags &= ~PASSEMOTES
host = null
return
/mob/living/simple_animal/borer/verb/infest()
set category = "Alien"
@@ -382,7 +456,7 @@ mob/living/simple_animal/borer/proc/detatch()
M << "Something slimy begins probing at the opening of your ear canal..."
src << "You slither up [M] and begin probing at their ear canal..."
if(!do_after(src,50))
if(!do_after(src,30))
src << "As [M] moves away, you are dislodged and fall to the ground."
return
@@ -409,8 +483,6 @@ mob/living/simple_animal/borer/proc/detatch()
var/datum/organ/external/head = H.get_organ("head")
head.implants += src
host_brain.name = M.name
host_brain.real_name = M.real_name
host.status_flags |= PASSEMOTES
return
@@ -477,7 +549,7 @@ mob/living/simple_animal/borer/proc/detatch()
src << text("\blue You have stopped hiding.")
//Procs for grabbing players.
mob/living/simple_animal/borer/proc/request_player()
/mob/living/simple_animal/borer/proc/request_player()
for(var/mob/dead/observer/O in player_list)
if(jobban_isbanned(O, "Syndicate"))
continue
@@ -485,7 +557,7 @@ mob/living/simple_animal/borer/proc/request_player()
if(O.client.prefs.be_special & BE_ALIEN)
question(O.client)
mob/living/simple_animal/borer/proc/question(var/client/C)
/mob/living/simple_animal/borer/proc/question(var/client/C)
spawn(0)
if(!C) return
var/response = alert(C, "A cortical borer needs a player. Are you interested?", "Cortical borer request", "Yes", "No", "Never for this round")
@@ -496,7 +568,7 @@ mob/living/simple_animal/borer/proc/question(var/client/C)
else if (response == "Never for this round")
C.prefs.be_special ^= BE_ALIEN
mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate)
/mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate)
if(!candidate)
return
@@ -504,4 +576,5 @@ mob/living/simple_animal/borer/proc/transfer_personality(var/client/candidate)
src.mind = candidate.mob.mind
src.ckey = candidate.ckey
if(src.mind)
src.mind.assigned_role = "Cortical Borer"
src.mind.assigned_role = "Cortical Borer"
src.mind.special_role = "Cortical Borer"
@@ -21,6 +21,7 @@
min_oxy = 16 //Require atleast 16kPA oxygen
minbodytemp = 223 //Below -50 Degrees Celcius
maxbodytemp = 323 //Above 50 Degrees Celcius
holder_type = /obj/item/weapon/holder/cat
/mob/living/simple_animal/cat/Life()
//MICE!
@@ -60,6 +61,18 @@
stop_automated_movement = 1
walk_to(src,movement_target,0,3)
/mob/living/simple_animal/cat/MouseDrop(atom/over_object)
var/mob/living/carbon/H = over_object
if(!istype(H)) return ..()
if(H.a_intent == "help")
get_scooped(H)
return
else
return ..()
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/cat/Runtime
name = "Runtime"
@@ -126,7 +126,7 @@
src << "<span class='warning'>You are too small to pull anything.</span>"
return
/mob/living/simple_animal/mouse/HasEntered(AM as mob|obj)
/mob/living/simple_animal/mouse/Crossed(AM as mob|obj)
if( ishuman(AM) )
if(!stat)
var/mob/M = AM
@@ -318,7 +318,7 @@
var/list/items = list()
for(var/obj/item/I in view(1,src))
if(I.loc != src && I.w_class <= 2)
if(I.loc != src && I.w_class <= 2 && I.Adjacent(src) )
items.Add(I)
var/obj/selection = input("Select an item.", "Pickup") in items
@@ -195,6 +195,10 @@
/mob/living/simple_animal/hostile/proc/DestroySurroundings()
if(prob(break_stuff_probability))
for(var/dir in cardinal) // North, South, East, West
for(var/obj/structure/window/obstacle in get_step(src, dir))
if(obstacle.dir == reverse_dir[dir]) // So that windows get smashed in the right order
obstacle.attack_animal(src)
return
var/obj/structure/obstacle = locate(/obj/structure, get_step(src, dir))
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
obstacle.attack_animal(src)
@@ -87,12 +87,9 @@
if(health > maxHealth)
health = maxHealth
if(stunned)
AdjustStunned(-1)
if(weakened)
AdjustWeakened(-1)
if(paralysis)
AdjustParalysis(-1)
handle_stunned()
handle_weakened()
handle_paralysed()
//Movement
if(!client && !stop_automated_movement && wander && !anchored)
@@ -142,47 +139,41 @@
var/atmos_suitable = 1
var/atom/A = src.loc
if(isturf(A))
if(istype(A,/turf))
var/turf/T = A
var/areatemp = T.temperature
if( abs(areatemp - bodytemperature) > 40 )
var/diff = areatemp - bodytemperature
diff = diff / 5
//world << "changed from [bodytemperature] by [diff] to [bodytemperature + diff]"
bodytemperature += diff
if(istype(T,/turf/simulated))
var/turf/simulated/ST = T
if(ST.air)
var/tox = ST.air.toxins
var/oxy = ST.air.oxygen
var/n2 = ST.air.nitrogen
var/co2 = ST.air.carbon_dioxide
var/datum/gas_mixture/Environment = T.return_air()
if(min_oxy)
if(oxy < min_oxy)
atmos_suitable = 0
if(max_oxy)
if(oxy > max_oxy)
atmos_suitable = 0
if(min_tox)
if(tox < min_tox)
atmos_suitable = 0
if(max_tox)
if(tox > max_tox)
atmos_suitable = 0
if(min_n2)
if(n2 < min_n2)
atmos_suitable = 0
if(max_n2)
if(n2 > max_n2)
atmos_suitable = 0
if(min_co2)
if(co2 < min_co2)
atmos_suitable = 0
if(max_co2)
if(co2 > max_co2)
atmos_suitable = 0
if(Environment)
if( abs(Environment.temperature - bodytemperature) > 40 )
bodytemperature += ((Environment.temperature - bodytemperature) / 5)
if(min_oxy)
if(Environment.gas["oxygen"] < min_oxy)
atmos_suitable = 0
if(max_oxy)
if(Environment.gas["oxygen"] > max_oxy)
atmos_suitable = 0
if(min_tox)
if(Environment.gas["toxins"] < min_tox)
atmos_suitable = 0
if(max_tox)
if(Environment.gas["toxins"] > max_tox)
atmos_suitable = 0
if(min_n2)
if(Environment.gas["nitrogen"] < min_n2)
atmos_suitable = 0
if(max_n2)
if(Environment.gas["nitrogen"] > max_n2)
atmos_suitable = 0
if(min_co2)
if(Environment.gas["carbon_dioxide"] < min_co2)
atmos_suitable = 0
if(max_co2)
if(Environment.gas["carbon_dioxide"] > max_co2)
atmos_suitable = 0
//Atmos effect
if(bodytemperature < minbodytemp)
@@ -235,7 +226,9 @@
adjustBruteLoss(damage)
/mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj)
if(!Proj) return
if(!Proj || Proj.nodamage)
return
adjustBruteLoss(Proj.damage)
return 0
@@ -341,7 +334,7 @@
var/damage = rand(1, 3)
if(istype(src, /mob/living/carbon/slime/adult))
if(M.is_adult)
damage = rand(20, 40)
else
damage = rand(5, 35)
+102 -31
View File
@@ -16,7 +16,7 @@
/mob/proc/generate_name()
return name
/mob/proc/Cell()
/*/mob/proc/Cell()
set category = "Admin"
set hidden = 1
@@ -34,7 +34,7 @@
usr << "\blue [trace_gas.type]: [trace_gas.moles] \n"
usr.show_message(t, 1)
*/
/mob/proc/show_message(msg, type, alt, alt_type)//Message, type of message (1 or 2), alternative message, alt message type (1 or 2)
if(!client) return
@@ -607,6 +607,20 @@ var/list/slot_equipment_priority = list( \
/mob/proc/is_active()
return (0 >= usr.stat)
/mob/proc/is_dead()
return stat == DEAD
/mob/proc/is_mechanical()
if(mind && (mind.assigned_role == "Cyborg" || mind.assigned_role == "AI"))
return 1
return istype(src, /mob/living/silicon) || get_species() == "Machine"
/mob/proc/is_ready()
return client && !!mind
/mob/proc/get_gender()
return gender
/mob/proc/see(message)
if(!is_active())
return 0
@@ -716,7 +730,7 @@ note dizziness decrements automatically in the mob's Life() proc.
stat(null,"Delta Countdown-[delta_level.timeleft()]")
if(listed_turf && client)
if(get_dist(listed_turf,src) > 1)
if(!TurfAdjacent(listed_turf))
listed_turf = null
else
statpanel(listed_turf.name, null, listed_turf)
@@ -750,24 +764,37 @@ note dizziness decrements automatically in the mob's Life() proc.
//Updates canmove, lying and icons. Could perhaps do with a rename but I can't think of anything to describe it.
/mob/proc/update_canmove()
if(buckled)
/* if(istype(buckled, /obj/vehicle))
var/obj/vehicle/V = buckled
if(stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH))
lying = 1
canmove = 0
pixel_y = V.mob_offset_y - 5
else
lying = 0
canmove = 1
pixel_y = V.mob_offset_y*/
if(buckled && (!buckled.movable))
anchored = 1
canmove = 0
if( istype(buckled,/obj/structure/stool/bed/chair) )
if(istype(buckled,/obj/structure/stool/bed/chair) )
lying = 0
else
lying = 1
else if (buckled && (buckled.movable))
anchored = 0
canmove = 1
lying = 0
else if( stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH))
lying = 1
canmove = 0
else if( stunned )
// lying = 0
canmove = 0
else if(captured)
anchored = 1
canmove = 0
lying = 0
else
else if (!buckled)
lying = !can_stand
canmove = has_limbs
@@ -790,36 +817,34 @@ note dizziness decrements automatically in the mob's Life() proc.
return canmove
/mob/verb/eastface()
set hidden = 1
/mob/proc/facedir(var/ndir)
if(!canface()) return 0
dir = EAST
dir = ndir
if(buckled && buckled.movable)
buckled.dir = ndir
buckled.handle_rotation()
client.move_delay += movement_delay()
return 1
/mob/verb/eastface()
set hidden = 1
return facedir(EAST)
/mob/verb/westface()
set hidden = 1
if(!canface()) return 0
dir = WEST
client.move_delay += movement_delay()
return 1
return facedir(WEST)
/mob/verb/northface()
set hidden = 1
if(!canface()) return 0
dir = NORTH
client.move_delay += movement_delay()
return 1
return facedir(NORTH)
/mob/verb/southface()
set hidden = 1
if(!canface()) return 0
dir = SOUTH
client.move_delay += movement_delay()
return 1
return facedir(SOUTH)
/mob/proc/IsAdvancedToolUser()//This might need a rename but it should replace the can this mob use things check
@@ -937,7 +962,7 @@ mob/proc/yank_out_object()
if(S == U)
self = 1 // Removing object from yourself.
valid_objects = get_visible_implants(1)
valid_objects = get_visible_implants(0)
if(!valid_objects.len)
if(self)
src << "You have nothing stuck in your body that is large enough to remove."
@@ -948,9 +973,9 @@ mob/proc/yank_out_object()
var/obj/item/weapon/selection = input("What do you want to yank out?", "Embedded objects") in valid_objects
if(self)
src << "<span class='warning'>You attempt to get a good grip on the [selection] in your body.</span>"
src << "<span class='warning'>You attempt to get a good grip on [selection] in your body.</span>"
else
U << "<span class='warning'>You attempt to get a good grip on the [selection] in [S]'s body.</span>"
U << "<span class='warning'>You attempt to get a good grip on [selection] in [S]'s body.</span>"
if(!do_after(U, 80))
return
@@ -965,8 +990,7 @@ mob/proc/yank_out_object()
if(valid_objects.len == 1) //Yanking out last object - removing verb.
src.verbs -= /mob/proc/yank_out_object
if(istype(src,/mob/living/carbon/human))
if(ishuman(src))
var/mob/living/carbon/human/H = src
var/datum/organ/external/affected
@@ -976,14 +1000,18 @@ mob/proc/yank_out_object()
affected = organ
affected.implants -= selection
H.shock_stage+=10
H.bloody_hands(S)
H.shock_stage+=20
affected.take_damage((selection.w_class * 3), 0, 0, 1, "Embedded object extraction")
if(prob(10)) //I'M SO ANEMIC I COULD JUST -DIE-.
var/datum/wound/internal_bleeding/I = new (15)
if(prob(selection.w_class * 5)) //I'M SO ANEMIC I COULD JUST -DIE-.
var/datum/wound/internal_bleeding/I = new (min(selection.w_class * 5, 15))
affected.wounds += I
H.custom_pain("Something tears wetly in your [affected] as [selection] is pulled free!", 1)
if (ishuman(U))
var/mob/living/carbon/human/human_user = U
human_user.bloody_hands(H)
selection.loc = get_turf(src)
for(var/obj/item/weapon/O in pinned)
@@ -992,3 +1020,46 @@ mob/proc/yank_out_object()
if(!pinned.len)
anchored = 0
return 1
/mob/living/proc/handle_statuses()
handle_stunned()
handle_weakened()
handle_stuttering()
handle_silent()
handle_drugged()
handle_slurring()
/mob/living/proc/handle_stunned()
if(stunned)
AdjustStunned(-1)
return stunned
/mob/living/proc/handle_weakened()
if(weakened)
weakened = max(weakened-1,0) //before you get mad Rockdtben: I done this so update_canmove isn't called multiple times
return weakened
/mob/living/proc/handle_stuttering()
if(stuttering)
stuttering = max(stuttering-1, 0)
return stuttering
/mob/living/proc/handle_silent()
if(silent)
silent = max(silent-1, 0)
return silent
/mob/living/proc/handle_drugged()
if(druggy)
druggy = max(druggy-1, 0)
return druggy
/mob/living/proc/handle_slurring()
if(slurring)
slurring = max(slurring-1, 0)
return slurring
/mob/living/proc/handle_paralysed() // Currently only used by simple_animal.dm, treated as a special case in other mobs
if(paralysis)
AdjustParalysis(-1)
return paralysis
+77 -68
View File
@@ -35,11 +35,6 @@
return 1
return 0
/proc/isslimeadult(A)
if(istype(A, /mob/living/carbon/slime/adult))
return 1
return 0
/proc/isrobot(A)
if(istype(A, /mob/living/silicon/robot))
return 1
@@ -124,8 +119,44 @@ proc/hasorgans(A)
return ishuman(A)
/proc/hsl2rgb(h, s, l)
return
return //TODO: Implement
/*
Miss Chance
*/
//TODO: Integrate defence zones and targeting body parts with the actual organ system, move these into organ definitions.
//The base miss chance for the different defence zones
var/list/global/base_miss_chance = list(
"head" = 40,
"chest" = 10,
"groin" = 20,
"l_leg" = 20,
"r_leg" = 20,
"l_arm" = 20,
"r_arm" = 20,
"l_hand" = 50,
"r_hand" = 50,
"l_foot" = 50,
"r_foot" = 50,
)
//Used to weight organs when an organ is hit randomly (i.e. not a directed, aimed attack).
//Also used to weight the protection value that armour provides for covering that body part when calculating protection from full-body effects.
var/list/global/organ_rel_size = list(
"head" = 25,
"chest" = 70,
"groin" = 30,
"l_leg" = 25,
"r_leg" = 25,
"l_arm" = 25,
"r_arm" = 25,
"l_hand" = 10,
"r_hand" = 10,
"l_foot" = 10,
"r_foot" = 10,
)
/proc/check_zone(zone)
if(!zone) return "chest"
@@ -134,35 +165,34 @@ proc/hasorgans(A)
zone = "head"
if("mouth")
zone = "head"
/* if("l_hand")
zone = "l_arm"
if("r_hand")
zone = "r_arm"
if("l_foot")
zone = "l_leg"
if("r_foot")
zone = "r_leg"
if("groin")
zone = "chest"
*/
return zone
// Returns zone with a certain probability. If the probability fails, or no zone is specified, then a random body part is chosen.
// Do not use this if someone is intentionally trying to hit a specific body part.
// Use get_zone_with_miss_chance() for that.
/proc/ran_zone(zone, probability)
zone = check_zone(zone)
if(!probability) probability = 90
if(probability == 100) return zone
if (zone)
zone = check_zone(zone)
if (prob(probability))
return zone
if(zone == "chest")
if(prob(probability)) return "chest"
var/t = rand(1, 9)
switch(t)
if(1 to 3) return "head"
if(4 to 6) return "l_arm"
if(7 to 9) return "r_arm"
if(prob(probability * 0.75)) return zone
return "chest"
var/ran_zone = zone
while (ran_zone == zone)
ran_zone = pick (
organ_rel_size["head"]; "head",
organ_rel_size["chest"]; "chest",
organ_rel_size["groin"]; "groin",
organ_rel_size["l_arm"]; "l_arm",
organ_rel_size["r_arm"]; "r_arm",
organ_rel_size["l_leg"]; "l_leg",
organ_rel_size["r_leg"]; "r_leg",
organ_rel_size["l_hand"]; "l_hand",
organ_rel_size["r_hand"]; "r_hand",
organ_rel_size["l_foot"]; "l_foot",
organ_rel_size["r_foot"]; "r_foot",
)
return ran_zone
// Emulates targetting a specific body part, and miss chances
// May return null if missed
@@ -173,42 +203,13 @@ proc/hasorgans(A)
// you can only miss if your target is standing and not restrained
if(!target.buckled && !target.lying)
var/miss_chance = 10
switch(zone)
if("head")
miss_chance = 40
if("l_leg")
miss_chance = 20
if("r_leg")
miss_chance = 20
if("l_arm")
miss_chance = 20
if("r_arm")
miss_chance = 20
if("l_hand")
miss_chance = 50
if("r_hand")
miss_chance = 50
if("l_foot")
miss_chance = 50
if("r_foot")
miss_chance = 50
if (zone in base_miss_chance)
miss_chance = base_miss_chance[zone]
miss_chance = max(miss_chance + miss_chance_mod, 0)
if(prob(miss_chance))
if(prob(70))
return null
else
var/t = rand(1, 10)
switch(t)
if(1) return "head"
if(2) return "l_arm"
if(3) return "r_arm"
if(4) return "chest"
if(5) return "l_foot"
if(6) return "r_foot"
if(7) return "l_hand"
if(8) return "r_hand"
if(9) return "l_leg"
if(10) return "r_leg"
return pick(base_miss_chance)
return zone
@@ -329,17 +330,25 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
/proc/shake_camera(mob/M, duration, strength=1)
if(!M || !M.client || M.shakecamera)
if(!M || !M.client || M.shakecamera)
return
M.shakecamera = 1
spawn(1)
var/oldeye=M.client.eye
var/atom/oldeye=M.client.eye
var/aiEyeFlag = 0
if(istype(oldeye, /mob/aiEye))
aiEyeFlag = 1
var/x
M.shakecamera = 1
for(x=0; x<duration, x++)
M.client.eye = locate(dd_range(1,M.loc.x+rand(-strength,strength),world.maxx),dd_range(1,M.loc.y+rand(-strength,strength),world.maxy),M.loc.z)
if(aiEyeFlag)
M.client.eye = locate(dd_range(1,oldeye.loc.x+rand(-strength,strength),world.maxx),dd_range(1,oldeye.loc.y+rand(-strength,strength),world.maxy),oldeye.loc.z)
else
M.client.eye = locate(dd_range(1,M.loc.x+rand(-strength,strength),world.maxx),dd_range(1,M.loc.y+rand(-strength,strength),world.maxy),M.loc.z)
sleep(1)
M.shakecamera = 0
M.client.eye=oldeye
M.shakecamera = 0
/proc/findname(msg)
+12 -8
View File
@@ -177,7 +177,9 @@
if(mob.stat==2) return
if(isAI(mob)) return AIMove(n,direct,mob)
// handle possible AI movement
if(isAI(mob))
return AIMove(n,direct,mob)
if(mob.monkeyizing) return//This is sota the goto stop mobs from moving var
@@ -197,17 +199,11 @@
if(s.zoom)
s.zoom()
if(Process_Grab()) return
// if(mob.buckled) //if we're buckled to something, tell it we moved.
// return mob.buckled.relaymove(mob, direct)
// if(!mob.canmove) return
if(!mob.canmove)
if (mob.buckled && (istype(mob.buckled, /obj/structure/stool/bed/chair/wheelchair))) // Exception for wheelchairs
else return
return
//if(istype(mob.loc, /turf/space) || (mob.flags & NOGRAV))
// if(!mob.Process_Spacemove(0)) return 0
@@ -218,6 +214,7 @@
if((istype(mob.loc, /turf/space)) || (mob.lastarea.has_gravity == 0))
if(!mob.Process_Spacemove(0)) return 0
if(isobj(mob.loc) || ismob(mob.loc))//Inside an object, tell it we moved
var/atom/O = mob.loc
return O.relaymove(mob, direct)
@@ -253,6 +250,13 @@
var/tickcomp = ((1/(world.tick_lag))*1.3)
move_delay = move_delay + tickcomp
// if(istype(mob.buckled, /obj/vehicle))
// return mob.buckled.relaymove(mob,direct)
if(istype(mob.machine, /obj/machinery))
if(mob.machine.relaymove(mob,direct))
return
if(mob.pulledby || mob.buckled) // Wheelchair driving!
if(istype(mob.loc, /turf/space))
return // No wheelchair driving in space
+56 -11
View File
@@ -95,7 +95,10 @@
return 1
if(href_list["ready"])
ready = !ready
if(!ticker || ticker.current_state <= GAME_STATE_PREGAME) // Make sure we don't ready up after the round has started
ready = !ready
else
ready = 0
if(href_list["refresh"])
src << browse(null, "window=playersetup") //closes the player setup window
@@ -134,6 +137,7 @@
return 1
if(href_list["late_join"])
if(!ticker || ticker.current_state != GAME_STATE_PLAYING)
usr << "\red The round is either not ready, or has already finished..."
return
@@ -143,6 +147,11 @@
src << alert("You are currently not whitelisted to play [client.prefs.species].")
return 0
var/datum/species/S = all_species[client.prefs.species]
if(!(S.flags & IS_WHITELISTED))
src << alert("Your current species,[client.prefs.species], is not available for play on the station.")
return 0
LateChoices()
if(href_list["manifest"])
@@ -159,7 +168,12 @@
src << alert("You are currently not whitelisted to play [client.prefs.species].")
return 0
AttemptLateSpawn(href_list["SelectedJob"])
var/datum/species/S = all_species[client.prefs.species]
if(!(S.flags & IS_WHITELISTED))
src << alert("Your current species,[client.prefs.species], is not available for play on the station.")
return 0
AttemptLateSpawn(href_list["SelectedJob"],client.prefs.spawnpoint)
return
if(href_list["privacy_poll"])
@@ -290,6 +304,7 @@
var/mob/living/carbon/human/character = create_character() //creates the human and transfers vars and mind
job_master.EquipRank(character, rank, 1) //equips the human
UpdateFactionList(character)
EquipCustomItems(character)
character.loc = pick(latejoin)
character.lastarea = get_area(loc)
@@ -329,12 +344,13 @@
dat += "Round Duration: [round(hours)]h [round(mins)]m<br>"
if(emergency_shuttle) //In case Nanotrasen decides reposess CentComm's shuttles.
if(emergency_shuttle.direction == 2) //Shuttle is going to centcomm, not recalled
if(emergency_shuttle.going_to_centcom()) //Shuttle is going to centcomm, not recalled
dat += "<font color='red'><b>The station has been evacuated.</b></font><br>"
if(emergency_shuttle.direction == 1 && emergency_shuttle.timeleft() < 300 && emergency_shuttle.alert == 0) // Emergency shuttle is past the point of no recall
dat += "<font color='red'>The station is currently undergoing evacuation procedures.</font><br>"
if(emergency_shuttle.direction == 1 && emergency_shuttle.alert == 1) // Crew transfer initiated
dat += "<font color='red'>The station is currently undergoing crew transfer procedures.</font><br>"
if(emergency_shuttle.online())
if (emergency_shuttle.evac) // Emergency shuttle is past the point of no recall
dat += "<font color='red'>The station is currently undergoing evacuation procedures.</font><br>"
else // Crew transfer initiated
dat += "<font color='red'>The station is currently undergoing crew transfer procedures.</font><br>"
dat += "Choose from the following open positions:<br>"
for(var/datum/job/job in job_master.occupations)
@@ -359,7 +375,8 @@
if(client.prefs.species)
chosen_species = all_species[client.prefs.species]
if(chosen_species)
if(is_alien_whitelisted(src, client.prefs.species) || !config.usealienwhitelist || !(chosen_species.flags & IS_WHITELISTED) || (client.holder.rights & R_ADMIN) )// Have to recheck admin due to no usr at roundstart. Latejoins are fine though.
// Have to recheck admin due to no usr at roundstart. Latejoins are fine though.
if(is_species_whitelisted(chosen_species) || has_admin_rights())
new_character = new(loc, client.prefs.species)
if(!new_character)
@@ -371,7 +388,7 @@
if(client.prefs.language)
chosen_language = all_languages["[client.prefs.language]"]
if(chosen_language)
if(is_alien_whitelisted(src, client.prefs.language) || !config.usealienwhitelist || !(chosen_language.flags & WHITELISTED))
if(is_alien_whitelisted(src, client.prefs.language) || !config.usealienwhitelist || !(chosen_language.flags & WHITELISTED) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs)))
new_character.add_language("[client.prefs.language]")
if(ticker.random_players)
@@ -403,13 +420,16 @@
// And uncomment this, too.
//new_character.dna.UpdateSE()
// Do the initial caching of the player's body icons.
new_character.regenerate_icons()
new_character.key = key //Manually transfer the key to log them in
return new_character
proc/ViewManifest()
var/dat = "<html><body>"
dat += "<h4>Crew Manifest</h4>"
dat += "<h4>Show Crew Manifest</h4>"
dat += data_core.get_manifest(OOC = 1)
src << browse(dat, "window=manifest;size=370x420;can_close=1")
@@ -417,11 +437,36 @@
Move()
return 0
proc/close_spawn_windows()
src << browse(null, "window=latechoices") //closes late choices window
src << browse(null, "window=playersetup") //closes the player setup window
proc/has_admin_rights()
return client.holder.rights & R_ADMIN
proc/is_species_whitelisted(datum/species/S)
if(!S) return 1
return is_alien_whitelisted(src, S.name) || !config.usealienwhitelist || !(S.flags & IS_WHITELISTED)
/mob/new_player/get_species()
var/datum/species/chosen_species
if(client.prefs.species)
chosen_species = all_species[client.prefs.species]
if(!chosen_species)
return "Human"
if(is_species_whitelisted(chosen_species) || has_admin_rights())
return chosen_species.name
return "Human"
/mob/new_player/get_gender()
if(!client || !client.prefs) ..()
return client.prefs.gender
/mob/new_player/is_ready()
return ready && ..()
/mob/new_player/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null)
return
+2 -2
View File
@@ -62,7 +62,7 @@ datum/skill/management
datum/skill/knowledge/law
ID = "law"
name = "NanoTrasen Law"
desc = "Your knowledge of NanoTrasen law and procedures. This includes Space Law, as well as general station rulings and procedures. A low level in this skill is typical for security officers, a high level in this skill is typical for captains."
desc = "Your knowledge of NanoTrasen law and procedures. This includes Corporate Regulations, as well as general station rulings and procedures. A low level in this skill is typical for security officers, a high level in this skill is typical for captains."
field = "Security"
secondary = 1
@@ -232,4 +232,4 @@ mob/living/carbon/human/verb/show_skills()
set category = "IC"
set name = "Show Own Skills"
show_skill_window(src, src)
show_skill_window(src, src)
+46 -58
View File
@@ -1,9 +1,6 @@
/mob/proc/say()
return
/mob/proc/sign()
return
/mob/verb/whisper()
set name = "Whisper"
set category = "IC"
@@ -65,7 +62,7 @@
M << rendered
continue
if(M.client && M.client.holder /*&& !is_mentor(M.client) */&& (M.client.prefs.toggles & CHAT_DEAD) ) // Show the message to admins/mods with deadchat toggled on
if(M.client && M.client.holder && (M.client.prefs.toggles & CHAT_DEAD) ) // Show the message to admins/mods with deadchat toggled on
M << rendered //Admins can hear deadchat, if they choose to, no matter if they're blind/deaf or not.
@@ -73,63 +70,53 @@
/mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null)
if(!other)
if (src.stat == 2) //Dead
return 1
//Universal speak makes everything understandable, for obvious reasons.
else if(other.universal_speak || src.universal_speak || src.universal_understand)
else if(src.universal_speak || src.universal_understand)
return 1
else if (src.stat == 2)
return 1
else if (speaking) //Language check.
var/understood
for(var/datum/language/L in src.languages)
if(speaking.name == L.name)
understood = 1
break
if(understood || universal_speak)
//Languages are handled after.
if (!speaking)
if(!other)
return 1
if(other.universal_speak)
return 1
if(isAI(src) && ispAI(other))
return 1
if (istype(other, src.type) || istype(src, other.type))
return 1
if(src.alien_talk_understand && other.alien_talk_understand)
return 1
return 0
//Language check.
for(var/datum/language/L in src.languages)
if(speaking.name == L.name)
return 1
else
return 0
else if(other.universal_speak || src.universal_speak || src.universal_understand)
return 1
else if(isAI(src) && ispAI(other))
return 1
else if (istype(other, src.type) || istype(src, other.type))
return 1
return 0
/mob/proc/say_quote(var/text,var/datum/language/speaking)
/*
***Deprecated***
let this be handled at the hear_say or hear_radio proc
This is left in for robot speaking when humans gain binary channel access until I get around to rewriting
robot_talk() proc.
There is no language handling build into it however there is at the /mob level so we accept the call
for it but just ignore it.
*/
if(!text)
return "says, \"...\""; //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code
//tcomms code is still runtiming somewhere here
var/ending = copytext(text, length(text))
/mob/proc/say_quote(var/message, var/datum/language/speaking = null)
var/verb = "says"
var/ending = copytext(message, length(message))
if(ending=="!")
verb=pick("exclaims","shouts","yells")
else if(ending=="?")
verb="asks"
var/speech_verb = "says"
var/speech_style = "body"
return verb
if (speaking)
speech_verb = speaking.speech_verb
speech_style = speaking.colour
else if(speak_emote && speak_emote.len)
speech_verb = pick(speak_emote)
else if (src.stuttering)
speech_verb = "stammers"
else if (src.slurring)
speech_verb = "slurrs"
else if (ending == "?")
speech_verb = "asks"
else if (ending == "!")
speech_verb = "exclaims"
else if(isliving(src))
var/mob/living/L = src
if (L.getBrainLoss() >= 60)
speech_verb = "gibbers"
return "<span class='say_quote'>[speech_verb],</span> \"<span class='[speech_style]'>[text]</span>\""
/mob/proc/emote(var/act, var/type, var/message)
if(act == "me")
@@ -151,11 +138,12 @@
return "2"
return "0"
//parses the message mode code (e.g. :h, ;) from text, such as that supplied to say.
//parses the message mode code (e.g. :h, :w) from text, such as that supplied to say.
//returns the message mode string or null for no message mode.
/mob/proc/parse_message_mode(var/message)
//standard mode is the mode returned for the special ';' radio code.
/mob/proc/parse_message_mode(var/message, var/standard_mode="headset")
if(length(message) >= 1 && copytext(message,1,2) == ";")
return "headset"
return standard_mode
if(length(message) >= 2)
var/channel_prefix = copytext(message, 1 ,3)
@@ -164,12 +152,12 @@
return null
//parses the language code (e.g. :j) from text, such as that supplied to say.
//returns the language object only if the code corresponds to a language that src knows, otherwise null.
//returns the language object only if the code corresponds to a language that src can speak, otherwise null.
/mob/proc/parse_language(var/message)
if(length(message) >= 2)
var/language_prefix = lowertext(copytext(message, 1 ,3))
for(var/datum/language/L in src.languages)
if(language_prefix == ":[L.key]")
return L
return null
var/datum/language/L = language_keys[language_prefix]
if (can_speak(L))
return L
return null
+7 -12
View File
@@ -120,14 +120,7 @@
O.show_laws()
O << "<b>These laws may be changed by other players, or by you being the traitor.</b>"
O.verbs += /mob/living/silicon/ai/proc/ai_call_shuttle
O.verbs += /mob/living/silicon/ai/proc/show_laws_verb
O.verbs += /mob/living/silicon/ai/proc/ai_camera_track
O.verbs += /mob/living/silicon/ai/proc/ai_alerts
O.verbs += /mob/living/silicon/ai/proc/ai_camera_list
O.verbs += /mob/living/silicon/ai/proc/ai_statuschange
O.verbs += /mob/living/silicon/ai/proc/ai_roster
O.add_ai_verbs()
O.job = "AI"
O.rename_self("ai",1)
@@ -179,7 +172,10 @@
else
O.mmi = new /obj/item/device/mmi(O)
if(O.mmi) O.mmi.transfer_identity(src) //Does not transfer key/client.
if(O.mmi)
O.mmi.transfer_identity(src)
callHook("borgify", list(O))
O.Namepick()
@@ -243,11 +239,10 @@
babies += M
new_slime = pick(babies)
else
new_slime = new /mob/living/carbon/slime(loc)
if(adult)
new_slime = new /mob/living/carbon/slime/adult(loc)
new_slime.is_adult = 1
else
new_slime = new /mob/living/carbon/slime(loc)
new_slime.a_intent = "hurt"
new_slime.key = key
new_slime << "<B>You are now a slime. Skreee!</B>"