thank you github
This commit is contained in:
@@ -492,7 +492,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] assumed direct control of [M].</span>")
|
||||
log_admin("[key_name(usr)] assumed direct control of [M].")
|
||||
var/mob/adminmob = src.mob
|
||||
M.ckey = src.ckey
|
||||
adminmob.transfer_ckey(M, send_signal = FALSE)
|
||||
if( isobserver(adminmob) )
|
||||
qdel(adminmob)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Assume Direct Control") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
@@ -484,11 +484,9 @@
|
||||
|
||||
user.do_attack_animation(L)
|
||||
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
|
||||
playsound(H, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
return FALSE
|
||||
if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
|
||||
playsound(L, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
return FALSE
|
||||
|
||||
switch (mode)
|
||||
if(BATON_STUN)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
icon = 'icons/mob/blob.dmi'
|
||||
icon_state = "blob_shield"
|
||||
desc = "A solid wall of slightly twitching tendrils."
|
||||
var/damaged_desc = "A wall of twitching tendrils."
|
||||
max_integrity = 150
|
||||
brute_resist = 0.25
|
||||
explosion_block = 3
|
||||
@@ -21,10 +22,10 @@
|
||||
|
||||
/obj/structure/blob/shield/update_icon()
|
||||
..()
|
||||
if(obj_integrity <= 70)
|
||||
icon_state = "blob_shield_damaged"
|
||||
name = "weakened strong blob"
|
||||
desc = "A wall of twitching tendrils."
|
||||
if(obj_integrity < max_integrity * 0.5)
|
||||
icon_state = "[initial(icon_state)]_damaged"
|
||||
name = "weakened [initial(name)]"
|
||||
desc = "[damaged_desc]"
|
||||
atmosblock = FALSE
|
||||
if(!weakened)
|
||||
armor = armor.setRating("melee" = 15, "bullet" = 15, "laser" = 5, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
@@ -37,4 +38,27 @@
|
||||
if(weakened)
|
||||
armor = armor.setRating("melee" = 25, "bullet" = 25, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
weakened = FALSE
|
||||
air_update_turf(1)
|
||||
air_update_turf(1)
|
||||
|
||||
/obj/structure/blob/shield/reflective
|
||||
name = "reflective blob"
|
||||
desc = "A solid wall of slightly twitching tendrils with a reflective glow."
|
||||
damaged_desc = "A wall of twitching tendrils with a reflective glow."
|
||||
icon_state = "blob_glow"
|
||||
flags_1 = CHECK_RICOCHET_1
|
||||
point_return = 8
|
||||
max_integrity = 50
|
||||
brute_resist = 1
|
||||
explosion_block = 2
|
||||
|
||||
/obj/structure/blob/shield/reflective/handle_ricochet(obj/item/projectile/P)
|
||||
var/turf/p_turf = get_turf(P)
|
||||
var/face_direction = get_dir(src, p_turf)
|
||||
var/face_angle = dir2angle(face_direction)
|
||||
var/incidence_s = GET_ANGLE_OF_INCIDENCE(face_angle, (P.Angle + 180))
|
||||
if(abs(incidence_s) > 90 && abs(incidence_s) < 270)
|
||||
return FALSE
|
||||
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
|
||||
P.setAngle(new_angle_s)
|
||||
visible_message("<span class='warning'>[P] reflects off [src]!</span>")
|
||||
return TRUE
|
||||
@@ -113,12 +113,22 @@
|
||||
|
||||
/mob/camera/blob/verb/create_shield_power()
|
||||
set category = "Blob"
|
||||
set name = "Create Shield Blob (15)"
|
||||
set desc = "Create a shield blob, which will block fire and is hard to kill."
|
||||
set name = "Create/Upgrade Shield Blob (15)"
|
||||
set desc = "Create a shield blob, which will block fire and is hard to kill. Using this on an existing shield blob turns it into a reflective blob, capable of reflecting most projectiles but making it much weaker than usual to brute attacks."
|
||||
create_shield()
|
||||
|
||||
/mob/camera/blob/proc/create_shield(turf/T)
|
||||
createSpecial(15, /obj/structure/blob/shield, 0, 0, T)
|
||||
var/obj/structure/blob/shield/S = locate(/obj/structure/blob/shield) in T
|
||||
if(S)
|
||||
if(!can_buy(15))
|
||||
return
|
||||
if(S.obj_integrity < S.max_integrity * 0.5)
|
||||
to_chat(src, "<span class='warning'>This shield blob is too damaged to be modified properly!</span>")
|
||||
return
|
||||
to_chat(src, "<span class='warning'>You secrete a reflective ooze over the shield blob, allowing it to reflect projectiles at the cost of reduced intregrity.</span>")
|
||||
S.change_to(/obj/structure/blob/shield/reflective, src)
|
||||
else
|
||||
createSpecial(15, /obj/structure/blob/shield, 0, 0, T)
|
||||
|
||||
/mob/camera/blob/verb/create_resource()
|
||||
set category = "Blob"
|
||||
@@ -359,7 +369,7 @@
|
||||
to_chat(src, "<b>You can expand, which will attack people, damage objects, or place a Normal Blob if the tile is clear.</b>")
|
||||
to_chat(src, "<i>Normal Blobs</i> will expand your reach and can be upgraded into special blobs that perform certain functions.")
|
||||
to_chat(src, "<b>You can upgrade normal blobs into the following types of blob:</b>")
|
||||
to_chat(src, "<i>Shield Blobs</i> are strong and expensive blobs which take more damage. In additon, they are fireproof and can block air, use these to protect yourself from station fires.")
|
||||
to_chat(src, "<i>Shield Blobs</i> are strong and expensive blobs which take more damage. In additon, they are fireproof and can block air, use these to protect yourself from station fires. Upgrading them again will result in a reflective blob, capable of reflecting most projectiles at the cost of the strong blob's extra health.")
|
||||
to_chat(src, "<i>Resource Blobs</i> are blobs which produce more resources for you, build as many of these as possible to consume the station. This type of blob must be placed near node blobs or your core to work.")
|
||||
to_chat(src, "<i>Factory Blobs</i> are blobs that spawn blob spores which will attack nearby enemies. This type of blob must be placed near node blobs or your core to work.")
|
||||
to_chat(src, "<i>Blobbernauts</i> can be produced from factories for a cost, and are hard to kill, powerful, and moderately smart. The factory used to create one will become fragile and briefly unable to produce spores.")
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
BuyPower(new /datum/action/bloodsucker/masquerade)
|
||||
BuyPower(new /datum/action/bloodsucker/veil)
|
||||
// Traits
|
||||
for (var/T in defaultTraits)
|
||||
for(var/T in defaultTraits)
|
||||
ADD_TRAIT(owner.current, T, "bloodsucker")
|
||||
if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you
|
||||
had_toxlover = TRUE
|
||||
@@ -200,10 +200,10 @@
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/datum/species/S = H.dna.species
|
||||
// Make Changes
|
||||
S.brutemod *= 0.5 // <-------------------- Start small, but burn mod increases based on rank!
|
||||
S.coldmod = 0
|
||||
S.stunmod *= 0.25
|
||||
S.siemens_coeff *= 0.75 //base electrocution coefficient 1
|
||||
H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank!
|
||||
H.physiology.cold_mod = 0
|
||||
H.physiology.stun_mod *= 0.35
|
||||
H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1
|
||||
//S.heatmod += 0.5 // Heat shouldn't affect. Only Fire.
|
||||
//S.punchstunthreshold = 8 //damage at which punches from this race will stun 9
|
||||
S.punchdamagelow += 1 //lowest possible punch damage 0
|
||||
@@ -319,12 +319,10 @@ datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
if(ishuman(owner.current))
|
||||
var/mob/living/carbon/human/H = owner.current
|
||||
var/datum/species/S = H.dna.species
|
||||
S.burnmod *= 0.025 // Slightly more burn damage
|
||||
S.stunmod *= 0.95 // Slightly less stun time.
|
||||
S.punchdamagelow += 0.5
|
||||
S.punchdamagehigh += 0.5 // NOTE: This affects the hitting power of Brawn.
|
||||
// More Health
|
||||
owner.current.setMaxHealth(owner.current.maxHealth + 5)
|
||||
owner.current.setMaxHealth(owner.current.maxHealth + 10)
|
||||
// Vamp Stats
|
||||
regenRate += 0.05 // Points of brute healed (starts at 0.3)
|
||||
feedAmount += 2 // Increase how quickly I munch down vics (15)
|
||||
|
||||
@@ -275,7 +275,7 @@
|
||||
// All done!
|
||||
if(convert_progress <= 0)
|
||||
// FAIL: Can't be Vassal
|
||||
if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) && HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
|
||||
if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
|
||||
to_chat(user, "<span class='danger'>[target] doesn't respond to your persuasion. It doesn't appear they can be converted to follow you, they either have a mindshield or their external loyalties are too difficult for you to break.<i>\[ALT+click to release\]</span>")
|
||||
convert_progress ++ // Pop it back up some. Avoids wasting Blood on a lost cause.
|
||||
// SUCCESS: All done!
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
antagpanel_category = "ClownOp"
|
||||
nukeop_outfit = /datum/outfit/syndicate/clownop
|
||||
|
||||
/datum/antagonist/nukeop/clownop/on_gain()
|
||||
. = ..()
|
||||
ADD_TRAIT(owner, TRAIT_CLOWN_MENTALITY, NUKEOP_ANTAGONIST)
|
||||
|
||||
/datum/antagonist/nukeop/clownop/on_removal()
|
||||
REMOVE_TRAIT(owner, TRAIT_CLOWN_MENTALITY, NUKEOP_ANTAGONIST)
|
||||
return ..()
|
||||
|
||||
/datum/antagonist/nukeop/leader/clownop
|
||||
name = "Clown Operative Leader"
|
||||
roundend_category = "clown operatives"
|
||||
|
||||
@@ -154,11 +154,6 @@
|
||||
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
|
||||
var/target_temperature
|
||||
var/target_heat_capacity
|
||||
// first calculate heat from radiation. there's an implied "* 1 tick" here.
|
||||
// 0.05 magic multiplicand is, first, 0.1 deciseconds; second, half of the radiation's going right back into the gas.
|
||||
var/share_constant = STEFANBOLTZMANN*(share_volume**(2/3))*0.05
|
||||
// Minimizing temp to 4 billion is mostly to prevent -infinity temperatures.
|
||||
var/heat = share_constant*(min(air.temperature,4000000000)**4)
|
||||
|
||||
if(isopenturf(target))
|
||||
|
||||
@@ -170,8 +165,8 @@
|
||||
|
||||
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
|
||||
var/delta_temperature = air.temperature - target_temperature
|
||||
heat -= share_constant*(min(target_temperature,4000000000)**4)
|
||||
heat += thermal_conductivity*delta_temperature* \
|
||||
|
||||
var/heat = thermal_conductivity*delta_temperature* \
|
||||
(partial_heat_capacity*target_heat_capacity/(partial_heat_capacity+target_heat_capacity))
|
||||
|
||||
air.temperature -= heat/total_heat_capacity
|
||||
@@ -188,8 +183,7 @@
|
||||
var/sharer_temperature_delta = 0
|
||||
|
||||
if((sharer_heat_capacity>0) && (partial_heat_capacity>0))
|
||||
heat -= share_constant*(min(target_temperature,4000000000)**4)
|
||||
heat += thermal_conductivity*delta_temperature* \
|
||||
var/heat = thermal_conductivity*delta_temperature* \
|
||||
(partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity))
|
||||
|
||||
self_temperature_delta = -heat/total_heat_capacity
|
||||
@@ -205,12 +199,10 @@
|
||||
if((target.heat_capacity>0) && (partial_heat_capacity>0))
|
||||
var/delta_temperature = air.temperature - target.temperature
|
||||
|
||||
heat -= share_constant*(min(target.temperature,4000000000)**4)
|
||||
heat += thermal_conductivity*delta_temperature* \
|
||||
var/heat = thermal_conductivity*delta_temperature* \
|
||||
(partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
|
||||
|
||||
air.temperature -= heat/total_heat_capacity
|
||||
air.temperature = CLAMP(air.temperature,TCMB,INFINITY) // i have no idea why TCMB needs to be the min but i ain't changing it
|
||||
update = TRUE
|
||||
|
||||
/datum/pipeline/proc/return_air()
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
var/turf/T = loc
|
||||
if(istype(T))
|
||||
if(T.blocks_air)
|
||||
if(islava(T))
|
||||
environment_temperature = 5000
|
||||
else if(T.blocks_air)
|
||||
environment_temperature = T.temperature
|
||||
else
|
||||
var/turf/open/OT = T
|
||||
|
||||
@@ -13,17 +13,16 @@
|
||||
//////////////////// Paperwork and Writing Supplies //////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* I did it Kevin
|
||||
/datum/supply_pack/misc/abandonedcrate
|
||||
name = "Abandoned Crate"
|
||||
desc = "Someone keeps finding these locked crates out in the boonies. How about you take a crack at it, we've had our fill. WARNING: EXPLOSIVE"
|
||||
name = "Loot Box"
|
||||
desc = "Try your luck with these highly secure loot boxes! Solve the lock, win great prizes! WARNING: EXPLOSIVE FAILURE."
|
||||
contraband = TRUE
|
||||
cost = 12800
|
||||
cost = 15000
|
||||
contains = list(/obj/structure/closet/crate/secure/loot)
|
||||
crate_name = "abandoned crate"
|
||||
crate_type = /obj/structure/closet/crate/large
|
||||
dangerous = TRUE
|
||||
*/
|
||||
|
||||
/datum/supply_pack/misc/artsupply
|
||||
name = "Art Supplies"
|
||||
desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!"
|
||||
|
||||
@@ -79,4 +79,8 @@
|
||||
var/client_keysend_amount = 0
|
||||
var/next_keysend_reset = 0
|
||||
var/next_keysend_trip_reset = 0
|
||||
var/keysend_tripped = FALSE
|
||||
var/keysend_tripped = FALSE
|
||||
|
||||
// stops players from coming back through ghost/midround roles after suicide/cryo
|
||||
// for a duration set by CONFIG_GET(number/suicide_reenter_round_timer) and CONFIG_GET(number/roundstart_suicide_time_limit)
|
||||
var/reenter_round_timeout = 0
|
||||
|
||||
@@ -195,6 +195,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/auto_fit_viewport = TRUE
|
||||
|
||||
var/uplink_spawn_loc = UPLINK_PDA
|
||||
|
||||
var/sprint_spacebar = FALSE
|
||||
var/sprint_toggle = FALSE
|
||||
|
||||
var/list/exp = list()
|
||||
var/list/menuoptions
|
||||
@@ -245,6 +248,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=2' [current_tab == 2 ? "class='linkOn'" : ""]>Character Appearance</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=3' [current_tab == 3 ? "class='linkOn'" : ""]>Loadout</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=1' [current_tab == 1 ? "class='linkOn'" : ""]>Game Preferences</a>"
|
||||
dat += "<a href='?_src_=prefs;preference=tab;tab=4' [current_tab == 4 ? "class='linkOn'" : ""]>Content Preferences</a>"
|
||||
|
||||
if(!path)
|
||||
dat += "<div class='notice'>Please create an account to save your preferences</div>"
|
||||
@@ -721,13 +725,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
|
||||
dat += "<h2>Clothing & Equipment</h2>"
|
||||
dat += "<b>Underwear:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=underwear;task=input'>[underwear]</a>"
|
||||
if(UNDIE_COLORABLE(GLOB.underwear_list[underwear]))
|
||||
if(GLOB.underwear_list[underwear]?.has_color)
|
||||
dat += "<b>Underwear Color:</b> <span style='border:1px solid #161616; background-color: #[undie_color];'> </span> <a href='?_src_=prefs;preference=undie_color;task=input'>Change</a><BR>"
|
||||
dat += "<b>Undershirt:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=undershirt;task=input'>[undershirt]</a>"
|
||||
if(UNDIE_COLORABLE(GLOB.undershirt_list[undershirt]))
|
||||
if(GLOB.undershirt_list[undershirt]?.has_color)
|
||||
dat += "<b>Undershirt Color:</b> <span style='border:1px solid #161616; background-color: #[shirt_color];'> </span> <a href='?_src_=prefs;preference=shirt_color;task=input'>Change</a><BR>"
|
||||
dat += "<b>Socks:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=socks;task=input'>[socks]</a>"
|
||||
if(UNDIE_COLORABLE(GLOB.socks_list[socks]))
|
||||
if(GLOB.socks_list[socks]?.has_color)
|
||||
dat += "<b>Socks Color:</b> <span style='border:1px solid #161616; background-color: #[socks_color];'> </span> <a href='?_src_=prefs;preference=socks_color;task=input'>Change</a><BR>"
|
||||
dat += "<b>Backpack:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=bag;task=input'>[backbag]</a>"
|
||||
dat += "<b>Jumpsuit:</b><BR><a href ='?_src_=prefs;preference=suit;task=input'>[jumpsuit_style]</a><BR>"
|
||||
@@ -834,13 +838,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
dat +="<td width='300px' height='300px' valign='top'>"
|
||||
dat += "<h2>Citadel Preferences</h2>" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe.
|
||||
dat += "<b>Arousal:</b><a href='?_src_=prefs;preference=arousable'>[arousable == TRUE ? "Enabled" : "Disabled"]</a><BR>"
|
||||
dat += "<b>Voracious MediHound sleepers:</b> <a href='?_src_=prefs;preference=hound_sleeper'>[(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Sounds:</b> <a href='?_src_=prefs;preference=toggleeatingnoise'>[(cit_toggles & EATING_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Digestion Sounds:</b> <a href='?_src_=prefs;preference=toggledigestionnoise'>[(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Lewdchem:</b><a href='?_src_=prefs;preference=lewdchem'>[lewdchem == TRUE ? "Enabled" : "Disabled"]</a><BR>"
|
||||
dat += "<b>Widescreen:</b> <a href='?_src_=prefs;preference=widescreenpref'>[widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]</a><br>"
|
||||
dat += "<b>Auto stand:</b> <a href='?_src_=prefs;preference=autostand'>[autostand ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Auto OOC:</b> <a href='?_src_=prefs;preference=auto_ooc'>[auto_ooc ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Screen Shake:</b> <a href='?_src_=prefs;preference=screenshake'>[(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]</a><br>"
|
||||
if (user && user.client && !user.client.prefs.screenshake==0)
|
||||
dat += "<b>Damage Screen Shake:</b> <a href='?_src_=prefs;preference=damagescreenshake'>[(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]</a><br>"
|
||||
@@ -892,6 +892,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "</a><br>"
|
||||
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'>[ambientocclusion ? "Enabled" : "Disabled"]</a><br>"
|
||||
dat += "<b>Fit Viewport:</b> <a href='?_src_=prefs;preference=auto_fit_viewport'>[auto_fit_viewport ? "Auto" : "Manual"]</a><br>"
|
||||
dat += "<b>Sprint Key:</b> <a href='?_src_=prefs;preference=sprint_key'>[sprint_spacebar ? "Space" : "Shift"]</a><br>"
|
||||
dat += "<b>Toggle Sprint:</b> <a href='?_src_=prefs;preference=sprint_toggle'>[sprint_toggle ? "Enabled" : "Disabled"]</a><br>"
|
||||
|
||||
if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation))
|
||||
var/p_map = preferred_map
|
||||
@@ -991,6 +993,26 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "</font>"
|
||||
dat += "</td><td><font size=2><i>[gear.description]</i></font></td></tr>"
|
||||
dat += "</table>"
|
||||
if(4) // Content preferences
|
||||
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
|
||||
dat += "<h2>Fetish content prefs</h2>"
|
||||
dat += "<b>Arousal:</b><a href='?_src_=prefs;preference=arousable'>[arousable == TRUE ? "Enabled" : "Disabled"]</a><BR>"
|
||||
dat += "<b>Voracious MediHound sleepers:</b> <a href='?_src_=prefs;preference=hound_sleeper'>[(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Sounds:</b> <a href='?_src_=prefs;preference=toggleeatingnoise'>[(cit_toggles & EATING_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Digestion Sounds:</b> <a href='?_src_=prefs;preference=toggledigestionnoise'>[(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Forced Feminization:</b> <a href='?_src_=prefs;preference=feminization'>[(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Forced Masculinization:</b> <a href='?_src_=prefs;preference=masculinization'>[(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Lewd Hypno:</b> <a href='?_src_=prefs;preference=hypno'>[(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "</td>"
|
||||
dat +="<td width='300px' height='300px' valign='top'>"
|
||||
dat += "<h2>Other content prefs</h2>"
|
||||
dat += "<b>Breast Enlargement:</b> <a href='?_src_=prefs;preference=breast_enlargement'>[(cit_toggles & BREAST_ENLARGEMENT) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Penis Enlargement:</b> <a href='?_src_=prefs;preference=penis_enlargement'>[(cit_toggles & PENIS_ENLARGEMENT) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Hypno:</b> <a href='?_src_=prefs;preference=never_hypno'>[(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]</a><br>"
|
||||
dat += "<b>Aphrodisiacs:</b> <a href='?_src_=prefs;preference=aphro'>[(cit_toggles & NO_APHRO) ? "Disallowed" : "Allowed"]</a><br>"
|
||||
dat += "<b>Ass Slapping:</b> <a href='?_src_=prefs;preference=ass_slap'>[(cit_toggles & NO_ASS_SLAP) ? "Disallowed" : "Allowed"]</a><br>"
|
||||
dat += "<br>"
|
||||
|
||||
|
||||
dat += "<hr><center>"
|
||||
|
||||
@@ -2036,8 +2058,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
features["genitals_use_skintone"] = !features["genitals_use_skintone"]
|
||||
if("arousable")
|
||||
arousable = !arousable
|
||||
if("lewdchem")
|
||||
lewdchem = !lewdchem
|
||||
if("has_cock")
|
||||
features["has_cock"] = !features["has_cock"]
|
||||
if(features["has_cock"] == FALSE)
|
||||
@@ -2069,6 +2089,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
user.client.change_view(CONFIG_GET(string/default_view))
|
||||
if("autostand")
|
||||
autostand = !autostand
|
||||
if("auto_ooc")
|
||||
auto_ooc = !auto_ooc
|
||||
if ("screenshake")
|
||||
var/desiredshake = input(user, "Set the amount of screenshake you want. \n(0 = disabled, 100 = full, 200 = maximum.)", "Character Preference", screenshake) as null|num
|
||||
if (!isnull(desiredshake))
|
||||
@@ -2184,6 +2206,31 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
if("toggledigestionnoise")
|
||||
cit_toggles ^= DIGESTION_NOISES
|
||||
|
||||
if("breast_enlargement")
|
||||
cit_toggles ^= BREAST_ENLARGEMENT
|
||||
|
||||
if("penis_enlargement")
|
||||
cit_toggles ^= PENIS_ENLARGEMENT
|
||||
|
||||
if("feminization")
|
||||
cit_toggles ^= FORCED_FEM
|
||||
|
||||
if("masculinization")
|
||||
cit_toggles ^= FORCED_MASC
|
||||
|
||||
if("hypno")
|
||||
cit_toggles ^= HYPNO
|
||||
|
||||
if("never_hypno")
|
||||
cit_toggles ^= NEVER_HYPNO
|
||||
|
||||
if("aphro")
|
||||
cit_toggles ^= NO_APHRO
|
||||
|
||||
if("ass_slap")
|
||||
cit_toggles ^= NO_ASS_SLAP
|
||||
|
||||
//END CITADEL EDIT
|
||||
|
||||
if("ambientocclusion")
|
||||
@@ -2197,6 +2244,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(auto_fit_viewport && parent)
|
||||
parent.fit_viewport()
|
||||
|
||||
if("sprint_key")
|
||||
sprint_spacebar = !sprint_spacebar
|
||||
|
||||
if("sprint_toggle")
|
||||
sprint_toggle = !sprint_toggle
|
||||
|
||||
if("save")
|
||||
save_preferences()
|
||||
save_character()
|
||||
|
||||
@@ -167,6 +167,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["parallax"] >> parallax
|
||||
S["ambientocclusion"] >> ambientocclusion
|
||||
S["auto_fit_viewport"] >> auto_fit_viewport
|
||||
S["sprint_spacebar"] >> sprint_spacebar
|
||||
S["sprint_toggle"] >> sprint_toggle
|
||||
S["menuoptions"] >> menuoptions
|
||||
S["enable_tips"] >> enable_tips
|
||||
S["tip_delay"] >> tip_delay
|
||||
@@ -181,8 +183,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["widescreenpref"] >> widescreenpref
|
||||
S["autostand"] >> autostand
|
||||
S["cit_toggles"] >> cit_toggles
|
||||
S["lewdchem"] >> lewdchem
|
||||
S["preferred_chaos"] >> preferred_chaos
|
||||
S["auto_ooc"] >> auto_ooc
|
||||
|
||||
|
||||
//try to fix any outdated data if necessary
|
||||
@@ -204,6 +206,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
|
||||
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
|
||||
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
|
||||
sprint_spacebar = sanitize_integer(sprint_spacebar, 0, 1, initial(sprint_spacebar))
|
||||
sprint_toggle = sanitize_integer(sprint_toggle, 0, 1, initial(sprint_toggle))
|
||||
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
|
||||
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
|
||||
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
|
||||
@@ -219,7 +223,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
|
||||
autostand = sanitize_integer(autostand, 0, 1, initial(autostand))
|
||||
cit_toggles = sanitize_integer(cit_toggles, 0, 65535, initial(cit_toggles))
|
||||
|
||||
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
|
||||
|
||||
return 1
|
||||
|
||||
@@ -264,6 +268,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["parallax"], parallax)
|
||||
WRITE_FILE(S["ambientocclusion"], ambientocclusion)
|
||||
WRITE_FILE(S["auto_fit_viewport"], auto_fit_viewport)
|
||||
WRITE_FILE(S["sprint_spacebar"], sprint_spacebar)
|
||||
WRITE_FILE(S["sprint_toggle"], sprint_toggle)
|
||||
WRITE_FILE(S["menuoptions"], menuoptions)
|
||||
WRITE_FILE(S["enable_tips"], enable_tips)
|
||||
WRITE_FILE(S["tip_delay"], tip_delay)
|
||||
@@ -278,8 +284,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["widescreenpref"], widescreenpref)
|
||||
WRITE_FILE(S["autostand"], autostand)
|
||||
WRITE_FILE(S["cit_toggles"], cit_toggles)
|
||||
WRITE_FILE(S["lewdchem"], lewdchem)
|
||||
WRITE_FILE(S["preferred_chaos"], preferred_chaos)
|
||||
WRITE_FILE(S["auto_ooc"], auto_ooc)
|
||||
|
||||
return 1
|
||||
|
||||
@@ -517,6 +523,21 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
all_quirks = SANITIZE_LIST(all_quirks)
|
||||
|
||||
for(var/V in all_quirks) // quirk migration
|
||||
switch(V)
|
||||
if("Acute hepatic pharmacokinesis")
|
||||
DISABLE_BITFIELD(cit_toggles, PENIS_ENLARGEMENT)
|
||||
DISABLE_BITFIELD(cit_toggles, BREAST_ENLARGEMENT)
|
||||
ENABLE_BITFIELD(cit_toggles,FORCED_FEM)
|
||||
ENABLE_BITFIELD(cit_toggles,FORCED_MASC)
|
||||
all_quirks -= V
|
||||
if("Crocin Immunity")
|
||||
ENABLE_BITFIELD(cit_toggles,NO_APHRO)
|
||||
all_quirks -= V
|
||||
if("Buns of Steel")
|
||||
ENABLE_BITFIELD(cit_toggles,NO_ASS_SLAP)
|
||||
all_quirks -= V
|
||||
|
||||
cit_character_pref_load(S)
|
||||
|
||||
return 1
|
||||
|
||||
@@ -298,6 +298,33 @@ BLIND // can't see anything
|
||||
user.regenerate_icons()
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/neck/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
// Polychrome stuff:
|
||||
if(hasprimary | hassecondary | hastertiary)
|
||||
var/choice = input(user,"polychromic thread options", "Clothing Recolor") as null|anything in list("[hasprimary ? "Primary Color" : ""]", "[hassecondary ? "Secondary Color" : ""]", "[hastertiary ? "Tertiary Color" : ""]") //generates a list depending on the enabled overlays
|
||||
switch(choice) //Lets the list's options actually lead to something
|
||||
if("Primary Color")
|
||||
var/primary_color_input = input(usr,"","Choose Primary Color",primary_color) as color|null //color input menu, the "|null" adds a cancel button to it.
|
||||
if(primary_color_input) //Checks if the color selected is NULL, rejects it if it is NULL.
|
||||
primary_color = sanitize_hexcolor(primary_color_input, desired_format=6, include_crunch=1) //formats the selected color properly
|
||||
update_icon() //updates the item icon
|
||||
user.regenerate_icons() //updates the worn icon. Probably a bad idea, but it works.
|
||||
if("Secondary Color")
|
||||
var/secondary_color_input = input(usr,"","Choose Secondary Color",secondary_color) as color|null
|
||||
if(secondary_color_input)
|
||||
secondary_color = sanitize_hexcolor(secondary_color_input, desired_format=6, include_crunch=1)
|
||||
update_icon()
|
||||
user.regenerate_icons()
|
||||
if("Tertiary Color")
|
||||
var/tertiary_color_input = input(usr,"","Choose Tertiary Color",tertiary_color) as color|null
|
||||
if(tertiary_color_input)
|
||||
tertiary_color = sanitize_hexcolor(tertiary_color_input, desired_format=6, include_crunch=1)
|
||||
update_icon()
|
||||
user.regenerate_icons()
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/under/verb/jumpsuit_adjust()
|
||||
set name = "Adjust Jumpsuit Style"
|
||||
|
||||
@@ -54,6 +54,9 @@
|
||||
H.blur_eyes(5)
|
||||
eyes.applyOrganDamage(5)
|
||||
|
||||
/obj/item/clothing/glasses/proc/ranged_attack(mob/living/carbon/human/user,atom/A, params)
|
||||
return FALSE
|
||||
|
||||
/obj/item/clothing/glasses/meson
|
||||
name = "optical meson scanner"
|
||||
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting conditions."
|
||||
|
||||
15
code/modules/clothing/glasses/disablerglasses.dm
Normal file
15
code/modules/clothing/glasses/disablerglasses.dm
Normal file
@@ -0,0 +1,15 @@
|
||||
/obj/item/clothing/glasses/hud/security/sunglasses/disablers
|
||||
name = "true stunglasses"
|
||||
desc = "Made for only the best of shitsec. Wear 'em like you're gonna robust all of those fuckers."
|
||||
var/beamtype = /obj/item/projectile/beam/disabler //change for adminbus
|
||||
|
||||
/obj/item/clothing/glasses/hud/security/sunglasses/disablers/ranged_attack(mob/living/carbon/human/user,atom/A, params)
|
||||
user.changeNext_move(CLICK_CD_RANGE)
|
||||
var/obj/item/projectile/beam/disabler/LE = new beamtype( loc )
|
||||
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
|
||||
LE.firer = src
|
||||
LE.def_zone = user.get_organ_target()
|
||||
LE.preparePixelProjectile(A, src, params)
|
||||
LE.fire()
|
||||
return TRUE
|
||||
//shamelessly copied
|
||||
@@ -90,7 +90,7 @@
|
||||
|
||||
for(var/i in rad_places)
|
||||
var/turf/place = i
|
||||
if(get_dist(user, place) >= range*2) //Rads are easier to see than wires under the floor
|
||||
if(get_dist(user, place) >= range*8) //Rads are easier to see than wires under the floor
|
||||
continue
|
||||
var/strength = round(rad_places[i] / 1000, 0.1)
|
||||
var/image/pic = new(loc = place)
|
||||
@@ -139,7 +139,6 @@
|
||||
item_state = "trayson-t-ray"
|
||||
desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
|
||||
range = 2
|
||||
|
||||
modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE)
|
||||
|
||||
/obj/item/clothing/glasses/meson/engine/tray/prescription
|
||||
@@ -152,7 +151,6 @@
|
||||
icon_state = "trayson-shuttle"
|
||||
item_state = "trayson-shuttle"
|
||||
desc = "Used to see the boundaries of shuttle regions."
|
||||
|
||||
modes = list(MODE_NONE = MODE_SHUTTLE, MODE_SHUTTLE = MODE_NONE)
|
||||
|
||||
#undef MODE_NONE
|
||||
|
||||
@@ -89,12 +89,12 @@
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(user.mind && user.mind.assigned_role == "Clown")
|
||||
if(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY))
|
||||
SEND_SIGNAL(user, COMSIG_CLEAR_MOOD_EVENT, "noshoes")
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/dropped(mob/user)
|
||||
. = ..()
|
||||
if(user.mind && user.mind.assigned_role == "Clown")
|
||||
if(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "noshoes", /datum/mood_event/noshoes)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/jester
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(!(HAS_TRAIT(H, TRAIT_CLUMSY)) && !(H.mind && H.mind.assigned_role == "Clown"))
|
||||
if(!(HAS_TRAIT(H, TRAIT_CLUMSY)) && !(H.mind && HAS_TRAIT(H.mind, TRAIT_CLOWN_MENTALITY)))
|
||||
return
|
||||
if(slot == SLOT_SHOES)
|
||||
spells = new
|
||||
|
||||
@@ -590,8 +590,7 @@
|
||||
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, slot)
|
||||
if(!..() || !ishuman(M))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.mind.assigned_role == "Clown")
|
||||
if(M.mind && HAS_TRAIT(M.mind, TRAIT_CLOWN_MENTALITY))
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
@@ -467,6 +467,33 @@
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/sundresswhite
|
||||
name = "white sundress"
|
||||
desc = "Makes you want to frolic in a field of lillies."
|
||||
icon_state = "sundress_white"
|
||||
item_color = "sundress_white"
|
||||
body_parts_covered = CHEST|GROIN
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/greendress
|
||||
name = "green dress"
|
||||
desc = "A tight green dress"
|
||||
icon_state = "dress_green"
|
||||
item_color = "dress_green"
|
||||
body_parts_covered = CHEST|GROIN
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/pinkdress
|
||||
name = "pink dress"
|
||||
desc = "A tight pink dress"
|
||||
icon_state = "dress_pink"
|
||||
item_color = "dress_pink"
|
||||
body_parts_covered = CHEST|GROIN
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/captainparade
|
||||
name = "captain's parade uniform"
|
||||
desc = "A captain's luxury-wear, for special occasions."
|
||||
@@ -509,6 +536,24 @@
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/westernbustle
|
||||
name = "western bustle dress"
|
||||
desc = "Filled with Western fire."
|
||||
icon_state = "western_bustle"
|
||||
item_state = "wcoat"
|
||||
item_color = "western_bustle"
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/flamenco
|
||||
name = "flamenco dress"
|
||||
desc = "Filled with Latin fire."
|
||||
icon_state = "flamenco"
|
||||
item_state = "wcoat"
|
||||
item_color = "flamenco"
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/stripeddress
|
||||
name = "striped dress"
|
||||
desc = "Fashion in space."
|
||||
@@ -529,6 +574,44 @@
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/flowerdress
|
||||
name = "flower dress"
|
||||
desc = "Lovely dress"
|
||||
icon_state = "flower_dress"
|
||||
item_state = "sailordress"
|
||||
item_color = "flower_dress"
|
||||
body_parts_covered = CHEST|GROIN
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/sweptskirt
|
||||
name = "swept skirt"
|
||||
desc = "Formal skirt"
|
||||
icon_state = "skirt_swept"
|
||||
item_color = "skirt_swept"
|
||||
body_parts_covered = GROIN
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/corset
|
||||
name = "black corset"
|
||||
desc = "Nanotrasen is not resposible for any organ damage"
|
||||
icon_state = "corset"
|
||||
item_color = "corset"
|
||||
body_parts_covered = CHEST|GROIN
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/croptop
|
||||
name = "crop top"
|
||||
desc = "We've saved money by giving you half a shirt!"
|
||||
icon_state = "sailor_dress"
|
||||
item_state = "sailordress"
|
||||
item_color = "sailor_dress"
|
||||
body_parts_covered = CHEST|GROIN|ARMS
|
||||
fitted = FEMALE_UNIFORM_TOP
|
||||
can_adjust = FALSE
|
||||
|
||||
/obj/item/clothing/under/redeveninggown
|
||||
name = "red evening gown"
|
||||
desc = "Fancy dress for space bar singers."
|
||||
|
||||
@@ -75,3 +75,34 @@
|
||||
desc = "A pair of woodland camouflage pants. Probably not the best choice for a space station."
|
||||
icon_state = "camopants"
|
||||
item_color = "camopants"
|
||||
|
||||
/obj/item/clothing/under/pants/jeanripped
|
||||
name = "ripped jeans"
|
||||
desc = "If you're wearing this you're poor or a rebel"
|
||||
icon_state = "jean_ripped"
|
||||
item_color = "jean_ripped"
|
||||
|
||||
/obj/item/clothing/under/pants/jeanshort
|
||||
name = "jean shorts"
|
||||
desc = "These are really just jeans cut in half"
|
||||
icon_state = "jean_shorts"
|
||||
item_color = "jean_shorts"
|
||||
|
||||
/obj/item/clothing/under/pants/denimskirt
|
||||
name = "denim skirt"
|
||||
desc = "These are really just a jean leg hole cut from a pair"
|
||||
icon_state = "denim_skirt"
|
||||
item_color = "denim_skirt"
|
||||
|
||||
/obj/item/clothing/under/pants/chaps
|
||||
name = "black chaps"
|
||||
body_parts_covered = LEGS
|
||||
desc = "Yeehaw"
|
||||
icon_state = "chaps"
|
||||
item_color = "chaps"
|
||||
|
||||
/obj/item/clothing/under/pants/yoga
|
||||
name = "yoga pants"
|
||||
desc = "Comfy!"
|
||||
icon_state = "yoga_pants"
|
||||
item_color = "yoga_pants"
|
||||
|
||||
@@ -358,3 +358,11 @@
|
||||
time = 100
|
||||
category = CAT_MISC
|
||||
always_availible = FALSE // Disabled til learned
|
||||
|
||||
/datum/crafting_recipe/coconut_bong
|
||||
name = "Coconut Bong"
|
||||
result = /obj/item/bong/coconut
|
||||
reqs = list(/obj/item/stack/sheet/mineral/bamboo = 2,
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut = 1)
|
||||
time = 70
|
||||
category = CAT_MISC
|
||||
@@ -37,6 +37,8 @@
|
||||
continue
|
||||
if(!H.client)
|
||||
continue
|
||||
if(HAS_TRAIT(H,TRAIT_EXEMPT_HEALTH_EVENTS))
|
||||
continue
|
||||
if(H.stat == DEAD)
|
||||
continue
|
||||
if(HAS_TRAIT(H, TRAIT_VIRUSIMMUNE)) //Don't pick someone who's virus immune, only for it to not do anything.
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/datum/round_event/heart_attack/start()
|
||||
var/list/heart_attack_contestants = list()
|
||||
for(var/mob/living/carbon/human/H in shuffle(GLOB.player_list))
|
||||
if(!H.client || H.stat == DEAD || H.InCritical() || !H.can_heartattack() || H.has_status_effect(STATUS_EFFECT_EXERCISED) || (/datum/disease/heart_failure in H.diseases) || H.undergoing_cardiac_arrest())
|
||||
if(!H.client || H.stat == DEAD || H.InCritical() || !H.can_heartattack() || H.has_status_effect(STATUS_EFFECT_EXERCISED) || (/datum/disease/heart_failure in H.diseases) || H.undergoing_cardiac_arrest() || HAS_TRAIT(H,TRAIT_EXEMPT_HEALTH_EVENTS))
|
||||
continue
|
||||
if(H.satiety <= -60) //Multiple junk food items recently
|
||||
heart_attack_contestants[H] = 3
|
||||
|
||||
@@ -35,4 +35,6 @@
|
||||
/datum/hallucination/delusion,
|
||||
/datum/hallucination/oh_yeah)
|
||||
for(var/mob/living/carbon/C in GLOB.alive_mob_list)
|
||||
if (HAS_TRAIT(C,TRAIT_EXEMPT_HEALTH_EVENTS))
|
||||
continue
|
||||
new picked_hallucination(C, TRUE)
|
||||
@@ -15,6 +15,8 @@
|
||||
continue
|
||||
if(H.stat == DEAD)
|
||||
continue
|
||||
if (HAS_TRAIT(H,TRAIT_EXEMPT_HEALTH_EVENTS))
|
||||
continue
|
||||
if(!H.getorgan(/obj/item/organ/appendix)) //Don't give the disease to some who lacks it, only for it to be auto-cured
|
||||
continue
|
||||
if(!(MOB_ORGANIC in H.mob_biotypes)) //biotype sleeper bugs strike again, once again making appendicitis pick a target that can't take it
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
name = "space cola snowcone"
|
||||
desc = "Space Cola drizzled over a snowball in a paper cup."
|
||||
icon_state = "soda_sc"
|
||||
list_reagents = list("nutriment" = 1, "space_cola" = 5)
|
||||
list_reagents = list("nutriment" = 1, "cola" = 5)
|
||||
tastes = list("ice" = 1, "water" = 1, "cola" = 5)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/snowcones/spacemountainwind
|
||||
@@ -248,4 +248,4 @@
|
||||
desc = "A very colorful snowball in a paper cup."
|
||||
icon_state = "rainbow_sc"
|
||||
list_reagents = list("nutriment" = 5, "laughter" = 25)
|
||||
tastes = list("ice" = 1, "water" = 1, "sunlight" = 5, "light" = 5, "slime" = 5, "paint" = 3, "clouds" = 3)
|
||||
tastes = list("ice" = 1, "water" = 1, "sunlight" = 5, "light" = 5, "slime" = 5, "paint" = 3, "clouds" = 3)
|
||||
|
||||
@@ -609,4 +609,68 @@
|
||||
filling_color = "#ECA735"
|
||||
tastes = list("fried corn" = 1)
|
||||
foodtype = JUNKFOOD | FRIED
|
||||
dunkable = TRUE
|
||||
dunkable = TRUE
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/marshmallow
|
||||
name = "marshmallow"
|
||||
desc = "A marshmallow filled with fluffy marshmallow fluff."
|
||||
icon_state = "marshmallow"
|
||||
list_reagents = list("sugar" = 5, "nutriment" = 2)
|
||||
filling_color = "#fafafa"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
tastes = list("marshmallow" = 2)
|
||||
foodtype = SUGAR | JUNKFOOD
|
||||
var/burned = 0
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/marshmallow/attackby(obj/item/I, mob/user)
|
||||
switch (I.get_temperature())
|
||||
if (355 to 1500)
|
||||
if (prob(30))
|
||||
burnmallow()
|
||||
if (1500 to 2000)
|
||||
if (prob(50))
|
||||
burnmallow()
|
||||
else
|
||||
burnmallow(TRUE)
|
||||
if (2000 to 3000)
|
||||
if (prob(10))
|
||||
burnmallow()
|
||||
else
|
||||
burnmallow(TRUE)
|
||||
if (3000 to INFINITY)
|
||||
burnmallow(TRUE)
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/marshmallow/proc/burnmallow(reallyburned = FALSE)
|
||||
if (reallyburned && burned == 1)
|
||||
icon_state = "marshmallowrburned"
|
||||
else if (burned == 0)
|
||||
icon_state = "marshmallowburned"
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/marshmallow/examine(mob/user)
|
||||
. = ..()
|
||||
if (burned == 2)
|
||||
. += "It looks very burned."
|
||||
if (burned == 1)
|
||||
. += "It looks just right for eating!"
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/marshmallow/fire_act(temp,volume)
|
||||
switch (temp)
|
||||
if (355 to 1500)
|
||||
if (prob(30))
|
||||
burnmallow()
|
||||
if (1500 to 2000)
|
||||
if (prob(50))
|
||||
burnmallow()
|
||||
else
|
||||
burnmallow(TRUE)
|
||||
if (2000 to 3000)
|
||||
if (prob(10))
|
||||
burnmallow()
|
||||
else
|
||||
burnmallow(TRUE)
|
||||
if (3000 to 7000)
|
||||
burnmallow(TRUE)
|
||||
if (7000 to INFINITY)
|
||||
burn()
|
||||
..()
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
dat += "</table>"
|
||||
else
|
||||
dat += "No trait-related genes detected in sample.<br>"
|
||||
if(can_insert && istype(disk.gene, /datum/plant_gene/trait))
|
||||
if(can_insert && istype(disk.gene, /datum/plant_gene/trait) && !seed.is_gene_forbidden(disk.gene.type))
|
||||
dat += "<a href='?src=[REF(src)];op=insert'>Insert: [disk.gene.get_name()]</a>"
|
||||
dat += "</div>"
|
||||
else
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
bitesize_mod = 2
|
||||
var/stacktype = /obj/item/stack/tile/grass
|
||||
var/tile_coefficient = 0.02 // 1/50
|
||||
wine_power = 15
|
||||
distill_reagent = /datum/reagent/consumable/ethanol/beer/light
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/grass/attack_self(mob/user)
|
||||
to_chat(user, "<span class='notice'>You prepare the astroturf.</span>")
|
||||
|
||||
@@ -232,7 +232,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/grown/cherry_bomb/proc/detonate()
|
||||
reagents.chem_temp = 1000 //Sets off the black powder
|
||||
reagents.handle_reactions()
|
||||
|
||||
|
||||
// Lavaland cactus
|
||||
|
||||
/obj/item/seeds/lavaland/cactus
|
||||
@@ -244,3 +244,279 @@
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
|
||||
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
|
||||
growthstages = 2
|
||||
|
||||
|
||||
// Coconut
|
||||
/obj/item/seeds/coconut
|
||||
name = "pack of coconut seeds"
|
||||
desc = "They're seeds that grow into coconut palm trees."
|
||||
icon_state = "seed-coconut"
|
||||
species = "coconut"
|
||||
plantname = "Coconut Palm Tree"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/coconut
|
||||
lifespan = 50
|
||||
endurance = 30
|
||||
potency = 35
|
||||
growing_icon = 'icons/obj/hydroponics/growing.dmi'
|
||||
icon_dead = "coconut-dead"
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
forbiddengenes = list(/datum/plant_gene/trait/squash, /datum/plant_gene/trait/stinging)
|
||||
reagents_add = list("coconutmilk" = 0.3)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut
|
||||
seed = /obj/item/seeds/coconut
|
||||
name = "coconut"
|
||||
desc = "Hard shell of a nut containing delicious milk inside. Perhaps try using something sharp?"
|
||||
icon_state = "coconut"
|
||||
item_state = "coconut"
|
||||
possible_transfer_amounts = list(5, 10, 15, 20, 25, 30, 50)
|
||||
spillable = FALSE
|
||||
resistance_flags = ACID_PROOF
|
||||
volume = 150 //so it won't cut reagents despite having the capacity for them
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 5
|
||||
throwforce = 5
|
||||
hitsound = 'sound/weapons/klonk.ogg'
|
||||
attack_verb = list("klonked", "donked", "bonked")
|
||||
var/opened = FALSE
|
||||
var/carved = FALSE
|
||||
var/chopped = FALSE
|
||||
var/straw = FALSE
|
||||
var/fused = FALSE
|
||||
var/fusedactive = FALSE
|
||||
var/defused = FALSE
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/Initialize(mapload, obj/item/seeds/new_seed)
|
||||
. = ..()
|
||||
var/newvolume = 50 + round(seed.potency,10)
|
||||
if (seed.get_gene(/datum/plant_gene/trait/maxchem))
|
||||
newvolume = newvolume + 50
|
||||
volume = newvolume
|
||||
reagents.maximum_volume = newvolume
|
||||
reagents.update_total()
|
||||
|
||||
transform *= TRANSFORM_USING_VARIABLE(40, 100) + 0.5 //temporary fix for size?
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/attack_self(mob/user)
|
||||
if (!opened)
|
||||
return
|
||||
|
||||
if(!possible_transfer_amounts.len)
|
||||
return
|
||||
var/i=0
|
||||
for(var/A in possible_transfer_amounts)
|
||||
i++
|
||||
if(A != amount_per_transfer_from_this)
|
||||
continue
|
||||
if(i<possible_transfer_amounts.len)
|
||||
amount_per_transfer_from_this = possible_transfer_amounts[i+1]
|
||||
else
|
||||
amount_per_transfer_from_this = possible_transfer_amounts[1]
|
||||
to_chat(user, "<span class='notice'>[src]'s transfer amount is now [amount_per_transfer_from_this] units.</span>")
|
||||
return
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/attackby(obj/item/W, mob/user, params)
|
||||
//DEFUSING NADE LOGIC
|
||||
if (W.tool_behaviour == TOOL_WIRECUTTER && fused)
|
||||
user.show_message("<span class='notice'>You cut the fuse!</span>", MSG_VISUAL)
|
||||
playsound(user, W.hitsound, 50, 1, -1)
|
||||
icon_state = "coconut_carved"
|
||||
desc = "A coconut. This one's got a hole in it."
|
||||
name = "coconut"
|
||||
defused = TRUE
|
||||
fused = FALSE
|
||||
fusedactive = FALSE
|
||||
if(!seed.get_gene(/datum/plant_gene/trait/glow))
|
||||
set_light(0, 0.0)
|
||||
return
|
||||
//IGNITING NADE LOGIC
|
||||
if(!fusedactive && fused)
|
||||
var/lighting_text = W.ignition_effect(src, user)
|
||||
if(lighting_text)
|
||||
user.visible_message("<span class='warning'>[user] ignites [src]'s fuse!</span>", "<span class='userdanger'>You ignite the [src]'s fuse!</span>")
|
||||
fusedactive = TRUE
|
||||
defused = FALSE
|
||||
playsound(src, 'sound/effects/fuse.ogg', 100, 0)
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] ignited a coconut bomb for detonation at [ADMIN_VERBOSEJMP(user)] [pretty_string_from_reagent_list(reagents.reagent_list)]")
|
||||
log_game("[key_name(user)] primed a coconut grenade for detonation at [AREACOORD(user)].")
|
||||
addtimer(CALLBACK(src, .proc/prime), 5 SECONDS)
|
||||
icon_state = "coconut_grenade_active"
|
||||
desc = "RUN!"
|
||||
if(!seed.get_gene(/datum/plant_gene/trait/glow))
|
||||
light_color = "#FFCC66" //for the fuse
|
||||
set_light(3, 0.8)
|
||||
return
|
||||
|
||||
//ADDING A FUSE, NADE LOGIC
|
||||
if (istype(W,/obj/item/stack/sheet/cloth) || istype(W,/obj/item/stack/sheet/durathread))
|
||||
if (carved && !straw && !fused)
|
||||
user.show_message("<span class='notice'>You add a fuse to the coconut!</span>", 1)
|
||||
W.use(1)
|
||||
fused = TRUE
|
||||
icon_state = "coconut_grenade"
|
||||
desc = "A makeshift bomb made out of a coconut. You estimate the fuse is long enough for 5 seconds."
|
||||
name = "coconut bomb"
|
||||
return
|
||||
//ADDING STRAW LOGIC
|
||||
if (istype(W,/obj/item/stack/sheet/mineral/bamboo) && opened && !straw && fused)
|
||||
user.show_message("<span class='notice'>You add a bamboo straw to the coconut!</span>", 1)
|
||||
straw = TRUE
|
||||
W.use(1)
|
||||
icon_state += "_straw"
|
||||
desc = "You can already feel like you're on a tropical vacation."
|
||||
return
|
||||
//OPENING THE NUT LOGIC
|
||||
if (!carved && !chopped)
|
||||
var/screwdrivered = W.tool_behaviour == TOOL_SCREWDRIVER
|
||||
if(screwdrivered || W.sharpness)
|
||||
user.show_message("<span class='notice'>You [screwdrivered ? "make a hole in the coconut" : "slice the coconut open"]!</span>", 1)
|
||||
carved = TRUE
|
||||
opened = TRUE
|
||||
spillable = !screwdrivered
|
||||
reagent_flags = OPENCONTAINER
|
||||
ENABLE_BITFIELD(reagents.reagents_holder_flags, OPENCONTAINER)
|
||||
icon_state = screwdrivered ? "coconut_carved" : "coconut_chopped"
|
||||
desc = "A coconut. [screwdrivered ? "This one's got a hole in it" : "This one's sliced open, with all its delicious contents for your eyes to savour"]."
|
||||
playsound(user, W.hitsound, 50, 1, -1)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/attack(mob/living/M, mob/user, obj/target)
|
||||
if(M && user.a_intent == INTENT_HARM && !spillable)
|
||||
var/obj/item/bodypart/affecting = user.zone_selected //Find what the player is aiming at
|
||||
if (affecting == BODY_ZONE_HEAD && prob(15))
|
||||
//smash the nut open
|
||||
var/armor_block = min(90, M.run_armor_check(affecting, "melee", null, null,armour_penetration)) // For normal attack damage
|
||||
M.apply_damage(force, BRUTE, affecting, armor_block)
|
||||
|
||||
//Sound
|
||||
playsound(user, hitsound, 100, 1, -1)
|
||||
|
||||
//Attack logs
|
||||
log_combat(user, M, "attacked", src)
|
||||
|
||||
//Display an attack message.
|
||||
if(M != user)
|
||||
M.visible_message("<span class='danger'>[user] has cracked open a [name] on [M]'s head!</span>", \
|
||||
"<span class='userdanger'>[user] has cracked open a [name] on [M]'s head!</span>")
|
||||
else
|
||||
user.visible_message("<span class='danger'>[M] cracks open a [name] on their [M.p_them()] head!</span>", \
|
||||
"<span class='userdanger'>[M] cracks open a [name] on [M.p_their()] head!</span>")
|
||||
|
||||
//The coconut breaks open so splash its reagents
|
||||
spillable = TRUE
|
||||
SplashReagents(M)
|
||||
|
||||
//Lastly we remove the nut
|
||||
qdel(src)
|
||||
else
|
||||
. = ..()
|
||||
return
|
||||
|
||||
if(fusedactive)
|
||||
return
|
||||
|
||||
if(!opened)
|
||||
return
|
||||
|
||||
if(!canconsume(M, user))
|
||||
return
|
||||
|
||||
if(!reagents || !reagents.total_volume)
|
||||
to_chat(user, "<span class='warning'>[src] is empty!</span>")
|
||||
return
|
||||
|
||||
if(user.a_intent == INTENT_HARM && spillable)
|
||||
var/R
|
||||
M.visible_message("<span class='danger'>[user] splashes the contents of [src] onto [M]!</span>", \
|
||||
"<span class='userdanger'>[user] splashes the contents of [src] onto [M]!</span>")
|
||||
if(reagents)
|
||||
for(var/datum/reagent/A in reagents.reagent_list)
|
||||
R += A.id + " ("
|
||||
R += num2text(A.volume) + "),"
|
||||
if(isturf(target) && reagents.reagent_list.len && thrownby)
|
||||
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
|
||||
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
|
||||
reagents.reaction(M, TOUCH)
|
||||
log_combat(user, M, "splashed", R)
|
||||
reagents.clear_reagents()
|
||||
else
|
||||
if(M != user)
|
||||
M.visible_message("<span class='danger'>[user] attempts to feed something to [M].</span>", \
|
||||
"<span class='userdanger'>[user] attempts to feed something to you.</span>")
|
||||
if(!do_mob(user, M))
|
||||
return
|
||||
if(!reagents || !reagents.total_volume)
|
||||
return // The drink might be empty after the delay, such as by spam-feeding
|
||||
M.visible_message("<span class='danger'>[user] feeds something to [M].</span>", "<span class='userdanger'>[user] feeds something to you.</span>")
|
||||
log_combat(user, M, "fed", reagents.log_list())
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You swallow a gulp of [src].</span>")
|
||||
var/fraction = min(5/reagents.total_volume, 1)
|
||||
reagents.reaction(M, INGEST, fraction)
|
||||
addtimer(CALLBACK(reagents, /datum/reagents.proc/trans_to, M, 5), 5)
|
||||
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/afterattack(obj/target, mob/user, proximity)
|
||||
. = ..()
|
||||
if(fusedactive)
|
||||
return
|
||||
|
||||
if((!proximity) || !check_allowed_items(target,target_self=1))
|
||||
return
|
||||
|
||||
if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it.
|
||||
if(!reagents.total_volume)
|
||||
to_chat(user, "<span class='warning'>[src] is empty!</span>")
|
||||
return
|
||||
|
||||
if(target.reagents.holder_full())
|
||||
to_chat(user, "<span class='warning'>[target] is full.</span>")
|
||||
return
|
||||
|
||||
var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
|
||||
to_chat(user, "<span class='notice'>You transfer [trans] unit\s of the solution to [target].</span>")
|
||||
|
||||
else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
|
||||
if(!target.reagents.total_volume)
|
||||
to_chat(user, "<span class='warning'>[target] is empty and can't be refilled!</span>")
|
||||
return
|
||||
|
||||
if(reagents.holder_full())
|
||||
to_chat(user, "<span class='warning'>[src] is full.</span>")
|
||||
return
|
||||
|
||||
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
|
||||
to_chat(user, "<span class='notice'>You fill [src] with [trans] unit\s of the contents of [target].</span>")
|
||||
|
||||
else if(reagents.total_volume)
|
||||
if(user.a_intent == INTENT_HARM && spillable == TRUE)
|
||||
user.visible_message("<span class='danger'>[user] splashes the contents of [src] onto [target]!</span>", \
|
||||
"<span class='notice'>You splash the contents of [src] onto [target].</span>")
|
||||
reagents.reaction(target, TOUCH)
|
||||
reagents.clear_reagents()
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/dropped(mob/user)
|
||||
. = ..()
|
||||
transform *= TRANSFORM_USING_VARIABLE(40, 100) + 0.5 //temporary fix for size?
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/proc/prime()
|
||||
if (defused)
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
reagents.chem_temp = 1000
|
||||
//Disable seperated contents when the grenade primes
|
||||
if (seed.get_gene(/datum/plant_gene/trait/noreact))
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, NO_REACT)
|
||||
reagents.handle_reactions()
|
||||
log_game("Coconut bomb detonation at [AREACOORD(T)], location [loc]")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/ex_act(severity)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut/deconstruct(disassembled = TRUE)
|
||||
if(!disassembled && fused)
|
||||
prime()
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
var/rarity = 0 // How rare the plant is. Used for giving points to cargo when shipping off to CentCom.
|
||||
var/list/mutatelist = list() // The type of plants that this plant can mutate into.
|
||||
var/list/genes = list() // Plant genes are stored here, see plant_genes.dm for more info.
|
||||
var/list/forbiddengenes = list()
|
||||
var/list/reagents_add = list()
|
||||
// A list of reagents to add to product.
|
||||
// Format: "reagent_id" = potency multiplier
|
||||
@@ -96,6 +97,10 @@
|
||||
S.reagents_add = reagents_add.Copy() // Faster than grabbing the list from genes.
|
||||
return S
|
||||
|
||||
obj/item/seeds/proc/is_gene_forbidden(typepath)
|
||||
return (typepath in forbiddengenes)
|
||||
|
||||
|
||||
/obj/item/seeds/proc/get_gene(typepath)
|
||||
return (locate(typepath) in genes)
|
||||
|
||||
@@ -448,7 +453,7 @@
|
||||
for(var/i in 1 to amount_random_traits)
|
||||
var/random_trait = pick((subtypesof(/datum/plant_gene/trait)-typesof(/datum/plant_gene/trait/plant_type)))
|
||||
var/datum/plant_gene/trait/T = new random_trait
|
||||
if(T.can_add(src))
|
||||
if(T.can_add(src) && !is_gene_forbidden(random_trait))
|
||||
genes += T
|
||||
else
|
||||
qdel(T)
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
access = list(ACCESS_THEATRE)
|
||||
minimal_access = list(ACCESS_THEATRE)
|
||||
|
||||
mind_traits = list(TRAIT_CLOWN_MENTALITY)
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_CLOWN
|
||||
|
||||
/datum/outfit/job/clown
|
||||
|
||||
@@ -58,13 +58,23 @@
|
||||
return
|
||||
switch(_key)
|
||||
if("Shift")
|
||||
sprint_hotkey(TRUE)
|
||||
if(!user.prefs.sprint_spacebar)
|
||||
user.prefs.sprint_toggle ? togglesprint() : sprint_hotkey(TRUE) //Yes, this looks hacky. Yes, this works.
|
||||
return
|
||||
if("Space")
|
||||
if(user.prefs.sprint_spacebar)
|
||||
user.prefs.sprint_toggle ? togglesprint() : sprint_hotkey(TRUE)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/key_up(_key, client/user)
|
||||
switch(_key)
|
||||
if("Shift")
|
||||
sprint_hotkey(FALSE)
|
||||
if(!user.prefs.sprint_spacebar && !user.prefs.sprint_toggle)
|
||||
sprint_hotkey(FALSE)
|
||||
return
|
||||
if("Space")
|
||||
if(user.prefs.sprint_spacebar && !user.prefs.sprint_toggle)
|
||||
sprint_hotkey(FALSE)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
/obj/machinery/mineral/ore_redemption/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
. += "<span class='notice'>The status display reads: Smelting <b>[sheet_per_ore]</b> sheet(s) per piece of ore.<br>Ore pickup speed at <b>[ore_pickup_rate]</b>.</span>"
|
||||
. += "<span class='notice'>The status display reads: Smelting <b>[sheet_per_ore]</b> sheet(s) per piece of ore.<br>Reward point generation at <b>[point_upgrade*100]%</b>.<br>Ore pickup speed at <b>[ore_pickup_rate]</b>.</span>"
|
||||
|
||||
/obj/machinery/mineral/ore_redemption/proc/smelt_ore(obj/item/stack/ore/O)
|
||||
var/datum/component/material_container/mat_container = materials.mat_container
|
||||
@@ -63,7 +63,7 @@
|
||||
ore_buffer -= O
|
||||
|
||||
if(O && O.refined_type)
|
||||
points += O.points * O.amount
|
||||
points += O.points * point_upgrade * O.amount
|
||||
|
||||
var/material_amount = mat_container.get_item_material_amount(O)
|
||||
|
||||
|
||||
@@ -74,4 +74,5 @@
|
||||
|
||||
/datum/sprite_accessory/underwear
|
||||
icon = 'icons/mob/underwear.dmi'
|
||||
var/has_color = FALSE
|
||||
var/has_color = FALSE
|
||||
var/has_digitigrade = FALSE
|
||||
@@ -2,6 +2,9 @@
|
||||
// Socks Definitions //
|
||||
///////////////////////
|
||||
|
||||
/datum/sprite_accessory/underwear/socks
|
||||
has_digitigrade = TRUE
|
||||
|
||||
/datum/sprite_accessory/underwear/socks/nude
|
||||
name = "Nude"
|
||||
icon_state = null
|
||||
|
||||
@@ -28,41 +28,49 @@
|
||||
name = "Boxers"
|
||||
icon_state = "boxers"
|
||||
has_color = TRUE
|
||||
has_digitigrade = TRUE
|
||||
gender = MALE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/male_bee
|
||||
name = "Boxers - Bee"
|
||||
icon_state = "bee_shorts"
|
||||
has_digitigrade = TRUE
|
||||
gender = MALE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/male_hearts
|
||||
name = "Boxers - Heart"
|
||||
icon_state = "boxers_heart"
|
||||
has_digitigrade = TRUE
|
||||
gender = MALE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/male_stripe
|
||||
name = "Boxers - Striped"
|
||||
icon_state = "boxers_striped"
|
||||
has_digitigrade = TRUE
|
||||
gender = MALE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/male_commie
|
||||
name = "Boxers - Striped Communist"
|
||||
icon_state = "boxers_commie"
|
||||
has_digitigrade = TRUE
|
||||
gender = MALE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/male_usastripe
|
||||
name = "Boxers - Striped Freedom"
|
||||
icon_state = "boxers_assblastusa"
|
||||
has_digitigrade = TRUE
|
||||
gender = MALE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/male_uk
|
||||
name = "Boxers - Striped UK"
|
||||
icon_state = "boxers_uk"
|
||||
has_digitigrade = TRUE
|
||||
gender = MALE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/boxer_briefs
|
||||
name = "Boxer Briefs"
|
||||
icon_state = "boxer_briefs"
|
||||
has_digitigrade = TRUE
|
||||
has_color = TRUE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/panties
|
||||
@@ -140,6 +148,7 @@
|
||||
/datum/sprite_accessory/underwear/bottom/longjon
|
||||
name = "Long John Bottoms"
|
||||
icon_state = "ljonb"
|
||||
has_digitigrade = TRUE
|
||||
has_color = TRUE
|
||||
|
||||
/datum/sprite_accessory/underwear/bottom/swimsuit_red
|
||||
|
||||
@@ -18,3 +18,6 @@
|
||||
|
||||
update_icon(preferred_form)
|
||||
updateghostimages()
|
||||
|
||||
client.reenter_round_timeout = max(client.reenter_round_timeout, clientless_round_timeout)
|
||||
clientless_round_timeout = client.reenter_round_timeout
|
||||
|
||||
@@ -3,8 +3,6 @@ GLOBAL_LIST_EMPTY(ghost_images_simple) //this is a list of all ghost images as t
|
||||
|
||||
GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
|
||||
#define CANT_REENTER_ROUND -1
|
||||
|
||||
/mob/dead/observer
|
||||
name = "ghost"
|
||||
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
|
||||
@@ -21,7 +19,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
|
||||
hud_type = /datum/hud/ghost
|
||||
movement_type = GROUND | FLYING
|
||||
var/can_reenter_corpse
|
||||
var/reenter_round_timeout = 0 // used to prevent people from coming back through ghost roles/midround antags as they suicide/cryo for a duration set by CONFIG_GET(number/suicide_reenter_round_timer) and CONFIG_GET(number/roundstart_suicide_time_limit)
|
||||
var/clientless_round_timeout = 0 //mobs will lack a client as long as their player is disconnected. See client_defines.dm "reenter_round_timeout"
|
||||
var/datum/hud/living/carbon/hud = null // hud
|
||||
var/bootime = 0
|
||||
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
|
||||
@@ -278,9 +276,16 @@ Works together with spawning an observer, noted above.
|
||||
if(world.time < roundstart_quit_limit) //add up the time difference to their antag rolling penalty if they quit before half a (ingame) hour even passed.
|
||||
penalty += roundstart_quit_limit - world.time
|
||||
if(penalty)
|
||||
ghost.reenter_round_timeout = world.realtime + penalty
|
||||
if(ghost.reenter_round_timeout - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
|
||||
ghost.reenter_round_timeout = CANT_REENTER_ROUND
|
||||
penalty += world.realtime
|
||||
if(penalty - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
|
||||
penalty = CANT_REENTER_ROUND
|
||||
if(client)
|
||||
client.reenter_round_timeout = penalty
|
||||
else //A disconnected player (quite likely for cryopods)
|
||||
ghost.clientless_round_timeout = penalty
|
||||
if (client && client.prefs && client.prefs.auto_ooc)
|
||||
if (!(client.prefs.chat_toggles & CHAT_OOC))
|
||||
client.prefs.chat_toggles ^= CHAT_OOC
|
||||
transfer_ckey(ghost, FALSE)
|
||||
return ghost
|
||||
|
||||
@@ -339,10 +344,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
ghostize(0, penalize = TRUE)
|
||||
|
||||
/mob/dead/observer/proc/can_reenter_round(silent = FALSE)
|
||||
if(reenter_round_timeout != CANT_REENTER_ROUND && reenter_round_timeout <= world.realtime)
|
||||
var/timeout = clientless_round_timeout
|
||||
if(client)
|
||||
timeout = client.reenter_round_timeout
|
||||
if(timeout != CANT_REENTER_ROUND && timeout <= world.realtime)
|
||||
return TRUE
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>You are unable to reenter the round[reenter_round_timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(reenter_round_timeout - world.realtime)]" : ""].</span>")
|
||||
if(!silent && client)
|
||||
to_chat(src, "<span class='warning'>You are unable to reenter the round[timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(timeout - world.realtime)]" : ""].</span>")
|
||||
return FALSE
|
||||
|
||||
/mob/dead/observer/Move(NewLoc, direct)
|
||||
@@ -898,5 +906,3 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
spawners_menu = new(src)
|
||||
|
||||
spawners_menu.ui_interact(src)
|
||||
|
||||
#undef CANT_REENTER_ROUND
|
||||
@@ -6,21 +6,21 @@
|
||||
return 2 //no ears
|
||||
|
||||
/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush)
|
||||
..(AM, skipcatch = TRUE, hitpush = FALSE)
|
||||
return ..(AM, skipcatch = TRUE, hitpush = FALSE)
|
||||
|
||||
/mob/living/carbon/alien/can_embed(obj/item/I)
|
||||
return FALSE
|
||||
|
||||
/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other.
|
||||
As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
|
||||
In all, this is a lot like the monkey code. /N
|
||||
*/
|
||||
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
|
||||
if(isturf(loc) && istype(loc.loc, /area/start))
|
||||
to_chat(M, "No attacking people at spawn, you jackass.")
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
|
||||
switch(M.a_intent)
|
||||
|
||||
if ("help")
|
||||
if (INTENT_HELP)
|
||||
if(!recoveringstam)
|
||||
resting = 0
|
||||
AdjustStun(-60)
|
||||
@@ -28,11 +28,7 @@ In all, this is a lot like the monkey code. /N
|
||||
AdjustUnconscious(-60)
|
||||
AdjustSleeping(-100)
|
||||
visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake [p_them()] up!</span>")
|
||||
|
||||
if ("grab")
|
||||
grabbedby(M)
|
||||
|
||||
else
|
||||
if(INTENT_DISARM, INTENT_HARM)
|
||||
if(health > 0)
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
|
||||
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
|
||||
@@ -50,28 +46,31 @@ In all, this is a lot like the monkey code. /N
|
||||
|
||||
|
||||
/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
|
||||
if(..()) //to allow surgery to return properly.
|
||||
return 0
|
||||
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
help_shake_act(M)
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
if ("harm")
|
||||
if (INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return TRUE
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
return 1
|
||||
if("disarm")
|
||||
if(INTENT_DISARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return TRUE
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(..())
|
||||
if (stat != DEAD)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(rand(1, 3), BRUTE, affecting)
|
||||
. = ..()
|
||||
if(.) //successful monkey bite.
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(rand(1, 3), BRUTE, affecting)
|
||||
|
||||
|
||||
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
|
||||
@@ -93,13 +92,15 @@ In all, this is a lot like the monkey code. /N
|
||||
adjustStaminaLoss(damage)
|
||||
|
||||
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 40)
|
||||
adjustBruteLoss(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
updatehealth()
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime attack
|
||||
return
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 40)
|
||||
adjustBruteLoss(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/alien/ex_act(severity, target, origin)
|
||||
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
|
||||
|
||||
@@ -63,12 +63,7 @@
|
||||
if(A)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
var/blocked = FALSE
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
|
||||
blocked = TRUE
|
||||
if(!blocked)
|
||||
if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
|
||||
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
|
||||
L.Knockdown(100)
|
||||
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
adjustBruteLoss(15)
|
||||
var/hitverb = "punched"
|
||||
if(mob_size < MOB_SIZE_LARGE)
|
||||
@@ -21,46 +23,46 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
|
||||
if(..())
|
||||
switch(M.a_intent)
|
||||
if ("harm")
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down.
|
||||
Unconscious(40)
|
||||
visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \
|
||||
"<span class='userdanger'>[M] has knocked [src] down!</span>")
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
log_combat(M, src, "attacked")
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if (INTENT_HARM)
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down.
|
||||
Unconscious(40)
|
||||
visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \
|
||||
"<span class='userdanger'>[M] has knocked [src] down!</span>")
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
log_combat(M, src, "attacked")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
if (INTENT_DISARM)
|
||||
if (!lying)
|
||||
if (prob(5))
|
||||
Unconscious(40)
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
log_combat(M, src, "pushed")
|
||||
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has pushed down [src]!</span>")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='userdanger'>[M] has attempted to punch [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
if ("disarm")
|
||||
if (!lying)
|
||||
if (prob(5))
|
||||
Unconscious(40)
|
||||
if (prob(50))
|
||||
dropItemToGround(get_active_held_item())
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
log_combat(M, src, "pushed")
|
||||
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has pushed down [src]!</span>")
|
||||
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
if (prob(50))
|
||||
dropItemToGround(get_active_held_item())
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='userdanger'>[M] has attempted to disarm [src]!</span>",\
|
||||
"<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to disarm [src]!</span>",\
|
||||
"<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
|
||||
if(!no_effect && !visual_effect_icon)
|
||||
|
||||
@@ -1,26 +1,33 @@
|
||||
|
||||
|
||||
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
|
||||
if(..())
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
log_combat(M, src, "attacked")
|
||||
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 4.9))
|
||||
Unconscious(rand(100,200))
|
||||
. = ..()
|
||||
if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB)
|
||||
return
|
||||
var/damage = rand(1, 9)
|
||||
if (prob(90))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
log_combat(M, src, "attacked")
|
||||
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if ((stat != DEAD) && (damage > 4.9))
|
||||
Unconscious(rand(100,200))
|
||||
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to kick [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to kick [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[user] has pummeled [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has pummeled [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
adjustBruteLoss(5 + rand(1,9))
|
||||
new /datum/forced_movement(src, get_step_away(user,src, 30), 1)
|
||||
return 1
|
||||
|
||||
@@ -103,15 +103,17 @@
|
||||
new_xeno.notransform = 0
|
||||
new_xeno.invisibility = 0
|
||||
|
||||
var/mob/living/carbon/old_owner = owner
|
||||
if(kill_on_sucess) //ITS TOO LATE
|
||||
new_xeno.visible_message("<span class='danger'>[new_xeno] bursts out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
|
||||
owner.apply_damage(rand(100,300),BRUTE,zone,FALSE) //Random high damage to torso so health sensors don't metagame.
|
||||
owner.spill_organs(TRUE,FALSE,TRUE) //Lets still make the death gruesome and impossible to just simply defib someone.
|
||||
var/obj/item/bodypart/B = owner.get_bodypart(zone)
|
||||
B.drop_organs(owner) //Lets still make the death gruesome and impossible to just simply defib someone.
|
||||
owner.death(FALSE) //Just in case some freak occurance occurs where you somehow survive all your organs being removed from you and the 100-300 brute damage.
|
||||
else //When it is removed via surgery at a late stage, rather than forced.
|
||||
new_xeno.visible_message("<span class='danger'>[new_xeno] wriggles out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>")
|
||||
owner.adjustBruteLoss(40)
|
||||
owner.cut_overlay(overlay)
|
||||
old_owner.cut_overlay(overlay)
|
||||
qdel(src)
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,41 +48,42 @@
|
||||
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
|
||||
affecting.dismember(P.damtype)
|
||||
|
||||
/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check)
|
||||
. = FALSE
|
||||
if(mind)
|
||||
if(mind.martial_art && mind.martial_art.dodge_chance == 100)
|
||||
return TRUE
|
||||
if(!skip_throw_mode_check && !in_throw_mode)
|
||||
/mob/living/carbon/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
. = ..()
|
||||
if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !in_throw_mode)
|
||||
return
|
||||
if(get_active_held_item())
|
||||
if(get_active_held_item() || restrained())
|
||||
return
|
||||
if(restrained())
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
|
||||
if(!skipcatch) //ugly, but easy
|
||||
if(can_catch_item())
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
if (mind)
|
||||
if (mind.martial_art && mind.martial_art.dodge_chance == 100) //autocatch for rising bass
|
||||
if (get_active_held_item())
|
||||
visible_message("<span class='warning'>[I] falls to the ground as [src] chops it out of the air!</span>")
|
||||
return 1
|
||||
if(!in_throw_mode)
|
||||
throw_mode_on()
|
||||
if(isturf(I.loc))
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
return 1
|
||||
..()
|
||||
I.attack_hand(src)
|
||||
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
|
||||
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
|
||||
throw_mode_off()
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/embed_item(obj/item/I)
|
||||
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
|
||||
var/obj/item/bodypart/L = pick(bodyparts)
|
||||
L.embedded_objects |= I
|
||||
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
|
||||
I.forceMove(src)
|
||||
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
|
||||
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
|
||||
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user)
|
||||
//CIT CHANGES START HERE - combatmode and resting checks
|
||||
var/totitemdamage = I.force
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/tempcarb = user
|
||||
if(!tempcarb.combatmode)
|
||||
totitemdamage *= 0.5
|
||||
if(user.resting)
|
||||
totitemdamage *= 0.5
|
||||
if(!combatmode)
|
||||
totitemdamage *= 1.5
|
||||
//CIT CHANGES END HERE
|
||||
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
|
||||
return FALSE
|
||||
var/obj/item/bodypart/affecting
|
||||
if(user == src)
|
||||
affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay!
|
||||
@@ -93,17 +94,6 @@
|
||||
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
|
||||
send_item_attack_message(I, user, affecting.name)
|
||||
if(I.force)
|
||||
//CIT CHANGES START HERE - combatmode and resting checks
|
||||
var/totitemdamage = I.force
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/tempcarb = user
|
||||
if(!tempcarb.combatmode)
|
||||
totitemdamage *= 0.5
|
||||
if(user.resting)
|
||||
totitemdamage *= 0.5
|
||||
if(!combatmode)
|
||||
totitemdamage *= 1.5
|
||||
//CIT CHANGES END HERE
|
||||
apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
|
||||
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
|
||||
var/basebloodychance = affecting.brute_dam + totitemdamage
|
||||
@@ -137,7 +127,9 @@
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
|
||||
|
||||
. = ..()
|
||||
if(.) //was the attack blocked?
|
||||
return
|
||||
for(var/thing in diseases)
|
||||
var/datum/disease/D = thing
|
||||
if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
|
||||
@@ -152,8 +144,7 @@
|
||||
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
|
||||
for(var/datum/surgery/S in surgeries)
|
||||
if(S.next_step(user, user.a_intent))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
|
||||
@@ -173,7 +164,8 @@
|
||||
help_shake_act(M)
|
||||
return 0
|
||||
|
||||
if(..()) //successful monkey bite.
|
||||
. = ..()
|
||||
if(.) //successful monkey bite.
|
||||
for(var/thing in M.diseases)
|
||||
var/datum/disease/D = thing
|
||||
ForceContractDisease(D)
|
||||
@@ -181,26 +173,27 @@
|
||||
|
||||
|
||||
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
if(M.powerlevel > 0)
|
||||
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
|
||||
if(prob(stunprob))
|
||||
M.powerlevel -= 3
|
||||
if(M.powerlevel < 0)
|
||||
M.powerlevel = 0
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(M.powerlevel > 0)
|
||||
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
|
||||
if(prob(stunprob))
|
||||
M.powerlevel -= 3
|
||||
if(M.powerlevel < 0)
|
||||
M.powerlevel = 0
|
||||
|
||||
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
|
||||
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
|
||||
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
|
||||
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
|
||||
|
||||
do_sparks(5, TRUE, src)
|
||||
var/power = M.powerlevel + rand(0,3)
|
||||
Knockdown(power*20)
|
||||
if(stuttering < power)
|
||||
stuttering = power
|
||||
if (prob(stunprob) && M.powerlevel >= 8)
|
||||
adjustFireLoss(M.powerlevel * rand(6,10))
|
||||
updatehealth()
|
||||
return 1
|
||||
do_sparks(5, TRUE, src)
|
||||
var/power = M.powerlevel + rand(0,3)
|
||||
Knockdown(power*20)
|
||||
if(stuttering < power)
|
||||
stuttering = power
|
||||
if (prob(stunprob) && M.powerlevel >= 8)
|
||||
adjustFireLoss(M.powerlevel * rand(6,10))
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone)
|
||||
if(!attacker.limb_destroyer)
|
||||
@@ -332,12 +325,12 @@
|
||||
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
else if(check_zone(M.zone_selected) == "r_arm" || check_zone(M.zone_selected) == "l_arm")
|
||||
M.visible_message( \
|
||||
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
|
||||
"<span class='notice'>You shake [src]'s hand.</span>", )
|
||||
|
||||
|
||||
else
|
||||
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
|
||||
"<span class='notice'>You hug [src] to make [p_them()] feel better!</span>")
|
||||
|
||||
@@ -308,7 +308,7 @@
|
||||
var/obj/item/organ/vocal_cords/Vc = user.getorganslot(ORGAN_SLOT_VOICE)
|
||||
if(Vc)
|
||||
if(istype(Vc, /obj/item/organ/vocal_cords/velvet))
|
||||
if(client?.prefs.lewdchem)
|
||||
if(client.prefs.cit_toggles & HYPNO)
|
||||
msg += "<span class='velvet'><i>You feel your chords resonate looking at them.</i></span>\n"
|
||||
|
||||
|
||||
|
||||
@@ -67,66 +67,36 @@
|
||||
P.setAngle(rand(0, 360))//SHING
|
||||
return FALSE
|
||||
|
||||
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
|
||||
if(P.is_reflectable)
|
||||
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
|
||||
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
|
||||
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
|
||||
// Find a turf near or on the original location to bounce to
|
||||
if(P.starting)
|
||||
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(src)
|
||||
return ..()
|
||||
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
var/new_angle_s = P.Angle + rand(120,240)
|
||||
while(new_angle_s > 180) // Translate to regular projectile degrees
|
||||
new_angle_s -= 360
|
||||
P.setAngle(new_angle_s)
|
||||
/mob/living/carbon/human/check_reflect(def_zone)
|
||||
if(wear_suit?.IsReflect(def_zone))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
return -1 // complete projectile permutation
|
||||
|
||||
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return 2
|
||||
|
||||
return (..(P , def_zone))
|
||||
|
||||
/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object
|
||||
if(wear_suit)
|
||||
if(wear_suit.IsReflect(def_zone) == 1)
|
||||
return 1
|
||||
for(var/obj/item/I in held_items)
|
||||
if(I.IsReflect(def_zone) == 1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/human/proc/check_shields(atom/AM, var/damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
|
||||
/mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
var/block_chance_modifier = round(damage / -3)
|
||||
|
||||
for(var/obj/item/I in held_items)
|
||||
if(!istype(I, /obj/item/clothing))
|
||||
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
|
||||
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
if(wear_suit)
|
||||
var/final_block_chance = wear_suit.block_chance - (CLAMP((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
|
||||
if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
return TRUE
|
||||
if(w_uniform)
|
||||
var/final_block_chance = w_uniform.block_chance - (CLAMP((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
|
||||
if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
return TRUE
|
||||
if(wear_neck)
|
||||
var/final_block_chance = wear_neck.block_chance - (CLAMP((armour_penetration-wear_neck.armour_penetration)/2,0,100)) + block_chance_modifier
|
||||
if(wear_neck.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/can_embed(obj/item/I)
|
||||
if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/proc/check_block()
|
||||
if(mind)
|
||||
@@ -135,39 +105,7 @@
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE)
|
||||
if(dna && dna.species)
|
||||
var/spec_return = dna.species.spec_hitby(AM, src)
|
||||
if(spec_return)
|
||||
return spec_return
|
||||
var/obj/item/I
|
||||
var/throwpower = 30
|
||||
if(istype(AM, /obj/item))
|
||||
I = AM
|
||||
throwpower = I.throwforce
|
||||
if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions
|
||||
return ..()
|
||||
if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
else if(I)
|
||||
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && !(mind.martial_art && mind.martial_art.dodge_chance == 100))
|
||||
if(can_embed(I))
|
||||
if(prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))
|
||||
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
|
||||
var/obj/item/bodypart/L = pick(bodyparts)
|
||||
L.embedded_objects |= I
|
||||
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
|
||||
I.forceMove(src)
|
||||
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
|
||||
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE //can't catch the now embedded item
|
||||
if (mind)
|
||||
if (mind.martial_art && mind.martial_art.dodge_chance == 100)
|
||||
skipcatch = FALSE
|
||||
return ..()
|
||||
return dna?.species?.spec_hitby(AM, src) || ..()
|
||||
|
||||
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
|
||||
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (HAS_TRAIT(src, TRAIT_FAT)) && ismonkey(pulling))
|
||||
@@ -201,12 +139,12 @@
|
||||
return dna.species.spec_attacked_by(I, user, affecting, a_intent, src)
|
||||
|
||||
|
||||
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
if(check_shields(user, 15, "the [hulk_verb]ing"))
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
..(user, 1)
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
|
||||
var/message = "[user] has [hulk_verb]ed [src]!"
|
||||
visible_message("<span class='danger'>[message]</span>", \
|
||||
@@ -215,7 +153,8 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/attack_hand(mob/user)
|
||||
if(..()) //to allow surgery to return properly.
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
@@ -227,8 +166,7 @@
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(M.a_intent == INTENT_HELP)
|
||||
..() //shaking
|
||||
return 0
|
||||
return ..() //shaking
|
||||
|
||||
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead.
|
||||
var/obj/item/I = get_active_held_item()
|
||||
@@ -249,78 +187,69 @@
|
||||
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
|
||||
if(..()) //successful monkey bite, this handles disease contraction.
|
||||
var/damage = rand(1, 3)
|
||||
if(check_shields(M, damage, "the [M.name]"))
|
||||
return 0
|
||||
if(stat != DEAD)
|
||||
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
|
||||
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(check_shields(M, 0, "the M.name"))
|
||||
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
|
||||
return 0
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
if (w_uniform)
|
||||
w_uniform.add_fingerprint(M)
|
||||
var/damage = prob(90) ? 20 : 0
|
||||
if(!damage)
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has lunged at [src]!</span>")
|
||||
return 0
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee", null, null,10)
|
||||
|
||||
if(..())
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
if (w_uniform)
|
||||
w_uniform.add_fingerprint(M)
|
||||
var/damage = prob(90) ? 20 : 0
|
||||
if(!damage)
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has lunged at [src]!</span>")
|
||||
return 0
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee", null, null,10)
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>")
|
||||
log_combat(M, src, "attacked")
|
||||
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>")
|
||||
log_combat(M, src, "attacked")
|
||||
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I && dropItemToGround(I))
|
||||
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] disarmed [src]!</span>")
|
||||
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
|
||||
var/obj/item/I = get_active_held_item()
|
||||
if(I && dropItemToGround(I))
|
||||
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
|
||||
"<span class='userdanger'>[M] disarmed [src]!</span>")
|
||||
else
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(!lying) //CITADEL EDIT
|
||||
Knockdown(100, TRUE, FALSE, 30, 25)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(!lying) //CITADEL EDIT
|
||||
Knockdown(100, TRUE, FALSE, 30, 25)
|
||||
else
|
||||
Knockdown(100)
|
||||
log_combat(M, src, "tackled")
|
||||
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [src]!</span>")
|
||||
|
||||
Knockdown(100)
|
||||
log_combat(M, src, "tackled")
|
||||
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [src]!</span>")
|
||||
|
||||
/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
|
||||
if(..()) //successful larva bite.
|
||||
var/damage = rand(1, 3)
|
||||
if(check_shields(L, damage, "the [L.name]"))
|
||||
return 0
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful larva bite.
|
||||
return
|
||||
var/damage = rand(1, 3)
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
|
||||
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
|
||||
if(check_shields(M, damage, "the [M.name]", MELEE_ATTACK, M.armour_penetration))
|
||||
return FALSE
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return TRUE
|
||||
@@ -332,23 +261,22 @@
|
||||
|
||||
|
||||
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
var/damage = rand(5, 25)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 35)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime attack
|
||||
return
|
||||
var/damage = rand(5, 25)
|
||||
if(M.is_adult)
|
||||
damage = rand(10, 35)
|
||||
|
||||
if(check_shields(M, damage, "the [M.name]"))
|
||||
return 0
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
var/armor_block = run_armor_check(affecting, "melee")
|
||||
apply_damage(damage, BRUTE, affecting, armor_block)
|
||||
|
||||
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
|
||||
if(M.occupant.a_intent == INTENT_HARM)
|
||||
@@ -652,7 +580,7 @@
|
||||
if(mind)
|
||||
if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") )
|
||||
gain = 100
|
||||
if(mind.assigned_role == "Clown")
|
||||
if(HAS_TRAIT(mind, TRAIT_CLOWN_MENTALITY))
|
||||
gain = rand(-300, 300)
|
||||
investigate_log("([key_name(src)]) has been consumed by the singularity.", INVESTIGATE_SINGULO) //Oh that's where the clown ended up!
|
||||
gib()
|
||||
|
||||
@@ -545,6 +545,20 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
//Underwear, Undershirts & Socks
|
||||
if(!(NO_UNDERWEAR in species_traits))
|
||||
|
||||
if(H.socks && H.get_num_legs(FALSE) >= 2)
|
||||
if(H.hidden_socks)
|
||||
H.socks = "Nude"
|
||||
else
|
||||
H.socks = H.saved_socks
|
||||
var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks]
|
||||
if(S)
|
||||
var/digilegs = ((DIGITIGRADE in species_traits) && S.has_digitigrade) ? "_d" : ""
|
||||
var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER)
|
||||
if(S.has_color)
|
||||
MA.color = "#[H.socks_color]"
|
||||
standing += MA
|
||||
|
||||
if(H.underwear)
|
||||
if(H.hidden_underwear)
|
||||
H.underwear = "Nude"
|
||||
@@ -552,8 +566,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
H.underwear = H.saved_underwear
|
||||
var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear]
|
||||
if(B)
|
||||
var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER)
|
||||
if(UNDIE_COLORABLE(B))
|
||||
var/digilegs = ((DIGITIGRADE in species_traits) && B.has_digitigrade) ? "_d" : ""
|
||||
var/mutable_appearance/MA = mutable_appearance(B.icon, "[B.icon_state][digilegs]", -BODY_LAYER)
|
||||
if(B.has_color)
|
||||
MA.color = "#[H.undie_color]"
|
||||
standing += MA
|
||||
|
||||
@@ -564,28 +579,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
H.undershirt = H.saved_undershirt
|
||||
var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt]
|
||||
if(T)
|
||||
var/state = "[T.icon_state][((DIGITIGRADE in species_traits) && T.has_digitigrade) ? "_d" : ""]"
|
||||
var/mutable_appearance/MA
|
||||
if(H.dna.species.sexes && H.gender == FEMALE)
|
||||
MA = wear_female_version(T.icon_state, T.icon, BODY_LAYER)
|
||||
MA = wear_female_version(state, T.icon, BODY_LAYER)
|
||||
else
|
||||
MA = mutable_appearance(T.icon, T.icon_state, -BODY_LAYER)
|
||||
if(UNDIE_COLORABLE(T))
|
||||
MA = mutable_appearance(T.icon, state, -BODY_LAYER)
|
||||
if(T.has_color)
|
||||
MA.color = "#[H.shirt_color]"
|
||||
standing += MA
|
||||
|
||||
if(H.socks && H.get_num_legs(FALSE) >= 2)
|
||||
if(H.hidden_socks)
|
||||
H.socks = "Nude"
|
||||
else
|
||||
H.socks = H.saved_socks
|
||||
var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks]
|
||||
if(S)
|
||||
var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : ""
|
||||
var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER)
|
||||
if(UNDIE_COLORABLE(S))
|
||||
MA.color = "#[H.socks_color]"
|
||||
standing += MA
|
||||
|
||||
if(standing.len)
|
||||
H.overlays_standing[BODY_LAYER] = standing
|
||||
|
||||
@@ -1589,20 +1592,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
user.adjustStaminaLossBuffered(3)
|
||||
return FALSE
|
||||
else if(aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
|
||||
if(target.client?.prefs.cit_toggles & NO_ASS_SLAP)
|
||||
to_chat(user,"A force stays your hand, preventing you from slapping \the [target]'s ass!")
|
||||
return FALSE
|
||||
user.do_attack_animation(target, ATTACK_EFFECT_ASS_SLAP)
|
||||
user.adjustStaminaLossBuffered(3)
|
||||
if(HAS_TRAIT(target, TRAIT_ASSBLASTUSA))
|
||||
var/hit_zone = (user.held_index_to_dir(user.active_hand_index) == "l" ? "l_":"r_") + "arm"
|
||||
user.adjustStaminaLoss(20, affected_zone = hit_zone)
|
||||
user.visible_message(\
|
||||
"<span class='danger'>\The [user] slaps \the [target]'s ass, but their hand bounces off like they hit metal!</span>",\
|
||||
"<span class='danger'>You slap [user == target ? "your" : "\the [target]'s"] ass, but feel an intense amount of pain as you realise their buns are harder than steel!</span>",\
|
||||
"You hear a slap."
|
||||
)
|
||||
playsound(target.loc, 'sound/weapons/tap.ogg', 50, 1, -1)
|
||||
user.emote("scream")
|
||||
return FALSE
|
||||
|
||||
playsound(target.loc, 'sound/weapons/slap.ogg', 50, 1, -1)
|
||||
user.visible_message(\
|
||||
"<span class='danger'>\The [user] slaps \the [target]'s ass!</span>",\
|
||||
@@ -1691,11 +1685,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
attacker_style = M.mind.martial_art
|
||||
if(attacker_style?.pacifism_check && HAS_TRAIT(M, TRAIT_PACIFISM)) // most martial arts are quite harmful, alas.
|
||||
attacker_style = null
|
||||
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
|
||||
log_combat(M, H, "attempted to touch")
|
||||
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
|
||||
return 0
|
||||
SEND_SIGNAL(M, COMSIG_MOB_ATTACK_HAND, M, H, attacker_style)
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
help(M, H, attacker_style)
|
||||
|
||||
@@ -51,11 +51,7 @@
|
||||
. = ..()
|
||||
to_chat(C, "[info_text]")
|
||||
|
||||
C.real_name = "[pick(GLOB.nightmare_names)]"
|
||||
C.name = C.real_name
|
||||
if(C.mind)
|
||||
C.mind.name = C.real_name
|
||||
C.dna.real_name = C.real_name
|
||||
C.fully_replace_character_name("[pick(GLOB.nightmare_names)]")
|
||||
|
||||
/datum/species/shadow/nightmare/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
|
||||
var/turf/T = H.loc
|
||||
@@ -127,8 +123,8 @@
|
||||
/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
|
||||
respawn_progress = 0
|
||||
if(blade && special != HEART_SPECIAL_SHADOWIFY)
|
||||
QDEL_NULL(blade)
|
||||
M.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
|
||||
QDEL_NULL(blade)
|
||||
..()
|
||||
|
||||
/obj/item/organ/heart/nightmare/Stop()
|
||||
@@ -183,15 +179,21 @@
|
||||
. = ..()
|
||||
if(!proximity)
|
||||
return
|
||||
if(isopenturf(AM)) //So you can actually melee with it
|
||||
return
|
||||
if(isliving(AM))
|
||||
if(isopenturf(AM))
|
||||
var/turf/open/T = AM
|
||||
if(T.light_range && !isspaceturf(T)) //no fairy grass or light tile can escape the fury of the darkness.
|
||||
to_chat(user, "<span class='notice'>You scrape away [T] with your [name] and snuff out its lights.</span>")
|
||||
T.ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
|
||||
else if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(iscyborg(AM))
|
||||
var/mob/living/silicon/robot/borg = AM
|
||||
if(!borg.lamp_cooldown)
|
||||
if(borg.lamp_intensity)
|
||||
borg.update_headlamp(TRUE, INFINITY)
|
||||
to_chat(borg, "<span class='danger'>Your headlamp is fried! You'll need a human to help replace it.</span>")
|
||||
for(var/obj/item/assembly/flash/cyborg/F in borg.held_items)
|
||||
if(!F.crit_fail)
|
||||
F.burn_out()
|
||||
else
|
||||
for(var/obj/item/O in AM)
|
||||
if(O.light_range && O.light_power)
|
||||
|
||||
@@ -369,6 +369,23 @@
|
||||
retaliate(L)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(M.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(M)
|
||||
else if(M.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
|
||||
retaliate(M)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(L)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(user)
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_paw(mob/living/L)
|
||||
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
|
||||
retaliate(L)
|
||||
|
||||
@@ -6,37 +6,55 @@
|
||||
..()
|
||||
|
||||
/mob/living/carbon/monkey/attack_paw(mob/living/M)
|
||||
if(..()) //successful monkey bite.
|
||||
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(M.limb_destroyer)
|
||||
dismembering_strike(M, affecting.body_zone)
|
||||
if(stat != DEAD)
|
||||
var/dmg = rand(1, 5)
|
||||
apply_damage(dmg, BRUTE, affecting)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful monkey bite.
|
||||
return
|
||||
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(M.limb_destroyer)
|
||||
dismembering_strike(M, affecting.body_zone)
|
||||
var/dmg = rand(1, 5)
|
||||
apply_damage(dmg, BRUTE, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(..()) //successful larva bite.
|
||||
var/damage = rand(1, 3)
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful larva bite
|
||||
return
|
||||
var/damage = rand(1, 3)
|
||||
if(stat != DEAD)
|
||||
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
|
||||
var/message = "[user] has [hulk_verb]ed [src]!"
|
||||
visible_message("<span class='danger'>[message]</span>", \
|
||||
"<span class='userdanger'>[message]</span>")
|
||||
adjustBruteLoss(15)
|
||||
return TRUE
|
||||
|
||||
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
|
||||
if(..()) //To allow surgery to return properly.
|
||||
. = ..()
|
||||
if(.) //To allow surgery to return properly.
|
||||
return
|
||||
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
help_shake_act(M)
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
if (prob(75))
|
||||
visible_message("<span class='danger'>[M] has punched [name]!</span>", \
|
||||
@@ -60,7 +78,7 @@
|
||||
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has attempted to punch [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has attempted to punch [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
if("disarm")
|
||||
if(INTENT_DISARM)
|
||||
if(!IsUnconscious())
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
if (prob(25))
|
||||
@@ -74,50 +92,51 @@
|
||||
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", "<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent.
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if ((prob(95) && health > 0))
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
var/damage = rand(15, 30)
|
||||
if (damage >= 25)
|
||||
damage = rand(20, 40)
|
||||
if(AmountUnconscious() < 300)
|
||||
Unconscious(rand(200, 300))
|
||||
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
log_combat(M, src, "attacked")
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if ((prob(95) && health > 0))
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
var/damage = rand(15, 30)
|
||||
if (damage >= 25)
|
||||
damage = rand(20, 40)
|
||||
if(AmountUnconscious() < 300)
|
||||
Unconscious(rand(200, 300))
|
||||
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -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>", null, COMBAT_MESSAGE_RANGE)
|
||||
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
if (M.a_intent == INTENT_DISARM)
|
||||
var/obj/item/I = null
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(prob(95))
|
||||
Knockdown(20)
|
||||
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
|
||||
log_combat(M, src, "attacked")
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
|
||||
return 1
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
else
|
||||
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -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>", null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
else
|
||||
var/obj/item/I = null
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
if(prob(95))
|
||||
Knockdown(20)
|
||||
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
|
||||
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = get_active_held_item()
|
||||
if(dropItemToGround(I))
|
||||
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = get_active_held_item()
|
||||
if(dropItemToGround(I))
|
||||
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
else
|
||||
I = null
|
||||
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
updatehealth()
|
||||
|
||||
I = null
|
||||
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
|
||||
updatehealth()
|
||||
|
||||
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
|
||||
. = ..()
|
||||
@@ -132,17 +151,19 @@
|
||||
apply_damage(damage, M.melee_damage_type, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime attack
|
||||
return
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
|
||||
if(!dam_zone) //Dismemberment successful
|
||||
return 1
|
||||
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
|
||||
if(!affecting)
|
||||
affecting = get_bodypart(BODY_ZONE_CHEST)
|
||||
apply_damage(damage, BRUTE, affecting)
|
||||
|
||||
/mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit)
|
||||
. = 1
|
||||
|
||||
@@ -91,7 +91,9 @@
|
||||
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST))
|
||||
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[get_area_name(T)]</b>.</span>"
|
||||
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
|
||||
|
||||
if (client && client.prefs && client.prefs.auto_ooc)
|
||||
if (!(client.prefs.chat_toggles & CHAT_OOC))
|
||||
client.prefs.chat_toggles ^= CHAT_OOC
|
||||
if (client)
|
||||
client.move_delay = initial(client.move_delay)
|
||||
|
||||
|
||||
@@ -36,7 +36,50 @@
|
||||
/mob/living/proc/on_hit(obj/item/projectile/P)
|
||||
return
|
||||
|
||||
/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
|
||||
var/block_chance_modifier = round(damage / -3)
|
||||
for(var/obj/item/I in held_items)
|
||||
if(!istype(I, /obj/item/clothing))
|
||||
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
|
||||
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/check_reflect(def_zone) //Reflection checks for anything in your hands, based on the reflection chance of the object(s)
|
||||
for(var/obj/item/I in held_items)
|
||||
if(I.IsReflect(def_zone))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/reflect_bullet_check(obj/item/projectile/P, def_zone)
|
||||
if(P.is_reflectable && check_reflect(def_zone)) // Checks if you've passed a reflection% check
|
||||
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
|
||||
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
|
||||
// Find a turf near or on the original location to bounce to
|
||||
if(P.starting)
|
||||
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
|
||||
var/turf/curloc = get_turf(src)
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
var/new_angle_s = P.Angle + rand(120,240)
|
||||
while(new_angle_s > 180) // Translate to regular projectile degrees
|
||||
new_angle_s -= 360
|
||||
P.setAngle(new_angle_s)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
|
||||
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
|
||||
if(reflect_bullet_check(P, def_zone))
|
||||
return -1 // complete projectile permutation
|
||||
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return 2
|
||||
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
|
||||
if(!P.nodamage)
|
||||
apply_damage(P.damage, P.damage_type, def_zone, armor)
|
||||
@@ -55,9 +98,32 @@
|
||||
else
|
||||
return 0
|
||||
|
||||
/mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
|
||||
return FALSE
|
||||
|
||||
/mob/living/proc/embed_item(obj/item/I)
|
||||
return
|
||||
|
||||
/mob/living/proc/can_embed(obj/item/I)
|
||||
return FALSE
|
||||
|
||||
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
|
||||
if(istype(AM, /obj/item))
|
||||
var/obj/item/I = AM
|
||||
var/obj/item/I
|
||||
var/throwpower = 30
|
||||
if(isitem(AM))
|
||||
I = AM
|
||||
throwpower = I.throwforce
|
||||
if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK))
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE
|
||||
blocked = TRUE
|
||||
else if(I && I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && can_embed(I, src) && prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE) && (!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) || incapacitated() || get_active_held_item()))
|
||||
embed_item(I)
|
||||
hitpush = FALSE
|
||||
skipcatch = TRUE //can't catch the now embedded item
|
||||
if(I)
|
||||
if(!skipcatch && isturf(I.loc) && catch_item(I))
|
||||
return TRUE
|
||||
var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
|
||||
var/dtype = BRUTE
|
||||
var/volume = I.get_volume_by_throwforce_and_or_w_class()
|
||||
@@ -214,6 +280,24 @@
|
||||
Move(user.loc)
|
||||
return 1
|
||||
|
||||
/mob/living/attack_hand(mob/user)
|
||||
..() //Ignoring parent return value here.
|
||||
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user)
|
||||
if((user != src) && user.a_intent != INTENT_HELP && check_shields(user, 0, user.name, attack_type = UNARMED_ATTACK))
|
||||
log_combat(user, src, "attempted to touch")
|
||||
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>")
|
||||
return TRUE
|
||||
|
||||
/mob/living/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return TRUE
|
||||
var/hulk_verb = pick("smash","pummel")
|
||||
if(user != src && check_shields(user, 15, "the [hulk_verb]ing"))
|
||||
return TRUE
|
||||
..()
|
||||
return FALSE
|
||||
|
||||
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(!SSticker.HasRoundStarted())
|
||||
@@ -229,6 +313,12 @@
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
|
||||
var/damage = rand(5, 35)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
if(check_shields(M, damage, "the [M.name]"))
|
||||
return FALSE
|
||||
|
||||
if (stat != DEAD)
|
||||
log_combat(M, src, "attacked")
|
||||
M.do_attack_animation(src)
|
||||
@@ -245,7 +335,8 @@
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
|
||||
if(check_shields(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", MELEE_ATTACK, M.armour_penetration))
|
||||
return FALSE
|
||||
if(M.attack_sound)
|
||||
playsound(loc, M.attack_sound, 50, 1, 1)
|
||||
M.do_attack_animation(src)
|
||||
@@ -256,10 +347,6 @@
|
||||
|
||||
|
||||
/mob/living/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(isturf(loc) && istype(loc.loc, /area/start))
|
||||
to_chat(M, "No attacking people at spawn, you jackass.")
|
||||
return FALSE
|
||||
|
||||
if (M.a_intent == INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
@@ -268,6 +355,8 @@
|
||||
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
|
||||
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
|
||||
return FALSE
|
||||
if(check_shields(M, 0, "the [M.name]"))
|
||||
return FALSE
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
|
||||
if (prob(75))
|
||||
log_combat(M, src, "attacked")
|
||||
@@ -282,15 +371,16 @@
|
||||
|
||||
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
switch(L.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
|
||||
return FALSE
|
||||
|
||||
else
|
||||
if(HAS_TRAIT(L, TRAIT_PACIFISM))
|
||||
to_chat(L, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return
|
||||
|
||||
return FALSE
|
||||
if(L != src && check_shields(L, rand(1, 3), "the [L.name]"))
|
||||
return FALSE
|
||||
L.do_attack_animation(src)
|
||||
if(prob(90))
|
||||
log_combat(L, src, "attacked")
|
||||
@@ -301,24 +391,29 @@
|
||||
else
|
||||
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
|
||||
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return FALSE
|
||||
|
||||
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if((M != src) && M.a_intent != INTENT_HELP && check_shields(M, 0, "the [M.name]"))
|
||||
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
|
||||
return FALSE
|
||||
switch(M.a_intent)
|
||||
if ("help")
|
||||
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
|
||||
if (INTENT_HELP)
|
||||
if(!isalien(src)) //I know it's ugly, but the alien vs alien attack_alien behaviour is a bit different.
|
||||
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
|
||||
return FALSE
|
||||
if ("grab")
|
||||
if (INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
return FALSE
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
|
||||
return FALSE
|
||||
M.do_attack_animation(src)
|
||||
if(!isalien(src))
|
||||
M.do_attack_animation(src)
|
||||
return TRUE
|
||||
if("disarm")
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
if(INTENT_DISARM)
|
||||
if(!isalien(src))
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
return TRUE
|
||||
|
||||
/mob/living/ex_act(severity, target, origin)
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
|
||||
/mob/living/silicon/ai/attacked_by(obj/item/I, mob/living/user, def_zone)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
|
||||
spark_system.start()
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(!SSticker.HasRoundStarted())
|
||||
to_chat(M, "You cannot attack people before the game has started.")
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
|
||||
return //immune to slimes
|
||||
|
||||
@@ -26,13 +26,14 @@
|
||||
fold_in(force = 1)
|
||||
Knockdown(200)
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user)
|
||||
switch(user.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
visible_message("<span class='notice'>[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.</span>")
|
||||
if("disarm")
|
||||
if(INTENT_DISARM)
|
||||
visible_message("<span class='notice'>[user] boops [src] on the head!</span>")
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
user.do_attack_animation(src)
|
||||
if (user.name == master)
|
||||
visible_message("<span class='notice'>Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.</span>")
|
||||
@@ -41,14 +42,19 @@
|
||||
if(user.put_in_hands(card))
|
||||
user.visible_message("<span class='notice'>[user] promptly scoops up [user.p_their()] pAI's card.</span>")
|
||||
else
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return
|
||||
visible_message("<span class='danger'>[user] stomps on [src]!.</span>")
|
||||
take_holo_damage(2)
|
||||
else
|
||||
grabbedby(user)
|
||||
|
||||
/mob/living/silicon/pai/bullet_act(obj/item/projectile/Proj)
|
||||
if(Proj.stun)
|
||||
/mob/living/silicon/pai/bullet_act(obj/item/projectile/P, def_zone)
|
||||
if(P.stun)
|
||||
fold_in(force = TRUE)
|
||||
src.visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
|
||||
. = ..(Proj)
|
||||
visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
|
||||
. = ..()
|
||||
|
||||
/mob/living/silicon/pai/stripPanelUnequip(obj/item/what, mob/who, where) //prevents stripping
|
||||
to_chat(src, "<span class='warning'>Your holochassis stutters and warps intensely as you attempt to interact with the object, forcing you to cease lest the field fail.</span>")
|
||||
|
||||
@@ -13,7 +13,19 @@
|
||||
spark_system.start()
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
spark_system.start()
|
||||
spawn(0)
|
||||
step_away(src,user,15)
|
||||
sleep(3)
|
||||
step_away(src,user,15)
|
||||
|
||||
/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if (M.a_intent == INTENT_DISARM)
|
||||
if(!(lying))
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
@@ -30,24 +42,19 @@
|
||||
visible_message("<span class='danger'>[M] has forced back [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has forced back [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1)
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime shock
|
||||
flash_act()
|
||||
var/stunprob = M.powerlevel * 7 + 10
|
||||
if(prob(stunprob) && M.powerlevel >= 8)
|
||||
adjustBruteLoss(M.powerlevel * rand(6,10))
|
||||
|
||||
var/damage = rand(1, 3)
|
||||
|
||||
. = ..()
|
||||
if(!.) //unsuccessful slime shock
|
||||
return
|
||||
var/stunprob = M.powerlevel * 7 + 10
|
||||
var/damage = M.powerlevel * rand(6,10)
|
||||
if(prob(stunprob) && M.powerlevel >= 8)
|
||||
flash_act(affect_silicon = TRUE) //my borg eyes!
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 40)
|
||||
damage += rand(10, 20)
|
||||
else
|
||||
damage = rand(5, 35)
|
||||
damage = round(damage / 2) // borgs receive half damage
|
||||
damage += rand(2, 17)
|
||||
adjustBruteLoss(damage)
|
||||
updatehealth()
|
||||
|
||||
@@ -56,23 +63,17 @@
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user)
|
||||
add_fingerprint(user)
|
||||
if(opened && !wiresexposed && !issilicon(user))
|
||||
if(cell)
|
||||
cell.update_icon()
|
||||
cell.add_fingerprint(user)
|
||||
user.put_in_active_hand(cell)
|
||||
to_chat(user, "<span class='notice'>You remove \the [cell].</span>")
|
||||
cell = null
|
||||
update_icons()
|
||||
diag_hud_set_borgcell()
|
||||
if(opened && !wiresexposed && cell && !issilicon(user))
|
||||
cell.update_icon()
|
||||
cell.add_fingerprint(user)
|
||||
user.put_in_active_hand(cell)
|
||||
to_chat(user, "<span class='notice'>You remove \the [cell].</span>")
|
||||
cell = null
|
||||
update_icons()
|
||||
diag_hud_set_borgcell()
|
||||
|
||||
if(!opened)
|
||||
if(..()) // hulk attack
|
||||
spark_system.start()
|
||||
spawn(0)
|
||||
step_away(src,user,15)
|
||||
sleep(3)
|
||||
step_away(src,user,15)
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/robot/fire_act()
|
||||
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
|
||||
@@ -182,9 +183,9 @@
|
||||
if (stat != DEAD)
|
||||
adjustBruteLoss(30)
|
||||
|
||||
/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj)
|
||||
..(Proj)
|
||||
/mob/living/silicon/robot/bullet_act(obj/item/projectile/P, def_zone)
|
||||
..()
|
||||
updatehealth()
|
||||
if(prob(75) && Proj.damage > 0)
|
||||
if(prob(75) && P.damage > 0)
|
||||
spark_system.start()
|
||||
return 2
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
return 2
|
||||
|
||||
/mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
var/damage = 20
|
||||
if (prob(90))
|
||||
log_combat(M, src, "attacked")
|
||||
@@ -49,34 +52,33 @@
|
||||
/mob/living/silicon/attack_paw(mob/living/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(L.a_intent == INTENT_HELP)
|
||||
visible_message("[L.name] rubs its head against [src].")
|
||||
|
||||
/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
adjustBruteLoss(rand(10, 15))
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[user] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has punched [src]!</span>")
|
||||
return 1
|
||||
return 0
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
/mob/living/silicon/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
if(.) //the attack was blocked
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if ("help")
|
||||
if (INTENT_HELP)
|
||||
M.visible_message("[M] pets [src].", \
|
||||
"<span class='notice'>You pet [src].</span>")
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
grabbedby(M)
|
||||
else
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
playsound(src.loc, 'sound/effects/bang.ogg', 10, 1)
|
||||
visible_message("<span class='danger'>[M] punches [src], but doesn't leave a dent.</span>", \
|
||||
"<span class='warning'>[M] punches [src], but doesn't leave a dent.</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
return 0
|
||||
|
||||
/mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M)
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
@@ -108,19 +110,25 @@
|
||||
M.visible_message("<span class='boldwarning'>[M] is thrown off of [src]!</span>")
|
||||
flash_act(affect_silicon = 1)
|
||||
|
||||
/mob/living/silicon/bullet_act(obj/item/projectile/Proj)
|
||||
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
|
||||
adjustBruteLoss(Proj.damage)
|
||||
if(prob(Proj.damage*1.5))
|
||||
/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
|
||||
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
|
||||
if(reflect_bullet_check(P, def_zone))
|
||||
return -1 // complete projectile permutation
|
||||
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
|
||||
P.on_hit(src, 100, def_zone)
|
||||
return 2
|
||||
if((P.damage_type == BRUTE || P.damage_type == BURN))
|
||||
adjustBruteLoss(P.damage)
|
||||
if(prob(P.damage*1.5))
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>")
|
||||
unbuckle_mob(M)
|
||||
M.Knockdown(40)
|
||||
if(Proj.stun || Proj.knockdown)
|
||||
if(P.stun || P.knockdown)
|
||||
for(var/mob/living/M in buckled_mobs)
|
||||
unbuckle_mob(M)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [Proj]!</span>")
|
||||
Proj.on_hit(src)
|
||||
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [P]!</span>")
|
||||
P.on_hit(src)
|
||||
return 2
|
||||
|
||||
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/static)
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
|
||||
|
||||
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
|
||||
..()
|
||||
. = ..()
|
||||
if(.) //the attack was blocked
|
||||
return
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
if (health > 0)
|
||||
visible_message("<span class='notice'>[M] [response_help] [src].</span>")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if("grab")
|
||||
if(INTENT_GRAB)
|
||||
if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
|
||||
vore_attack(M, pulling)
|
||||
else
|
||||
grabbedby(M)
|
||||
|
||||
if("harm", "disarm")
|
||||
if(INTENT_HARM, INTENT_DISARM)
|
||||
if(HAS_TRAIT(M, TRAIT_PACIFISM))
|
||||
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return
|
||||
@@ -27,12 +29,11 @@
|
||||
updatehealth()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
if(HAS_TRAIT(user, TRAIT_PACIFISM))
|
||||
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
|
||||
return FALSE
|
||||
..(user, 1)
|
||||
. = ..(user, TRUE)
|
||||
if(.)
|
||||
return
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[user] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[user] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
@@ -40,32 +41,32 @@
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(..()) //successful monkey bite.
|
||||
if(stat != DEAD)
|
||||
var/damage = rand(1, 3)
|
||||
attack_threshold_check(damage)
|
||||
return 1
|
||||
. = ..()
|
||||
if(.) //successful larva bite
|
||||
var/damage = rand(1, 3)
|
||||
attack_threshold_check(damage)
|
||||
return 1
|
||||
if (M.a_intent == INTENT_HELP)
|
||||
if (health > 0)
|
||||
visible_message("<span class='notice'>[M.name] [response_help] [src].</span>")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
|
||||
/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent.
|
||||
if(M.a_intent == INTENT_DISARM)
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
|
||||
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(M, src, "disarmed")
|
||||
else
|
||||
var/damage = rand(15, 30)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
attack_threshold_check(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
return 1
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
if(M.a_intent == INTENT_DISARM)
|
||||
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
|
||||
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(M, src, "disarmed")
|
||||
else
|
||||
var/damage = rand(15, 30)
|
||||
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
|
||||
attack_threshold_check(damage)
|
||||
log_combat(M, src, "attacked")
|
||||
|
||||
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
. = ..()
|
||||
@@ -82,7 +83,8 @@
|
||||
return attack_threshold_check(damage, M.melee_damage_type)
|
||||
|
||||
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
. = ..()
|
||||
if(.) //successful slime shock
|
||||
var/damage = rand(15, 25)
|
||||
if(M.is_adult)
|
||||
damage = rand(20, 35)
|
||||
|
||||
@@ -113,7 +113,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
mode = BOT_HUNT
|
||||
|
||||
/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
|
||||
if(H.a_intent == "harm")
|
||||
if(H.a_intent == INTENT_HARM)
|
||||
retaliate(H)
|
||||
addtimer(CALLBACK(src, .proc/react_buzz), 5)
|
||||
return ..()
|
||||
|
||||
@@ -232,9 +232,9 @@
|
||||
/mob/living/simple_animal/pet/cat/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
wuv(1, M)
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
wuv(-1, M)
|
||||
|
||||
/mob/living/simple_animal/pet/cat/proc/wuv(change, mob/M)
|
||||
@@ -290,7 +290,9 @@
|
||||
D.decorate_donut()
|
||||
|
||||
/mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L)
|
||||
..()
|
||||
. = ..()
|
||||
if(.) //the attack was blocked
|
||||
return
|
||||
if(L.a_intent == INTENT_HARM && L.reagents && !stat)
|
||||
L.reagents.add_reagent("nutriment", 0.4)
|
||||
L.reagents.add_reagent("vitamin", 0.4)
|
||||
|
||||
@@ -643,9 +643,9 @@
|
||||
/mob/living/simple_animal/pet/dog/attack_hand(mob/living/carbon/human/M)
|
||||
. = ..()
|
||||
switch(M.a_intent)
|
||||
if("help")
|
||||
if(INTENT_HELP)
|
||||
wuv(1,M)
|
||||
if("harm")
|
||||
if(INTENT_HARM)
|
||||
wuv(-1,M)
|
||||
|
||||
/mob/living/simple_animal/pet/dog/proc/wuv(change, mob/M)
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
|
||||
//picky up the drone c:
|
||||
/mob/living/simple_animal/drone/attack_hand(mob/user)
|
||||
..()
|
||||
if(user.a_intent == INTENT_HELP)
|
||||
mob_try_pickup(user)
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return ..() // TODO: convert picking up mobs into an element or component.
|
||||
mob_try_pickup(user)
|
||||
|
||||
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
|
||||
var/mob/dead/observer/G = get_ghost()
|
||||
|
||||
@@ -54,10 +54,8 @@
|
||||
var/blocked = FALSE
|
||||
if(hasmatchingsummoner(A)) //if the summoner matches don't hurt them
|
||||
blocked = TRUE
|
||||
if(ishuman(A))
|
||||
var/mob/living/carbon/human/H = A
|
||||
if(H.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
|
||||
blocked = TRUE
|
||||
if(L.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
|
||||
blocked = TRUE
|
||||
if(!blocked)
|
||||
L.drop_all_held_items()
|
||||
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] slams into you!</span>")
|
||||
|
||||
@@ -594,12 +594,15 @@ Difficulty: Normal
|
||||
var/list/hit_things = list() //we hit these already, ignore them
|
||||
var/friendly_fire_check = FALSE
|
||||
var/bursting = FALSE //if we're bursting and need to hit anyone crossing us
|
||||
var/list/nohurt
|
||||
|
||||
/obj/effect/temp_visual/hierophant/blast/Initialize(mapload, new_caster, friendly_fire, list/only_hit_once)
|
||||
/obj/effect/temp_visual/hierophant/blast/Initialize(mapload, new_caster, friendly_fire, list/only_hit_once, list/donthurt = null)
|
||||
. = ..()
|
||||
if(only_hit_once)
|
||||
hit_things = only_hit_once
|
||||
friendly_fire_check = friendly_fire
|
||||
if(donthurt)
|
||||
hit_things += donthurt
|
||||
if(new_caster)
|
||||
hit_things += new_caster
|
||||
if(ismineralturf(loc)) //drill mineral turfs
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
|
||||
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
||||
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
|
||||
var/list/crusher_loot
|
||||
var/medal_type
|
||||
var/score_type = BOSS_SCORE
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
var/list/attack_action_types = list()
|
||||
var/can_talk = FALSE
|
||||
var/obj/loot_drop = null
|
||||
|
||||
var/owner
|
||||
|
||||
//Gives player-controlled variants the ability to swap attacks
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -53,14 +54,14 @@
|
||||
if(ismineralturf(target))
|
||||
var/turf/closed/mineral/M = target
|
||||
M.gets_drilled()
|
||||
|
||||
|
||||
//Elites can't talk (normally)!
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
|
||||
if(can_talk)
|
||||
. = ..()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/*Basic setup for elite attacks, based on Whoneedspace's megafauna attack setup.
|
||||
While using this makes the system rely on OnFire, it still gives options for timers not tied to OnFire, and it makes using attacks consistent accross the board for player-controlled elites.*/
|
||||
|
||||
@@ -82,11 +83,11 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
/datum/action/innate/elite_attack/Activate()
|
||||
M.chosen_attack = chosen_attack_num
|
||||
to_chat(M, chosen_message)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/updatehealth()
|
||||
. = ..()
|
||||
update_health_hud()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/update_health_hud()
|
||||
if(hud_used)
|
||||
var/severity = 0
|
||||
@@ -144,7 +145,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
gpstag = "Menacing Signal"
|
||||
desc = "You're not quite sure how a signal can be menacing."
|
||||
invisibility = 100
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(ishuman(user))
|
||||
@@ -179,7 +180,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
|
||||
activity = TUMOR_INACTIVE
|
||||
activator = null
|
||||
|
||||
|
||||
|
||||
obj/structure/elite_tumor/proc/spawn_elite(var/mob/dead/observer/elitemind)
|
||||
var/selectedspawn = pick(potentialspawns)
|
||||
mychild = new selectedspawn(loc)
|
||||
@@ -199,18 +200,18 @@ obj/structure/elite_tumor/proc/return_elite()
|
||||
if(boosted)
|
||||
mychild.maxHealth = mychild.maxHealth * 2
|
||||
mychild.health = mychild.maxHealth
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/Initialize(mapload)
|
||||
. = ..()
|
||||
internal = new/obj/item/gps/internal/elite(src)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
mychild = null
|
||||
activator = null
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/process()
|
||||
if(isturf(loc))
|
||||
for(var/mob/living/simple_animal/hostile/asteroid/elite/elitehere in loc)
|
||||
@@ -218,7 +219,7 @@ obj/structure/elite_tumor/proc/return_elite()
|
||||
mychild.adjustHealth(-mychild.maxHealth*0.05)
|
||||
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(mychild))
|
||||
H.color = "#FF0000"
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/attackby(obj/item/I, mob/user, params)
|
||||
. = ..()
|
||||
if(istype(I, /obj/item/organ/regenerative_core) && activity == TUMOR_INACTIVE && !boosted)
|
||||
@@ -232,7 +233,7 @@ obj/structure/elite_tumor/proc/return_elite()
|
||||
desc = "[desc] This one seems to glow with a strong intensity."
|
||||
qdel(core)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/proc/arena_checks()
|
||||
if(activity != TUMOR_ACTIVE || QDELETED(src))
|
||||
return
|
||||
@@ -240,13 +241,13 @@ obj/structure/elite_tumor/proc/return_elite()
|
||||
INVOKE_ASYNC(src, .proc/arena_trap) //Gets another arena trap queued up for when this one runs out.
|
||||
INVOKE_ASYNC(src, .proc/border_check) //Checks to see if our fighters got out of the arena somehow.
|
||||
addtimer(CALLBACK(src, .proc/arena_checks), 50)
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/proc/fighters_check()
|
||||
if(activator != null && activator.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(activator))
|
||||
onEliteWon()
|
||||
if(mychild != null && mychild.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(mychild))
|
||||
onEliteLoss()
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/proc/arena_trap()
|
||||
var/turf/T = get_turf(src)
|
||||
if(loc == null)
|
||||
@@ -257,7 +258,7 @@ obj/structure/elite_tumor/proc/return_elite()
|
||||
newwall = new /obj/effect/temp_visual/elite_tumor_wall(t, src)
|
||||
newwall.activator = src.activator
|
||||
newwall.ourelite = src.mychild
|
||||
|
||||
|
||||
/obj/structure/elite_tumor/proc/border_check()
|
||||
if(activator != null && get_dist(src, activator) >= 12)
|
||||
activator.forceMove(loc)
|
||||
@@ -267,7 +268,7 @@ obj/structure/elite_tumor/proc/return_elite()
|
||||
mychild.forceMove(loc)
|
||||
visible_message("<span class='boldwarning'>[mychild] suddenly reappears above [src]!</span>")
|
||||
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
|
||||
|
||||
|
||||
obj/structure/elite_tumor/proc/onEliteLoss()
|
||||
playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, 0, 50, TRUE, TRUE)
|
||||
visible_message("<span class='boldwarning'>[src] begins to convulse violently before beginning to dissipate.</span>")
|
||||
@@ -286,7 +287,7 @@ obj/structure/elite_tumor/proc/onEliteLoss()
|
||||
mychild = null
|
||||
activator = null
|
||||
qdel(src)
|
||||
|
||||
|
||||
obj/structure/elite_tumor/proc/onEliteWon()
|
||||
activity = TUMOR_PASSIVE
|
||||
activator = null
|
||||
@@ -300,7 +301,7 @@ obj/structure/elite_tumor/proc/onEliteWon()
|
||||
to_chat(mychild, "<span class='boldwarning'>As the life in the activator's eyes fade, the forcefield around you dies out and you feel your power subside.\nDespite this inferno being your home, you feel as if you aren't welcome here anymore.\nWithout any guidance, your purpose is now for you to decide.</span>")
|
||||
to_chat(mychild, "<b>Your max health has been halved, but can now heal by standing on your tumor. Note, it's your only way to heal.\nBear in mind, if anyone interacts with your tumor, you'll be resummoned here to carry out another fight. In such a case, you will regain your full max health.\nAlso, be weary of your fellow inhabitants, they likely won't be happy to see you!</b>")
|
||||
to_chat(mychild, "<span class='big bold'>Note that you are a lavaland monster, and thus not allied to the station. You should not cooperate or act friendly with any station crew unless under extreme circumstances!</span>")
|
||||
|
||||
|
||||
/obj/item/tumor_shard
|
||||
name = "tumor shard"
|
||||
desc = "A strange, sharp, crystal shard from an odd tumor on Lavaland. Stabbing the corpse of a lavaland elite with this will revive them, assuming their soul still lingers. Revived lavaland elites only have half their max health, but are completely loyal to their reviver."
|
||||
@@ -313,7 +314,7 @@ obj/structure/elite_tumor/proc/onEliteWon()
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
|
||||
|
||||
/obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag)
|
||||
. = ..()
|
||||
if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag)
|
||||
@@ -331,10 +332,11 @@ obj/structure/elite_tumor/proc/onEliteWon()
|
||||
E.health = E.maxHealth
|
||||
E.desc = "[E.desc] However, this one appears appears less wild in nature, and calmer around people."
|
||||
E.sentience_type = SENTIENCE_ORGANIC
|
||||
E.owner = user
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='info'>[src] only works on the corpse of a sentient lavaland elite.</span>")
|
||||
|
||||
|
||||
/obj/effect/temp_visual/elite_tumor_wall
|
||||
name = "magic wall"
|
||||
icon = 'icons/turf/walls/hierophant_wall_temp.dmi'
|
||||
@@ -347,7 +349,7 @@ obj/structure/elite_tumor/proc/onEliteWon()
|
||||
color = rgb(255,0,0)
|
||||
light_range = MINIMUM_USEFUL_LIGHT_RANGE
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
|
||||
/obj/effect/temp_visual/elite_tumor_wall/Initialize(mapload, new_caster)
|
||||
. = ..()
|
||||
queue_smooth_neighbors(src)
|
||||
|
||||
@@ -44,34 +44,34 @@
|
||||
/datum/action/innate/elite_attack/magic_box,
|
||||
/datum/action/innate/elite_attack/pandora_teleport,
|
||||
/datum/action/innate/elite_attack/aoe_squares)
|
||||
|
||||
|
||||
var/sing_shot_length = 8
|
||||
var/cooldown_time = 20
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/singular_shot
|
||||
name = "Singular Shot"
|
||||
button_icon_state = "singular_shot"
|
||||
chosen_message = "<span class='boldwarning'>You are now creating a single linear magic square.</span>"
|
||||
chosen_attack_num = SINGULAR_SHOT
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/magic_box
|
||||
name = "Magic Box"
|
||||
button_icon_state = "magic_box"
|
||||
chosen_message = "<span class='boldwarning'>You are now attacking with a box of magic squares.</span>"
|
||||
chosen_attack_num = MAGIC_BOX
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/pandora_teleport
|
||||
name = "Line Teleport"
|
||||
button_icon_state = "pandora_teleport"
|
||||
chosen_message = "<span class='boldwarning'>You will now teleport to your target.</span>"
|
||||
chosen_attack_num = PANDORA_TELEPORT
|
||||
|
||||
|
||||
/datum/action/innate/elite_attack/aoe_squares
|
||||
name = "AOE Blast"
|
||||
button_icon_state = "aoe_squares"
|
||||
chosen_message = "<span class='boldwarning'>Your attacks will spawn an AOE blast at your target location.</span>"
|
||||
chosen_attack_num = AOE_SQUARES
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/OpenFire()
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
@@ -94,7 +94,7 @@
|
||||
pandora_teleport(target)
|
||||
if(AOE_SQUARES)
|
||||
aoe_squares(target)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/Life()
|
||||
. = ..()
|
||||
if(health >= maxHealth * 0.5)
|
||||
@@ -105,28 +105,28 @@
|
||||
return
|
||||
else
|
||||
cooldown_time = 10
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot(target)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot(target)
|
||||
ranged_cooldown = world.time + (cooldown_time * 0.5)
|
||||
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
|
||||
var/turf/T = get_step(get_turf(src), dir_to_target)
|
||||
singular_shot_line(sing_shot_length, dir_to_target, T)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot_line(var/procsleft, var/angleused, var/turf/T)
|
||||
if(procsleft <= 0)
|
||||
return
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src, null, null, list(owner))
|
||||
T = get_step(T, angleused)
|
||||
procsleft = procsleft - 1
|
||||
addtimer(CALLBACK(src, .proc/singular_shot_line, procsleft, angleused, T), 2)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/magic_box(target)
|
||||
ranged_cooldown = world.time + cooldown_time
|
||||
var/turf/T = get_turf(target)
|
||||
for(var/t in spiral_range_turfs(3, T))
|
||||
if(get_dist(t, T) > 1)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
|
||||
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner))
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport(target)
|
||||
ranged_cooldown = world.time + cooldown_time
|
||||
var/turf/T = get_turf(target)
|
||||
@@ -135,45 +135,45 @@
|
||||
new /obj/effect/temp_visual/hierophant/telegraph(source, src)
|
||||
playsound(source,'sound/machines/airlockopen.ogg', 200, 1)
|
||||
addtimer(CALLBACK(src, .proc/pandora_teleport_2, T, source), 2)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_2(var/turf/T, var/turf/source)
|
||||
new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src)
|
||||
new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, src)
|
||||
for(var/t in RANGE_TURFS(1, T))
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner))
|
||||
for(var/t in RANGE_TURFS(1, source))
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner))
|
||||
animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out
|
||||
visible_message("<span class='hierophant_warning'>[src] fades out!</span>")
|
||||
density = FALSE
|
||||
addtimer(CALLBACK(src, .proc/pandora_teleport_3, T), 2)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_3(var/turf/T)
|
||||
forceMove(T)
|
||||
animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN
|
||||
density = TRUE
|
||||
visible_message("<span class='hierophant_warning'>[src] fades in!</span>")
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares(target)
|
||||
ranged_cooldown = world.time + cooldown_time
|
||||
var/turf/T = get_turf(target)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src, null, null, list(owner))
|
||||
var/max_size = 2
|
||||
addtimer(CALLBACK(src, .proc/aoe_squares_2, T, 0, max_size), 2)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares_2(var/turf/T, var/ring, var/max_size)
|
||||
if(ring > max_size)
|
||||
return
|
||||
for(var/t in spiral_range_turfs(ring, T))
|
||||
if(get_dist(t, T) == ring)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
|
||||
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src, null, null, list(owner))
|
||||
addtimer(CALLBACK(src, .proc/aoe_squares_2, T, (ring + 1), max_size), 2)
|
||||
|
||||
|
||||
//The specific version of hiero's squares pandora uses
|
||||
/obj/effect/temp_visual/hierophant/blast/pandora
|
||||
damage = 20
|
||||
monster_damage_boost = FALSE
|
||||
|
||||
|
||||
//Pandora's loot: Hope
|
||||
/obj/item/clothing/accessory/pandora_hope
|
||||
name = "Hope"
|
||||
@@ -181,7 +181,7 @@
|
||||
icon = 'icons/obj/lavaland/elite_trophies.dmi'
|
||||
icon_state = "hope"
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
|
||||
/obj/item/clothing/accessory/pandora_hope/on_uniform_equip(obj/item/clothing/under/U, user)
|
||||
var/mob/living/L = user
|
||||
if(L && L.mind)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
var/icon_aggro = null
|
||||
var/crusher_drop_mod = 5
|
||||
var/crusher_drop_mod = 25
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -58,7 +58,7 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/death(gibbed)
|
||||
SSblackbox.record_feedback("tally", "mobs_killed_mining", 1, type)
|
||||
var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
|
||||
if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 20 creatures before getting the item
|
||||
if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 4 creatures before getting the item
|
||||
spawn_crusher_loot()
|
||||
..(gibbed)
|
||||
|
||||
|
||||
@@ -166,7 +166,9 @@
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M)
|
||||
..()
|
||||
. = ..()
|
||||
if(.) // the attack was blocked
|
||||
return
|
||||
if(M.a_intent == INTENT_HARM)
|
||||
Bruise()
|
||||
|
||||
|
||||
@@ -253,33 +253,34 @@
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M)
|
||||
if(..()) //successful slime attack
|
||||
if(M == src)
|
||||
return
|
||||
if(buckled)
|
||||
Feedstop(silent = TRUE)
|
||||
visible_message("<span class='danger'>[M] pulls [src] off!</span>")
|
||||
return
|
||||
attacked += 5
|
||||
if(nutrition >= 100) //steal some nutrition. negval handled in life()
|
||||
nutrition -= (50 + (40 * M.is_adult))
|
||||
M.add_nutrition(50 + (40 * M.is_adult))
|
||||
if(health > 0)
|
||||
M.adjustBruteLoss(-10 + (-10 * M.is_adult))
|
||||
M.updatehealth()
|
||||
. = ..()
|
||||
if(!. || M == src) //unsuccessful slime shock
|
||||
return
|
||||
if(buckled)
|
||||
Feedstop(silent = TRUE)
|
||||
visible_message("<span class='danger'>[M] pulls [src] off!</span>")
|
||||
return
|
||||
attacked += 5
|
||||
if(nutrition >= 100) //steal some nutrition. negval handled in life()
|
||||
nutrition -= (50 + (40 * M.is_adult))
|
||||
M.add_nutrition(50 + (40 * M.is_adult))
|
||||
if(health > 0)
|
||||
M.adjustBruteLoss(-10 + (-10 * M.is_adult))
|
||||
M.updatehealth()
|
||||
|
||||
/mob/living/simple_animal/slime/attack_animal(mob/living/simple_animal/M)
|
||||
. = ..()
|
||||
if(.)
|
||||
attacked += 10
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/attack_paw(mob/living/carbon/monkey/M)
|
||||
if(..()) //successful monkey bite.
|
||||
. = ..()
|
||||
if(.)//successful monkey bite.
|
||||
attacked += 10
|
||||
|
||||
/mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L)
|
||||
if(..()) //successful larva bite.
|
||||
. = ..()
|
||||
if(.) //successful larva bite.
|
||||
attacked += 10
|
||||
|
||||
/mob/living/simple_animal/slime/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
|
||||
@@ -321,9 +322,11 @@
|
||||
attacked += 10
|
||||
|
||||
/mob/living/simple_animal/slime/attack_alien(mob/living/carbon/alien/humanoid/M)
|
||||
if(..()) //if harm or disarm intent.
|
||||
attacked += 10
|
||||
discipline_slime(M)
|
||||
. = ..()
|
||||
if(!.) // the attack was blocked or was help/grab intent
|
||||
return
|
||||
attacked += 10
|
||||
discipline_slime(M)
|
||||
|
||||
|
||||
/mob/living/simple_animal/slime/attackby(obj/item/W, mob/living/user, params)
|
||||
|
||||
@@ -459,6 +459,11 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
|
||||
if(!ckey || !new_mob)
|
||||
CRASH("transfer_ckey() called [ckey ? "" : "on a ckey-less mob[new_mob ? "" : " and "]"][new_mob ? "" : "without a valid mob target"]!")
|
||||
SEND_SIGNAL(new_mob, COMSIG_MOB_PRE_PLAYER_CHANGE, new_mob, src)
|
||||
if (client && client.prefs && client.prefs.auto_ooc)
|
||||
if (client.prefs.chat_toggles & CHAT_OOC && isliving(new_mob))
|
||||
client.prefs.chat_toggles ^= CHAT_OOC
|
||||
if (!(client.prefs.chat_toggles & CHAT_OOC) && isdead(new_mob))
|
||||
client.prefs.chat_toggles ^= CHAT_OOC
|
||||
new_mob.ckey = ckey
|
||||
if(send_signal)
|
||||
SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src)
|
||||
|
||||
@@ -26,10 +26,9 @@ Contents:
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/enable_signals()
|
||||
if(!affecting)
|
||||
return
|
||||
RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth)
|
||||
RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth)
|
||||
RegisterSignal(affecting, COMSIG_MOVABLE_BUMP, .proc/bumping_stealth)
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/reduce_stealth(datum/source)
|
||||
affecting.alpha = min(affecting.alpha + 40, 100)
|
||||
|
||||
@@ -42,7 +41,7 @@ Contents:
|
||||
return FALSE
|
||||
stealth = !stealth
|
||||
stealth_cooldown = world.time + 5 SECONDS
|
||||
UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE))
|
||||
UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE))
|
||||
animate(affecting, alpha = 255, time = 3 SECONDS)
|
||||
affecting.visible_message("<span class='warning'>[affecting.name] appears from thin air!</span>", \
|
||||
"<span class='notice'>You are now visible.</span>")
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
/obj/item/paperplane/throw_impact(atom/hit_atom)
|
||||
if(iscarbon(hit_atom))
|
||||
var/mob/living/carbon/C = hit_atom
|
||||
if(C.can_catch_item(TRUE))
|
||||
if(!C.get_active_held_item() && !C.restrained())
|
||||
var/datum/action/innate/origami/origami_action = locate() in C.actions
|
||||
if(origami_action?.active) //if they're a master of origami and have the ability turned on, force throwmode on so they'll automatically catch the plane.
|
||||
C.throw_mode_on()
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
var/burst_spread = 0 //Spread induced by the gun itself during burst fire per iteration. Only checked if spread is 0.
|
||||
var/randomspread = 1 //Set to 0 for shotguns. This is used for weapons that don't fire all their bullets at once.
|
||||
var/inaccuracy_modifier = 1
|
||||
var/pb_knockback = 0
|
||||
|
||||
lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
|
||||
@@ -125,6 +126,10 @@
|
||||
if(message)
|
||||
if(pointblank)
|
||||
user.visible_message("<span class='danger'>[user] fires [src] point blank at [pbtarget]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
if(pb_knockback > 0)
|
||||
var/atom/throw_target = get_edge_target_turf(pbtarget, user.dir)
|
||||
pbtarget.throw_at(throw_target, pb_knockback, 2)
|
||||
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user] fires [src]!</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
|
||||
|
||||
@@ -267,6 +267,7 @@
|
||||
fire_delay = 0
|
||||
pin = /obj/item/firing_pin/implant/pindicate
|
||||
actions_types = list()
|
||||
pb_knockback = 2
|
||||
|
||||
/obj/item/gun/ballistic/automatic/shotgun/bulldog/unrestricted
|
||||
pin = /obj/item/firing_pin
|
||||
|
||||
@@ -273,6 +273,7 @@
|
||||
"Maple" = "dshotgun-l",
|
||||
"Rosewood" = "dshotgun-p"
|
||||
)
|
||||
pb_knockback = 3 // it's a super shotgun!
|
||||
|
||||
/obj/item/gun/ballistic/revolver/doublebarrel/attackby(obj/item/A, mob/user, params)
|
||||
..()
|
||||
@@ -352,7 +353,7 @@
|
||||
clumsy_check = 0
|
||||
|
||||
/obj/item/gun/ballistic/revolver/reverse/can_trigger_gun(mob/living/user)
|
||||
if((HAS_TRAIT(user, TRAIT_CLUMSY)) || (user.mind && user.mind.assigned_role == "Clown"))
|
||||
if((HAS_TRAIT(user, TRAIT_CLUMSY)) || (user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY)))
|
||||
return ..()
|
||||
if(process_fire(user, user, FALSE, null, BODY_ZONE_HEAD))
|
||||
user.visible_message("<span class='warning'>[user] somehow manages to shoot [user.p_them()]self in the face!</span>", "<span class='userdanger'>You somehow shoot yourself in the face! How the hell?!</span>")
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
var/recentpump = 0 // to prevent spammage
|
||||
weapon_weight = WEAPON_MEDIUM
|
||||
|
||||
pb_knockback = 2
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/attackby(obj/item/A, mob/user, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
item_flags = NONE
|
||||
casing_ejector = FALSE
|
||||
can_suppress = FALSE
|
||||
pb_knockback = 0
|
||||
|
||||
/obj/item/gun/ballistic/shotgun/toy/process_chamber(empty_chamber = 0)
|
||||
..()
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
// A gun with ultra-honk pin is useful for clown and useless for everyone else.
|
||||
/obj/item/firing_pin/clown/ultra/pin_auth(mob/living/user)
|
||||
playsound(src.loc, 'sound/items/bikehorn.ogg', 50, 1)
|
||||
if(user && (!(HAS_TRAIT(user, TRAIT_CLUMSY)) && !(user.mind && user.mind.assigned_role == "Clown")))
|
||||
if(user && (!(HAS_TRAIT(user, TRAIT_CLUMSY)) && !(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY))))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
if(!amount)
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 50)
|
||||
var/name = stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/pill/P
|
||||
@@ -287,7 +287,7 @@
|
||||
adjust_item_drop_location(P)
|
||||
reagents.trans_to(P,vol_each)
|
||||
else
|
||||
var/name = stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN)
|
||||
var/name = html_decode(stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location())
|
||||
@@ -313,7 +313,7 @@
|
||||
if(!amount)
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 40)
|
||||
var/name = stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/pill/P
|
||||
@@ -331,7 +331,7 @@
|
||||
return
|
||||
|
||||
if(condi)
|
||||
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/food/condiment/P = new(drop_location())
|
||||
@@ -344,7 +344,7 @@
|
||||
if(text2num(many))
|
||||
amount_full = round(reagents.total_volume / 30)
|
||||
vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals.
|
||||
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
|
||||
@@ -372,7 +372,7 @@
|
||||
if(text2num(many))
|
||||
amount_full = round(reagents.total_volume / 60)
|
||||
vol_part = reagents.total_volume % 60
|
||||
var/name = stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
|
||||
@@ -407,7 +407,7 @@
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 20)
|
||||
|
||||
var/name = stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
return
|
||||
|
||||
|
||||
@@ -247,6 +247,23 @@
|
||||
. = 1
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/coconutmilk
|
||||
name = "Coconut Milk"
|
||||
id = "coconutmilk"
|
||||
description = "A transparent white liquid extracted from coconuts. Rich in taste."
|
||||
color = "#DFDFDF" // rgb: 223, 223, 223
|
||||
taste_description = "sweet milk"
|
||||
quality = DRINK_GOOD
|
||||
glass_icon_state = "glass_white"
|
||||
glass_name = "glass of coconut milk"
|
||||
glass_desc = "White and nutritious goodness!"
|
||||
|
||||
/datum/reagent/consumable/coconutmilk/on_mob_life(mob/living/carbon/M)
|
||||
if(M.getBruteLoss() && prob(20))
|
||||
M.heal_bodypart_damage(2,0, 0)
|
||||
. = 1
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/cream
|
||||
name = "Cream"
|
||||
id = "cream"
|
||||
|
||||
@@ -622,7 +622,7 @@
|
||||
M.adjustBruteLoss(-1*REM, 0)
|
||||
M.adjustFireLoss(-1*REM, 0)
|
||||
M.adjustOxyLoss(-1*REM, 0)
|
||||
M.adjustToxLoss(-1*REM, 0)
|
||||
M.adjustToxLoss(-1*REM, 0, TRUE) //heals TOXINLOVERs
|
||||
..()
|
||||
|
||||
/datum/reagent/consumable/honey/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
|
||||
|
||||
@@ -26,12 +26,11 @@ Borg Hypospray
|
||||
var/bypass_protection = 0 //If the hypospray can go through armor or thick material
|
||||
|
||||
var/list/datum/reagents/reagent_list = list()
|
||||
var/list/reagent_ids = list("dexalin", "kelotane", "bicaridine", "antitoxin", "epinephrine", "spaceacillin", "salglu_solution")
|
||||
var/list/reagent_ids = list("dexalin", "kelotane", "bicaridine", "antitoxin", "epinephrine", "spaceacillin", "salglu_solution", "insulin")
|
||||
var/accepts_reagent_upgrades = TRUE //If upgrades can increase number of reagents dispensed.
|
||||
var/list/modes = list() //Basically the inverse of reagent_ids. Instead of having numbers as "keys" and strings as values it has strings as keys and numbers as values.
|
||||
//Used as list for input() in shakers.
|
||||
|
||||
|
||||
/obj/item/reagent_containers/borghypo/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -40,12 +39,10 @@ Borg Hypospray
|
||||
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/obj/item/reagent_containers/borghypo/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/reagent_containers/borghypo/process() //Every [recharge_time] seconds, recharge some reagents for the cyborg
|
||||
charge_tick++
|
||||
if(charge_tick >= recharge_time)
|
||||
@@ -162,7 +159,7 @@ Borg Hypospray
|
||||
icon_state = "borghypo_s"
|
||||
charge_cost = 20
|
||||
recharge_time = 2
|
||||
reagent_ids = list("syndicate_nanites", "potass_iodide", "morphine")
|
||||
reagent_ids = list("syndicate_nanites", "potass_iodide", "morphine", "insulin")
|
||||
bypass_protection = 1
|
||||
accepts_reagent_upgrades = FALSE
|
||||
|
||||
@@ -178,7 +175,6 @@ Borg Shaker
|
||||
charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster.
|
||||
recharge_time = 3
|
||||
accepts_reagent_upgrades = FALSE
|
||||
|
||||
reagent_ids = list("beer", "orangejuice", "grenadine", "limejuice", "tomatojuice", "cola", "tonic", "sodawater", "ice", "cream", "whiskey", "vodka", "rum", "gin", "tequila", "vermouth", "wine", "kahlua", "cognac", "ale", "milk", "coffee", "banana", "lemonjuice")
|
||||
|
||||
/obj/item/reagent_containers/borghypo/borgshaker/attack(mob/M, mob/user)
|
||||
@@ -234,23 +230,21 @@ Borg Shaker
|
||||
charge_cost = 20 //Lots of reagents all regenerating at once, so the charge cost is lower. They also regenerate faster.
|
||||
recharge_time = 3
|
||||
accepts_reagent_upgrades = FALSE
|
||||
|
||||
reagent_ids = list("fakebeer", "fernet")
|
||||
|
||||
/obj/item/reagent_containers/borghypo/peace
|
||||
name = "Peace Hypospray"
|
||||
|
||||
reagent_ids = list("dizzysolution","tiresolution","synthpax")
|
||||
reagent_ids = list("dizzysolution", "tiresolution", "synthpax", "insulin")
|
||||
accepts_reagent_upgrades = FALSE
|
||||
|
||||
/obj/item/reagent_containers/borghypo/peace/hacked
|
||||
desc = "Everything's peaceful in death!"
|
||||
icon_state = "borghypo_s"
|
||||
reagent_ids = list("dizzysolution","tiresolution","synthpax","tirizene","sulfonal","sodium_thiopental","cyanide","fentanyl")
|
||||
reagent_ids = list("dizzysolution", "tiresolution", "synthpax", "tirizene", "sulfonal", "sodium_thiopental", "cyanide", "fentanyl")
|
||||
accepts_reagent_upgrades = FALSE
|
||||
|
||||
/obj/item/reagent_containers/borghypo/epi
|
||||
name = "epinephrine injector"
|
||||
name = "Stabilizer injector"
|
||||
desc = "An advanced chemical synthesizer and injection system, designed to stabilize patients."
|
||||
reagent_ids = list("epinephrine")
|
||||
reagent_ids = list("epinephrine", "insulin")
|
||||
accepts_reagent_upgrades = FALSE
|
||||
|
||||
@@ -109,11 +109,13 @@
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker
|
||||
name = "beaker"
|
||||
desc = "A beaker. It can hold up to 50 units. Unable to withstand extreme pHes"
|
||||
desc = "A beaker. It can hold up to 60 units. Unable to withstand extreme pHes."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
volume = 60
|
||||
icon_state = "beaker"
|
||||
item_state = "beaker"
|
||||
materials = list(MAT_GLASS=500)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,60)
|
||||
beaker_weakness_bitflag = PH_WEAK
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/Initialize()
|
||||
@@ -156,28 +158,28 @@
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/jar
|
||||
name = "honey jar"
|
||||
desc = "A jar for honey. It can hold up to 50 units of sweet delight. Unable to withstand reagents of an extreme pH."
|
||||
desc = "A jar for honey. It can hold up to 60 units of sweet delight. Unable to withstand reagents of an extreme pH."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "vapour"
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/large
|
||||
name = "large beaker"
|
||||
desc = "A large beaker. Can hold up to 100 units. Unable to withstand reagents of an extreme pH."
|
||||
desc = "A large beaker. Can hold up to 120 units. Unable to withstand reagents of an extreme pH."
|
||||
icon_state = "beakerlarge"
|
||||
materials = list(MAT_GLASS=2500)
|
||||
volume = 100
|
||||
volume = 120
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,40,60,120)
|
||||
container_HP = 3
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/plastic
|
||||
name = "x-large beaker"
|
||||
desc = "An extra-large beaker. Can hold up to 150 units. Is able to resist acid and alkaline solutions, but melts at 444K"
|
||||
desc = "An extra-large beaker. Can hold up to 180 units. Is able to resist acid and alkaline solutions, but melts at 444 K."
|
||||
icon_state = "beakerwhite"
|
||||
materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000)
|
||||
volume = 150
|
||||
volume = 180
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,150)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,40,60,120,180)
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/plastic/Initialize()
|
||||
beaker_weakness_bitflag &= ~PH_WEAK
|
||||
@@ -191,14 +193,14 @@
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/meta
|
||||
name = "metamaterial beaker"
|
||||
desc = "A large beaker. Can hold up to 200 units. Is able to withstand all chemical situations."
|
||||
desc = "A large beaker. Can hold up to 240 units, and is able to withstand all chemical situations."
|
||||
icon_state = "beakergold"
|
||||
materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000, MAT_GOLD=1000, MAT_TITANIUM=1000)
|
||||
volume = 200
|
||||
volume = 240
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,200)
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,40,60,120,200,240)
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/meta/Initialize()
|
||||
/obj/item/reagent_containers/glass/beaker/meta/Initialize() // why the fuck can't you just set the beaker weakness bitflags to nothing? fuck you
|
||||
beaker_weakness_bitflag &= ~PH_WEAK
|
||||
. = ..()
|
||||
|
||||
@@ -228,7 +230,7 @@
|
||||
volume = 300
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,300)
|
||||
container_HP = 4
|
||||
container_HP = 5
|
||||
|
||||
/obj/item/reagent_containers/glass/beaker/cryoxadone
|
||||
list_reagents = list("cryoxadone" = 30)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//hypovials used with the MkII hypospray. See hypospray.dm.
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial
|
||||
/obj/item/reagent_containers/glass/bottle/vial // these have literally no fucking right to just be better beakers that you can shit out of a chemmaster
|
||||
name = "broken hypovial"
|
||||
desc = "A hypovial compatible with most hyposprays."
|
||||
icon_state = "hypovial"
|
||||
@@ -27,6 +27,8 @@
|
||||
for(var/R in comes_with)
|
||||
reagents.add_reagent(R,comes_with[R])
|
||||
update_icon()
|
||||
// beaker_weakness_bitflag |= PH_WEAK // fuck you if you're using these like beakers
|
||||
// beaker_weakness_bitflag |= TEMP_WEAK
|
||||
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial/on_reagent_change()
|
||||
@@ -60,11 +62,11 @@
|
||||
/obj/item/reagent_containers/glass/bottle/vial/small
|
||||
name = "hypovial"
|
||||
volume = 60
|
||||
possible_transfer_amounts = list(5,10)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30)
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial/small/bluespace
|
||||
volume = 120
|
||||
possible_transfer_amounts = list(5,10)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30,40)
|
||||
name = "bluespace hypovial"
|
||||
icon_state = "hypovialbs"
|
||||
unique_reskin = null
|
||||
@@ -74,7 +76,7 @@
|
||||
desc = "A large hypovial, for deluxe hypospray models."
|
||||
icon_state = "hypoviallarge"
|
||||
volume = 120
|
||||
possible_transfer_amounts = list(5,10,15,20)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30,40,60)
|
||||
unique_reskin = list("large hypovial" = "hypoviallarge",
|
||||
"large red hypovial" = "hypoviallarge-b",
|
||||
"large blue hypovial" = "hypoviallarge-d",
|
||||
@@ -106,7 +108,7 @@
|
||||
add_overlay(filling)
|
||||
|
||||
/obj/item/reagent_containers/glass/bottle/vial/large/bluespace
|
||||
possible_transfer_amounts = list(5,10,15,20)
|
||||
possible_transfer_amounts = list(1,2,5,10,20,30,40,60)
|
||||
name = "bluespace large hypovial"
|
||||
volume = 240
|
||||
icon_state = "hypoviallargebs"
|
||||
|
||||
@@ -152,6 +152,16 @@
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/telescopiciv
|
||||
name = "Telescopic IV Drip"
|
||||
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down."
|
||||
id = "telescopiciv"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(MAT_METAL = 5000, MAT_GLASS = 3500, MAT_SILVER = 1000)
|
||||
build_path = /obj/item/tele_iv
|
||||
category = list("Medical Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/datum/design/holobarrier_med
|
||||
name = "PENLITE holobarrier projector"
|
||||
desc = "PENLITE holobarriers, a device that halts individuals with malicious diseases."
|
||||
|
||||
@@ -25,6 +25,20 @@
|
||||
program_type = /datum/nanite_program/viral
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/research
|
||||
name = "Distributed Computing"
|
||||
desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
|
||||
id = "research_nanites"
|
||||
program_type = /datum/nanite_program/research
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/researchplus
|
||||
name = "Neural Network"
|
||||
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts. Can be overloaded to increase research output."
|
||||
id = "researchplus_nanites"
|
||||
program_type = /datum/nanite_program/researchplus
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/monitoring
|
||||
name = "Monitoring"
|
||||
desc = "The nanites monitor the host's vitals and location, sending them to the suit sensor network."
|
||||
@@ -39,6 +53,13 @@
|
||||
program_type = /datum/nanite_program/triggered/self_scan
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/dermal_button
|
||||
name = "Dermal Button"
|
||||
desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
|
||||
id = "dermal_button_nanites"
|
||||
program_type = /datum/nanite_program/dermal_button
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/stealth
|
||||
name = "Stealth"
|
||||
desc = "The nanites hide their activity and programming from superficial scans."
|
||||
@@ -46,6 +67,15 @@
|
||||
program_type = /datum/nanite_program/stealth
|
||||
category = list("Utility Nanites")
|
||||
|
||||
|
||||
/datum/design/nanites/reduced_diagnostics
|
||||
name = "Reduced Diagnostics"
|
||||
desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
|
||||
Doing so saves some power, slightly increasing their replication speed."
|
||||
id = "red_diag_nanites"
|
||||
program_type = /datum/nanite_program/reduced_diagnostics
|
||||
category = list("Utility Nanites")
|
||||
|
||||
/datum/design/nanites/access
|
||||
name = "Subdermal ID"
|
||||
desc = "The nanites store the host's ID access rights in a subdermal magnetic strip. Updates when triggered, copying the host's current access."
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
|
||||
/datum/nanite_program/stealth
|
||||
name = "Stealth"
|
||||
desc = "The nanites hide their activity and programming from superficial scans."
|
||||
desc = "The nanites mask their activity from superficial scans, becoming undetectable by HUDs and non-specialized scanners."
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
use_rate = 0.2
|
||||
|
||||
@@ -142,6 +142,22 @@
|
||||
. = ..()
|
||||
nanites.stealth = FALSE
|
||||
|
||||
/datum/nanite_program/reduced_diagnostics
|
||||
name = "Reduced Diagnostics"
|
||||
desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
|
||||
Doing so saves some power, slightly increasing their replication speed."
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
use_rate = -0.1
|
||||
|
||||
/datum/nanite_program/reduced_diagnostics/enable_passive_effect()
|
||||
. = ..()
|
||||
nanites.diagnostics = FALSE
|
||||
|
||||
/datum/nanite_program/reduced_diagnostics/disable_passive_effect()
|
||||
. = ..()
|
||||
nanites.diagnostics = TRUE
|
||||
|
||||
|
||||
/datum/nanite_program/relay
|
||||
name = "Relay"
|
||||
desc = "The nanites receive and relay long-range nanite signals."
|
||||
@@ -271,3 +287,138 @@
|
||||
if(fault == src)
|
||||
return
|
||||
fault.software_error()
|
||||
|
||||
/datum/nanite_program/dermal_button
|
||||
name = "Dermal Button"
|
||||
desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
|
||||
extra_settings = list("Sent Code","Button Name","Icon","Color")
|
||||
unique = FALSE
|
||||
var/datum/action/innate/nanite_button/button
|
||||
var/button_name = "Button"
|
||||
var/icon = "power"
|
||||
var/color = "green"
|
||||
var/sent_code = 0
|
||||
|
||||
/datum/nanite_program/dermal_button/set_extra_setting(user, setting)
|
||||
if(setting == "Sent Code")
|
||||
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
|
||||
if(isnull(new_code))
|
||||
return
|
||||
sent_code = CLAMP(round(new_code, 1), 1, 9999)
|
||||
if(setting == "Button Name")
|
||||
var/new_button_name = stripped_input(user, "Choose the name for the button.", "Button Name", button_name, MAX_NAME_LEN)
|
||||
if(!new_button_name)
|
||||
return
|
||||
button_name = new_button_name
|
||||
if(setting == "Icon")
|
||||
var/new_icon = input("Select the icon to display on the button:", name) as null|anything in list("one","two","three","four","five","plus","minus","power")
|
||||
if(!new_icon)
|
||||
return
|
||||
icon = new_icon
|
||||
if(setting == "Color")
|
||||
var/new_color = input("Select the color of the button's icon:", name) as null|anything in list("green","red","yellow","blue")
|
||||
if(!new_color)
|
||||
return
|
||||
color = new_color
|
||||
|
||||
/datum/nanite_program/dermal_button/get_extra_setting(setting)
|
||||
if(setting == "Sent Code")
|
||||
return sent_code
|
||||
if(setting == "Button Name")
|
||||
return button_name
|
||||
if(setting == "Icon")
|
||||
return capitalize(icon)
|
||||
if(setting == "Color")
|
||||
return capitalize(color)
|
||||
|
||||
/datum/nanite_program/dermal_button/copy_extra_settings_to(datum/nanite_program/dermal_button/target)
|
||||
target.sent_code = sent_code
|
||||
target.button_name = button_name
|
||||
target.icon = icon
|
||||
target.color = color
|
||||
|
||||
/datum/nanite_program/dermal_button/enable_passive_effect()
|
||||
. = ..()
|
||||
if(!button)
|
||||
button = new(src, button_name, icon, color)
|
||||
button.target = host_mob
|
||||
button.Grant(host_mob)
|
||||
|
||||
/datum/nanite_program/dermal_button/disable_passive_effect()
|
||||
. = ..()
|
||||
if(button)
|
||||
button.Remove(host_mob)
|
||||
|
||||
/datum/nanite_program/dermal_button/on_mob_remove()
|
||||
. = ..()
|
||||
qdel(button)
|
||||
|
||||
/datum/nanite_program/dermal_button/proc/press()
|
||||
if(activated)
|
||||
host_mob.visible_message("<span class='notice'>[host_mob] presses a button on [host_mob.p_their()] forearm.</span>",
|
||||
"<span class='notice'>You press the nanite button on your forearm.</span>", null, 2)
|
||||
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, sent_code, "a [name] program")
|
||||
|
||||
/datum/action/innate/nanite_button
|
||||
name = "Button"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
|
||||
button_icon_state = "power_green"
|
||||
var/datum/nanite_program/dermal_button/program
|
||||
|
||||
/datum/action/innate/nanite_button/New(datum/nanite_program/dermal_button/_program, _name, _icon, _color)
|
||||
..()
|
||||
program = _program
|
||||
name = _name
|
||||
button_icon_state = "[_icon]_[_color]"
|
||||
|
||||
/datum/action/innate/nanite_button/Activate()
|
||||
program.press()
|
||||
|
||||
/datum/nanite_program/research
|
||||
name = "Distributed Computing"
|
||||
desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
|
||||
use_rate = 0.2
|
||||
rogue_types = list(/datum/nanite_program/toxic)
|
||||
|
||||
/datum/nanite_program/research/active_effect()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
var/points = 1
|
||||
if(!host_mob.client) //less brainpower
|
||||
points *= 0.25
|
||||
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
|
||||
|
||||
/datum/nanite_program/researchplus
|
||||
name = "Neural Network"
|
||||
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts."
|
||||
use_rate = 0.3
|
||||
rogue_types = list(/datum/nanite_program/brain_decay)
|
||||
|
||||
/datum/nanite_program/researchplus/enable_passive_effect()
|
||||
. = ..()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
if(host_mob.client)
|
||||
SSnanites.neural_network_count++
|
||||
else
|
||||
SSnanites.neural_network_count += 0.25
|
||||
|
||||
/datum/nanite_program/researchplus/disable_passive_effect()
|
||||
. = ..()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
if(host_mob.client)
|
||||
SSnanites.neural_network_count--
|
||||
else
|
||||
SSnanites.neural_network_count -= 0.25
|
||||
|
||||
/datum/nanite_program/researchplus/active_effect()
|
||||
if(!iscarbon(host_mob))
|
||||
return
|
||||
var/mob/living/carbon/C = host_mob
|
||||
var/points = round(SSnanites.neural_network_count / 12, 0.1)
|
||||
if(!C.client) //less brainpower
|
||||
points *= 0.25
|
||||
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
|
||||
|
||||
|
||||
@@ -130,4 +130,16 @@
|
||||
program_type = /datum/nanite_program/pacifying
|
||||
|
||||
/obj/item/disk/nanite_program/stun
|
||||
program_type = /datum/nanite_program/triggered/stun
|
||||
program_type = /datum/nanite_program/triggered/stun
|
||||
|
||||
/obj/item/disk/nanite_program/dermal_button
|
||||
program_type = /datum/nanite_program/dermal_button
|
||||
|
||||
/obj/item/disk/nanite_program/research
|
||||
program_type = /datum/nanite_program/research
|
||||
|
||||
/obj/item/disk/nanite_program/researchplus
|
||||
program_type = /datum/nanite_program/researchplus
|
||||
|
||||
/obj/item/disk/nanite_program/reduced_diagnostics
|
||||
program_type = /datum/nanite_program/reduced_diagnostics
|
||||
@@ -71,7 +71,7 @@
|
||||
display_name = "Biological Technology"
|
||||
description = "What makes us tick." //the MC, silly!
|
||||
prereq_ids = list("base")
|
||||
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen")
|
||||
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
@@ -960,7 +960,7 @@
|
||||
prereq_ids = list("datatheory","robotics")
|
||||
design_ids = list("nanite_disk","nanite_remote","nanite_scanner",\
|
||||
"nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\
|
||||
"relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites")
|
||||
"relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
@@ -969,7 +969,7 @@
|
||||
display_name = "Smart Nanite Programming"
|
||||
description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets."
|
||||
prereq_ids = list("nanite_base","adv_robotics")
|
||||
design_ids = list("purging_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
|
||||
design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000)
|
||||
export_price = 4000
|
||||
|
||||
@@ -978,7 +978,7 @@
|
||||
display_name = "Mesh Nanite Programming"
|
||||
description = "Nanite programs that require static structures and membranes."
|
||||
prereq_ids = list("nanite_base","engineering")
|
||||
design_ids = list("hardening_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
|
||||
design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
@@ -1015,7 +1015,7 @@
|
||||
display_name = "Harmonic Nanite Programming"
|
||||
description = "Nanite programs that require seamless integration between nanites and biology."
|
||||
prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh")
|
||||
design_ids = list("fakedeath_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
|
||||
design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000)
|
||||
export_price = 8000
|
||||
|
||||
|
||||
@@ -560,7 +560,7 @@
|
||||
else if((findtext(message, honk_words)))
|
||||
cooldown = COOLDOWN_MEME
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, get_turf(user), 'sound/items/bikehorn.ogg', 300, 1), 25)
|
||||
if(user.mind && user.mind.assigned_role == "Clown")
|
||||
if(user.mind && HAS_TRAIT(user.mind, TRAIT_CLOWN_MENTALITY))
|
||||
for(var/mob/living/carbon/C in listeners)
|
||||
C.slip(140 * power_multiplier)
|
||||
cooldown = COOLDOWN_MEME
|
||||
@@ -807,9 +807,8 @@
|
||||
E.enthrallTally += (power_multiplier*(((length(message))/200) + 1)) //encourage players to say more than one word.
|
||||
else
|
||||
E.enthrallTally += power_multiplier*1.25 //thinking about it, I don't know how this can proc
|
||||
if(L.canbearoused)
|
||||
if(L.client?.prefs.lewdchem)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='nicegreen'><i><b>[E.enthrallGender] is so nice to listen to.</b></i></span>"), 5)
|
||||
if(L.canbearoused && E.lewd)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='nicegreen'><i><b>[E.enthrallGender] is so nice to listen to.</b></i></span>"), 5)
|
||||
E.cooldown += 1
|
||||
|
||||
//REWARD mixable works
|
||||
@@ -820,7 +819,7 @@
|
||||
power_multiplier *= distancelist[get_dist(user, V)+1]
|
||||
if(L == user)
|
||||
continue
|
||||
if (L.client?.prefs.lewdchem)
|
||||
if (E.lewd)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='love'>[E.enthrallGender] has praised me!!</span>"), 5)
|
||||
if(HAS_TRAIT(L, TRAIT_NYMPHO))
|
||||
L.adjustArousalLoss(2*power_multiplier)
|
||||
@@ -832,7 +831,7 @@
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='nicegreen'><b><i>I've been praised for doing a good job!</b></i></span>"), 5)
|
||||
E.resistanceTally -= power_multiplier
|
||||
E.enthrallTally += power_multiplier
|
||||
var/descmessage = "<span class='love'><i>[(L.client?.prefs.lewdchem?"I feel so happy! I'm a good pet who [E.enthrallGender] loves!":"I did a good job!")]</i></span>"
|
||||
var/descmessage = "<span class='love'><i>[(E.lewd?"I feel so happy! I'm a good pet who [E.enthrallGender] loves!":"I did a good job!")]</i></span>"
|
||||
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "enthrallpraise", /datum/mood_event/enthrallpraise, descmessage)
|
||||
E.cooldown += 1
|
||||
|
||||
@@ -841,10 +840,10 @@
|
||||
for(var/V in listeners)
|
||||
var/mob/living/L = V
|
||||
var/datum/status_effect/chem/enthrall/E = L.has_status_effect(/datum/status_effect/chem/enthrall)
|
||||
var/descmessage = "[(L.client?.prefs.lewdchem?"I've failed [E.enthrallGender]... What a bad, bad pet!":"I did a bad job...")]"
|
||||
var/descmessage = "[(E.lewd?"I've failed [E.enthrallGender]... What a bad, bad pet!":"I did a bad job...")]"
|
||||
if(L == user)
|
||||
continue
|
||||
if (L.client?.prefs.lewdchem)
|
||||
if (E.lewd)
|
||||
if(HAS_TRAIT(L, TRAIT_MASO))
|
||||
L.adjustArousalLoss(3*power_multiplier)
|
||||
descmessage += "And yet, it feels so good..!</span>" //I don't really understand masco, is this the right sort of thing they like?
|
||||
@@ -871,7 +870,7 @@
|
||||
var/datum/status_effect/chem/enthrall/E = C.has_status_effect(/datum/status_effect/chem/enthrall)
|
||||
REMOVE_TRAIT(C, TRAIT_MUTE, "enthrall")
|
||||
C.silent = 0
|
||||
if(C.client?.prefs.lewdchem)
|
||||
if(E.lewd)
|
||||
addtimer(CALLBACK(C, /atom/movable/proc/say, "[E.enthrallGender]"), 5)
|
||||
else
|
||||
addtimer(CALLBACK(C, /atom/movable/proc/say, "[E.master]"), 5)
|
||||
@@ -887,7 +886,7 @@
|
||||
E.phase = 3
|
||||
E.status = null
|
||||
user.emote("snap")
|
||||
if(L.client?.prefs.lewdchem)
|
||||
if(E.lewd)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='big warning'>The snapping of your [E.enthrallGender]'s fingers brings you back to your enthralled state, obedient and ready to serve.</b></span>"), 5)
|
||||
else
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='big warning'>The snapping of [E.master]'s fingers brings you back to being under their influence.</b></span>"), 5)
|
||||
@@ -910,11 +909,11 @@
|
||||
addtimer(CALLBACK(H, /atom/movable/proc/say, "I feel happy being with you."), 5)
|
||||
continue
|
||||
if(2)
|
||||
speaktrigger += "[(H.client?.prefs.lewdchem?"I think I'm in love with you... ":"I find you really inspirational, ")]" //'
|
||||
speaktrigger += "[(E.lewd?"I think I'm in love with you... ":"I find you really inspirational, ")]" //'
|
||||
if(3)
|
||||
speaktrigger += "[(H.client?.prefs.lewdchem?"I'm devoted to being your pet":"I'm commited to following your cause!")]! "
|
||||
speaktrigger += "[(E.lewd?"I'm devoted to being your pet":"I'm commited to following your cause!")]! "
|
||||
if(4)
|
||||
speaktrigger += "[(H.client?.prefs.lewdchem?"You are my whole world and all of my being belongs to you, ":"I cannot think of anything else but aiding your cause, ")] "//Redflags!!
|
||||
speaktrigger += "[(E.lewd?"You are my whole world and all of my being belongs to you, ":"I cannot think of anything else but aiding your cause, ")] "//Redflags!!
|
||||
|
||||
//mood
|
||||
var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
|
||||
@@ -1003,7 +1002,7 @@
|
||||
speaktrigger += "I feel like I'm on the brink of losing my mind, "
|
||||
|
||||
//horny
|
||||
if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && H.client?.prefs.lewdchem)
|
||||
if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd)
|
||||
switch(H.getArousalLoss())
|
||||
if(40 to 60)
|
||||
speaktrigger += "I'm feeling a little horny, "
|
||||
@@ -1013,10 +1012,10 @@
|
||||
speaktrigger += "I'm really, really horny, "
|
||||
|
||||
//collar
|
||||
if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && H.client?.prefs.lewdchem)
|
||||
if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && E.lewd)
|
||||
speaktrigger += "I love the collar you gave me, "
|
||||
//End
|
||||
if(H.client?.prefs.lewdchem)
|
||||
if(E.lewd)
|
||||
speaktrigger += "[E.enthrallGender]!"
|
||||
else
|
||||
speaktrigger += "[user.first_name()]!"
|
||||
@@ -1044,7 +1043,7 @@
|
||||
REMOVE_TRAIT(C, TRAIT_MUTE, "enthrall")
|
||||
C.silent = 0
|
||||
E.cooldown += 3
|
||||
to_chat(user, "<span class='notice'><i>You [(C.client?.prefs.lewdchem?"allow [C] to speak again":"encourage [C] to speak again")].</i></span>")
|
||||
to_chat(user, "<span class='notice'><i>You [(E.lewd?"allow [C] to speak again":"encourage [C] to speak again")].</i></span>")
|
||||
|
||||
|
||||
//Antiresist
|
||||
@@ -1074,7 +1073,7 @@
|
||||
for(var/mob/living/carbon/C in listeners)
|
||||
var/datum/status_effect/chem/enthrall/E = C.has_status_effect(/datum/status_effect/chem/enthrall)
|
||||
if(E.phase == 4)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='warning'>You're unable to forget about [(C.client?.prefs.lewdchem?"the dominating presence of [E.enthrallGender]":"[E.master]")]!</b></span>"), 5)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='warning'>You're unable to forget about [(E.lewd?"the dominating presence of [E.enthrallGender]":"[E.master]")]!</b></span>"), 5)
|
||||
continue
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='warning'>You wake up, forgetting everything that just happened. You must've dozed off..? How embarassing!</b></span>"), 5)
|
||||
C.Sleeping(50)
|
||||
@@ -1086,7 +1085,7 @@
|
||||
if(3)
|
||||
E.phase = 0
|
||||
E.cooldown = 0
|
||||
if(C.client?.prefs.lewdchem)
|
||||
if(E.lewd)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='big warning'>You revert to yourself before being enthralled by your [E.enthrallGender], with no memory of what happened.</b></span>"), 5)
|
||||
else
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='big warning'>You revert to who you were before, with no memory of what happened with [E.master].</b></span>"), 5)
|
||||
@@ -1112,7 +1111,7 @@
|
||||
var/mob/living/carbon/human/H = V
|
||||
var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall)
|
||||
if(E.phase > 1)
|
||||
if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && H.client?.prefs.lewdchem) // probably a redundant check but for good measure
|
||||
if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd) // probably a redundant check but for good measure
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='love'>Your [E.enthrallGender] pushes you over the limit, overwhelming your body with pleasure.</b></span>"), 5)
|
||||
H.mob_climax(forced_climax=TRUE)
|
||||
H.SetStun(20)
|
||||
@@ -1168,7 +1167,7 @@
|
||||
for(var/obj/item/W in items)
|
||||
if(W == H.wear_suit)
|
||||
H.dropItemToGround(W, TRUE)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='[(H.client?.prefs.lewdchem?"love":"warning")]'>Before you can even think about it, you quickly remove your clothes in response to [(H.client?.prefs.lewdchem?"your [E.enthrallGender]'s command'":"[E.master]'s directive'")].</b></span>"), 5)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='[(E.lewd?"love":"warning")]'>Before you can even think about it, you quickly remove your clothes in response to [(E.lewd?"your [E.enthrallGender]'s command'":"[E.master]'s directive'")].</b></span>"), 5)
|
||||
E.cooldown += 10
|
||||
|
||||
//WALK
|
||||
@@ -1206,7 +1205,7 @@
|
||||
if(2 to INFINITY)
|
||||
L.lay_down()
|
||||
E.cooldown += 10
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[(L.client?.prefs.lewdchem?"<span class='love'>You eagerly lie down!":"<span class='notice'>You suddenly lie down!")]</b></span>"), 5)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "[(E.lewd?"<span class='love'>You eagerly lie down!":"<span class='notice'>You suddenly lie down!")]</b></span>"), 5)
|
||||
to_chat(user, "<span class='notice'><i>You encourage [L] to lie down.</i></span>")
|
||||
|
||||
//KNOCKDOWN
|
||||
@@ -1237,7 +1236,7 @@
|
||||
for (var/trigger in E.customTriggers)
|
||||
speaktrigger += "[trigger], "
|
||||
to_chat(user, "<b>[C]</b> whispers, \"<i>[speaktrigger] are my triggers.</i>\"")//So they don't trigger themselves!
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='notice'>You whisper your triggers to [(C.client?.prefs.lewdchem?"Your [E.enthrallGender]":"[E.master]")].</span>"), 5)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='notice'>You whisper your triggers to [(E.lewd?"Your [E.enthrallGender]":"[E.master]")].</span>"), 5)
|
||||
|
||||
|
||||
//CUSTOM TRIGGERS
|
||||
@@ -1249,7 +1248,7 @@
|
||||
if (get_dist(user, H) > 1)//Requires user to be next to their pet.
|
||||
to_chat(user, "<span class='warning'>You need to be next to your pet to give them a new trigger!</b></span>")
|
||||
continue
|
||||
if(!H.client?.prefs.lewdchem)
|
||||
if(!E.lewd)
|
||||
to_chat(user, "<span class='warning'>[H] seems incapable of being implanted with triggers.</b></span>")
|
||||
continue
|
||||
else
|
||||
@@ -1272,7 +1271,7 @@
|
||||
E.customTriggers[trigger] = trigger2
|
||||
log_game("FERMICHEM: [H] has been implanted by [user] with [trigger], triggering [trigger2].")
|
||||
E.mental_capacity -= 5
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='notice'>[(H.client?.prefs.lewdchem?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger.</span>"), 5)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='notice'>[(E.lewd?"your [E.enthrallGender]":"[E.master]")] whispers you a new trigger.</span>"), 5)
|
||||
to_chat(user, "<span class='notice'><i>You sucessfully set the trigger word [trigger] in [H]</i></span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Your pet looks at you confused, it seems they don't understand that effect!</b></span>")
|
||||
@@ -1290,7 +1289,7 @@
|
||||
if (get_dist(user, H) > 1)//Requires user to be next to their pet.
|
||||
to_chat(user, "<span class='warning'>You need to be next to your pet to give them a new echophrase!</b></span>")
|
||||
continue
|
||||
if(!H.client?.prefs.lewdchem)
|
||||
if(!E.lewd)
|
||||
to_chat(user, "<span class='warning'>[H] seems incapable of being implanted with an echoing phrase.</b></span>")
|
||||
continue
|
||||
else
|
||||
@@ -1334,7 +1333,7 @@
|
||||
objective = replacetext(lowertext(objective), "suicide", "self-love")
|
||||
message_admins("[H] has been implanted by [user] with the objective [objective].")
|
||||
log_game("FERMICHEM: [H] has been implanted by [user] with the objective [objective] via MKUltra.")
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='notice'>[(H.client?.prefs.lewdchem?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective.</span>"), 5)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='notice'>[(E.lewd?"Your [E.enthrallGender]":"[E.master]")] whispers you a new objective.</span>"), 5)
|
||||
brainwash(H, objective)
|
||||
E.mental_capacity -= 200
|
||||
to_chat(user, "<span class='notice'><i>You sucessfully give an objective to [H]</i></span>")
|
||||
@@ -1348,7 +1347,7 @@
|
||||
for(var/V in listeners)
|
||||
var/mob/living/carbon/human/H = V
|
||||
var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall)
|
||||
if(E.phase >= 3 && H.client?.prefs.lewdchem)
|
||||
if(E.phase >= 3 && E.lewd)
|
||||
var/instill = stripped_input(user, "Instill an emotion in [H].", MAX_MESSAGE_LEN)
|
||||
to_chat(H, "<i>[instill]</i>")
|
||||
to_chat(user, "<span class='notice'><i>You sucessfully instill a feeling in [H]</i></span>")
|
||||
@@ -1363,7 +1362,7 @@
|
||||
if(E.phase > 1)
|
||||
if(user.ckey == E.enthrallID && user.real_name == E.master.real_name)
|
||||
E.master = user
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='nicegreen'>[(H.client?.prefs.lewdchem?"You hear the words of your [E.enthrallGender] again!! They're back!!":"You recognise the voice of [E.master].")]</b></span>"), 5)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='nicegreen'>[(E.lewd?"You hear the words of your [E.enthrallGender] again!! They're back!!":"You recognise the voice of [E.master].")]</b></span>"), 5)
|
||||
to_chat(user, "<span class='notice'><i>[H] looks at you with sparkling eyes, recognising you!</i></span>")
|
||||
|
||||
//I dunno how to do state objectives without them revealing they're an antag
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
/obj/vehicle/sealed/car/clowncar/auto_assign_occupant_flags(mob/M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.mind && H.mind.assigned_role == "Clown") //Ensures only clowns can drive the car. (Including more at once)
|
||||
if(H.mind && HAS_TRAIT(H.mind, TRAIT_CLOWN_MENTALITY)) //Ensures only clowns can drive the car. (Including more at once)
|
||||
add_control_flags(M, VEHICLE_CONTROL_DRIVE|VEHICLE_CONTROL_PERMISSION)
|
||||
return
|
||||
add_control_flags(M, VEHICLE_CONTROL_KIDNAPPED)
|
||||
|
||||
@@ -70,14 +70,22 @@
|
||||
/obj/item/clothing/under/skirt/red = 3,
|
||||
/obj/item/clothing/under/skirt/purple = 3,
|
||||
/obj/item/clothing/under/sundress = 4,
|
||||
/obj/item/clothing/under/sundresswhite = 4,
|
||||
/obj/item/clothing/under/stripeddress = 3,
|
||||
/obj/item/clothing/under/sailordress = 3,
|
||||
/obj/item/clothing/under/sweptskirt = 3,
|
||||
/obj/item/clothing/under/greendress = 3,
|
||||
/obj/item/clothing/under/pinkdress = 3,
|
||||
/obj/item/clothing/under/redeveninggown = 3,
|
||||
/obj/item/clothing/under/blacktango = 3,
|
||||
/obj/item/clothing/under/westernbustle = 3,
|
||||
/obj/item/clothing/under/flamenco = 3,
|
||||
/obj/item/clothing/under/flowerdress = 3,
|
||||
/obj/item/clothing/under/plaid_skirt = 3,
|
||||
/obj/item/clothing/under/plaid_skirt/blue = 3,
|
||||
/obj/item/clothing/under/plaid_skirt/purple = 3,
|
||||
/obj/item/clothing/under/plaid_skirt/green = 3,
|
||||
/obj/item/clothing/under/croptop = 3,
|
||||
/obj/item/clothing/glasses/regular = 2,
|
||||
/obj/item/clothing/glasses/regular/jamjar = 2,
|
||||
/obj/item/clothing/head/sombrero = 3,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
/obj/item/seeds/chanter = 3,
|
||||
/obj/item/seeds/chili = 3,
|
||||
/obj/item/seeds/cocoapod = 3,
|
||||
/obj/item/seeds/coconut = 3,
|
||||
/obj/item/seeds/coffee = 3,
|
||||
/obj/item/seeds/cotton = 3,
|
||||
/obj/item/seeds/corn = 3,
|
||||
|
||||
Reference in New Issue
Block a user