Merge pull request #5753 from Citadel-Station-13/upstream-merge-35440
[MIRROR] Adds minor roundstart traits! (ala CDDA, etc.)
This commit is contained in:
@@ -32,6 +32,12 @@
|
||||
font_color = "red"
|
||||
prayer_type = "CULTIST PRAYER"
|
||||
deity = "Nar-Sie"
|
||||
else if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
if(L.has_trait(TRAIT_SPIRITUAL))
|
||||
cross.icon_state = "holylight"
|
||||
font_color = "blue"
|
||||
prayer_type = "SPIRITUAL PRAYER"
|
||||
|
||||
msg = "<span class='adminnotice'>[icon2html(cross, GLOB.admins)]<b><font color=[font_color]>[prayer_type][deity ? " (to [deity])" : ""]: </font>[ADMIN_FULLMONTY(src)] [ADMIN_SC(src)]:</b> [msg]</span>"
|
||||
|
||||
|
||||
@@ -149,6 +149,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
//Mob preview
|
||||
var/icon/preview_icon = null
|
||||
|
||||
//Trait list
|
||||
var/list/positive_traits = list()
|
||||
var/list/negative_traits = list()
|
||||
var/list/neutral_traits = list()
|
||||
var/list/all_traits = list()
|
||||
var/list/character_traits = list()
|
||||
|
||||
//Jobs, uses bitflags
|
||||
var/job_civilian_high = 0
|
||||
var/job_civilian_med = 0
|
||||
@@ -252,6 +259,10 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
dat += "<center><h2>Occupation Choices</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=job;task=menu'>Set Occupation Preferences</a><br></center>"
|
||||
if(CONFIG_GET(flag/roundstart_traits))
|
||||
dat += "<center><h2>Trait Setup</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=trait;task=menu'>Configure Traits</a><br></center>"
|
||||
dat += "<center><b>Current traits:</b> [all_traits.len ? all_traits.Join(", ") : "None"]</center>"
|
||||
dat += "<h2>Identity</h2>"
|
||||
dat += "<table width='100%'><tr><td width='75%' valign='top'>"
|
||||
if(jobban_isbanned(user, "appearance"))
|
||||
@@ -868,6 +879,65 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
return job_engsec_low
|
||||
return 0
|
||||
|
||||
/datum/preferences/proc/SetTraits(mob/user)
|
||||
if(!SStraits)
|
||||
to_chat(user, "<span class='danger'>The trait subsystem is still initializing! Try again in a minute.</span>")
|
||||
return
|
||||
|
||||
var/list/dat = list()
|
||||
if(!SStraits.traits.len)
|
||||
dat += "The trait subsystem hasn't finished initializing, please hold..."
|
||||
dat += "<center><a href='?_src_=prefs;preference=trait;task=close'>Done</a></center><br>"
|
||||
|
||||
else
|
||||
dat += "<center><b>Choose trait setup</b></center><br>"
|
||||
dat += "<div align='center'>Left-click to add or remove traits. You need one negative trait for every positive trait.<br>\
|
||||
Traits are applied at roundstart and cannot normally be removed.</div>"
|
||||
dat += "<center><a href='?_src_=prefs;preference=trait;task=close'>Done</a></center>"
|
||||
dat += "<hr>"
|
||||
dat += "<center><b>Current traits:</b> [all_traits.len ? all_traits.Join(", ") : "None"]</center>"
|
||||
/*dat += "<center><font color='#AAFFAA'>[positive_traits.len] / [MAX_POSITIVE_TRAITS]</font> \
|
||||
| <font color='#AAAAFF'>[neutral_traits.len] / [MAX_NEUTRAL_TRAITS]</font> \
|
||||
| <font color='#FFAAAA'>[negative_traits.len] / [MAX_NEGATIVE_TRAITS]</font></center><br>"*/
|
||||
dat += "<center>[all_traits.len] / [MAX_TRAITS] max traits<br>\
|
||||
<b>Trait balance remaining:</b> [GetTraitBalance()]</center><br>"
|
||||
for(var/V in SStraits.traits)
|
||||
var/datum/trait/T = SStraits.traits[V]
|
||||
var/trait_name = initial(T.name)
|
||||
var/has_trait
|
||||
var/trait_cost = initial(T.value) * -1
|
||||
for(var/_V in all_traits)
|
||||
if(_V == trait_name)
|
||||
has_trait = TRUE
|
||||
if(has_trait)
|
||||
trait_cost *= -1 //invert it back, since we'd be regaining this amount
|
||||
if(trait_cost > 0)
|
||||
trait_cost = "+[trait_cost]"
|
||||
var/font_color = "#AAAAFF"
|
||||
if(initial(T.value) != 0)
|
||||
font_color = initial(T.value) > 0 ? "#AAFFAA" : "#FFAAAA"
|
||||
if(has_trait)
|
||||
dat += "<b><font color='[font_color]'>[trait_name]</font></b> - [initial(T.desc)] \
|
||||
<a href='?_src_=prefs;preference=trait;task=update;trait=[trait_name]'>[has_trait ? "Lose" : "Take"] ([trait_cost] pts.)</a><br>"
|
||||
else
|
||||
dat += "<font color='[font_color]'>[trait_name]</font> - [initial(T.desc)] \
|
||||
<a href='?_src_=prefs;preference=trait;task=update;trait=[trait_name]'>[has_trait ? "Lose" : "Take"] ([trait_cost] pts.)</a><br>"
|
||||
dat += "<br><center><a href='?_src_=prefs;preference=trait;task=reset'>Reset Traits</a></center>"
|
||||
|
||||
user << browse(null, "window=preferences")
|
||||
var/datum/browser/popup = new(user, "mob_occupation", "<div align='center'>Trait Preferences</div>", 900, 600) //no reason not to reuse the occupation window, as it's cleaner that way
|
||||
popup.set_window_options("can_close=0")
|
||||
popup.set_content(dat.Join())
|
||||
popup.open(0)
|
||||
return
|
||||
|
||||
/datum/preferences/proc/GetTraitBalance()
|
||||
var/bal = 0
|
||||
for(var/V in all_traits)
|
||||
var/datum/trait/T = SStraits.traits[V]
|
||||
bal -= initial(T.value)
|
||||
return bal
|
||||
|
||||
/datum/preferences/proc/process_link(mob/user, list/href_list)
|
||||
if(href_list["jobbancheck"])
|
||||
var/job = sanitizeSQL(href_list["jobbancheck"])
|
||||
@@ -915,6 +985,64 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
SetChoices(user)
|
||||
return 1
|
||||
|
||||
else if(href_list["preference"] == "trait")
|
||||
if(SSticker.HasRoundStarted() && !isnewplayer(user))
|
||||
to_chat(user, "<span class='danger'>The round has already started. Please wait until next round to set up your traits!</span>")
|
||||
return
|
||||
switch(href_list["task"])
|
||||
if("close")
|
||||
user << browse(null, "window=mob_occupation")
|
||||
ShowChoices(user)
|
||||
if("update")
|
||||
var/trait = href_list["trait"]
|
||||
var/value = SStraits.trait_points[trait]
|
||||
if(value == 0)
|
||||
if(trait in neutral_traits)
|
||||
neutral_traits -= trait
|
||||
all_traits -= trait
|
||||
else
|
||||
if(all_traits.len >= MAX_TRAITS)
|
||||
to_chat(user, "<span class='warning'>You can't have more than [MAX_TRAITS] traits!</span>")
|
||||
return
|
||||
neutral_traits += trait
|
||||
all_traits += trait
|
||||
else
|
||||
var/balance = GetTraitBalance()
|
||||
if(trait in positive_traits)
|
||||
positive_traits -= trait
|
||||
all_traits -= trait
|
||||
else if(trait in negative_traits)
|
||||
if(balance + value < 0)
|
||||
to_chat(user, "<span class='warning'>Refunding this would cause you to go below your balance!</span>")
|
||||
return
|
||||
negative_traits -= trait
|
||||
all_traits -= trait
|
||||
else if(value > 0)
|
||||
if(all_traits.len >= MAX_TRAITS)
|
||||
to_chat(user, "<span class='warning'>You can't have more than [MAX_TRAITS] traits!</span>")
|
||||
return
|
||||
if(balance - value < 0)
|
||||
to_chat(user, "<span class='warning'>You don't have enough balance to gain this trait!</span>")
|
||||
return
|
||||
positive_traits += trait
|
||||
all_traits += trait
|
||||
else
|
||||
if(all_traits.len >= MAX_TRAITS)
|
||||
to_chat(user, "<span class='warning'>You can't have more than [MAX_TRAITS] traits!</span>")
|
||||
return
|
||||
negative_traits += trait
|
||||
all_traits += trait
|
||||
SetTraits(user)
|
||||
if("reset")
|
||||
all_traits = list()
|
||||
positive_traits = list()
|
||||
negative_traits = list()
|
||||
neutral_traits = list()
|
||||
SetTraits(user)
|
||||
else
|
||||
SetTraits(user)
|
||||
return TRUE
|
||||
|
||||
switch(href_list["task"])
|
||||
if("random")
|
||||
switch(href_list["preference"])
|
||||
@@ -1781,3 +1909,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
character.update_hair()
|
||||
character.update_body_parts()
|
||||
character.update_genitals()
|
||||
|
||||
if(CONFIG_GET(flag/roundstart_traits))
|
||||
SStraits.AssignTraits(character, parent)
|
||||
|
||||
@@ -369,6 +369,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["job_engsec_med"] >> job_engsec_med
|
||||
S["job_engsec_low"] >> job_engsec_low
|
||||
|
||||
//Traits
|
||||
S["all_traits"] >> all_traits
|
||||
S["positive_traits"] >> positive_traits
|
||||
S["negative_traits"] >> negative_traits
|
||||
S["neutral_traits"] >> neutral_traits
|
||||
|
||||
//Citadel code
|
||||
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
|
||||
S["feature_exhibitionist"] >> features["exhibitionist"]
|
||||
@@ -477,6 +483,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med))
|
||||
job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low))
|
||||
|
||||
all_traits = SANITIZE_LIST(all_traits)
|
||||
positive_traits = SANITIZE_LIST(positive_traits)
|
||||
negative_traits = SANITIZE_LIST(negative_traits)
|
||||
neutral_traits = SANITIZE_LIST(neutral_traits)
|
||||
|
||||
cit_character_pref_load(S)
|
||||
|
||||
return 1
|
||||
@@ -542,6 +553,12 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["job_engsec_med"] , job_engsec_med)
|
||||
WRITE_FILE(S["job_engsec_low"] , job_engsec_low)
|
||||
|
||||
//Traits
|
||||
WRITE_FILE(S["all_traits"] , all_traits)
|
||||
WRITE_FILE(S["positive_traits"] , positive_traits)
|
||||
WRITE_FILE(S["negative_traits"] , negative_traits)
|
||||
WRITE_FILE(S["neutral_traits"] , neutral_traits)
|
||||
|
||||
cit_character_pref_save(S)
|
||||
|
||||
return 1
|
||||
|
||||
@@ -1197,3 +1197,28 @@ GLOBAL_LIST_INIT(hallucinations_major, list(
|
||||
H.preparePixelProjectile(target, start)
|
||||
H.fire()
|
||||
qdel(src)
|
||||
|
||||
//Reality Dissociation Syndrome hallucinations only trigger in special cases and have no cost
|
||||
/datum/hallucination/rds
|
||||
cost = 0
|
||||
|
||||
/datum/hallucination/rds/fourth_wall/New(mob/living/carbon/C, forced = TRUE)
|
||||
..()
|
||||
to_chat(C, "<span class='userdanger extremelybig'>[pick("Leave the server" , "Close the game window")] [pick("immediately", "right now")].</span>")
|
||||
|
||||
/datum/hallucination/rds/supermatter/New(mob/living/carbon/C, forced = TRUE)
|
||||
..()
|
||||
SEND_SOUND(C, 'sound/magic/charge.ogg')
|
||||
to_chat(C, "<span class='boldannounce'>You feel reality distort for a moment...</span>")
|
||||
|
||||
/datum/hallucination/rds/narsie/New(mob/living/carbon/C, forced = TRUE)
|
||||
C.playsound_local(C, 'sound/creatures/narsie_rises.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
to_chat(C, "<span class='narsie'>NAR-SIE HAS RISEN</span>")
|
||||
|
||||
/datum/hallucination/rds/ark/New(mob/living/carbon/C, forced = TRUE)
|
||||
set waitfor = FALSE
|
||||
..()
|
||||
C.playsound_local(C, 'sound/machines/clockcult/ark_deathrattle.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
C.playsound_local(C, 'sound/effects/clockcult_gateway_disrupted.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
sleep(27)
|
||||
C.playsound_local(C, 'sound/effects/explosion_distant.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
else
|
||||
gulp_size = max(round(reagents.total_volume / 5), 5)
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/attack(mob/M, mob/user, def_zone)
|
||||
/obj/item/reagent_containers/food/drinks/attack(mob/living/M, mob/user, def_zone)
|
||||
|
||||
if(!reagents || !reagents.total_volume)
|
||||
to_chat(user, "<span class='warning'>[src] is empty!</span>")
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
if(M == user)
|
||||
to_chat(M, "<span class='notice'>You swallow a gulp of [src].</span>")
|
||||
if(M.has_trait(TRAIT_VORACIOUS))
|
||||
M.changeNext_move(CLICK_CD_MELEE * 0.5) //chug! chug! chug!
|
||||
|
||||
else
|
||||
M.visible_message("<span class='danger'>[user] attempts to feed the contents of [src] to [M].</span>", "<span class='userdanger'>[user] attempts to feed the contents of [src] to [M].</span>")
|
||||
|
||||
@@ -19,13 +19,18 @@
|
||||
if(last_check_time + 50 < world.time)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(foodtype & H.dna.species.toxic_food)
|
||||
to_chat(H,"<span class='warning'>What the hell was that thing?!</span>")
|
||||
H.adjust_disgust(25 + 30 * fraction)
|
||||
else if(foodtype & H.dna.species.disliked_food)
|
||||
to_chat(H,"<span class='notice'>That didn't taste very good...</span>")
|
||||
H.adjust_disgust(11 + 15 * fraction)
|
||||
else if(foodtype & H.dna.species.liked_food)
|
||||
to_chat(H,"<span class='notice'>I love this taste!</span>")
|
||||
H.adjust_disgust(-5 + -2.5 * fraction)
|
||||
if(!H.has_trait(TRAIT_AGEUSIA))
|
||||
if(foodtype & H.dna.species.toxic_food)
|
||||
to_chat(H,"<span class='warning'>What the hell was that thing?!</span>")
|
||||
H.adjust_disgust(25 + 30 * fraction)
|
||||
else if(foodtype & H.dna.species.disliked_food)
|
||||
to_chat(H,"<span class='notice'>That didn't taste very good...</span>")
|
||||
H.adjust_disgust(11 + 15 * fraction)
|
||||
else if(foodtype & H.dna.species.liked_food)
|
||||
to_chat(H,"<span class='notice'>I love this taste!</span>")
|
||||
H.adjust_disgust(-5 + -2.5 * fraction)
|
||||
else
|
||||
if(foodtype & H.dna.species.toxic_food)
|
||||
to_chat(H, "<span class='warning'>You don't feel so good...</span>")
|
||||
H.adjust_disgust(25 + 30 * fraction)
|
||||
last_check_time = world.time
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
return
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/attack(mob/M, mob/user, def_zone)
|
||||
/obj/item/reagent_containers/food/snacks/attack(mob/living/M, mob/user, def_zone)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
if(!eatverb)
|
||||
@@ -82,6 +82,8 @@
|
||||
else if(fullness > (600 * (1 + M.overeatduration / 2000))) // The more you eat - the more you can eat
|
||||
to_chat(M, "<span class='warning'>You cannot force any more of \the [src] to go down your throat!</span>")
|
||||
return 0
|
||||
if(M.has_trait(TRAIT_VORACIOUS))
|
||||
M.changeNext_move(CLICK_CD_MELEE * 0.5) //nom nom nom
|
||||
else
|
||||
if(!isbrain(M)) //If you're feeding it to someone else.
|
||||
if(fullness <= (600 * (1 + M.overeatduration / 1000)))
|
||||
|
||||
@@ -379,6 +379,10 @@
|
||||
if(SSshuttle.emergency.timeLeft(1) > initial(SSshuttle.emergencyCallTime)*0.5)
|
||||
SSticker.mode.make_antag_chance(humanc)
|
||||
|
||||
for(var/V in character.roundstart_traits)
|
||||
var/datum/trait/T = V
|
||||
T.on_spawn() //so latejoins still get their correct traits
|
||||
|
||||
log_manifest(character.mind.key,character.mind,character,latejoin = TRUE)
|
||||
|
||||
/mob/dead/new_player/proc/AddEmploymentContract(mob/living/carbon/human/employee)
|
||||
|
||||
@@ -6,8 +6,14 @@
|
||||
var/t_him = p_them()
|
||||
var/t_has = p_have()
|
||||
var/t_is = p_are()
|
||||
var/obscure_name
|
||||
|
||||
var/msg = "<span class='info'>*---------*\nThis is <EM>[name]</EM>!\n"
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(L.has_trait(TRAIT_PROSOPAGNOSIA))
|
||||
obscure_name = TRUE
|
||||
|
||||
var/msg = "<span class='info'>*---------*\nThis is <EM>[!obscure_name ? name : "Unknown"]</EM>!\n"
|
||||
|
||||
var/list/obscured = check_obscured_slots()
|
||||
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
|
||||
@@ -269,6 +275,7 @@
|
||||
if(digitalcamo)
|
||||
msg += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly inhuman manner.\n"
|
||||
|
||||
var/traitstring = get_trait_string()
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/organ/cyberimp/eyes/hud/CIH = H.getorgan(/obj/item/organ/cyberimp/eyes/hud)
|
||||
@@ -296,6 +303,10 @@
|
||||
R = find_record("name", perpname, GLOB.data_core.medical)
|
||||
if(R)
|
||||
msg += "<a href='?src=[REF(src)];hud=m;evaluation=1'>\[Medical evaluation\]</a><br>"
|
||||
if(traitstring)
|
||||
msg += "<span class='info'>Detected physiological traits:<br></span>"
|
||||
msg += "<span class='info'>[traitstring]</span><br>"
|
||||
|
||||
|
||||
|
||||
if(istype(H.glasses, /obj/item/clothing/glasses/hud/security) || istype(CIH, /obj/item/organ/cyberimp/eyes/hud/security))
|
||||
@@ -312,6 +323,10 @@
|
||||
msg += "<a href='?src=[REF(src)];hud=s;add_crime=1'>\[Add crime\]</a> "
|
||||
msg += "<a href='?src=[REF(src)];hud=s;view_comment=1'>\[View comment log\]</a> "
|
||||
msg += "<a href='?src=[REF(src)];hud=s;add_comment=1'>\[Add comment\]</a>\n"
|
||||
|
||||
else if(isobserver(user) && traitstring)
|
||||
msg += "<span class='info'><b>Traits:</b> [traitstring]</span><br>"
|
||||
|
||||
if(print_flavor_text() && get_visible_name() != "Unknown")//Are we sure we know who this is? Don't show flavor text unless we can recognize them. Prevents certain metagaming with impersonation.
|
||||
msg += "[print_flavor_text()]\n"
|
||||
|
||||
|
||||
@@ -655,24 +655,33 @@
|
||||
if(prob(30))
|
||||
burndamage += rand(30,40)
|
||||
|
||||
if(brutedamage > 0)
|
||||
status = "bruised"
|
||||
if(brutedamage > 20)
|
||||
status = "battered"
|
||||
if(brutedamage > 40)
|
||||
status = "mangled"
|
||||
if(brutedamage > 0 && burndamage > 0)
|
||||
status += " and "
|
||||
if(burndamage > 40)
|
||||
status += "peeling away"
|
||||
if(has_trait(TRAIT_SELF_AWARE))
|
||||
status = "[brutedamage] brute damage and [burndamage] burn damage"
|
||||
if(!brutedamage && !burndamage)
|
||||
status = "no damage"
|
||||
|
||||
else if(burndamage > 10)
|
||||
status += "blistered"
|
||||
else if(burndamage > 0)
|
||||
status += "numb"
|
||||
if(status == "")
|
||||
status = "OK"
|
||||
to_chat(src, "\t <span class='[status == "OK" ? "notice" : "warning"]'>Your [LB.name] is [status].</span>")
|
||||
else
|
||||
if(brutedamage > 0)
|
||||
status = "bruised"
|
||||
if(brutedamage > 20)
|
||||
status = "battered"
|
||||
if(brutedamage > 40)
|
||||
status = "mangled"
|
||||
if(brutedamage > 0 && burndamage > 0)
|
||||
status += " and "
|
||||
if(burndamage > 40)
|
||||
status += "peeling away"
|
||||
|
||||
else if(burndamage > 10)
|
||||
status += "blistered"
|
||||
else if(burndamage > 0)
|
||||
status += "numb"
|
||||
if(status == "")
|
||||
status = "OK"
|
||||
var/no_damage
|
||||
if(status == "OK" || status == "no damage")
|
||||
no_damage = TRUE
|
||||
to_chat(src, "\t <span class='[no_damage ? "notice" : "warning"]'>Your [LB.name] [has_trait(TRAIT_SELF_AWARE) ? "has" : "is"] [status].</span>")
|
||||
|
||||
for(var/obj/item/I in LB.embedded_objects)
|
||||
to_chat(src, "\t <a href='?src=[REF(src)];embedded_object=[REF(I)];embedded_limb=[REF(LB)]' class='warning'>There is \a [I] embedded in your [LB.name]!</a>")
|
||||
@@ -687,6 +696,23 @@
|
||||
to_chat(src, "<span class='info'>You're completely exhausted.</span>")
|
||||
else
|
||||
to_chat(src, "<span class='info'>You feel fatigued.</span>")
|
||||
if(has_trait(TRAIT_SELF_AWARE))
|
||||
if(toxloss)
|
||||
if(toxloss > 10)
|
||||
to_chat(src, "<span class='danger'>You feel sick.</span>")
|
||||
else if(toxloss > 20)
|
||||
to_chat(src, "<span class='danger'>You feel nauseous.</span>")
|
||||
else if(toxloss > 40)
|
||||
to_chat(src, "<span class='danger'>You feel very unwell!</span>")
|
||||
if(oxyloss)
|
||||
if(oxyloss > 10)
|
||||
to_chat(src, "<span class='danger'>You feel lightheaded.</span>")
|
||||
else if(oxyloss > 20)
|
||||
to_chat(src, "<span class='danger'>Your thinking is clouded and distant.</span>")
|
||||
else if(oxyloss > 30)
|
||||
to_chat(src, "<span class='danger'>You're choking!</span>")
|
||||
if(roundstart_traits.len)
|
||||
to_chat(src, "<span class='notice'>You have these traits: [get_trait_string()].</span>")
|
||||
else
|
||||
if(wear_suit)
|
||||
wear_suit.add_fingerprint(M)
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
|
||||
/mob/living/carbon/human/Unconscious(amount, updating = 1, ignore_canunconscious = 0)
|
||||
amount = dna.species.spec_stun(src,amount)
|
||||
if(has_trait(TRAIT_HEAVY_SLEEPER))
|
||||
amount *= rand(1.25, 1.3)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/Sleeping(amount, updating = 1, ignore_sleepimmune = 0)
|
||||
if(has_trait(TRAIT_HEAVY_SLEEPER))
|
||||
amount *= rand(1.25, 1.3)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/cure_husk(list/sources)
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
var/list/status_traits = list()
|
||||
|
||||
var/list/roundstart_traits = list()
|
||||
|
||||
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
|
||||
|
||||
var/now_pushing = null //used by living/Collide() and living/PushAM() to prevent potential infinite loop.
|
||||
|
||||
@@ -146,10 +146,23 @@
|
||||
else
|
||||
status_traits[trait] |= list(source)
|
||||
|
||||
/mob/living/proc/remove_trait(trait, list/sources)
|
||||
/mob/living/proc/add_trait_datum(trait) //separate proc due to the way these ones are handled
|
||||
if(has_trait(trait))
|
||||
return
|
||||
if(!SStraits || !SStraits.traits[trait])
|
||||
return
|
||||
var/datum/trait/T = SStraits.traits[trait]
|
||||
new T (src)
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/remove_trait(trait, list/sources, force)
|
||||
|
||||
if(!status_traits[trait])
|
||||
return
|
||||
|
||||
if(locate(ROUNDSTART_TRAIT) in status_traits[trait] && !force) //mob traits applied through roundstart cannot normally be removed
|
||||
return
|
||||
|
||||
if(!sources) // No defined source cures the trait entirely.
|
||||
status_traits -= trait
|
||||
return
|
||||
@@ -167,6 +180,12 @@
|
||||
if(!LAZYLEN(status_traits[trait]))
|
||||
status_traits -= trait
|
||||
|
||||
/mob/living/proc/remove_trait_datum(trait)
|
||||
var/datum/trait/T = roundstart_traits[trait]
|
||||
if(T)
|
||||
qdel(T)
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/has_trait(trait, list/sources)
|
||||
if(!status_traits[trait])
|
||||
return FALSE
|
||||
@@ -181,6 +200,9 @@
|
||||
if(LAZYLEN(status_traits[trait]))
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/has_trait_datum(trait)
|
||||
return roundstart_traits[trait]
|
||||
|
||||
/mob/living/proc/remove_all_traits()
|
||||
status_traits = list()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
/mob/living/carbon/get_taste_sensitivity()
|
||||
var/obj/item/organ/tongue/tongue = getorganslot(ORGAN_SLOT_TONGUE)
|
||||
if(istype(tongue))
|
||||
if(istype(tongue) && !has_trait(TRAIT_AGEUSIA))
|
||||
. = tongue.taste_sensitivity
|
||||
else
|
||||
. = 101 // can't taste anything without a tongue
|
||||
|
||||
@@ -246,6 +246,8 @@
|
||||
var/rand_spr = rand()
|
||||
if(spread)
|
||||
randomized_gun_spread = rand(0,spread)
|
||||
if(user.has_trait(TRAIT_POOR_AIM)) //nice shootin' tex
|
||||
bonus_spread += 25
|
||||
var/randomized_bonus_spread = rand(0, bonus_spread)
|
||||
|
||||
if(burst_size > 1)
|
||||
|
||||
@@ -37,9 +37,12 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.drunkenness < volume * boozepwr * ALCOHOL_THRESHOLD_MODIFIER)
|
||||
H.drunkenness = max((H.drunkenness + (sqrt(volume) * boozepwr * ALCOHOL_RATE)), 0) //Volume, power, and server alcohol rate effect how quickly one gets drunk
|
||||
var/booze_power = boozepwr
|
||||
if(H.has_trait(TRAIT_ALCOHOL_TOLERANCE)) //we're an accomplished drinker
|
||||
booze_power *= 0.7
|
||||
H.drunkenness = max((H.drunkenness + (sqrt(volume) * booze_power * ALCOHOL_RATE)), 0) //Volume, power, and server alcohol rate effect how quickly one gets drunk
|
||||
var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER)
|
||||
H.applyLiverDamage((max(sqrt(volume) * boozepwr * L.alcohol_tolerance, 0))/4)
|
||||
H.applyLiverDamage((max(sqrt(volume) * booze_power * L.alcohol_tolerance, 0))/4)
|
||||
return ..() || .
|
||||
|
||||
/datum/reagent/consumable/ethanol/reaction_obj(obj/O, reac_volume)
|
||||
@@ -117,7 +120,8 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
M.dizziness = max(0,M.dizziness-5)
|
||||
M.drowsyness = max(0,M.drowsyness-3)
|
||||
M.AdjustSleeping(-40, FALSE)
|
||||
M.Jitter(5)
|
||||
if(!M.has_trait(TRAIT_ALCOHOL_TOLERANCE))
|
||||
M.Jitter(5)
|
||||
..()
|
||||
. = 1
|
||||
|
||||
@@ -150,7 +154,8 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
M.drowsyness = max(0,M.drowsyness-7)
|
||||
M.AdjustSleeping(-40)
|
||||
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
|
||||
M.Jitter(5)
|
||||
if(!M.has_trait(TRAIT_ALCOHOL_TOLERANCE))
|
||||
M.Jitter(5)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/vodka
|
||||
@@ -305,7 +310,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
shot_glass_icon_state = "shotglassgreen"
|
||||
|
||||
/datum/reagent/consumable/ethanol/absinthe/on_mob_life(mob/living/M)
|
||||
if(prob(10))
|
||||
if(prob(10) && !M.has_trait(TRAIT_ALCOHOL_TOLERANCE))
|
||||
M.hallucination += 4 //Reference to the urban myth
|
||||
..()
|
||||
|
||||
@@ -556,7 +561,10 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "Heavy, hot and strong. Just like the Iron fist of the LAW."
|
||||
|
||||
/datum/reagent/consumable/ethanol/beepsky_smash/on_mob_life(mob/living/M)
|
||||
M.Stun(40, 0)
|
||||
if(M.has_trait(TRAIT_ALCOHOL_TOLERANCE))
|
||||
M.Stun(30, 0) //this realistically does nothing to prevent chainstunning but will cause them to recover faster once it's out of their system
|
||||
else
|
||||
M.Stun(40, 0)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/consumable/ethanol/irish_cream
|
||||
@@ -585,7 +593,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
/datum/reagent/consumable/ethanol/manly_dorf/on_mob_add(mob/living/M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.dna.check_mutation(DWARFISM))
|
||||
if(H.dna.check_mutation(DWARFISM) || H.has_trait(TRAIT_ALCOHOL_TOLERANCE))
|
||||
to_chat(H, "<span class='notice'>Now THAT is MANLY!</span>")
|
||||
boozepwr = 5 //We've had worse in the mines
|
||||
dorf_mode = TRUE
|
||||
@@ -1148,8 +1156,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
|
||||
/datum/reagent/consumable/ethanol/atomicbomb/on_mob_life(mob/living/M)
|
||||
M.set_drugginess(50)
|
||||
M.confused = max(M.confused+2,0)
|
||||
M.Dizzy(10)
|
||||
if(!M.has_trait(TRAIT_ALCOHOL_TOLERANCE))
|
||||
M.confused = max(M.confused+2,0)
|
||||
M.Dizzy(10)
|
||||
if (!M.slurring)
|
||||
M.slurring = 1
|
||||
M.slurring += 3
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
/datum/reagent/toxin/mindbreaker
|
||||
name = "Mindbreaker Toxin"
|
||||
id = "mindbreaker"
|
||||
description = "A powerful hallucinogen. Not a thing to be messed with."
|
||||
description = "A powerful hallucinogen. Not a thing to be messed with. For some mental patients. it counteracts their symptoms and anchors them to reality."
|
||||
color = "#B31008" // rgb: 139, 166, 233
|
||||
toxpwr = 0
|
||||
taste_description = "sourness"
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
HMN.regenerate_icons()
|
||||
else
|
||||
eye_color = HMN.eye_color
|
||||
if(HMN.has_trait(TRAIT_NIGHT_VISION) && !lighting_alpha)
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_NV_TRAIT
|
||||
M.update_tint()
|
||||
owner.update_sight()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user