Merge remote-tracking branch 'upstream/master'
@@ -52,4 +52,4 @@
|
||||
#define ORGAN_VITAL (1<<4) //Currently only the brain
|
||||
#define ORGAN_NO_SPOIL (1<<5) //Do not spoil under any circumstances
|
||||
#define ORGAN_NO_DISMEMBERMENT (1<<6) //Immune to disembowelment.
|
||||
#define ORGAN_EDIBLE (1<<5) //is a snack? :D
|
||||
#define ORGAN_EDIBLE (1<<7) //is a snack? :D
|
||||
|
||||
@@ -324,6 +324,13 @@
|
||||
result = /obj/item/toy/sword/cx
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/catgirlplushie
|
||||
name = "Catgirl Plushie"
|
||||
reqs = list(/obj/item/toy/plush/hairball = 3)
|
||||
result = /obj/item/toy/plush/catgirl
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
|
||||
////////////
|
||||
//Unsorted//
|
||||
|
||||
@@ -196,3 +196,7 @@
|
||||
description = "<span class='nicegreen'>That work of art was so great it made me believe in the goodness of humanity. Says a lot in a place like this.</span>\n"
|
||||
mood_change = 4
|
||||
timeout = 4 MINUTES
|
||||
|
||||
/datum/mood_event/cleared_stomach
|
||||
description = "<span class='nicegreen'>Feels nice to get that out of the way!</span>\n"
|
||||
mood_change = 3
|
||||
|
||||
@@ -152,6 +152,11 @@
|
||||
user.visible_message("<span class='notice'>[user] licks the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You lick some of the wounds on [victim]'s [limb.name]</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='green'>[user] licks the wounds on your [limb.name]!</span")
|
||||
blood_flow -= 0.5
|
||||
if(isinsect(victim) || iscatperson(victim) || ismammal(victim) || isdwarf(victim) || ismonkey(victim)) // Yep you can lick monkeys.
|
||||
user.reagents.add_reagent(/datum/reagent/hairball, 2)
|
||||
|
||||
else if(ishumanbasic(victim) || isflyperson(victim) || islizard(victim) || isdullahan(victim))
|
||||
user.reagents.add_reagent(/datum/reagent/hairball, 1)
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
try_handling(user)
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
if(visualsOnly)
|
||||
return
|
||||
H.dna.add_mutation(SMILE)
|
||||
H.faction |= "clown"
|
||||
|
||||
/datum/outfit/syndicate/clownop/leader
|
||||
name = "Clown Operative Leader - Basic"
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
var/max_occupant_weight = MOB_SIZE_SMALL //This is calculated from the mob sizes of occupants
|
||||
var/entrance_name = "door" //name of the entrance to the item
|
||||
var/escape_time = 200 //how long it takes for mobs above small sizes to escape (for small sizes, its randomly 1.5 to 2x this)
|
||||
var/alternate_escape_time = 0 //how long it takes for mobs to escape when the entrance is open
|
||||
var/load_time = 30 //how long it takes for mobs to be loaded into the pet carrier
|
||||
var/has_lock_sprites = TRUE //whether to load the lock overlays or not
|
||||
var/allows_hostiles = FALSE //does the pet carrier allow hostile entities to be held within it?
|
||||
@@ -108,6 +109,7 @@
|
||||
return
|
||||
if(ishostile(target) && (!allows_hostiles || istype(target, /mob/living/simple_animal/hostile/carp/cayenne)) || target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers, but let cayenne in!
|
||||
to_chat(user, "<span class='warning'>You have a feeling you shouldn't keep this as a pet.</span>")
|
||||
return
|
||||
load_occupant(user, target)
|
||||
|
||||
/obj/item/pet_carrier/relaymove(mob/living/user, direction)
|
||||
@@ -128,10 +130,17 @@
|
||||
/obj/item/pet_carrier/container_resist(mob/living/user)
|
||||
//don't do the whole resist timer thing if it's open!
|
||||
if(open)
|
||||
loc.visible_message("<span class='notice'>[user] climbs out of [src]!</span>", \
|
||||
"<span class='warning'>[user] jumps out of [src]!</span>")
|
||||
remove_occupant(user)
|
||||
return
|
||||
if(alternate_escape_time > 0)
|
||||
loc.visible_message("<span class='notice'>The [src] begins to shake!</span>")
|
||||
if(do_after(user, alternate_escape_time, target = user))
|
||||
loc.visible_message("<span class='notice'>[user] jumps out of [src]</span>")
|
||||
remove_occupant(user)
|
||||
return
|
||||
else //instant escape, different message
|
||||
loc.visible_message("<span class='notice'>[user] climbs out of [src]!</span>", \
|
||||
"<span class='warning'>[user] jumps out of [src]!</span>")
|
||||
remove_occupant(user)
|
||||
return
|
||||
|
||||
user.changeNext_move(CLICK_CD_BREAKOUT)
|
||||
user.last_special = world.time + CLICK_CD_BREAKOUT
|
||||
@@ -147,7 +156,7 @@
|
||||
update_icon()
|
||||
else
|
||||
loc.visible_message("<span class='warning'>[src] starts rattling as something pushes against the [entrance_name]!</span>", null, null, null, user)
|
||||
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about 20 seconds.)</span>")
|
||||
to_chat(user, "<span class='notice'>You start pushing out of [src]... (This will take about [escape_time/10] seconds.)</span>")
|
||||
if(!do_after(user, escape_time, target = user) || open || !locked || !(user in occupants))
|
||||
return
|
||||
loc.visible_message("<span class='warning'>[user] shoves out of [src]!</span>", null, null, null, user)
|
||||
@@ -180,21 +189,22 @@
|
||||
/obj/item/pet_carrier/proc/load_occupant(mob/living/user, mob/living/target)
|
||||
if(pet_carrier_full(src))
|
||||
to_chat(user, "<span class='warning'>[src] is already carrying too much!</span>")
|
||||
return
|
||||
return FALSE
|
||||
user.visible_message("<span class='notice'>[user] starts loading [target] into [src].</span>", \
|
||||
"<span class='notice'>You start loading [target] into [src]...</span>", null, null, target)
|
||||
to_chat(target, "<span class='userdanger'>[user] starts loading you into [user.p_their()] [name]!</span>")
|
||||
if(!do_mob(user, target, load_time))
|
||||
return
|
||||
return FALSE
|
||||
if(target in occupants)
|
||||
return
|
||||
return FALSE
|
||||
if(pet_carrier_full(src)) //Run the checks again, just in case
|
||||
to_chat(user, "<span class='warning'>[src] is already carrying too much!</span>")
|
||||
return
|
||||
return FALSE
|
||||
user.visible_message("<span class='notice'>[user] loads [target] into [src]!</span>", \
|
||||
"<span class='notice'>You load [target] into [src].</span>", null, null, target)
|
||||
to_chat(target, "<span class='userdanger'>[user] loads you into [user.p_their()] [name]!</span>")
|
||||
add_occupant(target)
|
||||
return TRUE
|
||||
|
||||
/obj/item/pet_carrier/proc/add_occupant(mob/living/occupant)
|
||||
if(occupant in occupants || !istype(occupant))
|
||||
@@ -230,7 +240,8 @@
|
||||
allows_hostiles = TRUE //can fit hostile creatures, with the move resist restrictions in place, this means they still cannot take things like legions/goliaths/etc regardless
|
||||
has_lock_sprites = FALSE //jar doesn't show the regular lock overlay
|
||||
custom_materials = list(/datum/material/glass = 1000, /datum/material/bluespace = 600)
|
||||
escape_time = 10 //half the time of a bluespace bodybag
|
||||
escape_time = 200 //equal to the time of a bluespace bodybag
|
||||
alternate_escape_time = 100
|
||||
var/datum/gas_mixture/occupant_gas_supply
|
||||
|
||||
/obj/item/pet_carrier/bluespace/update_icon_state()
|
||||
@@ -271,10 +282,15 @@
|
||||
REMOVE_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath")
|
||||
REMOVE_TRAIT(occupant, TRAIT_RESISTHIGHPRESSURE, "bluespace_container_resist_high_pressure")
|
||||
REMOVE_TRAIT(occupant, TRAIT_RESISTLOWPRESSURE, "bluespace_container_resist_low_pressure")
|
||||
name = initial(name)
|
||||
|
||||
/obj/item/pet_carrier/bluespace/return_air()
|
||||
if(!occupant_gas_supply)
|
||||
occupant_gas_supply = new
|
||||
return occupant_gas_supply
|
||||
|
||||
/obj/item/pet_carrier/bluespace/load_occupant(mob/living/user, mob/living/target)
|
||||
if(..())
|
||||
name = "[initial(name)] ([target])"
|
||||
|
||||
#undef pet_carrier_full
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
resistance_flags = FLAMMABLE
|
||||
var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this
|
||||
var/stuffed = TRUE //If the plushie has stuffing in it
|
||||
var/unstuffable = FALSE //for plushies that can't be stuffed
|
||||
var/obj/item/grenade/grenade //You can remove the stuffing from a plushie and add a grenade to it for *nefarious uses*
|
||||
//--love ~<3--
|
||||
gender = NEUTER
|
||||
@@ -174,6 +175,9 @@
|
||||
/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params)
|
||||
if(I.get_sharpness())
|
||||
if(!grenade)
|
||||
if(unstuffable)
|
||||
to_chat(user, "<span class='notice'>Nothing to do here.</span>")
|
||||
return
|
||||
if(!stuffed)
|
||||
to_chat(user, "<span class='warning'>You already murdered it!</span>")
|
||||
return
|
||||
@@ -187,6 +191,13 @@
|
||||
grenade = null
|
||||
return
|
||||
if(istype(I, /obj/item/grenade))
|
||||
if(unstuffable)
|
||||
to_chat(user, "<span class='warning'>No... you should destroy it now!</span>")
|
||||
sleep(10)
|
||||
if(QDELETED(user) || QDELETED(src))
|
||||
return
|
||||
SEND_SOUND(user, 'sound/weapons/armbomb.ogg')
|
||||
return
|
||||
if(stuffed)
|
||||
to_chat(user, "<span class='warning'>You need to remove some stuffing first!</span>")
|
||||
return
|
||||
@@ -743,3 +754,14 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
|
||||
attack_verb = list("headbutt", "scritched", "bit")
|
||||
squeak_override = list('modular_citadel/sound/voice/nya.ogg' = 1)
|
||||
can_random_spawn = FALSE
|
||||
|
||||
|
||||
/obj/item/toy/plush/hairball
|
||||
name = "Hairball"
|
||||
desc = "A bundle of undigested fibers and scales. Yuck."
|
||||
icon_state = "Hairball"
|
||||
unstuffable = TRUE
|
||||
young = TRUE // Your own mouth-baby.
|
||||
squeak_override = list('sound/misc/splort.ogg'=1)
|
||||
attack_verb = list("sploshed", "splorted", "slushed")
|
||||
can_random_spawn = FALSE
|
||||
|
||||
@@ -241,9 +241,9 @@
|
||||
for(var/obj/item/mop/cyborg/M in R.module.modules)
|
||||
R.module.remove_module(M, TRUE)
|
||||
|
||||
var/obj/item/mop/advanced/cyborg/A = new /obj/item/mop/advanced/cyborg(R.module)
|
||||
R.module.basic_modules += A
|
||||
R.module.add_module(A, FALSE, TRUE)
|
||||
var/obj/item/mop/advanced/cyborg/A = new /obj/item/mop/advanced/cyborg(R.module)
|
||||
R.module.basic_modules += A
|
||||
R.module.add_module(A, FALSE, TRUE)
|
||||
|
||||
/obj/item/borg/upgrade/amop/deactivate(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
|
||||
@@ -247,6 +247,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
|
||||
new/datum/stack_recipe("painting frame", /obj/item/wallframe/painting, 1, time = 10),\
|
||||
new/datum/stack_recipe("wooden buckler", /obj/item/shield/riot/buckler, 20, time = 40), \
|
||||
new/datum/stack_recipe("baseball bat", /obj/item/melee/baseball_bat, 5, time = 15),\
|
||||
new/datum/stack_recipe("training bokken", /obj/item/melee/bokken, 10, time = 15),\
|
||||
null, \
|
||||
new/datum/stack_recipe("wooden chair", /obj/structure/chair/wood/, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
new/datum/stack_recipe("winged wooden chair", /obj/structure/chair/wood/wings, 3, time = 10, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
|
||||
@@ -249,6 +249,118 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
||||
playsound(src, 'sound/weapons/bladeslice.ogg', 50, 1)
|
||||
return(BRUTELOSS)
|
||||
|
||||
/obj/item/melee/bokken // parrying stick
|
||||
name = "bokken"
|
||||
desc = "A space-Japanese training sword made of wood and shaped like a katana."
|
||||
icon_state = "bokken"
|
||||
item_state = "bokken"
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
slot_flags = ITEM_SLOT_BELT | ITEM_SLOT_BACK
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 9
|
||||
throwforce = 10
|
||||
damtype = STAMINA
|
||||
attack_verb = list("whacked", "smacked", "struck")
|
||||
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
|
||||
hitsound = 'sound/weapons/grenadelaunch.ogg' // no good wood thunk sounds
|
||||
var/harm = FALSE // TRUE = brute, FALSE = stam
|
||||
var/reinforced = FALSE
|
||||
var/burnt = FALSE
|
||||
var/burned_in // text you burned in (with a welder)
|
||||
var/quick_parry = FALSE // false = default parry, true = really small parry window
|
||||
item_flags = ITEM_CAN_PARRY
|
||||
block_parry_data = /datum/block_parry_data/bokken
|
||||
bare_wound_bonus = 0
|
||||
wound_bonus = 0
|
||||
|
||||
/datum/block_parry_data/bokken // fucked up parry data, emphasizing quicker, shorter parries
|
||||
parry_stamina_cost = 8 // be wise about when you parry, though, else you won't be able to fight enough to make it count
|
||||
parry_time_windup = 0
|
||||
parry_time_active = 10 // small parry window
|
||||
parry_time_spindown = 0
|
||||
// parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK // bokken users can no longer strike while parrying
|
||||
parry_time_perfect = 1.5
|
||||
parry_time_perfect_leeway = 1
|
||||
parry_imperfect_falloff_percent = 7.5
|
||||
parry_efficiency_to_counterattack = 100
|
||||
parry_efficiency_considered_successful = 65 // VERY generous
|
||||
parry_efficiency_perfect = 120
|
||||
parry_failed_stagger_duration = 3 SECONDS
|
||||
parry_data = list(PARRY_COUNTERATTACK_MELEE_ATTACK_CHAIN = 2.5) // 7*2.5 = 17.5, 8*2.5 = 20, 9*2.5 = 22.5, 10*2.5 = 25
|
||||
|
||||
/datum/block_parry_data/bokken/quick_parry // emphasizing REALLY SHORT PARRIES
|
||||
parry_stamina_cost = 6 // still more costly than most parries, but less than a full bokken parry
|
||||
parry_time_active = 5 // REALLY small parry window
|
||||
parry_time_perfect = 2.5 // however...
|
||||
parry_time_perfect_leeway = 2.5 // the entire time, the parry is perfect
|
||||
parry_failed_stagger_duration = 1 SECONDS
|
||||
parry_failed_clickcd_duration = 1 SECONDS // more forgiving punishments for missed parries
|
||||
// still, don't fucking miss your parries or you're down stamina and staggered to shit
|
||||
|
||||
/obj/item/melee/bokken/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/sword_point)
|
||||
|
||||
/obj/item/melee/bokken/attack_self(mob/user)
|
||||
harm = !harm
|
||||
if(harm)
|
||||
force -= 2
|
||||
damtype = BRUTE
|
||||
attack_verb = list("bashed", "smashed", "attacked")
|
||||
bare_wound_bonus = 15 // having your leg smacked by a wooden stick is probably not great for it if it's naked
|
||||
wound_bonus = 0
|
||||
else
|
||||
force += 2
|
||||
damtype = STAMINA
|
||||
attack_verb = list("whacked", "smacked", "struck")
|
||||
bare_wound_bonus = 0
|
||||
wound_bonus = 0
|
||||
to_chat(user, "<span class='notice'>[src] is now [harm ? "harmful" : "not quite as harmful"].</span>")
|
||||
|
||||
/obj/item/melee/bokken/AltClick(mob/user)
|
||||
. = ..()
|
||||
quick_parry = !quick_parry
|
||||
if(quick_parry)
|
||||
block_parry_data = /datum/block_parry_data/bokken/quick_parry
|
||||
else
|
||||
block_parry_data = /datum/block_parry_data/bokken
|
||||
to_chat(user, "<span class='notice'>[src] is now [quick_parry ? "emphasizing shorter parries, forcing you to riposte or be staggered" : "emphasizing longer parries, with a shorter window to riposte but more forgiving parries"].</span>")
|
||||
|
||||
/obj/item/melee/bokken/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/pen))
|
||||
var/new_name = stripped_input(user, "What do you wish to name [src]?", "New Name", "bokken", 30)
|
||||
if(new_name)
|
||||
name = new_name
|
||||
if(I.tool_behaviour == TOOL_WELDER)
|
||||
var/new_burn = stripped_input(user, "What do you wish to burn into [src]?", "Burnt Inscription","", 140)
|
||||
if(new_burn)
|
||||
burned_in = new_burn
|
||||
if(!burnt)
|
||||
icon_state += "_burnt"
|
||||
item_state += "_burnt"
|
||||
burnt = TRUE
|
||||
update_icon()
|
||||
update_icon_state()
|
||||
if(istype(I, /obj/item/stack/rods))
|
||||
var/obj/item/stack/rods/R = I
|
||||
if(!reinforced)
|
||||
if(R.use(1))
|
||||
force++
|
||||
reinforced = TRUE
|
||||
to_chat(user, "<span class='notice'>You slide a metal rod into [src]\'s hilt. It feels a little heftier in your hands.")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] already has a weight slid into the hilt.")
|
||||
|
||||
/obj/item/melee/bokken/examine(mob/user)
|
||||
. = ..()
|
||||
if(quick_parry)
|
||||
. += " [src] is gripped in a way to emphasize quicker parries."
|
||||
if(reinforced)
|
||||
. += " There's a metal rod shoved into the base."
|
||||
if(burnt)
|
||||
. += " Burned into the \"blade\" is [burned_in]."
|
||||
|
||||
/obj/item/wirerod
|
||||
name = "wired rod"
|
||||
desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit."
|
||||
|
||||
@@ -198,24 +198,27 @@
|
||||
//////////////////////////SPACEWIND/////////////////////////////
|
||||
|
||||
/turf/open/proc/consider_pressure_difference(turf/T, difference)
|
||||
SSair.high_pressure_delta[src] = TRUE
|
||||
if(difference > pressure_difference)
|
||||
pressure_direction = get_dir(src, T)
|
||||
pressure_difference = difference
|
||||
SSair.high_pressure_delta[src] = TRUE
|
||||
|
||||
/turf/open/proc/high_pressure_movements()
|
||||
var/atom/movable/M
|
||||
var/multiplier = 1
|
||||
var/diff = pressure_difference
|
||||
if(locate(/obj/structure/rack) in src)
|
||||
multiplier *= 0.1
|
||||
diff *= 0.1
|
||||
else if(locate(/obj/structure/table) in src)
|
||||
multiplier *= 0.2
|
||||
for(var/thing in src)
|
||||
M = thing
|
||||
if (!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
|
||||
M.experience_pressure_difference(pressure_difference * multiplier, pressure_direction, 0, pressure_specific_target)
|
||||
diff *= 0.2
|
||||
for(var/obj/M in src)
|
||||
if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
|
||||
M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target)
|
||||
for(var/mob/M in src)
|
||||
if(!M.anchored && !M.pulledby && M.last_high_pressure_movement_air_cycle < SSair.times_fired)
|
||||
M.experience_pressure_difference(diff, pressure_direction, 0, pressure_specific_target)
|
||||
/*
|
||||
if(pressure_difference > 100)
|
||||
new /obj/effect/temp_visual/dir_setting/space_wind(src, pressure_direction, clamp(round(sqrt(pressure_difference) * 2), 10, 255))
|
||||
*/
|
||||
|
||||
/atom/movable/var/pressure_resistance = 10
|
||||
/atom/movable/var/last_high_pressure_movement_air_cycle = 0
|
||||
|
||||
@@ -471,6 +471,11 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
//////////////
|
||||
|
||||
/client/Del()
|
||||
if(!gc_destroyed)
|
||||
Destroy()
|
||||
return ..()
|
||||
|
||||
/client/Destroy()
|
||||
if(credits)
|
||||
QDEL_LIST(credits)
|
||||
log_access("Logout: [key_name(src)]")
|
||||
@@ -504,9 +509,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
movingmob.client_mobs_in_contents -= mob
|
||||
UNSETEMPTY(movingmob.client_mobs_in_contents)
|
||||
Master.UpdateTickRate()
|
||||
return ..()
|
||||
|
||||
/client/Destroy()
|
||||
. = ..()
|
||||
return QDEL_HINT_HARDDEL_NOW
|
||||
|
||||
/client/proc/set_client_age_from_db(connectiontopic)
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
// Set the clothing's integrity back to 100%, remove all damage to bodyparts, and generally fix it up
|
||||
/obj/item/clothing/proc/repair(mob/user, params)
|
||||
damaged_clothes = CLOTHING_PRISTINE
|
||||
update_clothes_damaged_state()
|
||||
update_clothes_damaged_state(FALSE)
|
||||
obj_integrity = max_integrity
|
||||
name = initial(name) // remove "tattered" or "shredded" if there's a prefix
|
||||
body_parts_covered = initial(body_parts_covered)
|
||||
@@ -265,7 +265,6 @@
|
||||
var/index = "[REF(initial(icon))]-[initial(icon_state)]"
|
||||
var/static/list/damaged_clothes_icons = list()
|
||||
if(damaging)
|
||||
damaged_clothes = 1
|
||||
var/icon/damaged_clothes_icon = damaged_clothes_icons[index]
|
||||
if(!damaged_clothes_icon)
|
||||
damaged_clothes_icon = icon(initial(icon), initial(icon_state), , 1) //we only want to apply damaged effect to the initial icon_state for each object
|
||||
@@ -273,12 +272,10 @@
|
||||
damaged_clothes_icon.Blend(icon('icons/effects/item_damage.dmi', "itemdamaged"), ICON_MULTIPLY) //adds damage effect and the remaining white areas become transparant
|
||||
damaged_clothes_icon = fcopy_rsc(damaged_clothes_icon)
|
||||
damaged_clothes_icons[index] = damaged_clothes_icon
|
||||
add_overlay(damaged_clothes_icon, 1)
|
||||
add_overlay(damaged_clothes_icon, TRUE)
|
||||
else
|
||||
damaged_clothes = 0
|
||||
cut_overlay(damaged_clothes_icons[index], TRUE)
|
||||
|
||||
|
||||
/*
|
||||
SEE_SELF // can see self, no matter what
|
||||
SEE_MOBS // can see all mobs, no matter what
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
REMOVE_TRAIT(user, secondary_trait, GLOVE_TRAIT)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.dna.species.punchdamagehigh = initial(H.dna.species.punchdamagehigh)
|
||||
H.dna.species.punchdamagelow = initial(H.dna.species.punchdamagelow)
|
||||
H.dna.species.punchdamagehigh -= enhancement
|
||||
H.dna.species.punchdamagelow -= enhancement
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/gloves/fingerless/pugilist/chaplain
|
||||
|
||||
@@ -143,6 +143,8 @@
|
||||
add_log("<span class='info'><B>Blood:</B></span>")
|
||||
found_something = TRUE
|
||||
for(var/B in blood)
|
||||
if(B == "color")
|
||||
continue
|
||||
add_log("Type: <font color='red'>[blood[B]]</font> DNA: <font color='red'>[B]</font>")
|
||||
|
||||
//Fibers
|
||||
|
||||
@@ -19,7 +19,7 @@ GLOBAL_LIST_INIT(marker_beacon_colors, list(
|
||||
singular_name = "marker beacon"
|
||||
desc = "Prism-brand path illumination devices. Used by miners to mark paths and warn of danger."
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
icon_state = "markerbronze"
|
||||
icon_state = "marker"
|
||||
merge_type = /obj/item/stack/marker_beacon
|
||||
max_amount = 100
|
||||
novariants = TRUE
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
return " (as [get_id_name("Unknown")])"
|
||||
|
||||
/mob/living/carbon/human/proc/forcesay(list/append) //this proc is at the bottom of the file because quote fuckery makes notepad++ cri
|
||||
set waitfor = FALSE // WINGET IS A SLEEP. DO. NOT. SLEEP.
|
||||
if(stat == CONSCIOUS)
|
||||
if(client)
|
||||
var/temp = winget(client, "input", "text")
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
var/datum/block_parry_data/data = get_parry_data()
|
||||
if(data.parry_sounds)
|
||||
playsound(src, pick(data.parry_sounds), 75)
|
||||
visible_message("<span class='danger'>[src] parries \the [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""]!</span>")
|
||||
visible_message("<span class='danger'>[src] parries [attack_text][length(effect_text)? ", [english_list(effect_text)] [attacker]" : ""]!</span>")
|
||||
|
||||
/// Run counterattack if any
|
||||
/mob/living/proc/run_parry_countereffects(atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/return_list = list(), parry_efficiency)
|
||||
|
||||
@@ -361,8 +361,7 @@
|
||||
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmed"),
|
||||
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamed"),
|
||||
"Eyebot" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "eyebotmed"),
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed"),
|
||||
"Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_med")
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymed")
|
||||
)
|
||||
var/list/L = list("Medihound" = "medihound", "Medihound Dark" = "medihounddark", "Vale" = "valemed")
|
||||
for(var/a in L)
|
||||
@@ -378,8 +377,6 @@
|
||||
switch(med_borg_icon)
|
||||
if("Default")
|
||||
cyborg_base_icon = "medical"
|
||||
if("Zoomba")
|
||||
cyborg_base_icon = "zoomba_med"
|
||||
if("Droid")
|
||||
cyborg_base_icon = "medical"
|
||||
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
|
||||
@@ -481,8 +478,7 @@
|
||||
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "caneng"),
|
||||
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinaeng"),
|
||||
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidereng"),
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng"),
|
||||
"Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_engi")
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyeng")
|
||||
)
|
||||
var/list/L = list("Pup Dozer" = "pupdozer", "Vale" = "valeeng")
|
||||
for(var/a in L)
|
||||
@@ -498,8 +494,6 @@
|
||||
switch(engi_borg_icon)
|
||||
if("Default")
|
||||
cyborg_base_icon = "engineer"
|
||||
if("Zoomba")
|
||||
cyborg_base_icon = "zoomba_engi"
|
||||
if("Default - Treads")
|
||||
cyborg_base_icon = "engi-tread"
|
||||
special_light_key = "engineer"
|
||||
@@ -580,8 +574,7 @@
|
||||
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "cansec"),
|
||||
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinasec"),
|
||||
"Spider" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "spidersec"),
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec"),
|
||||
"Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_sec")
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavysec")
|
||||
)
|
||||
var/list/L = list("K9" = "k9", "Vale" = "valesec", "K9 Dark" = "k9dark")
|
||||
for(var/a in L)
|
||||
@@ -597,8 +590,6 @@
|
||||
switch(sec_borg_icon)
|
||||
if("Default")
|
||||
cyborg_base_icon = "sec"
|
||||
if("Zoomba")
|
||||
cyborg_base_icon = "zoomba_sec"
|
||||
if("Default - Treads")
|
||||
cyborg_base_icon = "sec-tread"
|
||||
special_light_key = "sec"
|
||||
@@ -836,8 +827,7 @@
|
||||
"(Janitor) Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinajan"),
|
||||
"(Janitor) Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekjan"),
|
||||
"(Janitor) Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canjan"),
|
||||
"(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan"),
|
||||
"Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_jani")
|
||||
"(Janitor) Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavyjan")
|
||||
)
|
||||
var/list/L = list("(Service) DarkK9" = "k50", "(Service) Vale" = "valeserv", "(Service) ValeDark" = "valeservdark",
|
||||
"(Janitor) Scrubpuppy" = "scrubpup")
|
||||
@@ -852,8 +842,6 @@
|
||||
service_icons = sortList(service_icons)
|
||||
var/service_robot_icon = show_radial_menu(R, R , service_icons, custom_check = CALLBACK(src, .proc/check_menu, R), radius = 42, require_near = TRUE)
|
||||
switch(service_robot_icon)
|
||||
if("Zoomba")
|
||||
cyborg_base_icon = "zoomba_jani"
|
||||
if("(Service) Waitress")
|
||||
cyborg_base_icon = "service_f"
|
||||
special_light_key = "service"
|
||||
@@ -956,8 +944,7 @@
|
||||
"Sleek" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "sleekmin"),
|
||||
"Marina" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "marinamin"),
|
||||
"Can" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "canmin"),
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin"),
|
||||
"Zoomba" = image(icon = 'icons/mob/robots.dmi', icon_state = "zoomba_miner")
|
||||
"Heavy" = image(icon = 'modular_citadel/icons/mob/robots.dmi', icon_state = "heavymin")
|
||||
)
|
||||
var/list/L = list("Blade" = "blade", "Vale" = "valemine")
|
||||
for(var/a in L)
|
||||
@@ -1001,8 +988,6 @@
|
||||
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
|
||||
sleeper_overlay = "valeminesleeper"
|
||||
dogborg = TRUE
|
||||
if("Zoomba")
|
||||
cyborg_base_icon = "zoomba_miner"
|
||||
else
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
var/banana_type = /obj/item/grown/bananapeel
|
||||
var/attack_reagent
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/Initialize(mapload)
|
||||
. = ..()
|
||||
faction |= "clown"
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/handle_temperature_damage()
|
||||
if(bodytemperature < minbodytemp)
|
||||
adjustBruteLoss(10)
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
laugher.emote("laugh")
|
||||
|
||||
/mob/living/simple_animal/pickle/death()
|
||||
..()
|
||||
if(original_body)
|
||||
original_body.adjustOrganLoss(ORGAN_SLOT_BRAIN, 200) //to be fair, you have to have a very high iq to understand-
|
||||
original_body.forceMove(get_turf(src))
|
||||
if(mind)
|
||||
mind.transfer_to(original_body)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/pickle/wabbajack_act() //restore users name before its used on the new mob
|
||||
if(original_body)
|
||||
|
||||
@@ -623,7 +623,7 @@
|
||||
pixel_x = trajectory.return_px()
|
||||
pixel_y = trajectory.return_py()
|
||||
else if(T != loc)
|
||||
var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 2 + 1
|
||||
var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 5 + 1
|
||||
while(T != loc)
|
||||
if(!--safety)
|
||||
CRASH("[type] took too long (allowed: [CEILING(pixel_increment_amount/world.icon_size,1)*2] moves) to get to its location.")
|
||||
|
||||
@@ -2336,3 +2336,53 @@
|
||||
reagent_state = SOLID
|
||||
color = "#E6E6DA"
|
||||
taste_mult = 0
|
||||
|
||||
|
||||
/datum/reagent/hairball
|
||||
name = "Hairball"
|
||||
description = "A bundle of keratinous bits and fibers, not easily digestible."
|
||||
reagent_state = SOLID
|
||||
can_synth = FALSE
|
||||
metabolization_rate = 0.05 * REAGENTS_METABOLISM
|
||||
taste_description = "wet hair"
|
||||
var/amount = 0
|
||||
var/knotted = FALSE
|
||||
|
||||
/datum/reagent/hairball/on_mob_life(mob/living/carbon/M)
|
||||
amount = M.reagents.get_reagent_amount(/datum/reagent/hairball)
|
||||
|
||||
if(amount < 10)
|
||||
if(prob(10))
|
||||
M.losebreath += 1
|
||||
M.emote("cough")
|
||||
to_chat(M, "<span class='notice'>You clear your throat.</span>")
|
||||
else
|
||||
if(!knotted)
|
||||
to_chat(M, "<span class='notice'>You feel a knot in your stomach.</span>")
|
||||
knotted = TRUE
|
||||
|
||||
if(prob(5 + amount * 0.5)) // don't want this to cause too much damage
|
||||
M.losebreath += 2
|
||||
to_chat(M, "<span class='notice'>You feel a knot in your throat.</span>")
|
||||
M.emote("cough")
|
||||
|
||||
else if(prob(amount - 4))
|
||||
to_chat(M, "<span class='warning'>Your stomach feels awfully bloated.</span>")
|
||||
playsound(M,'sound/voice/catpeople/distressed.ogg', 50, FALSE)
|
||||
M.visible_message("<span class='warning'>[M] seems distressed!.</span>", ignored_mobs=M)
|
||||
|
||||
else if(prob(amount - 8))
|
||||
knotted = FALSE
|
||||
playsound(M,'sound/voice/catpeople/puking.ogg', 110, FALSE)
|
||||
M.Immobilize(30)
|
||||
sleep(30) //snowflake but it works, don't wanna proc this
|
||||
if(QDELETED(M) || QDELETED(src)) //this handles race conditions about m or src not existing.
|
||||
return
|
||||
M.visible_message("<span class='warning'>[M] throws up a hairball! Disgusting!</span>", ignored_mobs=M)
|
||||
new /obj/item/toy/plush/hairball(get_turf(M))
|
||||
to_chat(M, "<span class='notice'>Aaaah that's better!</span>")
|
||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "cleared_stomach", /datum/mood_event/cleared_stomach, name)
|
||||
M.reagents.del_reagent(/datum/reagent/hairball)
|
||||
return
|
||||
..()
|
||||
|
||||
|
||||
@@ -50,6 +50,36 @@
|
||||
-->
|
||||
<div class="commit sansserif">
|
||||
|
||||
<h2 class="date">27 July 2020</h2>
|
||||
<h3 class="author">Hatterhat updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Training bokkens! Make 'em from wood, use 'em in-hand to toggle between harmful and not-so-harmful, practice your parrying with them!</li>
|
||||
<li class="bugfix">Marker beacons should have a sprite again.</li>
|
||||
</ul>
|
||||
<h3 class="author">silicons updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">clownops and clown mobs now share the same faction. HONK!</li>
|
||||
</ul>
|
||||
<h3 class="author">timothyteakettle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">modern pickle technology now allows people who have been turned into pickles, to be retrieved through the medical course of dying</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">26 July 2020</h2>
|
||||
<h3 class="author">DeltaFire15 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Organs now decay again.</li>
|
||||
</ul>
|
||||
<h3 class="author">Iatots updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Licking wounds now may cause you to spit out a hairball once in a while!</li>
|
||||
<li class="rscadd">You can now craft a catgirl plushie with 3 of a new ingredient occasionally found in medbay!</li>
|
||||
</ul>
|
||||
<h3 class="author">dapnee updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">removed legacy public mining shuttle area and remade lounge</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">25 July 2020</h2>
|
||||
<h3 class="author">CameronWoof updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
|
||||
@@ -26518,3 +26518,22 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
|
||||
- bugfix: Aloe now has an icon.
|
||||
timothyteakettle:
|
||||
- bugfix: beepsky replaces the word THREAT_LEVEL with the actual threat level
|
||||
2020-07-26:
|
||||
DeltaFire15:
|
||||
- bugfix: Organs now decay again.
|
||||
Iatots:
|
||||
- tweak: Licking wounds now may cause you to spit out a hairball once in a while!
|
||||
- rscadd: You can now craft a catgirl plushie with 3 of a new ingredient occasionally
|
||||
found in medbay!
|
||||
dapnee:
|
||||
- tweak: removed legacy public mining shuttle area and remade lounge
|
||||
2020-07-27:
|
||||
Hatterhat:
|
||||
- rscadd: Training bokkens! Make 'em from wood, use 'em in-hand to toggle between
|
||||
harmful and not-so-harmful, practice your parrying with them!
|
||||
- bugfix: Marker beacons should have a sprite again.
|
||||
silicons:
|
||||
- rscadd: clownops and clown mobs now share the same faction. HONK!
|
||||
timothyteakettle:
|
||||
- bugfix: modern pickle technology now allows people who have been turned into pickles,
|
||||
to be retrieved through the medical course of dying
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "timothyteakettle"
|
||||
delete-after: True
|
||||
changes:
|
||||
- bugfix: "changed up pet carriers / bluespace jars a bit so you can't fit certain things inside them and also the text shown for resist times is accurate"
|
||||
@@ -0,0 +1,4 @@
|
||||
author: "Sishen1542"
|
||||
delete-after: True
|
||||
changes:
|
||||
- rscdel: "removed zoomba"
|
||||
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 249 KiB After Width: | Height: | Size: 224 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,2 @@
|
||||
distressed_cat.ogg from Cat annoyed meow / wail by jbierfeldt at https://freesound.org/people/jbierfeldt/sounds/440735/, chopped up and ogged
|
||||
cat_puking.ogg from catpuking mp3 by NoiseCollector and Mocha the cat at https://freesound.org/people/NoiseCollector/sounds/80778/, chopped up, volume altered and ogged
|
||||