thank you github

This commit is contained in:
BlackMajor
2020-01-02 22:16:47 +13:00
parent da3ab71222
commit 08d042901c
309 changed files with 4101 additions and 1577 deletions
+8 -9
View File
@@ -9,13 +9,12 @@
#define META_GAS_FUSION_POWER 7 #define META_GAS_FUSION_POWER 7
//ATMOS //ATMOS
//stuff you should probably leave well alone! //stuff you should probably leave well alone!
#define R_IDEAL_GAS_EQUATION 8.31446261815324 //kPa*L/(K*mol) #define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa #define ONE_ATMOSPHERE 101.325 //kPa
#define TCMB 2.7 // -270.3degC #define TCMB 2.7 // -270.3degC
#define TCRYO 225 // -48.15degC #define TCRYO 225 // -48.15degC
#define T0C 273.15 // 0degC #define T0C 273.15 // 0degC
#define T20C 293.15 // 20degC #define T20C 293.15 // 20degC
#define STEFANBOLTZMANN (5.670373*10e-8) // W/(m^2*K^4)
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC #define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity #define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005) //compared against for superconductivity
@@ -150,9 +149,9 @@
//OPEN TURF ATMOS //OPEN TURF ATMOS
#define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15" //the default air mix that open turfs spawn #define OPENTURF_DEFAULT_ATMOS "o2=22;n2=82;TEMP=293.15" //the default air mix that open turfs spawn
#define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms #define TCOMMS_ATMOS "n2=100;TEMP=80" //-193,15°C telecommunications. also used for xenobiology slime killrooms
#define AIRLESS_ATMOS "TEMP=2.7" //space #define AIRLESS_ATMOS "TEMP=2.7" //space
#define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs #define FROZEN_ATMOS "o2=22;n2=82;TEMP=180" //-93.15°C snow and ice turfs
#define BURNMIX_ATMOS "o2=2500;plasma=5000;TEMP=370" //used in the holodeck burn test program #define BURNMIX_ATMOS "o2=2500;plasma=5000;TEMP=370" //used in the holodeck burn test program
//ATMOSPHERICS DEPARTMENT GAS TANK TURFS //ATMOSPHERICS DEPARTMENT GAS TANK TURFS
+9 -1
View File
@@ -109,8 +109,16 @@
#define MEDIHOUND_SLEEPER (1<<0) #define MEDIHOUND_SLEEPER (1<<0)
#define EATING_NOISES (1<<1) #define EATING_NOISES (1<<1)
#define DIGESTION_NOISES (1<<2) #define DIGESTION_NOISES (1<<2)
#define BREAST_ENLARGEMENT (1<<3)
#define PENIS_ENLARGEMENT (1<<4)
#define FORCED_FEM (1<<5)
#define FORCED_MASC (1<<6)
#define HYPNO (1<<7)
#define NEVER_HYPNO (1<<8)
#define NO_APHRO (1<<9)
#define NO_ASS_SLAP (1<<10)
#define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES) #define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES|BREAST_ENLARGEMENT|PENIS_ENLARGEMENT)
//component stuff //component stuff
#define COMSIG_COMBAT_TOGGLED "combatmode_toggled" //called by combat mode toggle on all equipped items. args: (mob/user, combatmode) #define COMSIG_COMBAT_TOGGLED "combatmode_toggled" //called by combat mode toggle on all equipped items. args: (mob/user, combatmode)
+2
View File
@@ -528,3 +528,5 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define FOURSPACES "&nbsp;&nbsp;&nbsp;&nbsp;" #define FOURSPACES "&nbsp;&nbsp;&nbsp;&nbsp;"
#define CRYOMOBS 'icons/obj/cryo_mobs.dmi' #define CRYOMOBS 'icons/obj/cryo_mobs.dmi'
#define CANT_REENTER_ROUND -1
+5 -3
View File
@@ -134,6 +134,7 @@
#define TRAIT_NORUNNING "norunning" // You walk! #define TRAIT_NORUNNING "norunning" // You walk!
#define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites. #define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites.
#define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat. #define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat.
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
//non-mob traits //non-mob traits
@@ -160,17 +161,16 @@
#define TRAIT_TAGGER "tagger" #define TRAIT_TAGGER "tagger"
#define TRAIT_PHOTOGRAPHER "photographer" #define TRAIT_PHOTOGRAPHER "photographer"
#define TRAIT_MUSICIAN "musician" #define TRAIT_MUSICIAN "musician"
#define TRAIT_CROCRIN_IMMUNE "crocin_immune"
#define TRAIT_NYMPHO "nymphomania" #define TRAIT_NYMPHO "nymphomania"
#define TRAIT_MASO "masochism" #define TRAIT_MASO "masochism"
#define TRAIT_EXHIBITIONIST "exhibitionist" #define TRAIT_EXHIBITIONIST "exhibitionist"
#define TRAIT_HIGH_BLOOD "high_blood" #define TRAIT_HIGH_BLOOD "high_blood"
#define TRAIT_PHARMA "hepatic_pharmacokinesis"
#define TRAIT_PARA "paraplegic" #define TRAIT_PARA "paraplegic"
#define TRAIT_EMPATH "empath" #define TRAIT_EMPATH "empath"
#define TRAIT_FRIENDLY "friendly" #define TRAIT_FRIENDLY "friendly"
#define TRAIT_ASSBLASTUSA "assblastusa"
#define TRAIT_CULT_EYES "cult_eyes" #define TRAIT_CULT_EYES "cult_eyes"
#define TRAIT_AUTO_CATCH_ITEM "auto_catch_item"
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
#define TRAIT_FREESPRINT "free_sprinting" #define TRAIT_FREESPRINT "free_sprinting"
@@ -193,6 +193,7 @@
#define ABSTRACT_ITEM_TRAIT "abstract-item" #define ABSTRACT_ITEM_TRAIT "abstract-item"
#define STATUS_EFFECT_TRAIT "status-effect" #define STATUS_EFFECT_TRAIT "status-effect"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention #define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
#define GHOSTROLE_TRAIT "ghostrole"
// unique trait sources, still defines // unique trait sources, still defines
#define STATUE_MUTE "statue" #define STATUE_MUTE "statue"
@@ -228,6 +229,7 @@
#define SLEEPING_CARP_TRAIT "sleeping_carp" #define SLEEPING_CARP_TRAIT "sleeping_carp"
#define RISING_BASS_TRAIT "rising_bass" #define RISING_BASS_TRAIT "rising_bass"
#define ABDUCTOR_ANTAGONIST "abductor-antagonist" #define ABDUCTOR_ANTAGONIST "abductor-antagonist"
#define NUKEOP_ANTAGONIST "nukeop-antagonist"
#define MADE_UNCLONEABLE "made-uncloneable" #define MADE_UNCLONEABLE "made-uncloneable"
#define NUKEOP_TRAIT "nuke-op" #define NUKEOP_TRAIT "nuke-op"
#define DEATHSQUAD_TRAIT "deathsquad" #define DEATHSQUAD_TRAIT "deathsquad"
+1 -1
View File
@@ -447,7 +447,7 @@
var/list/candidates = list() var/list/candidates = list()
for(var/mob/dead/observer/G in GLOB.player_list) for(var/mob/dead/observer/G in GLOB.player_list)
if(G.reenter_round_timeout < world.realtime) if(G.can_reenter_round(TRUE))
candidates += G candidates += G
return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates) return pollCandidates(Question, jobbanType, gametypeCheck, be_special_flag, poll_time, ignore_category, flashwindow, candidates)
-2
View File
@@ -20,8 +20,6 @@
else else
return "000" return "000"
#define UNDIE_COLORABLE(U) (U?.has_color)
/proc/random_underwear(gender) /proc/random_underwear(gender)
if(!GLOB.underwear_list.len) if(!GLOB.underwear_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/bottom, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f) init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear/bottom, GLOB.underwear_list, GLOB.underwear_m, GLOB.underwear_f)
+3
View File
@@ -19,6 +19,9 @@
var/list/mob_data = list() var/list/mob_data = list()
if(isnewplayer(m)) if(isnewplayer(m))
continue continue
if (m.client && m.client.prefs && m.client.prefs.auto_ooc)
if (!(m.client.prefs.chat_toggles & CHAT_OOC))
m.client.prefs.chat_toggles ^= CHAT_OOC
if(m.mind) if(m.mind)
if(m.stat != DEAD && !isbrain(m) && !iscameramob(m)) if(m.stat != DEAD && !isbrain(m) && !iscameramob(m))
num_survivors++ num_survivors++
-10
View File
@@ -758,16 +758,6 @@ GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
/obj/item/stack/rods, /obj/item/stack/rods,
/obj/item/pipe))) /obj/item/pipe)))
/proc/can_embed(obj/item/W)
if(W.get_sharpness())
return 1
if(is_pointed(W))
return 1
if(is_type_in_typecache(W, GLOB.can_embed_types))
return 1
/* /*
Checks if that loc and dir has an item on the wall Checks if that loc and dir has an item on the wall
*/ */
@@ -115,5 +115,6 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/clothing/shoes/kindleKicks = 1, /obj/item/clothing/shoes/kindleKicks = 1,
/obj/item/autosurgeon/penis = 1, /obj/item/autosurgeon/penis = 1,
/obj/item/autosurgeon/testicles = 1, /obj/item/autosurgeon/testicles = 1,
/obj/item/storage/box/marshmallow = 2,
"" = 3 "" = 3
)) ))
+11 -9
View File
@@ -98,17 +98,19 @@
take_damage(I.force, I.damtype, "melee", 1) take_damage(I.force, I.damtype, "melee", 1)
/mob/living/attacked_by(obj/item/I, mob/living/user) /mob/living/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
//CIT CHANGES END HERE
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
return FALSE
send_item_attack_message(I, user) send_item_attack_message(I, user)
if(I.force) 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
//CIT CHANGES END HERE
apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage apply_damage(totitemdamage, I.damtype) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW)) if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
if(prob(33)) if(prob(33))
+2
View File
@@ -91,6 +91,8 @@
var/obj/item/clothing/gloves/G = gloves var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves if(istype(G) && G.Touch(A,0)) // for magic gloves
return return
if (istype(glasses) && glasses.ranged_attack(src,A,mouseparams))
return
for(var/datum/mutation/human/HM in dna.mutations) for(var/datum/mutation/human/HM in dna.mutations)
HM.on_ranged_attack(src, A, mouseparams) HM.on_ranged_attack(src, A, mouseparams)
@@ -6,6 +6,7 @@ PROCESSING_SUBSYSTEM_DEF(nanites)
var/list/datum/nanite_cloud_backup/cloud_backups = list() var/list/datum/nanite_cloud_backup/cloud_backups = list()
var/list/mob/living/nanite_monitored_mobs = list() var/list/mob/living/nanite_monitored_mobs = list()
var/list/datum/nanite_program/relay/nanite_relays = list() var/list/datum/nanite_program/relay/nanite_relays = list()
var/neural_network_count = 0
/datum/controller/subsystem/processing/nanites/proc/check_hardware(datum/nanite_cloud_backup/backup) /datum/controller/subsystem/processing/nanites/proc/check_hardware(datum/nanite_cloud_backup/backup)
if(QDELETED(backup.storage) || (backup.storage.stat & (NOPOWER|BROKEN))) if(QDELETED(backup.storage) || (backup.storage.stat & (NOPOWER|BROKEN)))
+3
View File
@@ -401,6 +401,9 @@ SUBSYSTEM_DEF(ticker)
qdel(player) qdel(player)
living.notransform = TRUE living.notransform = TRUE
if(living.client) if(living.client)
if (living.client.prefs && living.client.prefs.auto_ooc)
if (living.client.prefs.chat_toggles & CHAT_OOC)
living.client.prefs.chat_toggles ^= CHAT_OOC
var/obj/screen/splash/S = new(living.client, TRUE) var/obj/screen/splash/S = new(living.client, TRUE)
S.Fade(TRUE) S.Fade(TRUE)
livings += living livings += living
+2 -2
View File
@@ -32,7 +32,7 @@
if(ishuman(M) && source.force && source.get_sharpness()) if(ishuman(M) && source.force && source.get_sharpness())
var/mob/living/carbon/human/H = M var/mob/living/carbon/human/H = M
if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping()) && user.zone_selected == BODY_ZONE_HEAD) // Only sleeping, neck grabbed, or crit, can be sliced. if((H.health <= H.crit_threshold || (user.pulling == H && user.grab_state >= GRAB_NECK) || H.IsSleeping()) && user.zone_selected == BODY_ZONE_PRECISE_MOUTH) // Only sleeping, neck grabbed, or crit, can be sliced.
if(H.has_status_effect(/datum/status_effect/neck_slice)) if(H.has_status_effect(/datum/status_effect/neck_slice))
user.show_message("<span class='warning'>[H]'s neck has already been already cut, you can't make the bleeding any worse!</span>", 1, \ user.show_message("<span class='warning'>[H]'s neck has already been already cut, you can't make the bleeding any worse!</span>", 1, \
"<span class='warning'>Their neck has already been already cut, you can't make the bleeding any worse!</span>") "<span class='warning'>Their neck has already been already cut, you can't make the bleeding any worse!</span>")
@@ -120,4 +120,4 @@
if(eater.safety_mode || (eater.stat & (BROKEN|NOPOWER))) //I'm so sorry. if(eater.safety_mode || (eater.stat & (BROKEN|NOPOWER))) //I'm so sorry.
return return
if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results)) if(L.stat == DEAD && (L.butcher_results || L.guaranteed_butcher_results))
Butcher(parent, L) Butcher(parent, L)
+5 -4
View File
@@ -11,8 +11,9 @@
var/list/datum/nanite_program/programs = list() var/list/datum/nanite_program/programs = list()
var/max_programs = NANITE_PROGRAM_LIMIT var/max_programs = NANITE_PROGRAM_LIMIT
var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans, and does not display the program list on nanite scans var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans
var/diagnostics = TRUE //if TRUE, displays program list when scanned by nanite scanners
/datum/component/nanites/Initialize(amount = 100, cloud = 0) /datum/component/nanites/Initialize(amount = 100, cloud = 0)
if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup)) if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup))
return COMPONENT_INCOMPATIBLE return COMPONENT_INCOMPATIBLE
@@ -252,8 +253,8 @@
to_chat(user, "<span class='info'>Cloud ID: [cloud_id ? cloud_id : "Disabled"]</span>") to_chat(user, "<span class='info'>Cloud ID: [cloud_id ? cloud_id : "Disabled"]</span>")
to_chat(user, "<span class='info'>================</span>") to_chat(user, "<span class='info'>================</span>")
to_chat(user, "<span class='info'>Program List:</span>") to_chat(user, "<span class='info'>Program List:</span>")
if(stealth) if(!diagnostics)
to_chat(user, "<span class='alert'>%#$ENCRYPTED&^@</span>") to_chat(user, "<span class='alert'>Diagnostics Disabled</span>")
else else
for(var/X in programs) for(var/X in programs)
var/datum/nanite_program/NP = X var/datum/nanite_program/NP = X
+3 -1
View File
@@ -150,7 +150,9 @@
if(!.) if(!.)
return return
ADD_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT) ADD_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT)
ADD_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT)
/datum/martial_art/the_rising_bass/on_remove(mob/living/carbon/human/H) /datum/martial_art/the_rising_bass/on_remove(mob/living/carbon/human/H)
. = ..() . = ..()
REMOVE_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT) REMOVE_TRAIT(H, TRAIT_NOGUNS, RISING_BASS_TRAIT)
REMOVE_TRAIT(H, TRAIT_AUTO_CATCH_ITEM, RISING_BASS_TRAIT)
+3
View File
@@ -135,6 +135,9 @@
if(L.client && L.client.prefs) if(L.client && L.client.prefs)
L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting... L.canbearoused = L.client.prefs.arousable //Technically this should make taking over a character mean the body gain the new minds setting...
L.update_arousal_hud() //Removes the old icon L.update_arousal_hud() //Removes the old icon
if (L.client.prefs.auto_ooc)
if (L.client.prefs.chat_toggles & CHAT_OOC)
L.client.prefs.chat_toggles ^= CHAT_OOC
SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character) SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character)
+1 -1
View File
@@ -117,7 +117,7 @@
continue continue
contam_atoms += thing contam_atoms += thing
var/did_contam = 0 var/did_contam = 0
if(can_contam) if(length(can_contam))
var/rad_strength = ((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT)/contam_atoms.len var/rad_strength = ((strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT)/contam_atoms.len
for(var/k in 1 to contam_atoms.len) for(var/k in 1 to contam_atoms.len)
var/atom/thing = contam_atoms[k] var/atom/thing = contam_atoms[k]
+2
View File
@@ -292,6 +292,7 @@
var/mob/living/carbon/C = owner var/mob/living/carbon/C = owner
for(var/X in C.bodyparts) for(var/X in C.bodyparts)
var/obj/item/bodypart/BP = X var/obj/item/bodypart/BP = X
BP.max_damage *= 10
BP.brute_dam *= 10 BP.brute_dam *= 10
BP.burn_dam *= 10 BP.burn_dam *= 10
owner.toxloss *= 10 owner.toxloss *= 10
@@ -377,6 +378,7 @@
var/obj/item/bodypart/BP = X var/obj/item/bodypart/BP = X
BP.brute_dam *= 0.1 BP.brute_dam *= 0.1
BP.burn_dam *= 0.1 BP.burn_dam *= 0.1
BP.max_damage /= 10
owner.toxloss *= 0.1 owner.toxloss *= 0.1
owner.oxyloss *= 0.1 owner.oxyloss *= 0.1
owner.cloneloss *= 0.1 owner.cloneloss *= 0.1
-29
View File
@@ -88,15 +88,6 @@
if(quirk_holder) if(quirk_holder)
quirk_holder.remove_client_colour(/datum/client_colour/monochrome) quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
/datum/quirk/crocrin_immunity
name = "Crocin Immunity"
desc = "You're one of the few people in the galaxy who are genetically immune to Crocin and Hexacrocin products and their addictive properties! However, you can still get brain damage from Hexacrocin addiction."
mob_trait = TRAIT_CROCRIN_IMMUNE
value = 0
gain_text = "<span class='notice'>You feel more prudish.</span>"
lose_text = "<span class='notice'>You don't feel as prudish as before.</span>"
medical_record_text = "Patient exhibits a special gene that makes them immune to aphrodisiacs."
/datum/quirk/libido /datum/quirk/libido
name = "Nymphomania" name = "Nymphomania"
desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual." desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
@@ -130,23 +121,3 @@
mob_trait = TRAIT_EXHIBITIONIST mob_trait = TRAIT_EXHIBITIONIST
gain_text = "<span class='notice'>You feel like exposing yourself to the world.</span>" gain_text = "<span class='notice'>You feel like exposing yourself to the world.</span>"
lose_text = "<span class='notice'>Indecent exposure doesn't sound as charming to you anymore.</span>" lose_text = "<span class='notice'>Indecent exposure doesn't sound as charming to you anymore.</span>"
/datum/quirk/pharmacokinesis //Prevents unwanted organ additions.
name = "Acute hepatic pharmacokinesis"
desc = "You've a rare genetic disorder that causes Incubus draft and Sucubus milk to be absorbed by your liver instead."
value = 0
mob_trait = TRAIT_PHARMA
lose_text = "<span class='notice'>Your liver feels different.</span>"
medical_record_text = "Non-invasive tests report that the patient's metabolism is indeed incompatible with a certain \"stimulants\"."
var/active = FALSE
var/power = 0
var/cachedmoveCalc = 1
/datum/quirk/assblastusa
name = "Buns of Steel"
desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand."
mob_trait = TRAIT_ASSBLASTUSA
value = 0
medical_record_text = "Patient never skipped ass day."
gain_text = "<span class='notice'>Your ass rivals those of golems.</span>"
lose_text = "<span class='notice'>Your butt feels more squishy and slappable.</span>"
+1 -1
View File
@@ -166,7 +166,7 @@
return FALSE return FALSE
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0) /atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
if(does_attack_animation) if(does_attack_animation)
user.changeNext_move(CLICK_CD_MELEE) user.changeNext_move(CLICK_CD_MELEE)
+3 -3
View File
@@ -515,10 +515,10 @@
step(src, AM.dir) step(src, AM.dir)
..() ..()
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) /atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE)
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback) return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, messy_throw)
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback) //If this returns FALSE then callback will not be called. /atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) //If this returns FALSE then callback will not be called.
. = FALSE . = FALSE
if (!target || speed <= 0) if (!target || speed <= 0)
return return
@@ -57,7 +57,6 @@
..() ..()
if(visualsOnly) if(visualsOnly)
return return
H.dna.add_mutation(CLOWNMUT)
H.dna.add_mutation(SMILE) H.dna.add_mutation(SMILE)
/datum/outfit/syndicate/clownop/leader /datum/outfit/syndicate/clownop/leader
+17 -1
View File
@@ -222,5 +222,21 @@
. += "\t<span class='notice'>[attached ? attached : "No one"] is attached.</span>" . += "\t<span class='notice'>[attached ? attached : "No one"] is attached.</span>"
/obj/machinery/iv_drip/telescopic
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."
icon_state = "iv_drip"
/obj/machinery/iv_drip/telescopic/update_icon()
..()
icon_state = icon_state + "_tele"
/obj/machinery/iv_drip/telescopic/AltClick(mob/user)
if (attached || beaker || !user.canUseTopic(src, BE_CLOSE))
return ..()
new /obj/item/tele_iv(get_turf(src))
qdel(src)
return TRUE
#undef IV_TAKING #undef IV_TAKING
#undef IV_INJECTING #undef IV_INJECTING
+9 -8
View File
@@ -578,21 +578,22 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
itempush = 0 //too light to push anything itempush = 0 //too light to push anything
return A.hitby(src, 0, itempush) return A.hitby(src, 0, itempush)
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) /obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, messy_throw = TRUE)
thrownby = thrower thrownby = thrower
callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own callback = CALLBACK(src, .proc/after_throw, callback, (spin && messy_throw)) //replace their callback with our own
. = ..(target, range, speed, thrower, spin, diagonals_first, callback) . = ..(target, range, speed, thrower, spin, diagonals_first, callback)
/obj/item/proc/after_throw(datum/callback/callback) /obj/item/proc/after_throw(datum/callback/callback, messy_throw)
if (callback) //call the original callback if (callback) //call the original callback
. = callback.Invoke() . = callback.Invoke()
throw_speed = initial(throw_speed) //explosions change this. throw_speed = initial(throw_speed) //explosions change this.
item_flags &= ~IN_INVENTORY item_flags &= ~IN_INVENTORY
var/matrix/M = matrix(transform) if(messy_throw)
M.Turn(rand(-170, 170)) var/matrix/M = matrix(transform)
transform = M M.Turn(rand(-170, 170))
pixel_x = rand(-8, 8) transform = M
pixel_y = rand(-8, 8) pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
/obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/storage /obj/item/proc/remove_item_from_storage(atom/newLoc) //please use this if you're going to snowflake an item out of a obj/item/storage
if(!newLoc) if(!newLoc)
+202
View File
@@ -863,3 +863,205 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(reagents && reagents.total_volume) if(reagents && reagents.total_volume)
hand_reagents() hand_reagents()
///////////////
/////BONGS/////
///////////////
/obj/item/bong
name = "bong"
desc = "A water bong used for smoking dried plants."
icon = 'icons/obj/bongs.dmi'
icon_state = null
item_state = null
w_class = WEIGHT_CLASS_NORMAL
light_color = "#FFCC66"
var/icon_off = "bong"
var/icon_on = "bong_lit"
var/chem_volume = 100
var/last_used_time //for cooldown
var/firecharges = 0 //used for counting how many hits can be taken before the flame goes out
var/list/list_reagents = list() //For the base reagents bongs could get
/obj/item/bong/Initialize()
. = ..()
create_reagents(chem_volume, NO_REACT) // so it doesn't react until you light it
reagents.add_reagent_list(list_reagents)
icon_state = icon_off
/obj/item/bong/attackby(obj/item/O, mob/user, params)
. = ..()
//If we're using a dried plant..
if(istype(O,/obj/item/reagent_containers/food/snacks))
var/obj/item/reagent_containers/food/snacks/DP = O
if (DP.dry)
//Nothing if our bong is full
if (reagents.holder_full())
user.show_message("<span class='notice'>The bowl is full!</span>", MSG_VISUAL)
return
//Transfer reagents and remove the plant
user.show_message("<span class='notice'>You stuff the [DP] into the [src]'s bowl.</span>", MSG_VISUAL)
DP.reagents.trans_to(src, 100)
qdel(DP)
return
else
user.show_message("<span class='warning'>[DP] must be dried first!</span>", MSG_VISUAL)
return
if (O.get_temperature() <= 500)
return
if (reagents && reagents.total_volume) //if there's stuff in the bong
var/lighting_text = O.ignition_effect(src, user)
if(lighting_text)
//Logic regarding igniting it on
if (firecharges == 0)
user.show_message("<span class='notice'>You light the [src] with the [O]!</span>", MSG_VISUAL)
bongturnon()
else
user.show_message("<span class='notice'>You rekindle [src]'s flame with the [O]!</span>", MSG_VISUAL)
firecharges = 1
return
else
user.show_message("<span warning='notice'>There's nothing to light up in the bowl.</span>", MSG_VISUAL)
return
/obj/item/bong/CtrlShiftClick(mob/user) //empty reagents on alt click
..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if (reagents && reagents.total_volume)
user.show_message("<span class='notice'>You empty the [src].</span>", MSG_VISUAL)
reagents.clear_reagents()
if(firecharges)
firecharges = 0
bongturnoff()
else
user.show_message("<span class='notice'>The [src] is already empty.</span>", MSG_VISUAL)
/obj/item/bong/AltClick(mob/user)
..()
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
return
if(firecharges)
firecharges = 0
bongturnoff()
user.show_message("<span class='notice'>You quench the flame.</span>", MSG_VISUAL)
return TRUE
/obj/item/bong/examine(mob/user)
. = ..()
if(!reagents.total_volume)
. += "<span class='notice'>The bowl is empty.</span>"
else if (reagents.total_volume > 80)
. += "<span class='notice'>The bowl is filled to the brim.</span>"
else if (reagents.total_volume > 40)
. += "<span class='notice'>The bowl has plenty weed in it.</span>"
else
. += "<span class='notice'>The bowl has some weed in it.</span>"
. += "<span class='notice'>Ctrl+Shift-click to empty.</span>"
. += "<span class='notice'>Alt-click to extinguish.</span>"
/obj/item/bong/ignition_effect(atom/A, mob/user)
if(firecharges)
. = "<span class='notice'>[user] lights [A] off of the [src].</span>"
else
. = ""
/obj/item/bong/attack(mob/living/carbon/M, mob/living/carbon/user, obj/target)
//if it's lit up, some stuff in the bowl and the user is a target, and we're not on cooldown
if (M != user)
return ..()
if(user.is_mouth_covered(head_only = 1))
to_chat(user, "<span class='warning'>Remove your headgear first.</span>")
return ..()
if(user.is_mouth_covered(mask_only = 1))
to_chat(user, "<span class='warning'>Remove your mask first.</span>")
return ..()
if (!reagents.total_volume)
to_chat(user, "<span class='warning'>There's nothing in the bowl.</span>")
return ..()
if (!firecharges)
to_chat(user, "<span class='warning'>You have to light it up first.</span>")
return ..()
if (last_used_time + 30 >= world.time)
return ..()
var/hit_strength
var/noise
var/hittext = ""
//if the intent is help then you take a small hit, else a big one
if (user.a_intent == INTENT_HARM)
hit_strength = 2
noise = 100
hittext = "big hit"
else
hit_strength = 1
noise = 70
hittext = "hit"
//bubbling sound
playsound(user.loc,'sound/effects/bonghit.ogg', noise, 1)
last_used_time = world.time
//message
user.visible_message("<span class='notice'>[user] begins to take a [hittext] from the [src]!</span>", \
"<span class='notice'>You begin to take a [hittext] from [src].</span>")
//we take a hit here, after an uninterrupted delay
if(!do_after(user, 25, target = user))
return
if (!(reagents && reagents.total_volume))
return
var/fraction = 12 * hit_strength
var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
s.set_up(reagents, hit_strength, 18, user.loc)
s.start()
reagents.reaction(user, INGEST, fraction)
if(!reagents.trans_to(user, fraction))
reagents.remove_any(fraction)
if (hit_strength == 2 && prob(15))
user.emote("cough")
user.adjustOxyLoss(15)
user.visible_message("<span class='notice'>[user] takes a [hittext] from the [src]!</span>", \
"<span class='notice'>You take a [hittext] from [src].</span>")
firecharges = firecharges - 1
if (!firecharges)
bongturnoff()
if (!reagents.total_volume)
firecharges = 0
bongturnoff()
/obj/item/bong/proc/bongturnon()
icon_state = icon_on
set_light(3, 0.8)
/obj/item/bong/proc/bongturnoff()
icon_state = icon_off
set_light(0, 0.0)
/obj/item/bong/coconut
name = "coconut bong"
icon_off = "coconut_bong"
icon_on = "coconut_bong_lit"
desc = "A water bong used for smoking dried plants. This one's made out of a coconut and some bamboo."
@@ -2,7 +2,7 @@
name = "forcefield projector" name = "forcefield projector"
desc = "An experimental device that can create several forcefields at a distance." desc = "An experimental device that can create several forcefields at a distance."
icon = 'icons/obj/device.dmi' icon = 'icons/obj/device.dmi'
icon_state = "signmaker_engi" icon_state = "signmaker_forcefield"
slot_flags = ITEM_SLOT_BELT slot_flags = ITEM_SLOT_BELT
w_class = WEIGHT_CLASS_SMALL w_class = WEIGHT_CLASS_SMALL
item_flags = NOBLUDGEON item_flags = NOBLUDGEON
+1 -1
View File
@@ -79,7 +79,7 @@
/obj/item/holosign_creator/atmos /obj/item/holosign_creator/atmos
name = "ATMOS holofan projector" name = "ATMOS holofan projector"
desc = "A holographic projector that creates holographic barriers that prevent changes in atmosphere conditions." desc = "A holographic projector that creates holographic barriers that prevent changes in atmosphere conditions."
icon_state = "signmaker_engi" icon_state = "signmaker_atmos"
holosign_type = /obj/structure/holosign/barrier/atmos holosign_type = /obj/structure/holosign/barrier/atmos
creation_time = 0 creation_time = 0
max_signs = 3 max_signs = 3
+1 -1
View File
@@ -374,7 +374,7 @@
It appears to have a wooden grip and a shaved down guard." It appears to have a wooden grip and a shaved down guard."
icon_state = "cxsword_hilt_traitor" icon_state = "cxsword_hilt_traitor"
force_on = 30 force_on = 30
armour_penetration = 50 armour_penetration = 35
embedding = list("embedded_pain_multiplier" = 10, "embed_chance" = 75, "embedded_fall_chance" = 0, "embedded_impact_pain_multiplier" = 10) embedding = list("embedded_pain_multiplier" = 10, "embed_chance" = 75, "embedded_fall_chance" = 0, "embedded_impact_pain_multiplier" = 10)
block_chance = 50 block_chance = 50
hitsound_on = 'sound/weapons/blade1.ogg' hitsound_on = 'sound/weapons/blade1.ogg'
+3 -2
View File
@@ -216,10 +216,11 @@
return return
else else
if(last_hit < world.time) if(last_hit < world.time)
if(target.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
playsound(target, 'sound/weapons/genhit.ogg', 50, 1)
return
if(ishuman(target)) if(ishuman(target))
var/mob/living/carbon/human/H = target var/mob/living/carbon/human/H = target
if (H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
return
if(check_martial_counter(H, user)) if(check_martial_counter(H, user))
return return
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1) playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
+3 -5
View File
@@ -11,11 +11,9 @@
var/charge_cost = 30 var/charge_cost = 30
/obj/item/borg/stun/attack(mob/living/M, mob/living/user) /obj/item/borg/stun/attack(mob/living/M, mob/living/user)
if(ishuman(M)) if(M.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK))
var/mob/living/carbon/human/H = M playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
if(H.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK)) return FALSE
playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(iscyborg(user)) if(iscyborg(user))
var/mob/living/silicon/robot/R = user var/mob/living/silicon/robot/R = user
if(!R.cell.use(charge_cost)) if(!R.cell.use(charge_cost))
+5 -4
View File
@@ -61,6 +61,7 @@
/obj/item/radio, /obj/item/radio,
/obj/item/clothing/gloves, /obj/item/clothing/gloves,
/obj/item/holosign_creator, /obj/item/holosign_creator,
/obj/item/forcefield_projector,
/obj/item/assembly/signaler /obj/item/assembly/signaler
)) ))
STR.can_hold = can_hold STR.can_hold = can_hold
@@ -458,8 +459,7 @@
/obj/item/extinguisher/mini, /obj/item/extinguisher/mini,
/obj/item/radio, /obj/item/radio,
/obj/item/clothing/gloves, /obj/item/clothing/gloves,
/obj/item/holosign_creator/atmos, /obj/item/holosign_creator,
/obj/item/holosign_creator/engineering,
/obj/item/forcefield_projector, /obj/item/forcefield_projector,
/obj/item/assembly/signaler, /obj/item/assembly/signaler,
/obj/item/lightreplacer, /obj/item/lightreplacer,
@@ -571,6 +571,7 @@
/obj/item/reagent_containers/spray, /obj/item/reagent_containers/spray,
/obj/item/soap, /obj/item/soap,
/obj/item/holosign_creator, /obj/item/holosign_creator,
/obj/item/forcefield_projector,
/obj/item/key/janitor, /obj/item/key/janitor,
/obj/item/clothing/gloves, /obj/item/clothing/gloves,
/obj/item/melee/flyswatter, /obj/item/melee/flyswatter,
@@ -582,7 +583,7 @@
/obj/item/storage/belt/bandolier /obj/item/storage/belt/bandolier
name = "bandolier" name = "bandolier"
desc = "A bandolier for holding shotgun ammunition." desc = "A bandolier for holding ammunition."
icon_state = "bandolier" icon_state = "bandolier"
item_state = "bandolier" item_state = "bandolier"
@@ -592,7 +593,7 @@
STR.max_items = 18 STR.max_items = 18
STR.display_numerical_stacking = TRUE STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list( STR.can_hold = typecacheof(list(
/obj/item/ammo_casing/shotgun /obj/item/ammo_casing
)) ))
/obj/item/storage/belt/bandolier/durathread /obj/item/storage/belt/bandolier/durathread
+9
View File
@@ -1259,3 +1259,12 @@
var/obj/item/stack/sheet/cardboard/I = new(user.drop_location()) var/obj/item/stack/sheet/cardboard/I = new(user.drop_location())
qdel(src) qdel(src)
user.put_in_hands(I) user.put_in_hands(I)
/obj/item/storage/box/marshmallow
name = "box of marshmallows"
desc = "A box of marshmallows."
illustration = "marshmallow"
/obj/item/storage/box/marshmallow/PopulateContents()
for (var/i in 1 to 5)
new /obj/item/reagent_containers/food/snacks/marshmallow(src)
+3 -5
View File
@@ -168,11 +168,9 @@
/obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user) /obj/item/melee/baton/proc/baton_stun(mob/living/L, mob/user)
if(ishuman(L)) if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
var/mob/living/carbon/human/H = L playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that return FALSE
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
var/stunpwr = stunforce var/stunpwr = stunforce
var/obj/item/stock_parts/cell/our_cell = get_cell() var/obj/item/stock_parts/cell/our_cell = get_cell()
if(!our_cell) if(!our_cell)
+17
View File
@@ -0,0 +1,17 @@
/obj/item/tele_iv
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."
icon = 'icons/obj/iv_drip.dmi'
icon_state = "tele_iv"
/obj/item/tele_iv/attack_self(mob/user)
deploy_iv(user, user.loc)
/obj/item/tele_iv/afterattack(atom/target, mob/user, proximity)
. = ..()
if(proximity && isopenturf(target) && user.CanReach(target))
deploy_iv(user, target)
/obj/item/tele_iv/proc/deploy_iv(mob/user, atom/location)
new /obj/machinery/iv_drip/telescopic(location)
qdel(src)
+2 -3
View File
@@ -80,13 +80,12 @@
SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue) SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue)
anchored = anchorvalue anchored = anchorvalue
/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback) /obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, messy_throw)
..() . = ..()
if(obj_flags & FROZEN) if(obj_flags & FROZEN)
visible_message("<span class='danger'>[src] shatters into a million pieces!</span>") visible_message("<span class='danger'>[src] shatters into a million pieces!</span>")
qdel(src) qdel(src)
/obj/assume_air(datum/gas_mixture/giver) /obj/assume_air(datum/gas_mixture/giver)
if(loc) if(loc)
return loc.assume_air(giver) return loc.assume_air(giver)
@@ -12,18 +12,12 @@
new /obj/item/clothing/head/hardhat/white(src) new /obj/item/clothing/head/hardhat/white(src)
new /obj/item/clothing/head/hardhat/weldhat/white(src) new /obj/item/clothing/head/hardhat/weldhat/white(src)
new /obj/item/clothing/gloves/color/yellow(src) new /obj/item/clothing/gloves/color/yellow(src)
new /obj/item/clothing/shoes/sneakers/brown(src)
new /obj/item/tank/jetpack/suit(src) new /obj/item/tank/jetpack/suit(src)
new /obj/item/cartridge/ce(src) new /obj/item/cartridge/ce(src)
new /obj/item/radio/headset/heads/ce(src) new /obj/item/radio/headset/heads/ce(src)
new /obj/item/storage/toolbox/mechanical(src)
new /obj/item/clothing/suit/hazardvest(src)
new /obj/item/megaphone/command(src) new /obj/item/megaphone/command(src)
new /obj/item/areaeditor/blueprints(src) new /obj/item/areaeditor/blueprints(src)
new /obj/item/airlock_painter(src)
new /obj/item/holosign_creator/engineering(src) new /obj/item/holosign_creator/engineering(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/multitool(src)
new /obj/item/assembly/flash/handheld(src) new /obj/item/assembly/flash/handheld(src)
new /obj/item/clothing/glasses/meson/engine(src) new /obj/item/clothing/glasses/meson/engine(src)
new /obj/item/door_remote/chief_engineer(src) new /obj/item/door_remote/chief_engineer(src)
@@ -67,7 +61,7 @@
for(var/i in 1 to 3) for(var/i in 1 to 3)
new /obj/item/clothing/head/welding(src) new /obj/item/clothing/head/welding(src)
for(var/i in 1 to 3) for(var/i in 1 to 3)
new /obj/item/weldingtool(src) new /obj/item/weldingtool/largetank(src)
/obj/structure/closet/secure_closet/engineering_personal /obj/structure/closet/secure_closet/engineering_personal
name = "engineer's locker" name = "engineer's locker"
@@ -84,7 +78,6 @@
new /obj/item/clothing/glasses/meson/engine(src) new /obj/item/clothing/glasses/meson/engine(src)
new /obj/item/storage/box/emptysandbags(src) new /obj/item/storage/box/emptysandbags(src)
/obj/structure/closet/secure_closet/atmospherics /obj/structure/closet/secure_closet/atmospherics
name = "\proper atmospheric technician's locker" name = "\proper atmospheric technician's locker"
req_access = list(ACCESS_ATMOSPHERICS) req_access = list(ACCESS_ATMOSPHERICS)
@@ -103,3 +96,33 @@
new /obj/item/clothing/head/hardhat/atmos(src) new /obj/item/clothing/head/hardhat/atmos(src)
new /obj/item/clothing/glasses/meson/engine/tray(src) new /obj/item/clothing/glasses/meson/engine/tray(src)
new /obj/item/extinguisher/advanced(src) new /obj/item/extinguisher/advanced(src)
/*
* Empty lockers
* Some of the lockers are filled with junk, and sometimes its nice to just fill it with your own set-up for your own map gimmicks.
*/
/obj/structure/closet/secure_closet/engineering_chief/empty
/obj/structure/closet/secure_closet/engineering_chief/empty/PopulateContents()
return
/obj/structure/closet/secure_closet/engineering_electrical/empty
/obj/structure/closet/secure_closet/engineering_electrical/empty/PopulateContents()
return
/obj/structure/closet/secure_closet/engineering_welding/empty
/obj/structure/closet/secure_closet/engineering_welding/empty/PopulateContents()
return
/obj/structure/closet/secure_closet/engineering_personal/empty
/obj/structure/closet/secure_closet/engineering_personal/empty/PopulateContents()
return
/obj/structure/closet/secure_closet/atmospherics/empty
/obj/structure/closet/secure_closet/atmospherics/empty/PopulateContents()
return
+3 -3
View File
@@ -30,11 +30,11 @@
return return
var/list/undergarment_choices = list("Underwear", "Underwear Color", "Undershirt", "Undershirt Color", "Socks", "Socks Color") var/list/undergarment_choices = list("Underwear", "Underwear Color", "Undershirt", "Undershirt Color", "Socks", "Socks Color")
if(!UNDIE_COLORABLE(GLOB.underwear_list[H.underwear])) if(!(GLOB.underwear_list[H.underwear]?.has_color))
undergarment_choices -= "Underwear Color" undergarment_choices -= "Underwear Color"
if(!UNDIE_COLORABLE(GLOB.undershirt_list[H.undershirt])) if(!(GLOB.undershirt_list[H.undershirt]?.has_color))
undergarment_choices -= "Undershirt Color" undergarment_choices -= "Undershirt Color"
if(!UNDIE_COLORABLE(GLOB.socks_list[H.socks])) if(!(GLOB.socks_list[H.socks]?.has_color))
undergarment_choices -= "Socks Color" undergarment_choices -= "Socks Color"
var/choice = input(H, "Underwear, Undershirt, or Socks?", "Changing") as null|anything in undergarment_choices var/choice = input(H, "Underwear, Undershirt, or Socks?", "Changing") as null|anything in undergarment_choices
@@ -30,6 +30,8 @@
new/obj/structure/fluff/empty_terrarium(get_turf(src)) new/obj/structure/fluff/empty_terrarium(get_turf(src))
return ..() return ..()
/obj/effect/mob_spawn/human/seed_vault/special(mob/living/carbon/human/new_spawn)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
//Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers. //Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers.
/obj/effect/mob_spawn/human/ash_walker /obj/effect/mob_spawn/human/ash_walker
@@ -251,6 +253,9 @@
new/obj/structure/fluff/empty_cryostasis_sleeper(get_turf(src)) new/obj/structure/fluff/empty_cryostasis_sleeper(get_turf(src))
return ..() return ..()
/obj/effect/mob_spawn/human/hermit/special(mob/living/carbon/human/new_spawn)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
//Broken rejuvenation pod: Spawns in animal hospitals in lavaland. Ghosts become disoriented interns and are advised to search for help. //Broken rejuvenation pod: Spawns in animal hospitals in lavaland. Ghosts become disoriented interns and are advised to search for help.
/obj/effect/mob_spawn/human/doctor/alive/lavaland /obj/effect/mob_spawn/human/doctor/alive/lavaland
name = "broken rejuvenation pod" name = "broken rejuvenation pod"
@@ -353,6 +358,9 @@
new/obj/structure/fluff/empty_sleeper/syndicate(get_turf(src)) new/obj/structure/fluff/empty_sleeper/syndicate(get_turf(src))
..() ..()
/obj/effect/mob_spawn/human/hotel_staff/special(mob/living/carbon/human/new_spawn)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
/obj/effect/mob_spawn/human/demonic_friend /obj/effect/mob_spawn/human/demonic_friend
name = "Essence of friendship" name = "Essence of friendship"
desc = "Oh boy! Oh boy! A friend!" desc = "Oh boy! Oh boy! A friend!"
@@ -597,7 +605,7 @@
rank = "Gunner" rank = "Gunner"
/obj/effect/mob_spawn/human/ghostcafe /obj/effect/mob_spawn/human/ghostcafe
name = "ghost cafe sleeper" name = "Ghost Cafe Sleeper"
uses = -1 uses = -1
icon = 'icons/obj/machines/sleeper.dmi' icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper" icon_state = "sleeper"
@@ -618,12 +626,14 @@
O.equip(new_spawn, FALSE, new_spawn.client) O.equip(new_spawn, FALSE, new_spawn.client)
SSjob.equip_loadout(null, new_spawn, FALSE) SSjob.equip_loadout(null, new_spawn, FALSE)
SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn) SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
/datum/outfit/ghostcafe /datum/outfit/ghostcafe
name = "ID, jumpsuit and shoes" name = "ID, jumpsuit and shoes"
uniform = /obj/item/clothing/under/color/random uniform = /obj/item/clothing/under/color/random
shoes = /obj/item/clothing/shoes/sneakers/black shoes = /obj/item/clothing/shoes/sneakers/black
id = /obj/item/card/id id = /obj/item/card/id
r_hand = /obj/item/storage/box/syndie_kit/chameleon/ghostcafe
/datum/outfit/ghostcafe/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) /datum/outfit/ghostcafe/pre_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source)
@@ -639,4 +649,18 @@
uniform = /obj/item/clothing/under/color/random uniform = /obj/item/clothing/under/color/random
else else
uniform = /obj/item/clothing/under/skirt/color/random uniform = /obj/item/clothing/under/skirt/color/random
/obj/item/storage/box/syndie_kit/chameleon/ghostcafe
name = "ghost cafe costuming kit"
desc = "Look just the way you did in life - or better!"
/obj/item/storage/box/syndie_kit/chameleon/ghostcafe/PopulateContents() // Doesn't contain a PDA, for isolation reasons.
new /obj/item/clothing/under/chameleon(src)
new /obj/item/clothing/suit/chameleon(src)
new /obj/item/clothing/gloves/chameleon(src)
new /obj/item/clothing/shoes/chameleon(src)
new /obj/item/clothing/glasses/chameleon(src)
new /obj/item/clothing/head/chameleon(src)
new /obj/item/clothing/mask/chameleon(src)
new /obj/item/storage/backpack/chameleon(src)
new /obj/item/clothing/neck/cloak/chameleon(src)
+1 -1
View File
@@ -492,7 +492,7 @@ GLOBAL_PROTECT(AdminProcCallSpamPrevention)
message_admins("<span class='adminnotice'>[key_name_admin(usr)] assumed direct control of [M].</span>") 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].") log_admin("[key_name(usr)] assumed direct control of [M].")
var/mob/adminmob = src.mob var/mob/adminmob = src.mob
M.ckey = src.ckey adminmob.transfer_ckey(M, send_signal = FALSE)
if( isobserver(adminmob) ) if( isobserver(adminmob) )
qdel(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! 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) user.do_attack_animation(L)
if(ishuman(L)) if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
var/mob/living/carbon/human/H = L playsound(L, 'sound/weapons/genhit.ogg', 50, TRUE)
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) return FALSE
playsound(H, 'sound/weapons/genhit.ogg', 50, TRUE)
return FALSE
switch (mode) switch (mode)
if(BATON_STUN) if(BATON_STUN)
@@ -3,6 +3,7 @@
icon = 'icons/mob/blob.dmi' icon = 'icons/mob/blob.dmi'
icon_state = "blob_shield" icon_state = "blob_shield"
desc = "A solid wall of slightly twitching tendrils." desc = "A solid wall of slightly twitching tendrils."
var/damaged_desc = "A wall of twitching tendrils."
max_integrity = 150 max_integrity = 150
brute_resist = 0.25 brute_resist = 0.25
explosion_block = 3 explosion_block = 3
@@ -21,10 +22,10 @@
/obj/structure/blob/shield/update_icon() /obj/structure/blob/shield/update_icon()
..() ..()
if(obj_integrity <= 70) if(obj_integrity < max_integrity * 0.5)
icon_state = "blob_shield_damaged" icon_state = "[initial(icon_state)]_damaged"
name = "weakened strong blob" name = "weakened [initial(name)]"
desc = "A wall of twitching tendrils." desc = "[damaged_desc]"
atmosblock = FALSE atmosblock = FALSE
if(!weakened) if(!weakened)
armor = armor.setRating("melee" = 15, "bullet" = 15, "laser" = 5, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) 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) if(weakened)
armor = armor.setRating("melee" = 25, "bullet" = 25, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) armor = armor.setRating("melee" = 25, "bullet" = 25, "laser" = 15, "energy" = 10, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
weakened = FALSE 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
+14 -4
View File
@@ -113,12 +113,22 @@
/mob/camera/blob/verb/create_shield_power() /mob/camera/blob/verb/create_shield_power()
set category = "Blob" set category = "Blob"
set name = "Create Shield Blob (15)" set name = "Create/Upgrade Shield Blob (15)"
set desc = "Create a shield blob, which will block fire and is hard to kill." 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() create_shield()
/mob/camera/blob/proc/create_shield(turf/T) /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() /mob/camera/blob/verb/create_resource()
set category = "Blob" 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, "<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, "<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, "<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>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>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.") 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/masquerade)
BuyPower(new /datum/action/bloodsucker/veil) BuyPower(new /datum/action/bloodsucker/veil)
// Traits // Traits
for (var/T in defaultTraits) for(var/T in defaultTraits)
ADD_TRAIT(owner.current, T, "bloodsucker") ADD_TRAIT(owner.current, T, "bloodsucker")
if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you
had_toxlover = TRUE had_toxlover = TRUE
@@ -200,10 +200,10 @@
var/mob/living/carbon/human/H = owner.current var/mob/living/carbon/human/H = owner.current
var/datum/species/S = H.dna.species var/datum/species/S = H.dna.species
// Make Changes // Make Changes
S.brutemod *= 0.5 // <-------------------- Start small, but burn mod increases based on rank! H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank!
S.coldmod = 0 H.physiology.cold_mod = 0
S.stunmod *= 0.25 H.physiology.stun_mod *= 0.35
S.siemens_coeff *= 0.75 //base electrocution coefficient 1 H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1
//S.heatmod += 0.5 // Heat shouldn't affect. Only Fire. //S.heatmod += 0.5 // Heat shouldn't affect. Only Fire.
//S.punchstunthreshold = 8 //damage at which punches from this race will stun 9 //S.punchstunthreshold = 8 //damage at which punches from this race will stun 9
S.punchdamagelow += 1 //lowest possible punch damage 0 S.punchdamagelow += 1 //lowest possible punch damage 0
@@ -319,12 +319,10 @@ datum/antagonist/bloodsucker/proc/SpendRank()
if(ishuman(owner.current)) if(ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current var/mob/living/carbon/human/H = owner.current
var/datum/species/S = H.dna.species 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.punchdamagelow += 0.5
S.punchdamagehigh += 0.5 // NOTE: This affects the hitting power of Brawn. S.punchdamagehigh += 0.5 // NOTE: This affects the hitting power of Brawn.
// More Health // More Health
owner.current.setMaxHealth(owner.current.maxHealth + 5) owner.current.setMaxHealth(owner.current.maxHealth + 10)
// Vamp Stats // Vamp Stats
regenRate += 0.05 // Points of brute healed (starts at 0.3) regenRate += 0.05 // Points of brute healed (starts at 0.3)
feedAmount += 2 // Increase how quickly I munch down vics (15) feedAmount += 2 // Increase how quickly I munch down vics (15)
@@ -275,7 +275,7 @@
// All done! // All done!
if(convert_progress <= 0) if(convert_progress <= 0)
// FAIL: Can't be Vassal // 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>") 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. convert_progress ++ // Pop it back up some. Avoids wasting Blood on a lost cause.
// SUCCESS: All done! // SUCCESS: All done!
@@ -5,6 +5,14 @@
antagpanel_category = "ClownOp" antagpanel_category = "ClownOp"
nukeop_outfit = /datum/outfit/syndicate/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 /datum/antagonist/nukeop/leader/clownop
name = "Clown Operative Leader" name = "Clown Operative Leader"
roundend_category = "clown operatives" roundend_category = "clown operatives"
@@ -154,11 +154,6 @@
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume) var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
var/target_temperature var/target_temperature
var/target_heat_capacity 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)) if(isopenturf(target))
@@ -170,8 +165,8 @@
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0)) if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.temperature - target_temperature 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)) (partial_heat_capacity*target_heat_capacity/(partial_heat_capacity+target_heat_capacity))
air.temperature -= heat/total_heat_capacity air.temperature -= heat/total_heat_capacity
@@ -188,8 +183,7 @@
var/sharer_temperature_delta = 0 var/sharer_temperature_delta = 0
if((sharer_heat_capacity>0) && (partial_heat_capacity>0)) if((sharer_heat_capacity>0) && (partial_heat_capacity>0))
heat -= share_constant*(min(target_temperature,4000000000)**4) var/heat = thermal_conductivity*delta_temperature* \
heat += thermal_conductivity*delta_temperature* \
(partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity)) (partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity))
self_temperature_delta = -heat/total_heat_capacity self_temperature_delta = -heat/total_heat_capacity
@@ -205,12 +199,10 @@
if((target.heat_capacity>0) && (partial_heat_capacity>0)) if((target.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.temperature - target.temperature var/delta_temperature = air.temperature - target.temperature
heat -= share_constant*(min(target.temperature,4000000000)**4) var/heat = thermal_conductivity*delta_temperature* \
heat += thermal_conductivity*delta_temperature* \
(partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity)) (partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
air.temperature -= heat/total_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 update = TRUE
/datum/pipeline/proc/return_air() /datum/pipeline/proc/return_air()
@@ -26,7 +26,9 @@
var/turf/T = loc var/turf/T = loc
if(istype(T)) if(istype(T))
if(T.blocks_air) if(islava(T))
environment_temperature = 5000
else if(T.blocks_air)
environment_temperature = T.temperature environment_temperature = T.temperature
else else
var/turf/open/OT = T var/turf/open/OT = T
+4 -5
View File
@@ -13,17 +13,16 @@
//////////////////// Paperwork and Writing Supplies ////////////////////////// //////////////////// Paperwork and Writing Supplies //////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/* I did it Kevin
/datum/supply_pack/misc/abandonedcrate /datum/supply_pack/misc/abandonedcrate
name = "Abandoned Crate" name = "Loot Box"
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" desc = "Try your luck with these highly secure loot boxes! Solve the lock, win great prizes! WARNING: EXPLOSIVE FAILURE."
contraband = TRUE contraband = TRUE
cost = 12800 cost = 15000
contains = list(/obj/structure/closet/crate/secure/loot) contains = list(/obj/structure/closet/crate/secure/loot)
crate_name = "abandoned crate" crate_name = "abandoned crate"
crate_type = /obj/structure/closet/crate/large crate_type = /obj/structure/closet/crate/large
dangerous = TRUE dangerous = TRUE
*/
/datum/supply_pack/misc/artsupply /datum/supply_pack/misc/artsupply
name = "Art Supplies" name = "Art Supplies"
desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!" desc = "Make some happy little accidents with six canvasses, two easels, two boxes of crayons, and a rainbow crayon!"
+5 -1
View File
@@ -79,4 +79,8 @@
var/client_keysend_amount = 0 var/client_keysend_amount = 0
var/next_keysend_reset = 0 var/next_keysend_reset = 0
var/next_keysend_trip_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
+63 -10
View File
@@ -195,6 +195,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/auto_fit_viewport = TRUE var/auto_fit_viewport = TRUE
var/uplink_spawn_loc = UPLINK_PDA var/uplink_spawn_loc = UPLINK_PDA
var/sprint_spacebar = FALSE
var/sprint_toggle = FALSE
var/list/exp = list() var/list/exp = list()
var/list/menuoptions 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=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=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=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) if(!path)
dat += "<div class='notice'>Please create an account to save your preferences</div>" 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 += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Clothing & Equipment</h2>" dat += "<h2>Clothing & Equipment</h2>"
dat += "<b>Underwear:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=underwear;task=input'>[underwear]</a>" 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];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=undie_color;task=input'>Change</a><BR>" dat += "<b>Underwear Color:</b> <span style='border:1px solid #161616; background-color: #[undie_color];'>&nbsp;&nbsp;&nbsp;</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>" 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];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=shirt_color;task=input'>Change</a><BR>" dat += "<b>Undershirt Color:</b> <span style='border:1px solid #161616; background-color: #[shirt_color];'>&nbsp;&nbsp;&nbsp;</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>" 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];'>&nbsp;&nbsp;&nbsp;</span> <a href='?_src_=prefs;preference=socks_color;task=input'>Change</a><BR>" dat += "<b>Socks Color:</b> <span style='border:1px solid #161616; background-color: #[socks_color];'>&nbsp;&nbsp;&nbsp;</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>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>" 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 +="<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 += "<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>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 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>" 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) 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>" 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 += "</a><br>"
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'>[ambientocclusion ? "Enabled" : "Disabled"]</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>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)) if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation))
var/p_map = preferred_map var/p_map = preferred_map
@@ -991,6 +993,26 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</font>" dat += "</font>"
dat += "</td><td><font size=2><i>[gear.description]</i></font></td></tr>" dat += "</td><td><font size=2><i>[gear.description]</i></font></td></tr>"
dat += "</table>" 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>" dat += "<hr><center>"
@@ -2036,8 +2058,6 @@ GLOBAL_LIST_EMPTY(preferences_datums)
features["genitals_use_skintone"] = !features["genitals_use_skintone"] features["genitals_use_skintone"] = !features["genitals_use_skintone"]
if("arousable") if("arousable")
arousable = !arousable arousable = !arousable
if("lewdchem")
lewdchem = !lewdchem
if("has_cock") if("has_cock")
features["has_cock"] = !features["has_cock"] features["has_cock"] = !features["has_cock"]
if(features["has_cock"] == FALSE) if(features["has_cock"] == FALSE)
@@ -2069,6 +2089,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
user.client.change_view(CONFIG_GET(string/default_view)) user.client.change_view(CONFIG_GET(string/default_view))
if("autostand") if("autostand")
autostand = !autostand autostand = !autostand
if("auto_ooc")
auto_ooc = !auto_ooc
if ("screenshake") 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 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)) if (!isnull(desiredshake))
@@ -2184,6 +2206,31 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("toggledigestionnoise") if("toggledigestionnoise")
cit_toggles ^= DIGESTION_NOISES 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 //END CITADEL EDIT
if("ambientocclusion") if("ambientocclusion")
@@ -2197,6 +2244,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(auto_fit_viewport && parent) if(auto_fit_viewport && parent)
parent.fit_viewport() parent.fit_viewport()
if("sprint_key")
sprint_spacebar = !sprint_spacebar
if("sprint_toggle")
sprint_toggle = !sprint_toggle
if("save") if("save")
save_preferences() save_preferences()
save_character() save_character()
+24 -3
View File
@@ -167,6 +167,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["parallax"] >> parallax S["parallax"] >> parallax
S["ambientocclusion"] >> ambientocclusion S["ambientocclusion"] >> ambientocclusion
S["auto_fit_viewport"] >> auto_fit_viewport S["auto_fit_viewport"] >> auto_fit_viewport
S["sprint_spacebar"] >> sprint_spacebar
S["sprint_toggle"] >> sprint_toggle
S["menuoptions"] >> menuoptions S["menuoptions"] >> menuoptions
S["enable_tips"] >> enable_tips S["enable_tips"] >> enable_tips
S["tip_delay"] >> tip_delay S["tip_delay"] >> tip_delay
@@ -181,8 +183,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["widescreenpref"] >> widescreenpref S["widescreenpref"] >> widescreenpref
S["autostand"] >> autostand S["autostand"] >> autostand
S["cit_toggles"] >> cit_toggles S["cit_toggles"] >> cit_toggles
S["lewdchem"] >> lewdchem
S["preferred_chaos"] >> preferred_chaos S["preferred_chaos"] >> preferred_chaos
S["auto_ooc"] >> auto_ooc
//try to fix any outdated data if necessary //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) parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion)) ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport)) 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_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit)) 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) 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)) widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
autostand = sanitize_integer(autostand, 0, 1, initial(autostand)) autostand = sanitize_integer(autostand, 0, 1, initial(autostand))
cit_toggles = sanitize_integer(cit_toggles, 0, 65535, initial(cit_toggles)) cit_toggles = sanitize_integer(cit_toggles, 0, 65535, initial(cit_toggles))
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
return 1 return 1
@@ -264,6 +268,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["parallax"], parallax) WRITE_FILE(S["parallax"], parallax)
WRITE_FILE(S["ambientocclusion"], ambientocclusion) WRITE_FILE(S["ambientocclusion"], ambientocclusion)
WRITE_FILE(S["auto_fit_viewport"], auto_fit_viewport) 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["menuoptions"], menuoptions)
WRITE_FILE(S["enable_tips"], enable_tips) WRITE_FILE(S["enable_tips"], enable_tips)
WRITE_FILE(S["tip_delay"], tip_delay) 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["widescreenpref"], widescreenpref)
WRITE_FILE(S["autostand"], autostand) WRITE_FILE(S["autostand"], autostand)
WRITE_FILE(S["cit_toggles"], cit_toggles) WRITE_FILE(S["cit_toggles"], cit_toggles)
WRITE_FILE(S["lewdchem"], lewdchem)
WRITE_FILE(S["preferred_chaos"], preferred_chaos) WRITE_FILE(S["preferred_chaos"], preferred_chaos)
WRITE_FILE(S["auto_ooc"], auto_ooc)
return 1 return 1
@@ -517,6 +523,21 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
all_quirks = SANITIZE_LIST(all_quirks) 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) cit_character_pref_load(S)
return 1 return 1
+27
View File
@@ -298,6 +298,33 @@ BLIND // can't see anything
user.regenerate_icons() user.regenerate_icons()
return TRUE 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() /obj/item/clothing/under/verb/jumpsuit_adjust()
set name = "Adjust Jumpsuit Style" set name = "Adjust Jumpsuit Style"
@@ -54,6 +54,9 @@
H.blur_eyes(5) H.blur_eyes(5)
eyes.applyOrganDamage(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 /obj/item/clothing/glasses/meson
name = "optical meson scanner" name = "optical meson scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting conditions." desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting conditions."
@@ -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) for(var/i in rad_places)
var/turf/place = i 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 continue
var/strength = round(rad_places[i] / 1000, 0.1) var/strength = round(rad_places[i] / 1000, 0.1)
var/image/pic = new(loc = place) var/image/pic = new(loc = place)
@@ -139,7 +139,6 @@
item_state = "trayson-t-ray" item_state = "trayson-t-ray"
desc = "Used by engineering staff to see underfloor objects such as cables and pipes." desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
range = 2 range = 2
modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE) modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE)
/obj/item/clothing/glasses/meson/engine/tray/prescription /obj/item/clothing/glasses/meson/engine/tray/prescription
@@ -152,7 +151,6 @@
icon_state = "trayson-shuttle" icon_state = "trayson-shuttle"
item_state = "trayson-shuttle" item_state = "trayson-shuttle"
desc = "Used to see the boundaries of shuttle regions." desc = "Used to see the boundaries of shuttle regions."
modes = list(MODE_NONE = MODE_SHUTTLE, MODE_SHUTTLE = MODE_NONE) modes = list(MODE_NONE = MODE_SHUTTLE, MODE_SHUTTLE = MODE_NONE)
#undef MODE_NONE #undef MODE_NONE
+2 -2
View File
@@ -89,12 +89,12 @@
/obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot) /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") SEND_SIGNAL(user, COMSIG_CLEAR_MOOD_EVENT, "noshoes")
/obj/item/clothing/shoes/clown_shoes/dropped(mob/user) /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) SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "noshoes", /datum/mood_event/noshoes)
/obj/item/clothing/shoes/clown_shoes/jester /obj/item/clothing/shoes/clown_shoes/jester
+1 -1
View File
@@ -13,7 +13,7 @@
if(!ishuman(user)) if(!ishuman(user))
return return
var/mob/living/carbon/human/H = user 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 return
if(slot == SLOT_SHOES) if(slot == SLOT_SHOES)
spells = new spells = new
+1 -2
View File
@@ -590,8 +590,7 @@
/obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, slot) /obj/item/clothing/suit/space/hardsuit/clown/mob_can_equip(mob/M, slot)
if(!..() || !ishuman(M)) if(!..() || !ishuman(M))
return FALSE return FALSE
var/mob/living/carbon/human/H = M if(M.mind && HAS_TRAIT(M.mind, TRAIT_CLOWN_MENTALITY))
if(H.mind.assigned_role == "Clown")
return TRUE return TRUE
else else
return FALSE return FALSE
@@ -467,6 +467,33 @@
fitted = FEMALE_UNIFORM_TOP fitted = FEMALE_UNIFORM_TOP
can_adjust = FALSE 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 /obj/item/clothing/under/captainparade
name = "captain's parade uniform" name = "captain's parade uniform"
desc = "A captain's luxury-wear, for special occasions." desc = "A captain's luxury-wear, for special occasions."
@@ -509,6 +536,24 @@
fitted = FEMALE_UNIFORM_TOP fitted = FEMALE_UNIFORM_TOP
can_adjust = FALSE 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 /obj/item/clothing/under/stripeddress
name = "striped dress" name = "striped dress"
desc = "Fashion in space." desc = "Fashion in space."
@@ -529,6 +574,44 @@
fitted = FEMALE_UNIFORM_TOP fitted = FEMALE_UNIFORM_TOP
can_adjust = FALSE 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 /obj/item/clothing/under/redeveninggown
name = "red evening gown" name = "red evening gown"
desc = "Fancy dress for space bar singers." desc = "Fancy dress for space bar singers."
+31
View File
@@ -75,3 +75,34 @@
desc = "A pair of woodland camouflage pants. Probably not the best choice for a space station." desc = "A pair of woodland camouflage pants. Probably not the best choice for a space station."
icon_state = "camopants" icon_state = "camopants"
item_color = "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 time = 100
category = CAT_MISC category = CAT_MISC
always_availible = FALSE // Disabled til learned 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
+2
View File
@@ -37,6 +37,8 @@
continue continue
if(!H.client) if(!H.client)
continue continue
if(HAS_TRAIT(H,TRAIT_EXEMPT_HEALTH_EVENTS))
continue
if(H.stat == DEAD) if(H.stat == DEAD)
continue continue
if(HAS_TRAIT(H, TRAIT_VIRUSIMMUNE)) //Don't pick someone who's virus immune, only for it to not do anything. if(HAS_TRAIT(H, TRAIT_VIRUSIMMUNE)) //Don't pick someone who's virus immune, only for it to not do anything.
+1 -1
View File
@@ -9,7 +9,7 @@
/datum/round_event/heart_attack/start() /datum/round_event/heart_attack/start()
var/list/heart_attack_contestants = list() var/list/heart_attack_contestants = list()
for(var/mob/living/carbon/human/H in shuffle(GLOB.player_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 continue
if(H.satiety <= -60) //Multiple junk food items recently if(H.satiety <= -60) //Multiple junk food items recently
heart_attack_contestants[H] = 3 heart_attack_contestants[H] = 3
@@ -35,4 +35,6 @@
/datum/hallucination/delusion, /datum/hallucination/delusion,
/datum/hallucination/oh_yeah) /datum/hallucination/oh_yeah)
for(var/mob/living/carbon/C in GLOB.alive_mob_list) 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) new picked_hallucination(C, TRUE)
@@ -15,6 +15,8 @@
continue continue
if(H.stat == DEAD) if(H.stat == DEAD)
continue 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 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 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 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" name = "space cola snowcone"
desc = "Space Cola drizzled over a snowball in a paper cup." desc = "Space Cola drizzled over a snowball in a paper cup."
icon_state = "soda_sc" 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) tastes = list("ice" = 1, "water" = 1, "cola" = 5)
/obj/item/reagent_containers/food/snacks/snowcones/spacemountainwind /obj/item/reagent_containers/food/snacks/snowcones/spacemountainwind
@@ -248,4 +248,4 @@
desc = "A very colorful snowball in a paper cup." desc = "A very colorful snowball in a paper cup."
icon_state = "rainbow_sc" icon_state = "rainbow_sc"
list_reagents = list("nutriment" = 5, "laughter" = 25) 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" filling_color = "#ECA735"
tastes = list("fried corn" = 1) tastes = list("fried corn" = 1)
foodtype = JUNKFOOD | FRIED 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()
..()
+1 -1
View File
@@ -240,7 +240,7 @@
dat += "</table>" dat += "</table>"
else else
dat += "No trait-related genes detected in sample.<br>" 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 += "<a href='?src=[REF(src)];op=insert'>Insert: [disk.gene.get_name()]</a>"
dat += "</div>" dat += "</div>"
else else
@@ -27,7 +27,7 @@
bitesize_mod = 2 bitesize_mod = 2
var/stacktype = /obj/item/stack/tile/grass var/stacktype = /obj/item/stack/tile/grass
var/tile_coefficient = 0.02 // 1/50 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) /obj/item/reagent_containers/food/snacks/grown/grass/attack_self(mob/user)
to_chat(user, "<span class='notice'>You prepare the astroturf.</span>") to_chat(user, "<span class='notice'>You prepare the astroturf.</span>")
+277 -1
View File
@@ -232,7 +232,7 @@
/obj/item/reagent_containers/food/snacks/grown/cherry_bomb/proc/detonate() /obj/item/reagent_containers/food/snacks/grown/cherry_bomb/proc/detonate()
reagents.chem_temp = 1000 //Sets off the black powder reagents.chem_temp = 1000 //Sets off the black powder
reagents.handle_reactions() reagents.handle_reactions()
// Lavaland cactus // Lavaland cactus
/obj/item/seeds/lavaland/cactus /obj/item/seeds/lavaland/cactus
@@ -244,3 +244,279 @@
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi' growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
growthstages = 2 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)
+6 -1
View File
@@ -27,6 +27,7 @@
var/rarity = 0 // How rare the plant is. Used for giving points to cargo when shipping off to CentCom. 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/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/genes = list() // Plant genes are stored here, see plant_genes.dm for more info.
var/list/forbiddengenes = list()
var/list/reagents_add = list() var/list/reagents_add = list()
// A list of reagents to add to product. // A list of reagents to add to product.
// Format: "reagent_id" = potency multiplier // Format: "reagent_id" = potency multiplier
@@ -96,6 +97,10 @@
S.reagents_add = reagents_add.Copy() // Faster than grabbing the list from genes. S.reagents_add = reagents_add.Copy() // Faster than grabbing the list from genes.
return S return S
obj/item/seeds/proc/is_gene_forbidden(typepath)
return (typepath in forbiddengenes)
/obj/item/seeds/proc/get_gene(typepath) /obj/item/seeds/proc/get_gene(typepath)
return (locate(typepath) in genes) return (locate(typepath) in genes)
@@ -448,7 +453,7 @@
for(var/i in 1 to amount_random_traits) 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/random_trait = pick((subtypesof(/datum/plant_gene/trait)-typesof(/datum/plant_gene/trait/plant_type)))
var/datum/plant_gene/trait/T = new random_trait 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 genes += T
else else
qdel(T) qdel(T)
+2
View File
@@ -14,6 +14,8 @@
access = list(ACCESS_THEATRE) access = list(ACCESS_THEATRE)
minimal_access = list(ACCESS_THEATRE) minimal_access = list(ACCESS_THEATRE)
mind_traits = list(TRAIT_CLOWN_MENTALITY)
display_order = JOB_DISPLAY_ORDER_CLOWN display_order = JOB_DISPLAY_ORDER_CLOWN
/datum/outfit/job/clown /datum/outfit/job/clown
+12 -2
View File
@@ -58,13 +58,23 @@
return return
switch(_key) switch(_key)
if("Shift") 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
return ..() return ..()
/mob/living/carbon/human/key_up(_key, client/user) /mob/living/carbon/human/key_up(_key, client/user)
switch(_key) switch(_key)
if("Shift") 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
return ..() return ..()
+2 -2
View File
@@ -50,7 +50,7 @@
/obj/machinery/mineral/ore_redemption/examine(mob/user) /obj/machinery/mineral/ore_redemption/examine(mob/user)
. = ..() . = ..()
if(in_range(user, src) || isobserver(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) /obj/machinery/mineral/ore_redemption/proc/smelt_ore(obj/item/stack/ore/O)
var/datum/component/material_container/mat_container = materials.mat_container var/datum/component/material_container/mat_container = materials.mat_container
@@ -63,7 +63,7 @@
ore_buffer -= O ore_buffer -= O
if(O && O.refined_type) 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) var/material_amount = mat_container.get_item_material_amount(O)
@@ -74,4 +74,5 @@
/datum/sprite_accessory/underwear /datum/sprite_accessory/underwear
icon = 'icons/mob/underwear.dmi' icon = 'icons/mob/underwear.dmi'
var/has_color = FALSE var/has_color = FALSE
var/has_digitigrade = FALSE
@@ -2,6 +2,9 @@
// Socks Definitions // // Socks Definitions //
/////////////////////// ///////////////////////
/datum/sprite_accessory/underwear/socks
has_digitigrade = TRUE
/datum/sprite_accessory/underwear/socks/nude /datum/sprite_accessory/underwear/socks/nude
name = "Nude" name = "Nude"
icon_state = null icon_state = null
@@ -28,41 +28,49 @@
name = "Boxers" name = "Boxers"
icon_state = "boxers" icon_state = "boxers"
has_color = TRUE has_color = TRUE
has_digitigrade = TRUE
gender = MALE gender = MALE
/datum/sprite_accessory/underwear/bottom/male_bee /datum/sprite_accessory/underwear/bottom/male_bee
name = "Boxers - Bee" name = "Boxers - Bee"
icon_state = "bee_shorts" icon_state = "bee_shorts"
has_digitigrade = TRUE
gender = MALE gender = MALE
/datum/sprite_accessory/underwear/bottom/male_hearts /datum/sprite_accessory/underwear/bottom/male_hearts
name = "Boxers - Heart" name = "Boxers - Heart"
icon_state = "boxers_heart" icon_state = "boxers_heart"
has_digitigrade = TRUE
gender = MALE gender = MALE
/datum/sprite_accessory/underwear/bottom/male_stripe /datum/sprite_accessory/underwear/bottom/male_stripe
name = "Boxers - Striped" name = "Boxers - Striped"
icon_state = "boxers_striped" icon_state = "boxers_striped"
has_digitigrade = TRUE
gender = MALE gender = MALE
/datum/sprite_accessory/underwear/bottom/male_commie /datum/sprite_accessory/underwear/bottom/male_commie
name = "Boxers - Striped Communist" name = "Boxers - Striped Communist"
icon_state = "boxers_commie" icon_state = "boxers_commie"
has_digitigrade = TRUE
gender = MALE gender = MALE
/datum/sprite_accessory/underwear/bottom/male_usastripe /datum/sprite_accessory/underwear/bottom/male_usastripe
name = "Boxers - Striped Freedom" name = "Boxers - Striped Freedom"
icon_state = "boxers_assblastusa" icon_state = "boxers_assblastusa"
has_digitigrade = TRUE
gender = MALE gender = MALE
/datum/sprite_accessory/underwear/bottom/male_uk /datum/sprite_accessory/underwear/bottom/male_uk
name = "Boxers - Striped UK" name = "Boxers - Striped UK"
icon_state = "boxers_uk" icon_state = "boxers_uk"
has_digitigrade = TRUE
gender = MALE gender = MALE
/datum/sprite_accessory/underwear/bottom/boxer_briefs /datum/sprite_accessory/underwear/bottom/boxer_briefs
name = "Boxer Briefs" name = "Boxer Briefs"
icon_state = "boxer_briefs" icon_state = "boxer_briefs"
has_digitigrade = TRUE
has_color = TRUE has_color = TRUE
/datum/sprite_accessory/underwear/bottom/panties /datum/sprite_accessory/underwear/bottom/panties
@@ -140,6 +148,7 @@
/datum/sprite_accessory/underwear/bottom/longjon /datum/sprite_accessory/underwear/bottom/longjon
name = "Long John Bottoms" name = "Long John Bottoms"
icon_state = "ljonb" icon_state = "ljonb"
has_digitigrade = TRUE
has_color = TRUE has_color = TRUE
/datum/sprite_accessory/underwear/bottom/swimsuit_red /datum/sprite_accessory/underwear/bottom/swimsuit_red
+3
View File
@@ -18,3 +18,6 @@
update_icon(preferred_form) update_icon(preferred_form)
updateghostimages() updateghostimages()
client.reenter_round_timeout = max(client.reenter_round_timeout, clientless_round_timeout)
clientless_round_timeout = client.reenter_round_timeout
+17 -11
View File
@@ -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) GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
#define CANT_REENTER_ROUND -1
/mob/dead/observer /mob/dead/observer
name = "ghost" name = "ghost"
desc = "It's a g-g-g-g-ghooooost!" //jinkies! 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 hud_type = /datum/hud/ghost
movement_type = GROUND | FLYING movement_type = GROUND | FLYING
var/can_reenter_corpse 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/datum/hud/living/carbon/hud = null // hud
var/bootime = 0 var/bootime = 0
var/started_as_observer //This variable is set to 1 when you enter the game as an observer. 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. 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 penalty += roundstart_quit_limit - world.time
if(penalty) if(penalty)
ghost.reenter_round_timeout = world.realtime + penalty penalty += world.realtime
if(ghost.reenter_round_timeout - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime) if(penalty - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
ghost.reenter_round_timeout = CANT_REENTER_ROUND 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) transfer_ckey(ghost, FALSE)
return ghost 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) ghostize(0, penalize = TRUE)
/mob/dead/observer/proc/can_reenter_round(silent = FALSE) /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 return TRUE
if(!silent) if(!silent && client)
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>") 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 return FALSE
/mob/dead/observer/Move(NewLoc, direct) /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 = new(src)
spawners_menu.ui_interact(src) spawners_menu.ui_interact(src)
#undef CANT_REENTER_ROUND
@@ -6,21 +6,21 @@
return 2 //no ears return 2 //no ears
/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush) /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. /*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. 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 In all, this is a lot like the monkey code. /N
*/ */
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M) /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 return
switch(M.a_intent) switch(M.a_intent)
if (INTENT_HELP)
if ("help")
if(!recoveringstam) if(!recoveringstam)
resting = 0 resting = 0
AdjustStun(-60) AdjustStun(-60)
@@ -28,11 +28,7 @@ In all, this is a lot like the monkey code. /N
AdjustUnconscious(-60) AdjustUnconscious(-60)
AdjustSleeping(-100) AdjustSleeping(-100)
visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake [p_them()] up!</span>") visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake [p_them()] up!</span>")
if(INTENT_DISARM, INTENT_HARM)
if ("grab")
grabbedby(M)
else
if(health > 0) if(health > 0)
M.do_attack_animation(src, ATTACK_EFFECT_BITE) M.do_attack_animation(src, ATTACK_EFFECT_BITE)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1) 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) /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) switch(M.a_intent)
if("help") if(INTENT_HELP)
help_shake_act(M) help_shake_act(M)
if("grab") if(INTENT_GRAB)
grabbedby(M) 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) M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
return 1 if(INTENT_DISARM)
if("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) M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return 1
return 0
/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M) /mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
if(..()) . = ..()
if (stat != DEAD) if(.) //successful monkey bite.
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(rand(1, 3), BRUTE, affecting) apply_damage(rand(1, 3), BRUTE, affecting)
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M) /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) adjustStaminaLoss(damage)
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M) /mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack . = ..()
var/damage = rand(5, 35) if(!.) //unsuccessful slime attack
if(M.is_adult) return
damage = rand(10, 40) var/damage = rand(5, 35)
adjustBruteLoss(damage) if(M.is_adult)
log_combat(M, src, "attacked") damage = rand(10, 40)
updatehealth() adjustBruteLoss(damage)
log_combat(M, src, "attacked")
updatehealth()
/mob/living/carbon/alien/ex_act(severity, target, origin) /mob/living/carbon/alien/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src)) if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
@@ -63,12 +63,7 @@
if(A) if(A)
if(isliving(A)) if(isliving(A))
var/mob/living/L = A var/mob/living/L = A
var/blocked = FALSE if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
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)
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>") L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
L.Knockdown(100) L.Knockdown(100)
sleep(2)//Runtime prevention (infinite bump() calls on hulks) sleep(2)//Runtime prevention (infinite bump() calls on hulks)
@@ -5,9 +5,11 @@
else 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) if(user.a_intent == INTENT_HARM)
..(user, 1) . = ..(user, TRUE)
if(.)
return
adjustBruteLoss(15) adjustBruteLoss(15)
var/hitverb = "punched" var/hitverb = "punched"
if(mob_size < MOB_SIZE_LARGE) if(mob_size < MOB_SIZE_LARGE)
@@ -21,46 +23,46 @@
return 1 return 1
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M) /mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
if(..()) . = ..()
switch(M.a_intent) if(.) //To allow surgery to return properly.
if ("harm") return
var/damage = rand(1, 9) switch(M.a_intent)
if (prob(90)) if (INTENT_HARM)
playsound(loc, "punch", 25, 1, -1) var/damage = rand(1, 9)
visible_message("<span class='danger'>[M] has punched [src]!</span>", \ if (prob(90))
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE) playsound(loc, "punch", 25, 1, -1)
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down. visible_message("<span class='danger'>[M] has punched [src]!</span>", \
Unconscious(40) "<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \ if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down.
"<span class='userdanger'>[M] has knocked [src] down!</span>") Unconscious(40)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected)) visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \
apply_damage(damage, BRUTE, affecting) "<span class='userdanger'>[M] has knocked [src] down!</span>")
log_combat(M, src, "attacked") 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 else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) if (prob(50))
visible_message("<span class='userdanger'>[M] has attempted to punch [src]!</span>", \ dropItemToGround(get_active_held_item())
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ("disarm")
if (!lying)
if (prob(5))
Unconscious(40)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
log_combat(M, src, "pushed") visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \ "<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else else
if (prob(50)) playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
dropItemToGround(get_active_held_item()) visible_message("<span class='danger'>[M] has attempted to disarm [src]!</span>",\
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) "<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
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)
/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) /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) if(!no_effect && !visual_effect_icon)
@@ -1,26 +1,33 @@
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M) /mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
if(..()) . = ..()
var/damage = rand(1, 9) if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB)
if (prob(90)) return
playsound(loc, "punch", 25, 1, -1) var/damage = rand(1, 9)
log_combat(M, src, "attacked") if (prob(90))
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \ playsound(loc, "punch", 25, 1, -1)
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE) log_combat(M, src, "attacked")
if ((stat != DEAD) && (damage > 4.9)) visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
Unconscious(rand(100,200)) "<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)) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting) apply_damage(damage, BRUTE, affecting)
else else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \ 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) "<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) 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)) adjustBruteLoss(5 + rand(1,9))
new /datum/forced_movement(src, get_step_away(user,src, 30), 1) new /datum/forced_movement(src, get_step_away(user,src, 30), 1)
return 1 return 1
@@ -103,15 +103,17 @@
new_xeno.notransform = 0 new_xeno.notransform = 0
new_xeno.invisibility = 0 new_xeno.invisibility = 0
var/mob/living/carbon/old_owner = owner
if(kill_on_sucess) //ITS TOO LATE 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>") 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.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. 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. 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>") 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.adjustBruteLoss(40)
owner.cut_overlay(overlay) old_owner.cut_overlay(overlay)
qdel(src) 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)) if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
affecting.dismember(P.damtype) affecting.dismember(P.damtype)
/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check) /mob/living/carbon/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
. = FALSE . = ..()
if(mind) if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !in_throw_mode)
if(mind.martial_art && mind.martial_art.dodge_chance == 100)
return TRUE
if(!skip_throw_mode_check && !in_throw_mode)
return return
if(get_active_held_item()) if(get_active_held_item() || restrained())
return return
if(restrained()) I.attack_hand(src)
return if(get_active_held_item() == I) //if our attack_hand() picks up the item...
return TRUE visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
throw_mode_off()
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE) return TRUE
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
..()
/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) /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 var/obj/item/bodypart/affecting
if(user == src) if(user == src)
affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay! 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_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
send_item_attack_message(I, user, affecting.name) send_item_attack_message(I, user, affecting.name)
if(I.force) 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 apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC) if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
var/basebloodychance = affecting.brute_dam + totitemdamage var/basebloodychance = affecting.brute_dam + totitemdamage
@@ -137,7 +127,9 @@
//ATTACK HAND IGNORING PARENT RETURN VALUE //ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/carbon/attack_hand(mob/living/carbon/human/user) /mob/living/carbon/attack_hand(mob/living/carbon/human/user)
. = ..()
if(.) //was the attack blocked?
return
for(var/thing in diseases) for(var/thing in diseases)
var/datum/disease/D = thing var/datum/disease/D = thing
if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN) if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
@@ -152,8 +144,7 @@
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM) if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
for(var/datum/surgery/S in surgeries) for(var/datum/surgery/S in surgeries)
if(S.next_step(user, user.a_intent)) if(S.next_step(user, user.a_intent))
return 1 return TRUE
return 0
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M) /mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
@@ -173,7 +164,8 @@
help_shake_act(M) help_shake_act(M)
return 0 return 0
if(..()) //successful monkey bite. . = ..()
if(.) //successful monkey bite.
for(var/thing in M.diseases) for(var/thing in M.diseases)
var/datum/disease/D = thing var/datum/disease/D = thing
ForceContractDisease(D) ForceContractDisease(D)
@@ -181,26 +173,27 @@
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M) /mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack . = ..()
if(M.powerlevel > 0) if(!.)
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10 return
if(prob(stunprob)) if(M.powerlevel > 0)
M.powerlevel -= 3 var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
if(M.powerlevel < 0) if(prob(stunprob))
M.powerlevel = 0 M.powerlevel -= 3
if(M.powerlevel < 0)
M.powerlevel = 0
visible_message("<span class='danger'>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>") "<span class='userdanger'>The [M.name] has shocked [src]!</span>")
do_sparks(5, TRUE, src) do_sparks(5, TRUE, src)
var/power = M.powerlevel + rand(0,3) var/power = M.powerlevel + rand(0,3)
Knockdown(power*20) Knockdown(power*20)
if(stuttering < power) if(stuttering < power)
stuttering = power stuttering = power
if (prob(stunprob) && M.powerlevel >= 8) if (prob(stunprob) && M.powerlevel >= 8)
adjustFireLoss(M.powerlevel * rand(6,10)) adjustFireLoss(M.powerlevel * rand(6,10))
updatehealth() updatehealth()
return 1
/mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone) /mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone)
if(!attacker.limb_destroyer) if(!attacker.limb_destroyer)
@@ -332,12 +325,12 @@
else else
return return
else if(check_zone(M.zone_selected) == "r_arm" || check_zone(M.zone_selected) == "l_arm") else if(check_zone(M.zone_selected) == "r_arm" || check_zone(M.zone_selected) == "l_arm")
M.visible_message( \ M.visible_message( \
"<span class='notice'>[M] shakes [src]'s hand.</span>", \ "<span class='notice'>[M] shakes [src]'s hand.</span>", \
"<span class='notice'>You shake [src]'s hand.</span>", ) "<span class='notice'>You shake [src]'s hand.</span>", )
else else
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \ 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>") "<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) var/obj/item/organ/vocal_cords/Vc = user.getorganslot(ORGAN_SLOT_VOICE)
if(Vc) if(Vc)
if(istype(Vc, /obj/item/organ/vocal_cords/velvet)) 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" 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 P.setAngle(rand(0, 360))//SHING
return FALSE return FALSE
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself return ..()
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)
// redirect the projectile /mob/living/carbon/human/check_reflect(def_zone)
P.original = locate(new_x, new_y, P.z) if(wear_suit?.IsReflect(def_zone))
P.starting = curloc return TRUE
P.firer = src return ..()
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 -1 // complete projectile permutation /mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
. = ..()
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration)) if(.)
P.on_hit(src, 100, def_zone) return
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)
var/block_chance_modifier = round(damage / -3) 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) if(wear_suit)
var/final_block_chance = wear_suit.block_chance - (CLAMP((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier 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)) if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1 return TRUE
if(w_uniform) if(w_uniform)
var/final_block_chance = w_uniform.block_chance - (CLAMP((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier 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)) if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1 return TRUE
if(wear_neck) if(wear_neck)
var/final_block_chance = wear_neck.block_chance - (CLAMP((armour_penetration-wear_neck.armour_penetration)/2,0,100)) + block_chance_modifier 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)) if(wear_neck.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1 return TRUE
return 0 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() /mob/living/carbon/human/proc/check_block()
if(mind) if(mind)
@@ -135,39 +105,7 @@
return FALSE return FALSE
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) /mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE)
if(dna && dna.species) return dna?.species?.spec_hitby(AM, src) || ..()
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 ..()
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0) /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)) 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) 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) if(user.a_intent == INTENT_HARM)
var/hulk_verb = pick("smash","pummel") . = ..(user, TRUE)
if(check_shields(user, 15, "the [hulk_verb]ing")) if(.)
return return
..(user, 1) var/hulk_verb = pick("smash","pummel")
playsound(loc, user.dna.species.attack_sound, 25, 1, -1) playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
var/message = "[user] has [hulk_verb]ed [src]!" var/message = "[user] has [hulk_verb]ed [src]!"
visible_message("<span class='danger'>[message]</span>", \ visible_message("<span class='danger'>[message]</span>", \
@@ -215,7 +153,8 @@
return 1 return 1
/mob/living/carbon/human/attack_hand(mob/user) /mob/living/carbon/human/attack_hand(mob/user)
if(..()) //to allow surgery to return properly. . = ..()
if(.) //To allow surgery to return properly.
return return
if(ishuman(user)) if(ishuman(user))
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
@@ -227,8 +166,7 @@
if(!affecting) if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST) affecting = get_bodypart(BODY_ZONE_CHEST)
if(M.a_intent == INTENT_HELP) if(M.a_intent == INTENT_HELP)
..() //shaking return ..() //shaking
return 0
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead. 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() 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(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
if(..()) //successful monkey bite, this handles disease contraction. if(..()) //successful monkey bite, this handles disease contraction.
var/damage = rand(1, 3) var/damage = rand(1, 3)
if(check_shields(M, damage, "the [M.name]")) apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
return 0
if(stat != DEAD)
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
return 1 return 1
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M) /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>") if(!.)
return 0 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(..()) playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
if(M.a_intent == INTENT_HARM) visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
if (w_uniform) "<span class='userdanger'>[M] has slashed at [src]!</span>")
w_uniform.add_fingerprint(M) log_combat(M, src, "attacked")
var/damage = prob(90) ? 20 : 0 if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
if(!damage) return 1
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1) apply_damage(damage, BRUTE, affecting, armor_block)
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) if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \ var/obj/item/I = get_active_held_item()
"<span class='userdanger'>[M] has slashed at [src]!</span>") if(I && dropItemToGround(I))
log_combat(M, src, "attacked") playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
return 1 "<span class='userdanger'>[M] disarmed [src]!</span>")
apply_damage(damage, BRUTE, affecting, armor_block) else
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead. if(!lying) //CITADEL EDIT
var/obj/item/I = get_active_held_item() Knockdown(100, TRUE, FALSE, 30, 25)
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 else
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) Knockdown(100)
if(!lying) //CITADEL EDIT log_combat(M, src, "tackled")
Knockdown(100, TRUE, FALSE, 30, 25) visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
else "<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) /mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L)
. = ..()
if(..()) //successful larva bite. if(!.) //unsuccessful larva bite.
var/damage = rand(1, 3) return
if(check_shields(L, damage, "the [L.name]")) var/damage = rand(1, 3)
return 0 if(stat != DEAD)
if(stat != DEAD) L.amount_grown = min(L.amount_grown + damage, L.max_grown)
L.amount_grown = min(L.amount_grown + damage, L.max_grown) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) if(!affecting)
if(!affecting) affecting = get_bodypart(BODY_ZONE_CHEST)
affecting = get_bodypart(BODY_ZONE_CHEST) var/armor_block = run_armor_check(affecting, "melee")
var/armor_block = run_armor_check(affecting, "melee") apply_damage(damage, BRUTE, affecting, armor_block)
apply_damage(damage, BRUTE, affecting, armor_block)
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M) /mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
. = ..() . = ..()
if(.) if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) 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)) 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 if(!dam_zone) //Dismemberment successful
return TRUE return TRUE
@@ -332,23 +261,22 @@
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M) /mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack . = ..()
var/damage = rand(5, 25) if(!.) //unsuccessful slime attack
if(M.is_adult) return
damage = rand(10, 35) var/damage = rand(5, 25)
if(M.is_adult)
damage = rand(10, 35)
if(check_shields(M, damage, "the [M.name]")) 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))
return 0 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)) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!dam_zone) //Dismemberment successful if(!affecting)
return 1 affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) apply_damage(damage, BRUTE, affecting, armor_block)
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) /mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM) if(M.occupant.a_intent == INTENT_HARM)
@@ -652,7 +580,7 @@
if(mind) if(mind)
if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") ) if((mind.assigned_role == "Station Engineer") || (mind.assigned_role == "Chief Engineer") )
gain = 100 gain = 100
if(mind.assigned_role == "Clown") if(HAS_TRAIT(mind, TRAIT_CLOWN_MENTALITY))
gain = rand(-300, 300) 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! investigate_log("([key_name(src)]) has been consumed by the singularity.", INVESTIGATE_SINGULO) //Oh that's where the clown ended up!
gib() gib()
+24 -35
View File
@@ -545,6 +545,20 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//Underwear, Undershirts & Socks //Underwear, Undershirts & Socks
if(!(NO_UNDERWEAR in species_traits)) 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.underwear)
if(H.hidden_underwear) if(H.hidden_underwear)
H.underwear = "Nude" H.underwear = "Nude"
@@ -552,8 +566,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.underwear = H.saved_underwear H.underwear = H.saved_underwear
var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear] var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear]
if(B) if(B)
var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER) var/digilegs = ((DIGITIGRADE in species_traits) && B.has_digitigrade) ? "_d" : ""
if(UNDIE_COLORABLE(B)) var/mutable_appearance/MA = mutable_appearance(B.icon, "[B.icon_state][digilegs]", -BODY_LAYER)
if(B.has_color)
MA.color = "#[H.undie_color]" MA.color = "#[H.undie_color]"
standing += MA standing += MA
@@ -564,28 +579,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.undershirt = H.saved_undershirt H.undershirt = H.saved_undershirt
var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt] var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt]
if(T) if(T)
var/state = "[T.icon_state][((DIGITIGRADE in species_traits) && T.has_digitigrade) ? "_d" : ""]"
var/mutable_appearance/MA var/mutable_appearance/MA
if(H.dna.species.sexes && H.gender == FEMALE) 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 else
MA = mutable_appearance(T.icon, T.icon_state, -BODY_LAYER) MA = mutable_appearance(T.icon, state, -BODY_LAYER)
if(UNDIE_COLORABLE(T)) if(T.has_color)
MA.color = "#[H.shirt_color]" MA.color = "#[H.shirt_color]"
standing += MA 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) if(standing.len)
H.overlays_standing[BODY_LAYER] = standing H.overlays_standing[BODY_LAYER] = standing
@@ -1589,20 +1592,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
user.adjustStaminaLossBuffered(3) user.adjustStaminaLossBuffered(3)
return FALSE return FALSE
else if(aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin)) 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.do_attack_animation(target, ATTACK_EFFECT_ASS_SLAP)
user.adjustStaminaLossBuffered(3) 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) playsound(target.loc, 'sound/weapons/slap.ogg', 50, 1, -1)
user.visible_message(\ user.visible_message(\
"<span class='danger'>\The [user] slaps \the [target]'s ass!</span>",\ "<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 attacker_style = M.mind.martial_art
if(attacker_style?.pacifism_check && HAS_TRAIT(M, TRAIT_PACIFISM)) // most martial arts are quite harmful, alas. if(attacker_style?.pacifism_check && HAS_TRAIT(M, TRAIT_PACIFISM)) // most martial arts are quite harmful, alas.
attacker_style = null 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) switch(M.a_intent)
if("help") if("help")
help(M, H, attacker_style) help(M, H, attacker_style)
@@ -51,11 +51,7 @@
. = ..() . = ..()
to_chat(C, "[info_text]") to_chat(C, "[info_text]")
C.real_name = "[pick(GLOB.nightmare_names)]" C.fully_replace_character_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
/datum/species/shadow/nightmare/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H) /datum/species/shadow/nightmare/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
var/turf/T = H.loc var/turf/T = H.loc
@@ -127,8 +123,8 @@
/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0) /obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
respawn_progress = 0 respawn_progress = 0
if(blade && special != HEART_SPECIAL_SHADOWIFY) if(blade && special != HEART_SPECIAL_SHADOWIFY)
QDEL_NULL(blade)
M.visible_message("<span class='warning'>\The [blade] disintegrates!</span>") M.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
QDEL_NULL(blade)
..() ..()
/obj/item/organ/heart/nightmare/Stop() /obj/item/organ/heart/nightmare/Stop()
@@ -183,15 +179,21 @@
. = ..() . = ..()
if(!proximity) if(!proximity)
return return
if(isopenturf(AM)) //So you can actually melee with it if(isopenturf(AM))
return var/turf/open/T = AM
if(isliving(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 var/mob/living/L = AM
if(iscyborg(AM)) if(iscyborg(AM))
var/mob/living/silicon/robot/borg = AM var/mob/living/silicon/robot/borg = AM
if(!borg.lamp_cooldown) if(borg.lamp_intensity)
borg.update_headlamp(TRUE, INFINITY) 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>") 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 else
for(var/obj/item/O in AM) for(var/obj/item/O in AM)
if(O.light_range && O.light_power) if(O.light_range && O.light_power)
@@ -369,6 +369,23 @@
retaliate(L) retaliate(L)
return ..() 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) /mob/living/carbon/monkey/attack_paw(mob/living/L)
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB)) if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(L) retaliate(L)
@@ -6,37 +6,55 @@
..() ..()
/mob/living/carbon/monkey/attack_paw(mob/living/M) /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) if(!.) //unsuccessful monkey bite.
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) return
if(!affecting) 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)
affecting = get_bodypart(BODY_ZONE_CHEST) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(M.limb_destroyer) if(!affecting)
dismembering_strike(M, affecting.body_zone) affecting = get_bodypart(BODY_ZONE_CHEST)
if(stat != DEAD) if(M.limb_destroyer)
var/dmg = rand(1, 5) dismembering_strike(M, affecting.body_zone)
apply_damage(dmg, BRUTE, affecting) var/dmg = rand(1, 5)
apply_damage(dmg, BRUTE, affecting)
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L) /mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite. . = ..()
var/damage = rand(1, 3) if(!.) //unsuccessful larva bite
if(stat != DEAD) return
L.amount_grown = min(L.amount_grown + damage, L.max_grown) var/damage = rand(1, 3)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected)) if(stat != DEAD)
if(!affecting) L.amount_grown = min(L.amount_grown + damage, L.max_grown)
affecting = get_bodypart(BODY_ZONE_CHEST) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
apply_damage(damage, BRUTE, affecting) 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) /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 return
switch(M.a_intent) switch(M.a_intent)
if("help") if(INTENT_HELP)
help_shake_act(M) help_shake_act(M)
if("grab") if(INTENT_GRAB)
grabbedby(M) 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) M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
if (prob(75)) if (prob(75))
visible_message("<span class='danger'>[M] has punched [name]!</span>", \ visible_message("<span class='danger'>[M] has punched [name]!</span>", \
@@ -60,7 +78,7 @@
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1) playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [name]!</span>", \ 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) "<span class='userdanger'>[M] has attempted to punch [name]!</span>", null, COMBAT_MESSAGE_RANGE)
if("disarm") if(INTENT_DISARM)
if(!IsUnconscious()) if(!IsUnconscious())
M.do_attack_animation(src, ATTACK_EFFECT_DISARM) M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if (prob(25)) 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) 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) /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(!.) // the attack was blocked or was help/grab intent
if ((prob(95) && health > 0)) return
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) if (M.a_intent == INTENT_HARM)
var/damage = rand(15, 30) if ((prob(95) && health > 0))
if (damage >= 25) playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
damage = rand(20, 40) var/damage = rand(15, 30)
if(AmountUnconscious() < 300) if (damage >= 25)
Unconscious(rand(200, 300)) damage = rand(20, 40)
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \ if(AmountUnconscious() < 300)
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE) Unconscious(rand(200, 300))
else visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \ "<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
"<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)
else else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1) visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \ "<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
if (M.a_intent == INTENT_DISARM) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
var/obj/item/I = null log_combat(M, src, "attacked")
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) if(!affecting)
if(prob(95)) affecting = get_bodypart(BODY_ZONE_CHEST)
Knockdown(20) if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \ return 1
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE) 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 else
I = get_active_held_item() I = null
if(dropItemToGround(I)) log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE) updatehealth()
else
I = null
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
updatehealth()
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M) /mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
. = ..() . = ..()
@@ -132,17 +151,19 @@
apply_damage(damage, M.melee_damage_type, affecting) apply_damage(damage, M.melee_damage_type, affecting)
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M) /mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack . = ..()
var/damage = rand(5, 35) if(!.) //unsuccessful slime attack
if(M.is_adult) return
damage = rand(20, 40) var/damage = rand(5, 35)
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(M.is_adult)
if(!dam_zone) //Dismemberment successful damage = rand(20, 40)
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))
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) if(!dam_zone) //Dismemberment successful
if(!affecting) return 1
affecting = get_bodypart(BODY_ZONE_CHEST) var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
apply_damage(damage, BRUTE, affecting) if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
apply_damage(damage, BRUTE, affecting)
/mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit) /mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit)
. = 1 . = 1
+3 -1
View File
@@ -91,7 +91,9 @@
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST)) 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>" 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) 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) if (client)
client.move_delay = initial(client.move_delay) client.move_delay = initial(client.move_delay)
+113 -18
View File
@@ -36,7 +36,50 @@
/mob/living/proc/on_hit(obj/item/projectile/P) /mob/living/proc/on_hit(obj/item/projectile/P)
return 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) /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) var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
if(!P.nodamage) if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor) apply_damage(P.damage, P.damage_type, def_zone, armor)
@@ -55,9 +98,32 @@
else else
return 0 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) /mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
if(istype(AM, /obj/item)) var/obj/item/I
var/obj/item/I = AM 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/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class() var/volume = I.get_volume_by_throwforce_and_or_w_class()
@@ -214,6 +280,24 @@
Move(user.loc) Move(user.loc)
return 1 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) /mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!SSticker.HasRoundStarted()) if(!SSticker.HasRoundStarted())
@@ -229,6 +313,12 @@
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>") to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE 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) if (stat != DEAD)
log_combat(M, src, "attacked") log_combat(M, src, "attacked")
M.do_attack_animation(src) M.do_attack_animation(src)
@@ -245,7 +335,8 @@
if(HAS_TRAIT(M, TRAIT_PACIFISM)) if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>") to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE 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) if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1) playsound(loc, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src) M.do_attack_animation(src)
@@ -256,10 +347,6 @@
/mob/living/attack_paw(mob/living/carbon/monkey/M) /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 (M.a_intent == INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM)) if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>") 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)) 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>") to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
return FALSE return FALSE
if(check_shields(M, 0, "the [M.name]"))
return FALSE
M.do_attack_animation(src, ATTACK_EFFECT_BITE) M.do_attack_animation(src, ATTACK_EFFECT_BITE)
if (prob(75)) if (prob(75))
log_combat(M, src, "attacked") log_combat(M, src, "attacked")
@@ -282,15 +371,16 @@
/mob/living/attack_larva(mob/living/carbon/alien/larva/L) /mob/living/attack_larva(mob/living/carbon/alien/larva/L)
switch(L.a_intent) switch(L.a_intent)
if("help") if(INTENT_HELP)
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>") visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
return FALSE return FALSE
else else
if(HAS_TRAIT(L, TRAIT_PACIFISM)) if(HAS_TRAIT(L, TRAIT_PACIFISM))
to_chat(L, "<span class='notice'>You don't want to hurt anyone!</span>") 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) L.do_attack_animation(src)
if(prob(90)) if(prob(90))
log_combat(L, src, "attacked") log_combat(L, src, "attacked")
@@ -301,24 +391,29 @@
else else
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \ 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) "<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) /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) switch(M.a_intent)
if ("help") if (INTENT_HELP)
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>") 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 return FALSE
if ("grab") if (INTENT_GRAB)
grabbedby(M) grabbedby(M)
return FALSE return FALSE
if("harm") if(INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM)) if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>") to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE return FALSE
M.do_attack_animation(src) if(!isalien(src))
M.do_attack_animation(src)
return TRUE return TRUE
if("disarm") if(INTENT_DISARM)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM) if(!isalien(src))
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return TRUE return TRUE
/mob/living/ex_act(severity, target, origin) /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) /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. if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
spark_system.start() 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) /mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
return //immune to slimes return //immune to slimes
@@ -26,13 +26,14 @@
fold_in(force = 1) fold_in(force = 1)
Knockdown(200) Knockdown(200)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user) /mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user)
switch(user.a_intent) 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>") 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>") visible_message("<span class='notice'>[user] boops [src] on the head!</span>")
if("harm") if(INTENT_HARM)
user.do_attack_animation(src) user.do_attack_animation(src)
if (user.name == master) if (user.name == master)
visible_message("<span class='notice'>Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.</span>") 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)) if(user.put_in_hands(card))
user.visible_message("<span class='notice'>[user] promptly scoops up [user.p_their()] pAI's card.</span>") user.visible_message("<span class='notice'>[user] promptly scoops up [user.p_their()] pAI's card.</span>")
else 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>") visible_message("<span class='danger'>[user] stomps on [src]!.</span>")
take_holo_damage(2) take_holo_damage(2)
else
grabbedby(user)
/mob/living/silicon/pai/bullet_act(obj/item/projectile/Proj) /mob/living/silicon/pai/bullet_act(obj/item/projectile/P, def_zone)
if(Proj.stun) if(P.stun)
fold_in(force = TRUE) fold_in(force = TRUE)
src.visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>") visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
. = ..(Proj) . = ..()
/mob/living/silicon/pai/stripPanelUnequip(obj/item/what, mob/who, where) //prevents stripping /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>") 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() spark_system.start()
return ..() 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) /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 (M.a_intent == INTENT_DISARM)
if(!(lying)) if(!(lying))
M.do_attack_animation(src, ATTACK_EFFECT_DISARM) M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
@@ -30,24 +42,19 @@
visible_message("<span class='danger'>[M] has forced back [src]!</span>", \ visible_message("<span class='danger'>[M] has forced back [src]!</span>", \
"<span class='userdanger'>[M] has forced back [src]!</span>", null, COMBAT_MESSAGE_RANGE) "<span class='userdanger'>[M] has forced back [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1) playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1)
else
..()
return
/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M) /mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime shock . = ..()
flash_act() if(!.) //unsuccessful slime shock
var/stunprob = M.powerlevel * 7 + 10 return
if(prob(stunprob) && M.powerlevel >= 8) var/stunprob = M.powerlevel * 7 + 10
adjustBruteLoss(M.powerlevel * rand(6,10)) var/damage = M.powerlevel * rand(6,10)
if(prob(stunprob) && M.powerlevel >= 8)
var/damage = rand(1, 3) flash_act(affect_silicon = TRUE) //my borg eyes!
if(M.is_adult) if(M.is_adult)
damage = rand(20, 40) damage += rand(10, 20)
else else
damage = rand(5, 35) damage += rand(2, 17)
damage = round(damage / 2) // borgs receive half damage
adjustBruteLoss(damage) adjustBruteLoss(damage)
updatehealth() updatehealth()
@@ -56,23 +63,17 @@
//ATTACK HAND IGNORING PARENT RETURN VALUE //ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user) /mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user)
add_fingerprint(user) add_fingerprint(user)
if(opened && !wiresexposed && !issilicon(user)) if(opened && !wiresexposed && cell && !issilicon(user))
if(cell) cell.update_icon()
cell.update_icon() cell.add_fingerprint(user)
cell.add_fingerprint(user) user.put_in_active_hand(cell)
user.put_in_active_hand(cell) to_chat(user, "<span class='notice'>You remove \the [cell].</span>")
to_chat(user, "<span class='notice'>You remove \the [cell].</span>") cell = null
cell = null update_icons()
update_icons() diag_hud_set_borgcell()
diag_hud_set_borgcell()
if(!opened) if(!opened)
if(..()) // hulk attack return ..()
spark_system.start()
spawn(0)
step_away(src,user,15)
sleep(3)
step_away(src,user,15)
/mob/living/silicon/robot/fire_act() /mob/living/silicon/robot/fire_act()
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
@@ -182,9 +183,9 @@
if (stat != DEAD) if (stat != DEAD)
adjustBruteLoss(30) adjustBruteLoss(30)
/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj) /mob/living/silicon/robot/bullet_act(obj/item/projectile/P, def_zone)
..(Proj) ..()
updatehealth() updatehealth()
if(prob(75) && Proj.damage > 0) if(prob(75) && P.damage > 0)
spark_system.start() spark_system.start()
return 2 return 2
@@ -6,7 +6,10 @@
return 2 return 2
/mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M) /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 var/damage = 20
if (prob(90)) if (prob(90))
log_combat(M, src, "attacked") log_combat(M, src, "attacked")
@@ -49,34 +52,33 @@
/mob/living/silicon/attack_paw(mob/living/user) /mob/living/silicon/attack_paw(mob/living/user)
return attack_hand(user) return attack_hand(user)
/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L) /mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
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)
if(user.a_intent == INTENT_HARM) if(user.a_intent == INTENT_HARM)
..(user, 1) . = ..(user, TRUE)
if(.)
return
adjustBruteLoss(rand(10, 15)) adjustBruteLoss(rand(10, 15))
playsound(loc, "punch", 25, 1, -1) playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has punched [src]!</span>", \ visible_message("<span class='danger'>[user] has punched [src]!</span>", \
"<span class='userdanger'>[user] has punched [src]!</span>") "<span class='userdanger'>[user] has punched [src]!</span>")
return 1 return TRUE
return 0 return FALSE
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/attack_hand(mob/living/carbon/human/M) /mob/living/silicon/attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //the attack was blocked
return
switch(M.a_intent) switch(M.a_intent)
if ("help") if (INTENT_HELP)
M.visible_message("[M] pets [src].", \ M.visible_message("[M] pets [src].", \
"<span class='notice'>You pet [src].</span>") "<span class='notice'>You pet [src].</span>")
if("grab") if(INTENT_GRAB)
grabbedby(M) grabbedby(M)
else else
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH) M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
playsound(src.loc, 'sound/effects/bang.ogg', 10, 1) playsound(src.loc, 'sound/effects/bang.ogg', 10, 1)
visible_message("<span class='danger'>[M] punches [src], but doesn't leave a dent.</span>", \ 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) "<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) /mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M)
if(M.a_intent == INTENT_HARM) if(M.a_intent == INTENT_HARM)
@@ -108,19 +110,25 @@
M.visible_message("<span class='boldwarning'>[M] is thrown off of [src]!</span>") M.visible_message("<span class='boldwarning'>[M] is thrown off of [src]!</span>")
flash_act(affect_silicon = 1) flash_act(affect_silicon = 1)
/mob/living/silicon/bullet_act(obj/item/projectile/Proj) /mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN)) if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
adjustBruteLoss(Proj.damage) if(reflect_bullet_check(P, def_zone))
if(prob(Proj.damage*1.5)) 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) for(var/mob/living/M in buckled_mobs)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>") M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>")
unbuckle_mob(M) unbuckle_mob(M)
M.Knockdown(40) M.Knockdown(40)
if(Proj.stun || Proj.knockdown) if(P.stun || P.knockdown)
for(var/mob/living/M in buckled_mobs) for(var/mob/living/M in buckled_mobs)
unbuckle_mob(M) unbuckle_mob(M)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [Proj]!</span>") M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [P]!</span>")
Proj.on_hit(src) P.on_hit(src)
return 2 return 2
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/static) /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) /mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
..() . = ..()
if(.) //the attack was blocked
return
switch(M.a_intent) switch(M.a_intent)
if("help") if(INTENT_HELP)
if (health > 0) if (health > 0)
visible_message("<span class='notice'>[M] [response_help] [src].</span>") visible_message("<span class='notice'>[M] [response_help] [src].</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if("grab") if(INTENT_GRAB)
if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling)) if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
vore_attack(M, pulling) vore_attack(M, pulling)
else else
grabbedby(M) grabbedby(M)
if("harm", "disarm") if(INTENT_HARM, INTENT_DISARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM)) if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>") to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
return return
@@ -27,12 +29,11 @@
updatehealth() updatehealth()
return TRUE 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(user.a_intent == INTENT_HARM)
if(HAS_TRAIT(user, TRAIT_PACIFISM)) . = ..(user, TRUE)
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>") if(.)
return FALSE return
..(user, 1)
playsound(loc, "punch", 25, 1, -1) playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has punched [src]!</span>", \ visible_message("<span class='danger'>[user] has punched [src]!</span>", \
"<span class='userdanger'>[user] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE) "<span class='userdanger'>[user] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
@@ -40,32 +41,32 @@
return TRUE return TRUE
/mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M) /mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M)
if(..()) //successful monkey bite. . = ..()
if(stat != DEAD) if(.) //successful larva bite
var/damage = rand(1, 3) var/damage = rand(1, 3)
attack_threshold_check(damage) attack_threshold_check(damage)
return 1 return 1
if (M.a_intent == INTENT_HELP) if (M.a_intent == INTENT_HELP)
if (health > 0) if (health > 0)
visible_message("<span class='notice'>[M.name] [response_help] [src].</span>") visible_message("<span class='notice'>[M.name] [response_help] [src].</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1) playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M) /mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent. . = ..()
if(M.a_intent == INTENT_DISARM) if(!.) // the attack was blocked or was help/grab intent
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1) return
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \ if(M.a_intent == INTENT_DISARM)
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE) playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
log_combat(M, src, "disarmed") visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
else "<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
var/damage = rand(15, 30) log_combat(M, src, "disarmed")
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \ else
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE) var/damage = rand(15, 30)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
attack_threshold_check(damage) "<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
log_combat(M, src, "attacked") playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
return 1 attack_threshold_check(damage)
log_combat(M, src, "attacked")
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L) /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) return attack_threshold_check(damage, M.melee_damage_type)
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M) /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) var/damage = rand(15, 25)
if(M.is_adult) if(M.is_adult)
damage = rand(20, 35) damage = rand(20, 35)

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