This commit is contained in:
Ghommie
2020-01-02 17:49:01 +01:00
253 changed files with 2431 additions and 1295 deletions
+1 -1
View File
@@ -116,7 +116,7 @@
#define HYPNO (1<<7)
#define NEVER_HYPNO (1<<8)
#define NO_APHRO (1<<9)
#define NO_ASS_SLAP (1<<9)
#define NO_ASS_SLAP (1<<10)
#define TOGGLES_CITADEL (EATING_NOISES|DIGESTION_NOISES|BREAST_ENLARGEMENT|PENIS_ENLARGEMENT)
+1
View File
@@ -169,6 +169,7 @@
#define TRAIT_EMPATH "empath"
#define TRAIT_FRIENDLY "friendly"
#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"
-2
View File
@@ -20,8 +20,6 @@
else
return "000"
#define UNDIE_COLORABLE(U) (U?.has_color)
/proc/random_underwear(gender)
if(!GLOB.underwear_list.len)
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()
if(isnewplayer(m))
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.stat != DEAD && !isbrain(m) && !iscameramob(m))
num_survivors++
-10
View File
@@ -758,16 +758,6 @@ GLOBAL_LIST_INIT(can_embed_types, typecacheof(list(
/obj/item/stack/rods,
/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
*/
@@ -115,5 +115,6 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
/obj/item/clothing/shoes/kindleKicks = 1,
/obj/item/autosurgeon/penis = 1,
/obj/item/autosurgeon/testicles = 1,
/obj/item/storage/box/marshmallow = 2,
"" = 3
))
+11 -9
View File
@@ -98,17 +98,19 @@
take_damage(I.force, I.damtype, "melee", 1)
/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)
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
if(I.damtype == BRUTE && !HAS_TRAIT(src, TRAIT_NOMARROW))
if(prob(33))
+2
View File
@@ -91,6 +91,8 @@
var/obj/item/clothing/gloves/G = gloves
if(istype(G) && G.Touch(A,0)) // for magic gloves
return
if (istype(glasses) && glasses.ranged_attack(src,A,mouseparams))
return
for(var/datum/mutation/human/HM in dna.mutations)
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/mob/living/nanite_monitored_mobs = 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)
if(QDELETED(backup.storage) || (backup.storage.stat & (NOPOWER|BROKEN)))
+3
View File
@@ -401,6 +401,9 @@ SUBSYSTEM_DEF(ticker)
qdel(player)
living.notransform = TRUE
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)
S.Fade(TRUE)
livings += living
+5 -4
View File
@@ -11,8 +11,9 @@
var/list/datum/nanite_program/programs = list()
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)
if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup))
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'>================</span>")
to_chat(user, "<span class='info'>Program List:</span>")
if(stealth)
to_chat(user, "<span class='alert'>%#$ENCRYPTED&^@</span>")
if(!diagnostics)
to_chat(user, "<span class='alert'>Diagnostics Disabled</span>")
else
for(var/X in programs)
var/datum/nanite_program/NP = X
+3 -1
View File
@@ -150,7 +150,9 @@
if(!.)
return
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)
. = ..()
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)
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
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)
+2
View File
@@ -292,6 +292,7 @@
var/mob/living/carbon/C = owner
for(var/X in C.bodyparts)
var/obj/item/bodypart/BP = X
BP.max_damage *= 10
BP.brute_dam *= 10
BP.burn_dam *= 10
owner.toxloss *= 10
@@ -377,6 +378,7 @@
var/obj/item/bodypart/BP = X
BP.brute_dam *= 0.1
BP.burn_dam *= 0.1
BP.max_damage /= 10
owner.toxloss *= 0.1
owner.oxyloss *= 0.1
owner.cloneloss *= 0.1
+1 -1
View File
@@ -166,7 +166,7 @@
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)
if(does_attack_animation)
user.changeNext_move(CLICK_CD_MELEE)
+3 -3
View File
@@ -515,10 +515,10 @@
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)
return throw_at(target, range, speed, thrower, spin, diagonals_first, 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, 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
if (!target || speed <= 0)
return
+17 -1
View File
@@ -222,5 +222,21 @@
. += "\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_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
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
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)
/obj/item/proc/after_throw(datum/callback/callback)
/obj/item/proc/after_throw(datum/callback/callback, messy_throw)
if (callback) //call the original callback
. = callback.Invoke()
throw_speed = initial(throw_speed) //explosions change this.
item_flags &= ~IN_INVENTORY
var/matrix/M = matrix(transform)
M.Turn(rand(-170, 170))
transform = M
pixel_x = rand(-8, 8)
pixel_y = rand(-8, 8)
if(messy_throw)
var/matrix/M = matrix(transform)
M.Turn(rand(-170, 170))
transform = M
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
if(!newLoc)
+202
View File
@@ -863,3 +863,205 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(reagents && reagents.total_volume)
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."
+3 -2
View File
@@ -216,10 +216,11 @@
return
else
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))
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))
return
playsound(get_turf(src), 'sound/effects/woodhit.ogg', 75, 1, -1)
+3 -5
View File
@@ -11,11 +11,9 @@
var/charge_cost = 30
/obj/item/borg/stun/attack(mob/living/M, mob/living/user)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK))
playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(M.check_shields(src, 0, "[M]'s [name]", MELEE_ATTACK))
playsound(M, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(iscyborg(user))
var/mob/living/silicon/robot/R = user
if(!R.cell.use(charge_cost))
+2 -2
View File
@@ -582,7 +582,7 @@
/obj/item/storage/belt/bandolier
name = "bandolier"
desc = "A bandolier for holding shotgun ammunition."
desc = "A bandolier for holding ammunition."
icon_state = "bandolier"
item_state = "bandolier"
@@ -592,7 +592,7 @@
STR.max_items = 18
STR.display_numerical_stacking = TRUE
STR.can_hold = typecacheof(list(
/obj/item/ammo_casing/shotgun
/obj/item/ammo_casing
))
/obj/item/storage/belt/bandolier/durathread
+9
View File
@@ -1259,3 +1259,12 @@
var/obj/item/stack/sheet/cardboard/I = new(user.drop_location())
qdel(src)
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)
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK)) //No message; check_shields() handles that
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return FALSE
var/stunpwr = stunforce
var/obj/item/stock_parts/cell/our_cell = get_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)
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)
visible_message("<span class='danger'>[src] shatters into a million pieces!</span>")
qdel(src)
/obj/assume_air(datum/gas_mixture/giver)
if(loc)
return loc.assume_air(giver)
@@ -12,18 +12,12 @@
new /obj/item/clothing/head/hardhat/white(src)
new /obj/item/clothing/head/hardhat/weldhat/white(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/cartridge/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/areaeditor/blueprints(src)
new /obj/item/airlock_painter(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/clothing/glasses/meson/engine(src)
new /obj/item/door_remote/chief_engineer(src)
@@ -67,7 +61,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/head/welding(src)
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
name = "engineer's locker"
@@ -84,7 +78,6 @@
new /obj/item/clothing/glasses/meson/engine(src)
new /obj/item/storage/box/emptysandbags(src)
/obj/structure/closet/secure_closet/atmospherics
name = "\proper atmospheric technician's locker"
req_access = list(ACCESS_ATMOSPHERICS)
@@ -103,3 +96,33 @@
new /obj/item/clothing/head/hardhat/atmos(src)
new /obj/item/clothing/glasses/meson/engine/tray(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
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"
if(!UNDIE_COLORABLE(GLOB.undershirt_list[H.undershirt]))
if(!(GLOB.undershirt_list[H.undershirt]?.has_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"
var/choice = input(H, "Underwear, Undershirt, or Socks?", "Changing") as null|anything in undergarment_choices
@@ -605,7 +605,7 @@
rank = "Gunner"
/obj/effect/mob_spawn/human/ghostcafe
name = "ghost cafe sleeper"
name = "Ghost Cafe Sleeper"
uses = -1
icon = 'icons/obj/machines/sleeper.dmi'
icon_state = "sleeper"
@@ -633,6 +633,7 @@
uniform = /obj/item/clothing/under/color/random
shoes = /obj/item/clothing/shoes/sneakers/black
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)
@@ -649,3 +650,17 @@
else
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>")
log_admin("[key_name(usr)] assumed direct control of [M].")
var/mob/adminmob = src.mob
M.ckey = src.ckey
adminmob.transfer_ckey(M, send_signal = FALSE)
if( isobserver(adminmob) )
qdel(adminmob)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Assume Direct Control") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -484,11 +484,9 @@
user.do_attack_animation(L)
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
playsound(H, 'sound/weapons/genhit.ogg', 50, TRUE)
return FALSE
if(L.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
playsound(L, 'sound/weapons/genhit.ogg', 50, TRUE)
return FALSE
switch (mode)
if(BATON_STUN)
@@ -183,7 +183,7 @@
BuyPower(new /datum/action/bloodsucker/masquerade)
BuyPower(new /datum/action/bloodsucker/veil)
// Traits
for (var/T in defaultTraits)
for(var/T in defaultTraits)
ADD_TRAIT(owner.current, T, "bloodsucker")
if(HAS_TRAIT(owner.current, TRAIT_TOXINLOVER)) //No slime bonuses here, no thank you
had_toxlover = TRUE
@@ -200,10 +200,10 @@
var/mob/living/carbon/human/H = owner.current
var/datum/species/S = H.dna.species
// Make Changes
S.brutemod *= 0.5 // <-------------------- Start small, but burn mod increases based on rank!
S.coldmod = 0
S.stunmod *= 0.25
S.siemens_coeff *= 0.75 //base electrocution coefficient 1
H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank!
H.physiology.cold_mod = 0
H.physiology.stun_mod *= 0.35
H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1
//S.heatmod += 0.5 // Heat shouldn't affect. Only Fire.
//S.punchstunthreshold = 8 //damage at which punches from this race will stun 9
S.punchdamagelow += 1 //lowest possible punch damage 0
@@ -319,12 +319,10 @@ datum/antagonist/bloodsucker/proc/SpendRank()
if(ishuman(owner.current))
var/mob/living/carbon/human/H = owner.current
var/datum/species/S = H.dna.species
S.burnmod *= 0.025 // Slightly more burn damage
S.stunmod *= 0.95 // Slightly less stun time.
S.punchdamagelow += 0.5
S.punchdamagehigh += 0.5 // NOTE: This affects the hitting power of Brawn.
// More Health
owner.current.setMaxHealth(owner.current.maxHealth + 5)
owner.current.setMaxHealth(owner.current.maxHealth + 10)
// Vamp Stats
regenRate += 0.05 // Points of brute healed (starts at 0.3)
feedAmount += 2 // Increase how quickly I munch down vics (15)
@@ -275,7 +275,7 @@
// All done!
if(convert_progress <= 0)
// FAIL: Can't be Vassal
if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) && HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
to_chat(user, "<span class='danger'>[target] doesn't respond to your persuasion. It doesn't appear they can be converted to follow you, they either have a mindshield or their external loyalties are too difficult for you to break.<i>\[ALT+click to release\]</span>")
convert_progress ++ // Pop it back up some. Avoids wasting Blood on a lost cause.
// SUCCESS: All done!
+28 -5
View File
@@ -195,6 +195,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/auto_fit_viewport = TRUE
var/uplink_spawn_loc = UPLINK_PDA
var/sprint_spacebar = FALSE
var/sprint_toggle = FALSE
var/list/exp = list()
var/list/menuoptions
@@ -722,13 +725,13 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
dat += "<h2>Clothing & Equipment</h2>"
dat += "<b>Underwear:</b><a style='display:block;width:100px' href ='?_src_=prefs;preference=underwear;task=input'>[underwear]</a>"
if(UNDIE_COLORABLE(GLOB.underwear_list[underwear]))
if(GLOB.underwear_list[underwear]?.has_color)
dat += "<b>Underwear Color:</b> <span style='border:1px solid #161616; background-color: #[undie_color];'>&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>"
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>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>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>"
@@ -837,6 +840,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
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>Widescreen:</b> <a href='?_src_=prefs;preference=widescreenpref'>[widescreenpref ? "Enabled ([CONFIG_GET(string/default_view)])" : "Disabled (15x15)"]</a><br>"
dat += "<b>Auto stand:</b> <a href='?_src_=prefs;preference=autostand'>[autostand ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Auto OOC:</b> <a href='?_src_=prefs;preference=auto_ooc'>[auto_ooc ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Screen Shake:</b> <a href='?_src_=prefs;preference=screenshake'>[(screenshake==100) ? "Full" : ((screenshake==0) ? "None" : "[screenshake]")]</a><br>"
if (user && user.client && !user.client.prefs.screenshake==0)
dat += "<b>Damage Screen Shake:</b> <a href='?_src_=prefs;preference=damagescreenshake'>[(damagescreenshake==1) ? "On" : ((damagescreenshake==0) ? "Off" : "Only when down")]</a><br>"
@@ -888,6 +892,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "</a><br>"
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'>[ambientocclusion ? "Enabled" : "Disabled"]</a><br>"
dat += "<b>Fit Viewport:</b> <a href='?_src_=prefs;preference=auto_fit_viewport'>[auto_fit_viewport ? "Auto" : "Manual"]</a><br>"
dat += "<b>Sprint Key:</b> <a href='?_src_=prefs;preference=sprint_key'>[sprint_spacebar ? "Space" : "Shift"]</a><br>"
dat += "<b>Toggle Sprint:</b> <a href='?_src_=prefs;preference=sprint_toggle'>[sprint_toggle ? "Enabled" : "Disabled"]</a><br>"
if (CONFIG_GET(flag/maprotation) && CONFIG_GET(flag/tgstyle_maprotation))
var/p_map = preferred_map
@@ -1002,9 +1008,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
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=hypno'>[(cit_toggles & NEVER_HYPNO) ? "Disallowed" : "Allowed"]</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=aphro'>[(cit_toggles & NO_ASS_SLAP) ? "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>"
@@ -2083,6 +2089,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
user.client.change_view(CONFIG_GET(string/default_view))
if("autostand")
autostand = !autostand
if("auto_ooc")
auto_ooc = !auto_ooc
if ("screenshake")
var/desiredshake = input(user, "Set the amount of screenshake you want. \n(0 = disabled, 100 = full, 200 = maximum.)", "Character Preference", screenshake) as null|num
if (!isnull(desiredshake))
@@ -2214,6 +2222,15 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("hypno")
cit_toggles ^= HYPNO
if("never_hypno")
cit_toggles ^= NEVER_HYPNO
if("aphro")
cit_toggles ^= NO_APHRO
if("ass_slap")
cit_toggles ^= NO_ASS_SLAP
//END CITADEL EDIT
if("ambientocclusion")
@@ -2227,6 +2244,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(auto_fit_viewport && parent)
parent.fit_viewport()
if("sprint_key")
sprint_spacebar = !sprint_spacebar
if("sprint_toggle")
sprint_toggle = !sprint_toggle
if("save")
save_preferences()
save_character()
+9 -1
View File
@@ -167,6 +167,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["parallax"] >> parallax
S["ambientocclusion"] >> ambientocclusion
S["auto_fit_viewport"] >> auto_fit_viewport
S["sprint_spacebar"] >> sprint_spacebar
S["sprint_toggle"] >> sprint_toggle
S["menuoptions"] >> menuoptions
S["enable_tips"] >> enable_tips
S["tip_delay"] >> tip_delay
@@ -182,6 +184,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["autostand"] >> autostand
S["cit_toggles"] >> cit_toggles
S["preferred_chaos"] >> preferred_chaos
S["auto_ooc"] >> auto_ooc
//try to fix any outdated data if necessary
@@ -203,6 +206,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
sprint_spacebar = sanitize_integer(sprint_spacebar, 0, 1, initial(sprint_spacebar))
sprint_toggle = sanitize_integer(sprint_toggle, 0, 1, initial(sprint_toggle))
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
@@ -218,7 +223,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
autostand = sanitize_integer(autostand, 0, 1, initial(autostand))
cit_toggles = sanitize_integer(cit_toggles, 0, 65535, initial(cit_toggles))
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
return 1
@@ -263,6 +268,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["parallax"], parallax)
WRITE_FILE(S["ambientocclusion"], ambientocclusion)
WRITE_FILE(S["auto_fit_viewport"], auto_fit_viewport)
WRITE_FILE(S["sprint_spacebar"], sprint_spacebar)
WRITE_FILE(S["sprint_toggle"], sprint_toggle)
WRITE_FILE(S["menuoptions"], menuoptions)
WRITE_FILE(S["enable_tips"], enable_tips)
WRITE_FILE(S["tip_delay"], tip_delay)
@@ -278,6 +285,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["autostand"], autostand)
WRITE_FILE(S["cit_toggles"], cit_toggles)
WRITE_FILE(S["preferred_chaos"], preferred_chaos)
WRITE_FILE(S["auto_ooc"], auto_ooc)
return 1
@@ -54,6 +54,9 @@
H.blur_eyes(5)
eyes.applyOrganDamage(5)
/obj/item/clothing/glasses/proc/ranged_attack(mob/living/carbon/human/user,atom/A, params)
return FALSE
/obj/item/clothing/glasses/meson
name = "optical meson scanner"
desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting conditions."
@@ -0,0 +1,15 @@
/obj/item/clothing/glasses/hud/security/sunglasses/disablers
name = "true stunglasses"
desc = "Made for only the best of shitsec. Wear 'em like you're gonna robust all of those fuckers."
var/beamtype = /obj/item/projectile/beam/disabler //change for adminbus
/obj/item/clothing/glasses/hud/security/sunglasses/disablers/ranged_attack(mob/living/carbon/human/user,atom/A, params)
user.changeNext_move(CLICK_CD_RANGE)
var/obj/item/projectile/beam/disabler/LE = new beamtype( loc )
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
LE.firer = src
LE.def_zone = user.get_organ_target()
LE.preparePixelProjectile(A, src, params)
LE.fire()
return TRUE
//shamelessly copied
@@ -90,7 +90,7 @@
for(var/i in rad_places)
var/turf/place = i
if(get_dist(user, place) >= range*2) //Rads are easier to see than wires under the floor
if(get_dist(user, place) >= range*8) //Rads are easier to see than wires under the floor
continue
var/strength = round(rad_places[i] / 1000, 0.1)
var/image/pic = new(loc = place)
@@ -139,7 +139,6 @@
item_state = "trayson-t-ray"
desc = "Used by engineering staff to see underfloor objects such as cables and pipes."
range = 2
modes = list(MODE_NONE = MODE_TRAY, MODE_TRAY = MODE_NONE)
/obj/item/clothing/glasses/meson/engine/tray/prescription
@@ -152,7 +151,6 @@
icon_state = "trayson-shuttle"
item_state = "trayson-shuttle"
desc = "Used to see the boundaries of shuttle regions."
modes = list(MODE_NONE = MODE_SHUTTLE, MODE_SHUTTLE = MODE_NONE)
#undef MODE_NONE
@@ -358,3 +358,11 @@
time = 100
category = CAT_MISC
always_availible = FALSE // Disabled til learned
/datum/crafting_recipe/coconut_bong
name = "Coconut Bong"
result = /obj/item/bong/coconut
reqs = list(/obj/item/stack/sheet/mineral/bamboo = 2,
/obj/item/reagent_containers/food/snacks/grown/coconut = 1)
time = 70
category = CAT_MISC
@@ -609,4 +609,68 @@
filling_color = "#ECA735"
tastes = list("fried corn" = 1)
foodtype = JUNKFOOD | FRIED
dunkable = TRUE
dunkable = TRUE
/obj/item/reagent_containers/food/snacks/marshmallow
name = "marshmallow"
desc = "A marshmallow filled with fluffy marshmallow fluff."
icon_state = "marshmallow"
list_reagents = list("sugar" = 5, "nutriment" = 2)
filling_color = "#fafafa"
w_class = WEIGHT_CLASS_TINY
tastes = list("marshmallow" = 2)
foodtype = SUGAR | JUNKFOOD
var/burned = 0
/obj/item/reagent_containers/food/snacks/marshmallow/attackby(obj/item/I, mob/user)
switch (I.get_temperature())
if (355 to 1500)
if (prob(30))
burnmallow()
if (1500 to 2000)
if (prob(50))
burnmallow()
else
burnmallow(TRUE)
if (2000 to 3000)
if (prob(10))
burnmallow()
else
burnmallow(TRUE)
if (3000 to INFINITY)
burnmallow(TRUE)
return ..()
/obj/item/reagent_containers/food/snacks/marshmallow/proc/burnmallow(reallyburned = FALSE)
if (reallyburned && burned == 1)
icon_state = "marshmallowrburned"
else if (burned == 0)
icon_state = "marshmallowburned"
/obj/item/reagent_containers/food/snacks/marshmallow/examine(mob/user)
. = ..()
if (burned == 2)
. += "It looks very burned."
if (burned == 1)
. += "It looks just right for eating!"
/obj/item/reagent_containers/food/snacks/marshmallow/fire_act(temp,volume)
switch (temp)
if (355 to 1500)
if (prob(30))
burnmallow()
if (1500 to 2000)
if (prob(50))
burnmallow()
else
burnmallow(TRUE)
if (2000 to 3000)
if (prob(10))
burnmallow()
else
burnmallow(TRUE)
if (3000 to 7000)
burnmallow(TRUE)
if (7000 to INFINITY)
burn()
..()
+1 -1
View File
@@ -240,7 +240,7 @@
dat += "</table>"
else
dat += "No trait-related genes detected in sample.<br>"
if(can_insert && istype(disk.gene, /datum/plant_gene/trait))
if(can_insert && istype(disk.gene, /datum/plant_gene/trait) && !seed.is_gene_forbidden(disk.gene.type))
dat += "<a href='?src=[REF(src)];op=insert'>Insert: [disk.gene.get_name()]</a>"
dat += "</div>"
else
+276
View File
@@ -244,3 +244,279 @@
product = /obj/item/reagent_containers/food/snacks/grown/ash_flora/cactus_fruit
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
growthstages = 2
// Coconut
/obj/item/seeds/coconut
name = "pack of coconut seeds"
desc = "They're seeds that grow into coconut palm trees."
icon_state = "seed-coconut"
species = "coconut"
plantname = "Coconut Palm Tree"
product = /obj/item/reagent_containers/food/snacks/grown/coconut
lifespan = 50
endurance = 30
potency = 35
growing_icon = 'icons/obj/hydroponics/growing.dmi'
icon_dead = "coconut-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
forbiddengenes = list(/datum/plant_gene/trait/squash, /datum/plant_gene/trait/stinging)
reagents_add = list(/datum/reagent/consumable/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.type + " ("
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/list/mutatelist = list() // The type of plants that this plant can mutate into.
var/list/genes = list() // Plant genes are stored here, see plant_genes.dm for more info.
var/list/forbiddengenes = list()
var/list/reagents_add = list()
// A list of reagents to add to product.
// Format: "reagent_id" = potency multiplier
@@ -96,6 +97,10 @@
S.reagents_add = reagents_add.Copy() // Faster than grabbing the list from genes.
return S
obj/item/seeds/proc/is_gene_forbidden(typepath)
return (typepath in forbiddengenes)
/obj/item/seeds/proc/get_gene(typepath)
return (locate(typepath) in genes)
@@ -448,7 +453,7 @@
for(var/i in 1 to amount_random_traits)
var/random_trait = pick((subtypesof(/datum/plant_gene/trait)-typesof(/datum/plant_gene/trait/plant_type)))
var/datum/plant_gene/trait/T = new random_trait
if(T.can_add(src))
if(T.can_add(src) && !is_gene_forbidden(random_trait))
genes += T
else
qdel(T)
+12 -2
View File
@@ -58,13 +58,23 @@
return
switch(_key)
if("Shift")
sprint_hotkey(TRUE)
if(!user.prefs.sprint_spacebar)
user.prefs.sprint_toggle ? togglesprint() : sprint_hotkey(TRUE) //Yes, this looks hacky. Yes, this works.
return
if("Space")
if(user.prefs.sprint_spacebar)
user.prefs.sprint_toggle ? togglesprint() : sprint_hotkey(TRUE)
return
return ..()
/mob/living/carbon/human/key_up(_key, client/user)
switch(_key)
if("Shift")
sprint_hotkey(FALSE)
if(!user.prefs.sprint_spacebar && !user.prefs.sprint_toggle)
sprint_hotkey(FALSE)
return
if("Space")
if(user.prefs.sprint_spacebar && !user.prefs.sprint_toggle)
sprint_hotkey(FALSE)
return
return ..()
@@ -74,4 +74,5 @@
/datum/sprite_accessory/underwear
icon = 'icons/mob/underwear.dmi'
var/has_color = FALSE
var/has_color = FALSE
var/has_digitigrade = FALSE
@@ -2,6 +2,9 @@
// Socks Definitions //
///////////////////////
/datum/sprite_accessory/underwear/socks
has_digitigrade = TRUE
/datum/sprite_accessory/underwear/socks/nude
name = "Nude"
icon_state = null
@@ -28,41 +28,49 @@
name = "Boxers"
icon_state = "boxers"
has_color = TRUE
has_digitigrade = TRUE
gender = MALE
/datum/sprite_accessory/underwear/bottom/male_bee
name = "Boxers - Bee"
icon_state = "bee_shorts"
has_digitigrade = TRUE
gender = MALE
/datum/sprite_accessory/underwear/bottom/male_hearts
name = "Boxers - Heart"
icon_state = "boxers_heart"
has_digitigrade = TRUE
gender = MALE
/datum/sprite_accessory/underwear/bottom/male_stripe
name = "Boxers - Striped"
icon_state = "boxers_striped"
has_digitigrade = TRUE
gender = MALE
/datum/sprite_accessory/underwear/bottom/male_commie
name = "Boxers - Striped Communist"
icon_state = "boxers_commie"
has_digitigrade = TRUE
gender = MALE
/datum/sprite_accessory/underwear/bottom/male_usastripe
name = "Boxers - Striped Freedom"
icon_state = "boxers_assblastusa"
has_digitigrade = TRUE
gender = MALE
/datum/sprite_accessory/underwear/bottom/male_uk
name = "Boxers - Striped UK"
icon_state = "boxers_uk"
has_digitigrade = TRUE
gender = MALE
/datum/sprite_accessory/underwear/bottom/boxer_briefs
name = "Boxer Briefs"
icon_state = "boxer_briefs"
has_digitigrade = TRUE
has_color = TRUE
/datum/sprite_accessory/underwear/bottom/panties
@@ -140,6 +148,7 @@
/datum/sprite_accessory/underwear/bottom/longjon
name = "Long John Bottoms"
icon_state = "ljonb"
has_digitigrade = TRUE
has_color = TRUE
/datum/sprite_accessory/underwear/bottom/swimsuit_red
@@ -283,6 +283,9 @@ Works together with spawning an observer, noted above.
client.reenter_round_timeout = penalty
else //A disconnected player (quite likely for cryopods)
ghost.clientless_round_timeout = penalty
if (client && client.prefs && client.prefs.auto_ooc)
if (!(client.prefs.chat_toggles & CHAT_OOC))
client.prefs.chat_toggles ^= CHAT_OOC
transfer_ckey(ghost, FALSE)
return ghost
@@ -6,21 +6,21 @@
return 2 //no ears
/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush)
..(AM, skipcatch = TRUE, hitpush = FALSE)
return ..(AM, skipcatch = TRUE, hitpush = FALSE)
/mob/living/carbon/alien/can_embed(obj/item/I)
return FALSE
/*Code for aliens attacking aliens. Because aliens act on a hivemind, I don't see them as very aggressive with each other.
As such, they can either help or harm other aliens. Help works like the human help command while harm is a simple nibble.
In all, this is a lot like the monkey code. /N
*/
/mob/living/carbon/alien/attack_alien(mob/living/carbon/alien/M)
if(isturf(loc) && istype(loc.loc, /area/start))
to_chat(M, "No attacking people at spawn, you jackass.")
. = ..()
if(!.) // the attack was blocked or was help/grab intent
return
switch(M.a_intent)
if ("help")
if (INTENT_HELP)
if(!recoveringstam)
resting = 0
AdjustStun(-60)
@@ -28,11 +28,7 @@ In all, this is a lot like the monkey code. /N
AdjustUnconscious(-60)
AdjustSleeping(-100)
visible_message("<span class='notice'>[M.name] nuzzles [src] trying to wake [p_them()] up!</span>")
if ("grab")
grabbedby(M)
else
if(INTENT_DISARM, INTENT_HARM)
if(health > 0)
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
playsound(loc, 'sound/weapons/bite.ogg', 50, 1, -1)
@@ -50,28 +46,31 @@ In all, this is a lot like the monkey code. /N
/mob/living/carbon/alien/attack_hand(mob/living/carbon/human/M)
if(..()) //to allow surgery to return properly.
return 0
. = ..()
if(.) //To allow surgery to return properly.
return
switch(M.a_intent)
if("help")
if(INTENT_HELP)
help_shake_act(M)
if("grab")
if(INTENT_GRAB)
grabbedby(M)
if ("harm")
if (INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
return TRUE
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
return 1
if("disarm")
if(INTENT_DISARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
return TRUE
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return 1
return 0
/mob/living/carbon/alien/attack_paw(mob/living/carbon/monkey/M)
if(..())
if (stat != DEAD)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(rand(1, 3), BRUTE, affecting)
. = ..()
if(.) //successful monkey bite.
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(rand(1, 3), BRUTE, affecting)
/mob/living/carbon/alien/attack_animal(mob/living/simple_animal/M)
@@ -93,13 +92,15 @@ In all, this is a lot like the monkey code. /N
adjustStaminaLoss(damage)
/mob/living/carbon/alien/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(10, 40)
adjustBruteLoss(damage)
log_combat(M, src, "attacked")
updatehealth()
. = ..()
if(!.) //unsuccessful slime attack
return
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(10, 40)
adjustBruteLoss(damage)
log_combat(M, src, "attacked")
updatehealth()
/mob/living/carbon/alien/ex_act(severity, target, origin)
if(origin && istype(origin, /datum/spacevine_mutation) && isvineimmune(src))
@@ -63,12 +63,7 @@
if(A)
if(isliving(A))
var/mob/living/L = A
var/blocked = FALSE
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
blocked = TRUE
if(!blocked)
if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK))
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
L.Knockdown(100)
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
@@ -5,9 +5,11 @@
else
..()
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
/mob/living/carbon/alien/humanoid/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
..(user, 1)
. = ..(user, TRUE)
if(.)
return
adjustBruteLoss(15)
var/hitverb = "punched"
if(mob_size < MOB_SIZE_LARGE)
@@ -21,46 +23,46 @@
return 1
/mob/living/carbon/alien/humanoid/attack_hand(mob/living/carbon/human/M)
if(..())
switch(M.a_intent)
if ("harm")
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down.
Unconscious(40)
visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \
"<span class='userdanger'>[M] has knocked [src] down!</span>")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting)
log_combat(M, src, "attacked")
. = ..()
if(.) //To allow surgery to return properly.
return
switch(M.a_intent)
if (INTENT_HARM)
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
"<span class='userdanger'>[M] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ((stat != DEAD) && (damage > 9 || prob(5)))//Regular humans have a very small chance of knocking an alien down.
Unconscious(40)
visible_message("<span class='danger'>[M] has knocked [src] down!</span>", \
"<span class='userdanger'>[M] has knocked [src] down!</span>")
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting)
log_combat(M, src, "attacked")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [src]!</span>", \
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if (INTENT_DISARM)
if (!lying)
if (prob(5))
Unconscious(40)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
log_combat(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='userdanger'>[M] has attempted to punch [src]!</span>", \
"<span class='userdanger'>[M] has attempted to punch [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ("disarm")
if (!lying)
if (prob(5))
Unconscious(40)
if (prob(50))
dropItemToGround(get_active_held_item())
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
log_combat(M, src, "pushed")
visible_message("<span class='danger'>[M] has pushed down [src]!</span>", \
"<span class='userdanger'>[M] has pushed down [src]!</span>")
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
else
if (prob(50))
dropItemToGround(get_active_held_item())
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", \
"<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='userdanger'>[M] has attempted to disarm [src]!</span>",\
"<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to disarm [src]!</span>",\
"<span class='userdanger'>[M] has attempted to disarm [src]!</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect && !visual_effect_icon)
@@ -1,26 +1,33 @@
/mob/living/carbon/alien/larva/attack_hand(mob/living/carbon/human/M)
if(..())
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
log_combat(M, src, "attacked")
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ((stat != DEAD) && (damage > 4.9))
Unconscious(rand(100,200))
. = ..()
if(. || M.a_intent == INTENT_HELP || M.a_intent == INTENT_GRAB)
return
var/damage = rand(1, 9)
if (prob(90))
playsound(loc, "punch", 25, 1, -1)
log_combat(M, src, "attacked")
visible_message("<span class='danger'>[M] has kicked [src]!</span>", \
"<span class='userdanger'>[M] has kicked [src]!</span>", null, COMBAT_MESSAGE_RANGE)
if ((stat != DEAD) && (damage > 4.9))
Unconscious(rand(100,200))
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting)
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
"<span class='userdanger'>[M] has attempted to kick [src]!</span>", null, COMBAT_MESSAGE_RANGE)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
apply_damage(damage, BRUTE, affecting)
else
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to kick [src]!</span>", \
"<span class='userdanger'>[M] has attempted to kick [src]!</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
/mob/living/carbon/alien/larva/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
..(user, 1)
. = ..(user, TRUE)
if(.)
return
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has pummeled [src]!</span>", \
"<span class='userdanger'>[user] has pummeled [src]!</span>", null, COMBAT_MESSAGE_RANGE)
adjustBruteLoss(5 + rand(1,9))
new /datum/forced_movement(src, get_step_away(user,src, 30), 1)
return 1
@@ -103,15 +103,17 @@
new_xeno.notransform = 0
new_xeno.invisibility = 0
var/mob/living/carbon/old_owner = owner
if(kill_on_sucess) //ITS TOO LATE
new_xeno.visible_message("<span class='danger'>[new_xeno] bursts out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>", "<span class='italics'>You hear organic matter ripping and tearing!</span>")
owner.apply_damage(rand(100,300),BRUTE,zone,FALSE) //Random high damage to torso so health sensors don't metagame.
owner.spill_organs(TRUE,FALSE,TRUE) //Lets still make the death gruesome and impossible to just simply defib someone.
var/obj/item/bodypart/B = owner.get_bodypart(zone)
B.drop_organs(owner) //Lets still make the death gruesome and impossible to just simply defib someone.
owner.death(FALSE) //Just in case some freak occurance occurs where you somehow survive all your organs being removed from you and the 100-300 brute damage.
else //When it is removed via surgery at a late stage, rather than forced.
new_xeno.visible_message("<span class='danger'>[new_xeno] wriggles out of [owner]!</span>", "<span class='userdanger'>You exit [owner], your previous host.</span>")
owner.adjustBruteLoss(40)
owner.cut_overlay(overlay)
old_owner.cut_overlay(overlay)
qdel(src)
+2 -1
View File
@@ -157,6 +157,7 @@
if(getStaminaLoss() >= STAMINA_SOFTCRIT)
to_chat(src, "<span class='warning'>You're too exhausted.</span>")
return
var/random_turn = a_intent == INTENT_HARM
//END OF CIT CHANGES
var/obj/item/I = src.get_active_held_item()
@@ -204,7 +205,7 @@
do_attack_animation(target, no_effect = 1)
playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1)
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, random_turn)
@@ -48,41 +48,42 @@
if(affecting && affecting.dismemberable && affecting.get_damage() >= (affecting.max_damage - P.dismemberment))
affecting.dismember(P.damtype)
/mob/living/carbon/proc/can_catch_item(skip_throw_mode_check)
. = FALSE
if(mind)
if(mind.martial_art && mind.martial_art.dodge_chance == 100)
return TRUE
if(!skip_throw_mode_check && !in_throw_mode)
/mob/living/carbon/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
. = ..()
if(!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) && !skip_throw_mode_check && !in_throw_mode)
return
if(get_active_held_item())
if(get_active_held_item() || restrained())
return
if(restrained())
return
return TRUE
/mob/living/carbon/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
if(!skipcatch) //ugly, but easy
if(can_catch_item())
if(istype(AM, /obj/item))
var/obj/item/I = AM
if (mind)
if (mind.martial_art && mind.martial_art.dodge_chance == 100) //autocatch for rising bass
if (get_active_held_item())
visible_message("<span class='warning'>[I] falls to the ground as [src] chops it out of the air!</span>")
return 1
if(!in_throw_mode)
throw_mode_on()
if(isturf(I.loc))
I.attack_hand(src)
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
throw_mode_off()
return 1
..()
I.attack_hand(src)
if(get_active_held_item() == I) //if our attack_hand() picks up the item...
visible_message("<span class='warning'>[src] catches [I]!</span>") //catch that sucker!
throw_mode_off()
return TRUE
/mob/living/carbon/embed_item(obj/item/I)
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/bodypart/L = pick(bodyparts)
L.embedded_objects |= I
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
I.forceMove(src)
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(iscarbon(user))
var/mob/living/carbon/tempcarb = user
if(!tempcarb.combatmode)
totitemdamage *= 0.5
if(user.resting)
totitemdamage *= 0.5
if(!combatmode)
totitemdamage *= 1.5
//CIT CHANGES END HERE
if(user != src && check_shields(I, totitemdamage, "the [I.name]", MELEE_ATTACK, I.armour_penetration))
return FALSE
var/obj/item/bodypart/affecting
if(user == src)
affecting = get_bodypart(check_zone(user.zone_selected)) //we're self-mutilating! yay!
@@ -93,17 +94,6 @@
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
send_item_attack_message(I, user, affecting.name)
if(I.force)
//CIT CHANGES START HERE - combatmode and resting checks
var/totitemdamage = I.force
if(iscarbon(user))
var/mob/living/carbon/tempcarb = user
if(!tempcarb.combatmode)
totitemdamage *= 0.5
if(user.resting)
totitemdamage *= 0.5
if(!combatmode)
totitemdamage *= 1.5
//CIT CHANGES END HERE
apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
var/basebloodychance = affecting.brute_dam + totitemdamage
@@ -137,7 +127,9 @@
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/carbon/attack_hand(mob/living/carbon/human/user)
. = ..()
if(.) //was the attack blocked?
return
for(var/thing in diseases)
var/datum/disease/D = thing
if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
@@ -152,8 +144,7 @@
if(user.a_intent == INTENT_HELP || user.a_intent == INTENT_DISARM)
for(var/datum/surgery/S in surgeries)
if(S.next_step(user, user.a_intent))
return 1
return 0
return TRUE
/mob/living/carbon/attack_paw(mob/living/carbon/monkey/M)
@@ -173,7 +164,8 @@
help_shake_act(M)
return 0
if(..()) //successful monkey bite.
. = ..()
if(.) //successful monkey bite.
for(var/thing in M.diseases)
var/datum/disease/D = thing
ForceContractDisease(D)
@@ -181,26 +173,27 @@
/mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
if(M.powerlevel > 0)
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
if(prob(stunprob))
M.powerlevel -= 3
if(M.powerlevel < 0)
M.powerlevel = 0
. = ..()
if(!.)
return
if(M.powerlevel > 0)
var/stunprob = M.powerlevel * 7 + 10 // 17 at level 1, 80 at level 10
if(prob(stunprob))
M.powerlevel -= 3
if(M.powerlevel < 0)
M.powerlevel = 0
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
visible_message("<span class='danger'>The [M.name] has shocked [src]!</span>", \
"<span class='userdanger'>The [M.name] has shocked [src]!</span>")
do_sparks(5, TRUE, src)
var/power = M.powerlevel + rand(0,3)
Knockdown(power*20)
if(stuttering < power)
stuttering = power
if (prob(stunprob) && M.powerlevel >= 8)
adjustFireLoss(M.powerlevel * rand(6,10))
updatehealth()
return 1
do_sparks(5, TRUE, src)
var/power = M.powerlevel + rand(0,3)
Knockdown(power*20)
if(stuttering < power)
stuttering = power
if (prob(stunprob) && M.powerlevel >= 8)
adjustFireLoss(M.powerlevel * rand(6,10))
updatehealth()
/mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone)
if(!attacker.limb_destroyer)
@@ -67,66 +67,36 @@
P.setAngle(rand(0, 360))//SHING
return FALSE
if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself
if(P.is_reflectable)
if(check_reflect(def_zone)) // Checks if you've passed a reflection% check
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(src)
return ..()
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
var/new_angle_s = P.Angle + rand(120,240)
while(new_angle_s > 180) // Translate to regular projectile degrees
new_angle_s -= 360
P.setAngle(new_angle_s)
/mob/living/carbon/human/check_reflect(def_zone)
if(wear_suit?.IsReflect(def_zone))
return TRUE
return ..()
return -1 // complete projectile permutation
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
P.on_hit(src, 100, def_zone)
return 2
return (..(P , def_zone))
/mob/living/carbon/human/proc/check_reflect(def_zone) //Reflection checks for anything in your l_hand, r_hand, or wear_suit based on the reflection chance of the object
if(wear_suit)
if(wear_suit.IsReflect(def_zone) == 1)
return 1
for(var/obj/item/I in held_items)
if(I.IsReflect(def_zone) == 1)
return 1
return 0
/mob/living/carbon/human/proc/check_shields(atom/AM, var/damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
/mob/living/carbon/human/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
. = ..()
if(.)
return
var/block_chance_modifier = round(damage / -3)
for(var/obj/item/I in held_items)
if(!istype(I, /obj/item/clothing))
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(wear_suit)
var/final_block_chance = wear_suit.block_chance - (CLAMP((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
return TRUE
if(w_uniform)
var/final_block_chance = w_uniform.block_chance - (CLAMP((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
return TRUE
if(wear_neck)
var/final_block_chance = wear_neck.block_chance - (CLAMP((armour_penetration-wear_neck.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_neck.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
return 0
return TRUE
return FALSE
/mob/living/carbon/human/can_embed(obj/item/I)
if(I.get_sharpness() || is_pointed(I) || is_type_in_typecache(I, GLOB.can_embed_types))
return TRUE
return FALSE
/mob/living/carbon/human/proc/check_block()
if(mind)
@@ -135,39 +105,7 @@
return FALSE
/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE)
if(dna && dna.species)
var/spec_return = dna.species.spec_hitby(AM, src)
if(spec_return)
return spec_return
var/obj/item/I
var/throwpower = 30
if(istype(AM, /obj/item))
I = AM
throwpower = I.throwforce
if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions
return ..()
if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK))
hitpush = FALSE
skipcatch = TRUE
blocked = TRUE
else if(I)
if(I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && !(mind.martial_art && mind.martial_art.dodge_chance == 100))
if(can_embed(I))
if(prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE))
throw_alert("embeddedobject", /obj/screen/alert/embeddedobject)
var/obj/item/bodypart/L = pick(bodyparts)
L.embedded_objects |= I
I.add_mob_blood(src)//it embedded itself in you, of course it's bloody!
I.forceMove(src)
L.receive_damage(I.w_class*I.embedding.embedded_impact_pain_multiplier)
visible_message("<span class='danger'>[I] embeds itself in [src]'s [L.name]!</span>","<span class='userdanger'>[I] embeds itself in your [L.name]!</span>")
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
hitpush = FALSE
skipcatch = TRUE //can't catch the now embedded item
if (mind)
if (mind.martial_art && mind.martial_art.dodge_chance == 100)
skipcatch = FALSE
return ..()
return dna?.species?.spec_hitby(AM, src) || ..()
/mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0)
if(user == src && pulling && !pulling.anchored && grab_state >= GRAB_AGGRESSIVE && (HAS_TRAIT(src, TRAIT_FAT)) && ismonkey(pulling))
@@ -201,12 +139,12 @@
return dna.species.spec_attacked_by(I, user, affecting, a_intent, src)
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
var/hulk_verb = pick("smash","pummel")
if(check_shields(user, 15, "the [hulk_verb]ing"))
. = ..(user, TRUE)
if(.)
return
..(user, 1)
var/hulk_verb = pick("smash","pummel")
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
var/message = "[user] has [hulk_verb]ed [src]!"
visible_message("<span class='danger'>[message]</span>", \
@@ -215,7 +153,8 @@
return 1
/mob/living/carbon/human/attack_hand(mob/user)
if(..()) //to allow surgery to return properly.
. = ..()
if(.) //To allow surgery to return properly.
return
if(ishuman(user))
var/mob/living/carbon/human/H = user
@@ -227,8 +166,7 @@
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
if(M.a_intent == INTENT_HELP)
..() //shaking
return 0
return ..() //shaking
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stunned instead.
var/obj/item/I = get_active_held_item()
@@ -249,78 +187,69 @@
if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites.
if(..()) //successful monkey bite, this handles disease contraction.
var/damage = rand(1, 3)
if(check_shields(M, damage, "the [M.name]"))
return 0
if(stat != DEAD)
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
apply_damage(damage, BRUTE, affecting, run_armor_check(affecting, "melee"))
return 1
/mob/living/carbon/human/attack_alien(mob/living/carbon/alien/humanoid/M)
if(check_shields(M, 0, "the M.name"))
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
return 0
. = ..()
if(!.)
return
if(M.a_intent == INTENT_HARM)
if (w_uniform)
w_uniform.add_fingerprint(M)
var/damage = prob(90) ? 20 : 0
if(!damage)
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
"<span class='userdanger'>[M] has lunged at [src]!</span>")
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee", null, null,10)
if(..())
if(M.a_intent == INTENT_HARM)
if (w_uniform)
w_uniform.add_fingerprint(M)
var/damage = prob(90) ? 20 : 0
if(!damage)
playsound(loc, 'sound/weapons/slashmiss.ogg', 50, 1, -1)
visible_message("<span class='danger'>[M] has lunged at [src]!</span>", \
"<span class='userdanger'>[M] has lunged at [src]!</span>")
return 0
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee", null, null,10)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
log_combat(M, src, "attacked")
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting, armor_block)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>")
log_combat(M, src, "attacked")
if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting, armor_block)
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
var/obj/item/I = get_active_held_item()
if(I && dropItemToGround(I))
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] disarmed [src]!</span>")
if(M.a_intent == INTENT_DISARM) //Always drop item in hand, if no item, get stun instead.
var/obj/item/I = get_active_held_item()
if(I && dropItemToGround(I))
playsound(loc, 'sound/weapons/slash.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] disarmed [src]!</span>", \
"<span class='userdanger'>[M] disarmed [src]!</span>")
else
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(!lying) //CITADEL EDIT
Knockdown(100, TRUE, FALSE, 30, 25)
else
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(!lying) //CITADEL EDIT
Knockdown(100, TRUE, FALSE, 30, 25)
else
Knockdown(100)
log_combat(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
Knockdown(100)
log_combat(M, src, "tackled")
visible_message("<span class='danger'>[M] has tackled down [src]!</span>", \
"<span class='userdanger'>[M] has tackled down [src]!</span>")
/mob/living/carbon/human/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(check_shields(L, damage, "the [L.name]"))
return 0
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
. = ..()
if(!.) //unsuccessful larva bite.
return
var/damage = rand(1, 3)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
/mob/living/carbon/human/attack_animal(mob/living/simple_animal/M)
. = ..()
if(.)
var/damage = rand(M.melee_damage_lower, M.melee_damage_upper)
if(check_shields(M, damage, "the [M.name]", MELEE_ATTACK, M.armour_penetration))
return FALSE
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(!dam_zone) //Dismemberment successful
return TRUE
@@ -332,23 +261,22 @@
/mob/living/carbon/human/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 25)
if(M.is_adult)
damage = rand(10, 35)
. = ..()
if(!.) //unsuccessful slime attack
return
var/damage = rand(5, 25)
if(M.is_adult)
damage = rand(10, 35)
if(check_shields(M, damage, "the [M.name]"))
return 0
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(!dam_zone) //Dismemberment successful
return 1
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(!dam_zone) //Dismemberment successful
return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
var/armor_block = run_armor_check(affecting, "melee")
apply_damage(damage, BRUTE, affecting, armor_block)
/mob/living/carbon/human/mech_melee_attack(obj/mecha/M)
if(M.occupant.a_intent == INTENT_HARM)
+21 -23
View File
@@ -545,6 +545,20 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
//Underwear, Undershirts & Socks
if(!(NO_UNDERWEAR in species_traits))
if(H.socks && H.get_num_legs(FALSE) >= 2)
if(H.hidden_socks)
H.socks = "Nude"
else
H.socks = H.saved_socks
var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks]
if(S)
var/digilegs = ((DIGITIGRADE in species_traits) && S.has_digitigrade) ? "_d" : ""
var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER)
if(S.has_color)
MA.color = "#[H.socks_color]"
standing += MA
if(H.underwear)
if(H.hidden_underwear)
H.underwear = "Nude"
@@ -552,8 +566,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.underwear = H.saved_underwear
var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear]
if(B)
var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER)
if(UNDIE_COLORABLE(B))
var/digilegs = ((DIGITIGRADE in species_traits) && B.has_digitigrade) ? "_d" : ""
var/mutable_appearance/MA = mutable_appearance(B.icon, "[B.icon_state][digilegs]", -BODY_LAYER)
if(B.has_color)
MA.color = "#[H.undie_color]"
standing += MA
@@ -564,28 +579,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.undershirt = H.saved_undershirt
var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt]
if(T)
var/state = "[T.icon_state][((DIGITIGRADE in species_traits) && T.has_digitigrade) ? "_d" : ""]"
var/mutable_appearance/MA
if(H.dna.species.sexes && H.gender == FEMALE)
MA = wear_female_version(T.icon_state, T.icon, BODY_LAYER)
MA = wear_female_version(state, T.icon, BODY_LAYER)
else
MA = mutable_appearance(T.icon, T.icon_state, -BODY_LAYER)
if(UNDIE_COLORABLE(T))
MA = mutable_appearance(T.icon, state, -BODY_LAYER)
if(T.has_color)
MA.color = "#[H.shirt_color]"
standing += MA
if(H.socks && H.get_num_legs(FALSE) >= 2)
if(H.hidden_socks)
H.socks = "Nude"
else
H.socks = H.saved_socks
var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks]
if(S)
var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : ""
var/mutable_appearance/MA = mutable_appearance(S.icon, "[S.icon_state][digilegs]", -BODY_LAYER)
if(UNDIE_COLORABLE(S))
MA.color = "#[H.socks_color]"
standing += MA
if(standing.len)
H.overlays_standing[BODY_LAYER] = standing
@@ -1682,11 +1685,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
attacker_style = M.mind.martial_art
if(attacker_style?.pacifism_check && HAS_TRAIT(M, TRAIT_PACIFISM)) // most martial arts are quite harmful, alas.
attacker_style = null
if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(M, 0, M.name, attack_type = UNARMED_ATTACK))
log_combat(M, H, "attempted to touch")
H.visible_message("<span class='warning'>[M] attempted to touch [H]!</span>")
return 0
SEND_SIGNAL(M, COMSIG_MOB_ATTACK_HAND, M, H, attacker_style)
switch(M.a_intent)
if("help")
help(M, H, attacker_style)
@@ -369,6 +369,23 @@
retaliate(L)
return ..()
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
if(M.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(M)
else if(M.a_intent == INTENT_DISARM && prob(MONKEY_RETALIATE_DISARM_PROB))
retaliate(M)
return ..()
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(L)
return ..()
/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(user)
return ..()
/mob/living/carbon/monkey/attack_paw(mob/living/L)
if(L.a_intent == INTENT_HARM && prob(MONKEY_RETALIATE_HARM_PROB))
retaliate(L)
@@ -6,37 +6,55 @@
..()
/mob/living/carbon/monkey/attack_paw(mob/living/M)
if(..()) //successful monkey bite.
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
if(M.limb_destroyer)
dismembering_strike(M, affecting.body_zone)
if(stat != DEAD)
var/dmg = rand(1, 5)
apply_damage(dmg, BRUTE, affecting)
. = ..()
if(!.) //unsuccessful monkey bite.
return
var/dam_zone = pick(BODY_ZONE_CHEST, BODY_ZONE_PRECISE_L_HAND, BODY_ZONE_PRECISE_R_HAND, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
if(M.limb_destroyer)
dismembering_strike(M, affecting.body_zone)
var/dmg = rand(1, 5)
apply_damage(dmg, BRUTE, affecting)
/mob/living/carbon/monkey/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
var/damage = rand(1, 3)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
apply_damage(damage, BRUTE, affecting)
. = ..()
if(!.) //unsuccessful larva bite
return
var/damage = rand(1, 3)
if(stat != DEAD)
L.amount_grown = min(L.amount_grown + damage, L.max_grown)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(L.zone_selected))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
apply_damage(damage, BRUTE, affecting)
/mob/living/carbon/monkey/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
. = ..(user, TRUE)
if(.)
return
var/hulk_verb = pick("smash","pummel")
playsound(loc, user.dna.species.attack_sound, 25, 1, -1)
var/message = "[user] has [hulk_verb]ed [src]!"
visible_message("<span class='danger'>[message]</span>", \
"<span class='userdanger'>[message]</span>")
adjustBruteLoss(15)
return TRUE
/mob/living/carbon/monkey/attack_hand(mob/living/carbon/human/M)
if(..()) //To allow surgery to return properly.
. = ..()
if(.) //To allow surgery to return properly.
return
switch(M.a_intent)
if("help")
if(INTENT_HELP)
help_shake_act(M)
if("grab")
if(INTENT_GRAB)
grabbedby(M)
if("harm")
if(INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
return
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
if (prob(75))
visible_message("<span class='danger'>[M] has punched [name]!</span>", \
@@ -60,7 +78,7 @@
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to punch [name]!</span>", \
"<span class='userdanger'>[M] has attempted to punch [name]!</span>", null, COMBAT_MESSAGE_RANGE)
if("disarm")
if(INTENT_DISARM)
if(!IsUnconscious())
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if (prob(25))
@@ -74,50 +92,51 @@
visible_message("<span class='danger'>[M] has disarmed [src]!</span>", "<span class='userdanger'>[M] has disarmed [src]!</span>", null, COMBAT_MESSAGE_RANGE)
/mob/living/carbon/monkey/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent.
if (M.a_intent == INTENT_HARM)
if ((prob(95) && health > 0))
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
var/damage = rand(15, 30)
if (damage >= 25)
damage = rand(20, 40)
if(AmountUnconscious() < 300)
Unconscious(rand(200, 300))
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
log_combat(M, src, "attacked")
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting)
. = ..()
if(!.) // the attack was blocked or was help/grab intent
return
if (M.a_intent == INTENT_HARM)
if ((prob(95) && health > 0))
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
var/damage = rand(15, 30)
if (damage >= 25)
damage = rand(20, 40)
if(AmountUnconscious() < 300)
Unconscious(rand(200, 300))
visible_message("<span class='danger'>[M] has wounded [name]!</span>", \
"<span class='userdanger'>[M] has wounded [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
visible_message("<span class='danger'>[M] has slashed [name]!</span>", \
"<span class='userdanger'>[M] has slashed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
if (M.a_intent == INTENT_DISARM)
var/obj/item/I = null
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(prob(95))
Knockdown(20)
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(M.zone_selected))
log_combat(M, src, "attacked")
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
if(!dismembering_strike(M, affecting.body_zone)) //Dismemberment successful
return 1
apply_damage(damage, BRUTE, affecting)
else
playsound(loc, 'sound/weapons/slashmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to lunge at [name]!</span>", \
"<span class='userdanger'>[M] has attempted to lunge at [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
var/obj/item/I = null
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
if(prob(95))
Knockdown(20)
visible_message("<span class='danger'>[M] has tackled down [name]!</span>", \
"<span class='userdanger'>[M] has tackled down [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
I = get_active_held_item()
if(dropItemToGround(I))
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
I = get_active_held_item()
if(dropItemToGround(I))
visible_message("<span class='danger'>[M] has disarmed [name]!</span>", "<span class='userdanger'>[M] has disarmed [name]!</span>", null, COMBAT_MESSAGE_RANGE)
else
I = null
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
updatehealth()
I = null
log_combat(M, src, "disarmed", "[I ? " removing \the [I]" : ""]")
updatehealth()
/mob/living/carbon/monkey/attack_animal(mob/living/simple_animal/M)
. = ..()
@@ -132,17 +151,19 @@
apply_damage(damage, M.melee_damage_type, affecting)
/mob/living/carbon/monkey/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(!dam_zone) //Dismemberment successful
return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
apply_damage(damage, BRUTE, affecting)
. = ..()
if(!.) //unsuccessful slime attack
return
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
var/dam_zone = dismembering_strike(M, pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG))
if(!dam_zone) //Dismemberment successful
return 1
var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone))
if(!affecting)
affecting = get_bodypart(BODY_ZONE_CHEST)
apply_damage(damage, BRUTE, affecting)
/mob/living/carbon/monkey/acid_act(acidpwr, acid_volume, bodyzone_hit)
. = 1
+3 -1
View File
@@ -91,7 +91,9 @@
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST))
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[get_area_name(T)]</b>.</span>"
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
if (client && client.prefs && client.prefs.auto_ooc)
if (!(client.prefs.chat_toggles & CHAT_OOC))
client.prefs.chat_toggles ^= CHAT_OOC
if (client)
client.move_delay = initial(client.move_delay)
+113 -18
View File
@@ -36,7 +36,50 @@
/mob/living/proc/on_hit(obj/item/projectile/P)
return
/mob/living/proc/check_shields(atom/AM, damage, attack_text = "the attack", attack_type = MELEE_ATTACK, armour_penetration = 0)
var/block_chance_modifier = round(damage / -3)
for(var/obj/item/I in held_items)
if(!istype(I, /obj/item/clothing))
var/final_block_chance = I.block_chance - (CLAMP((armour_penetration-I.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(I.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return TRUE
return FALSE
/mob/living/proc/check_reflect(def_zone) //Reflection checks for anything in your hands, based on the reflection chance of the object(s)
for(var/obj/item/I in held_items)
if(I.IsReflect(def_zone))
return TRUE
return FALSE
/mob/living/proc/reflect_bullet_check(obj/item/projectile/P, def_zone)
if(P.is_reflectable && check_reflect(def_zone)) // Checks if you've passed a reflection% check
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", \
"<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
// Find a turf near or on the original location to bounce to
if(P.starting)
var/new_x = P.starting.x + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/new_y = P.starting.y + pick(0, 0, 0, 0, 0, -1, 1, -2, 2)
var/turf/curloc = get_turf(src)
// redirect the projectile
P.original = locate(new_x, new_y, P.z)
P.starting = curloc
P.firer = src
P.yo = new_y - curloc.y
P.xo = new_x - curloc.x
var/new_angle_s = P.Angle + rand(120,240)
while(new_angle_s > 180) // Translate to regular projectile degrees
new_angle_s -= 360
P.setAngle(new_angle_s)
return TRUE
return FALSE
/mob/living/bullet_act(obj/item/projectile/P, def_zone)
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
if(reflect_bullet_check(P, def_zone))
return -1 // complete projectile permutation
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
P.on_hit(src, 100, def_zone)
return 2
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
if(!P.nodamage)
apply_damage(P.damage, P.damage_type, def_zone, armor)
@@ -55,9 +98,32 @@
else
return 0
/mob/living/proc/catch_item(obj/item/I, skip_throw_mode_check = FALSE)
return FALSE
/mob/living/proc/embed_item(obj/item/I)
return
/mob/living/proc/can_embed(obj/item/I)
return FALSE
/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE)
if(istype(AM, /obj/item))
var/obj/item/I = AM
var/obj/item/I
var/throwpower = 30
if(isitem(AM))
I = AM
throwpower = I.throwforce
if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK))
hitpush = FALSE
skipcatch = TRUE
blocked = TRUE
else if(I && I.throw_speed >= EMBED_THROWSPEED_THRESHOLD && can_embed(I, src) && prob(I.embedding.embed_chance) && !HAS_TRAIT(src, TRAIT_PIERCEIMMUNE) && (!HAS_TRAIT(src, TRAIT_AUTO_CATCH_ITEM) || incapacitated() || get_active_held_item()))
embed_item(I)
hitpush = FALSE
skipcatch = TRUE //can't catch the now embedded item
if(I)
if(!skipcatch && isturf(I.loc) && catch_item(I))
return TRUE
var/zone = ran_zone(BODY_ZONE_CHEST, 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class()
@@ -214,6 +280,24 @@
Move(user.loc)
return 1
/mob/living/attack_hand(mob/user)
..() //Ignoring parent return value here.
SEND_SIGNAL(src, COMSIG_MOB_ATTACK_HAND, user)
if((user != src) && user.a_intent != INTENT_HELP && check_shields(user, 0, user.name, attack_type = UNARMED_ATTACK))
log_combat(user, src, "attempted to touch")
visible_message("<span class='warning'>[user] attempted to touch [src]!</span>")
return TRUE
/mob/living/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
return TRUE
var/hulk_verb = pick("smash","pummel")
if(user != src && check_shields(user, 15, "the [hulk_verb]ing"))
return TRUE
..()
return FALSE
/mob/living/attack_slime(mob/living/simple_animal/slime/M)
if(!SSticker.HasRoundStarted())
@@ -229,6 +313,12 @@
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE
var/damage = rand(5, 35)
if(M.is_adult)
damage = rand(20, 40)
if(check_shields(M, damage, "the [M.name]"))
return FALSE
if (stat != DEAD)
log_combat(M, src, "attacked")
M.do_attack_animation(src)
@@ -245,7 +335,8 @@
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE
if(check_shields(M, rand(M.melee_damage_lower, M.melee_damage_upper), "the [M.name]", MELEE_ATTACK, M.armour_penetration))
return FALSE
if(M.attack_sound)
playsound(loc, M.attack_sound, 50, 1, 1)
M.do_attack_animation(src)
@@ -256,10 +347,6 @@
/mob/living/attack_paw(mob/living/carbon/monkey/M)
if(isturf(loc) && istype(loc.loc, /area/start))
to_chat(M, "No attacking people at spawn, you jackass.")
return FALSE
if (M.a_intent == INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
@@ -268,6 +355,8 @@
if(M.is_muzzled() || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSMOUTH))
to_chat(M, "<span class='warning'>You can't bite with your mouth covered!</span>")
return FALSE
if(check_shields(M, 0, "the [M.name]"))
return FALSE
M.do_attack_animation(src, ATTACK_EFFECT_BITE)
if (prob(75))
log_combat(M, src, "attacked")
@@ -282,15 +371,16 @@
/mob/living/attack_larva(mob/living/carbon/alien/larva/L)
switch(L.a_intent)
if("help")
if(INTENT_HELP)
visible_message("<span class='notice'>[L.name] rubs its head against [src].</span>")
return FALSE
else
if(HAS_TRAIT(L, TRAIT_PACIFISM))
to_chat(L, "<span class='notice'>You don't want to hurt anyone!</span>")
return
return FALSE
if(L != src && check_shields(L, rand(1, 3), "the [L.name]"))
return FALSE
L.do_attack_animation(src)
if(prob(90))
log_combat(L, src, "attacked")
@@ -301,24 +391,29 @@
else
visible_message("<span class='danger'>[L.name] has attempted to bite [src]!</span>", \
"<span class='userdanger'>[L.name] has attempted to bite [src]!</span>", null, COMBAT_MESSAGE_RANGE)
return FALSE
/mob/living/attack_alien(mob/living/carbon/alien/humanoid/M)
if((M != src) && M.a_intent != INTENT_HELP && check_shields(M, 0, "the [M.name]"))
visible_message("<span class='danger'>[M] attempted to touch [src]!</span>")
return FALSE
switch(M.a_intent)
if ("help")
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
if (INTENT_HELP)
if(!isalien(src)) //I know it's ugly, but the alien vs alien attack_alien behaviour is a bit different.
visible_message("<span class='notice'>[M] caresses [src] with its scythe like arm.</span>")
return FALSE
if ("grab")
if (INTENT_GRAB)
grabbedby(M)
return FALSE
if("harm")
if(INTENT_HARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt anyone!</span>")
return FALSE
M.do_attack_animation(src)
if(!isalien(src))
M.do_attack_animation(src)
return TRUE
if("disarm")
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if(INTENT_DISARM)
if(!isalien(src))
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
return TRUE
/mob/living/ex_act(severity, target, origin)
@@ -1,15 +1,9 @@
/mob/living/silicon/ai/attacked_by(obj/item/I, mob/living/user, def_zone)
. = ..()
if(!.)
return FALSE
if(I.force && I.damtype != STAMINA && stat != DEAD) //only sparks if real damage is dealt.
spark_system.start()
return ..()
/mob/living/silicon/ai/attack_alien(mob/living/carbon/alien/humanoid/M)
if(!SSticker.HasRoundStarted())
to_chat(M, "You cannot attack people before the game has started.")
return
..()
/mob/living/silicon/ai/attack_slime(mob/living/simple_animal/slime/user)
return //immune to slimes
@@ -26,13 +26,14 @@
fold_in(force = 1)
Knockdown(200)
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/pai/attack_hand(mob/living/carbon/human/user)
switch(user.a_intent)
if("help")
if(INTENT_HELP)
visible_message("<span class='notice'>[user] gently pats [src] on the head, eliciting an off-putting buzzing from its holographic field.</span>")
if("disarm")
if(INTENT_DISARM)
visible_message("<span class='notice'>[user] boops [src] on the head!</span>")
if("harm")
if(INTENT_HARM)
user.do_attack_animation(src)
if (user.name == master)
visible_message("<span class='notice'>Responding to its master's touch, [src] disengages its holochassis emitter, rapidly losing coherence.</span>")
@@ -41,14 +42,19 @@
if(user.put_in_hands(card))
user.visible_message("<span class='notice'>[user] promptly scoops up [user.p_their()] pAI's card.</span>")
else
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
return
visible_message("<span class='danger'>[user] stomps on [src]!.</span>")
take_holo_damage(2)
else
grabbedby(user)
/mob/living/silicon/pai/bullet_act(obj/item/projectile/Proj)
if(Proj.stun)
/mob/living/silicon/pai/bullet_act(obj/item/projectile/P, def_zone)
if(P.stun)
fold_in(force = TRUE)
src.visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
. = ..(Proj)
visible_message("<span class='warning'>The electrically-charged projectile disrupts [src]'s holomatrix, forcing [src] to fold in!</span>")
. = ..()
/mob/living/silicon/pai/stripPanelUnequip(obj/item/what, mob/who, where) //prevents stripping
to_chat(src, "<span class='warning'>Your holochassis stutters and warps intensely as you attempt to interact with the object, forcing you to cease lest the field fail.</span>")
@@ -13,7 +13,19 @@
spark_system.start()
return ..()
/mob/living/silicon/robot/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
. = ..()
if(.)
spark_system.start()
spawn(0)
step_away(src,user,15)
sleep(3)
step_away(src,user,15)
/mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/humanoid/M)
. = ..()
if(!.) // the attack was blocked or was help/grab intent
return
if (M.a_intent == INTENT_DISARM)
if(!(lying))
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
@@ -30,24 +42,19 @@
visible_message("<span class='danger'>[M] has forced back [src]!</span>", \
"<span class='userdanger'>[M] has forced back [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/pierce.ogg', 50, 1, -1)
else
..()
return
/mob/living/silicon/robot/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime shock
flash_act()
var/stunprob = M.powerlevel * 7 + 10
if(prob(stunprob) && M.powerlevel >= 8)
adjustBruteLoss(M.powerlevel * rand(6,10))
var/damage = rand(1, 3)
. = ..()
if(!.) //unsuccessful slime shock
return
var/stunprob = M.powerlevel * 7 + 10
var/damage = M.powerlevel * rand(6,10)
if(prob(stunprob) && M.powerlevel >= 8)
flash_act(affect_silicon = TRUE) //my borg eyes!
if(M.is_adult)
damage = rand(20, 40)
damage += rand(10, 20)
else
damage = rand(5, 35)
damage = round(damage / 2) // borgs receive half damage
damage += rand(2, 17)
adjustBruteLoss(damage)
updatehealth()
@@ -56,23 +63,17 @@
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/robot/attack_hand(mob/living/carbon/human/user)
add_fingerprint(user)
if(opened && !wiresexposed && !issilicon(user))
if(cell)
cell.update_icon()
cell.add_fingerprint(user)
user.put_in_active_hand(cell)
to_chat(user, "<span class='notice'>You remove \the [cell].</span>")
cell = null
update_icons()
diag_hud_set_borgcell()
if(opened && !wiresexposed && cell && !issilicon(user))
cell.update_icon()
cell.add_fingerprint(user)
user.put_in_active_hand(cell)
to_chat(user, "<span class='notice'>You remove \the [cell].</span>")
cell = null
update_icons()
diag_hud_set_borgcell()
if(!opened)
if(..()) // hulk attack
spark_system.start()
spawn(0)
step_away(src,user,15)
sleep(3)
step_away(src,user,15)
return ..()
/mob/living/silicon/robot/fire_act()
if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them
@@ -182,9 +183,9 @@
if (stat != DEAD)
adjustBruteLoss(30)
/mob/living/silicon/robot/bullet_act(var/obj/item/projectile/Proj)
..(Proj)
/mob/living/silicon/robot/bullet_act(obj/item/projectile/P, def_zone)
..()
updatehealth()
if(prob(75) && Proj.damage > 0)
if(prob(75) && P.damage > 0)
spark_system.start()
return 2
@@ -6,7 +6,10 @@
return 2
/mob/living/silicon/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent
. = ..()
if(!.) // the attack was blocked or was help/grab intent
return
if(M.a_intent == INTENT_HARM)
var/damage = 20
if (prob(90))
log_combat(M, src, "attacked")
@@ -49,34 +52,33 @@
/mob/living/silicon/attack_paw(mob/living/user)
return attack_hand(user)
/mob/living/silicon/attack_larva(mob/living/carbon/alien/larva/L)
if(L.a_intent == INTENT_HELP)
visible_message("[L.name] rubs its head against [src].")
/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
/mob/living/silicon/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
..(user, 1)
. = ..(user, TRUE)
if(.)
return
adjustBruteLoss(rand(10, 15))
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has punched [src]!</span>", \
"<span class='userdanger'>[user] has punched [src]!</span>")
return 1
return 0
return TRUE
return FALSE
//ATTACK HAND IGNORING PARENT RETURN VALUE
/mob/living/silicon/attack_hand(mob/living/carbon/human/M)
. = ..()
if(.) //the attack was blocked
return
switch(M.a_intent)
if ("help")
if (INTENT_HELP)
M.visible_message("[M] pets [src].", \
"<span class='notice'>You pet [src].</span>")
if("grab")
if(INTENT_GRAB)
grabbedby(M)
else
M.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
playsound(src.loc, 'sound/effects/bang.ogg', 10, 1)
visible_message("<span class='danger'>[M] punches [src], but doesn't leave a dent.</span>", \
"<span class='warning'>[M] punches [src], but doesn't leave a dent.</span>", null, COMBAT_MESSAGE_RANGE)
return 0
/mob/living/silicon/attack_drone(mob/living/simple_animal/drone/M)
if(M.a_intent == INTENT_HARM)
@@ -108,19 +110,25 @@
M.visible_message("<span class='boldwarning'>[M] is thrown off of [src]!</span>")
flash_act(affect_silicon = 1)
/mob/living/silicon/bullet_act(obj/item/projectile/Proj)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
adjustBruteLoss(Proj.damage)
if(prob(Proj.damage*1.5))
/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
if(reflect_bullet_check(P, def_zone))
return -1 // complete projectile permutation
if(check_shields(P, P.damage, "the [P.name]", PROJECTILE_ATTACK, P.armour_penetration))
P.on_hit(src, 100, def_zone)
return 2
if((P.damage_type == BRUTE || P.damage_type == BURN))
adjustBruteLoss(P.damage)
if(prob(P.damage*1.5))
for(var/mob/living/M in buckled_mobs)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src]!</span>")
unbuckle_mob(M)
M.Knockdown(40)
if(Proj.stun || Proj.knockdown)
if(P.stun || P.knockdown)
for(var/mob/living/M in buckled_mobs)
unbuckle_mob(M)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [Proj]!</span>")
Proj.on_hit(src)
M.visible_message("<span class='boldwarning'>[M] is knocked off of [src] by the [P]!</span>")
P.on_hit(src)
return 2
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /obj/screen/fullscreen/flash/static)
@@ -1,20 +1,22 @@
/mob/living/simple_animal/attack_hand(mob/living/carbon/human/M)
..()
. = ..()
if(.) //the attack was blocked
return
switch(M.a_intent)
if("help")
if(INTENT_HELP)
if (health > 0)
visible_message("<span class='notice'>[M] [response_help] [src].</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
if("grab")
if(INTENT_GRAB)
if(grab_state >= GRAB_AGGRESSIVE && isliving(pulling))
vore_attack(M, pulling)
else
grabbedby(M)
if("harm", "disarm")
if(INTENT_HARM, INTENT_DISARM)
if(HAS_TRAIT(M, TRAIT_PACIFISM))
to_chat(M, "<span class='notice'>You don't want to hurt [src]!</span>")
return
@@ -27,12 +29,11 @@
updatehealth()
return TRUE
/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
/mob/living/simple_animal/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
to_chat(user, "<span class='notice'>You don't want to hurt [src]!</span>")
return FALSE
..(user, 1)
. = ..(user, TRUE)
if(.)
return
playsound(loc, "punch", 25, 1, -1)
visible_message("<span class='danger'>[user] has punched [src]!</span>", \
"<span class='userdanger'>[user] has punched [src]!</span>", null, COMBAT_MESSAGE_RANGE)
@@ -40,32 +41,32 @@
return TRUE
/mob/living/simple_animal/attack_paw(mob/living/carbon/monkey/M)
if(..()) //successful monkey bite.
if(stat != DEAD)
var/damage = rand(1, 3)
attack_threshold_check(damage)
return 1
. = ..()
if(.) //successful larva bite
var/damage = rand(1, 3)
attack_threshold_check(damage)
return 1
if (M.a_intent == INTENT_HELP)
if (health > 0)
visible_message("<span class='notice'>[M.name] [response_help] [src].</span>")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
/mob/living/simple_animal/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent.
if(M.a_intent == INTENT_DISARM)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
log_combat(M, src, "disarmed")
else
var/damage = rand(15, 30)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
attack_threshold_check(damage)
log_combat(M, src, "attacked")
return 1
. = ..()
if(!.) // the attack was blocked or was help/grab intent
return
if(M.a_intent == INTENT_DISARM)
playsound(loc, 'sound/weapons/pierce.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] [response_disarm] [name]!</span>", \
"<span class='userdanger'>[M] [response_disarm] [name]!</span>", null, COMBAT_MESSAGE_RANGE)
log_combat(M, src, "disarmed")
else
var/damage = rand(15, 30)
visible_message("<span class='danger'>[M] has slashed at [src]!</span>", \
"<span class='userdanger'>[M] has slashed at [src]!</span>", null, COMBAT_MESSAGE_RANGE)
playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1)
attack_threshold_check(damage)
log_combat(M, src, "attacked")
/mob/living/simple_animal/attack_larva(mob/living/carbon/alien/larva/L)
. = ..()
@@ -82,7 +83,8 @@
return attack_threshold_check(damage, M.melee_damage_type)
/mob/living/simple_animal/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
. = ..()
if(.) //successful slime shock
var/damage = rand(15, 25)
if(M.is_adult)
damage = rand(20, 35)
@@ -113,7 +113,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
mode = BOT_HUNT
/mob/living/simple_animal/bot/honkbot/attack_hand(mob/living/carbon/human/H)
if(H.a_intent == "harm")
if(H.a_intent == INTENT_HARM)
retaliate(H)
addtimer(CALLBACK(src, .proc/react_buzz), 5)
return ..()
@@ -232,9 +232,9 @@
/mob/living/simple_animal/pet/cat/attack_hand(mob/living/carbon/human/M)
. = ..()
switch(M.a_intent)
if("help")
if(INTENT_HELP)
wuv(1, M)
if("harm")
if(INTENT_HARM)
wuv(-1, M)
/mob/living/simple_animal/pet/cat/proc/wuv(change, mob/M)
@@ -290,7 +290,9 @@
D.decorate_donut()
/mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L)
..()
. = ..()
if(.) //the attack was blocked
return
if(L.a_intent == INTENT_HARM && L.reagents && !stat)
L.reagents.add_reagent(/datum/reagent/consumable/nutriment, 0.4)
L.reagents.add_reagent(/datum/reagent/consumable/nutriment/vitamin, 0.4)
@@ -643,9 +643,9 @@
/mob/living/simple_animal/pet/dog/attack_hand(mob/living/carbon/human/M)
. = ..()
switch(M.a_intent)
if("help")
if(INTENT_HELP)
wuv(1,M)
if("harm")
if(INTENT_HARM)
wuv(-1,M)
/mob/living/simple_animal/pet/dog/proc/wuv(change, mob/M)
@@ -31,9 +31,9 @@
//picky up the drone c:
/mob/living/simple_animal/drone/attack_hand(mob/user)
..()
if(user.a_intent == INTENT_HELP)
mob_try_pickup(user)
if(user.a_intent != INTENT_HELP)
return ..() // TODO: convert picking up mobs into an element or component.
mob_try_pickup(user)
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
var/mob/dead/observer/G = get_ghost()
@@ -54,10 +54,8 @@
var/blocked = FALSE
if(hasmatchingsummoner(A)) //if the summoner matches don't hurt them
blocked = TRUE
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
blocked = TRUE
if(L.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
blocked = TRUE
if(!blocked)
L.drop_all_held_items()
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] slams into you!</span>")
@@ -25,7 +25,7 @@
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
var/list/crusher_loot
var/medal_type
var/score_type = BOSS_SCORE
@@ -166,7 +166,9 @@
..()
/mob/living/simple_animal/hostile/mushroom/attack_hand(mob/living/carbon/human/M)
..()
. = ..()
if(.) // the attack was blocked
return
if(M.a_intent == INTENT_HARM)
Bruise()
@@ -253,33 +253,34 @@
return
/mob/living/simple_animal/slime/attack_slime(mob/living/simple_animal/slime/M)
if(..()) //successful slime attack
if(M == src)
return
if(buckled)
Feedstop(silent = TRUE)
visible_message("<span class='danger'>[M] pulls [src] off!</span>")
return
attacked += 5
if(nutrition >= 100) //steal some nutrition. negval handled in life()
nutrition -= (50 + (40 * M.is_adult))
M.add_nutrition(50 + (40 * M.is_adult))
if(health > 0)
M.adjustBruteLoss(-10 + (-10 * M.is_adult))
M.updatehealth()
. = ..()
if(!. || M == src) //unsuccessful slime shock
return
if(buckled)
Feedstop(silent = TRUE)
visible_message("<span class='danger'>[M] pulls [src] off!</span>")
return
attacked += 5
if(nutrition >= 100) //steal some nutrition. negval handled in life()
nutrition -= (50 + (40 * M.is_adult))
M.add_nutrition(50 + (40 * M.is_adult))
if(health > 0)
M.adjustBruteLoss(-10 + (-10 * M.is_adult))
M.updatehealth()
/mob/living/simple_animal/slime/attack_animal(mob/living/simple_animal/M)
. = ..()
if(.)
attacked += 10
/mob/living/simple_animal/slime/attack_paw(mob/living/carbon/monkey/M)
if(..()) //successful monkey bite.
. = ..()
if(.)//successful monkey bite.
attacked += 10
/mob/living/simple_animal/slime/attack_larva(mob/living/carbon/alien/larva/L)
if(..()) //successful larva bite.
. = ..()
if(.) //successful larva bite.
attacked += 10
/mob/living/simple_animal/slime/attack_hulk(mob/living/carbon/human/user, does_attack_animation = 0)
@@ -321,9 +322,11 @@
attacked += 10
/mob/living/simple_animal/slime/attack_alien(mob/living/carbon/alien/humanoid/M)
if(..()) //if harm or disarm intent.
attacked += 10
discipline_slime(M)
. = ..()
if(!.) // the attack was blocked or was help/grab intent
return
attacked += 10
discipline_slime(M)
/mob/living/simple_animal/slime/attackby(obj/item/W, mob/living/user, params)
+5
View File
@@ -459,6 +459,11 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
if(!ckey || !new_mob)
CRASH("transfer_ckey() called [ckey ? "" : "on a ckey-less mob[new_mob ? "" : " and "]"][new_mob ? "" : "without a valid mob target"]!")
SEND_SIGNAL(new_mob, COMSIG_MOB_PRE_PLAYER_CHANGE, new_mob, src)
if (client && client.prefs && client.prefs.auto_ooc)
if (client.prefs.chat_toggles & CHAT_OOC && isliving(new_mob))
client.prefs.chat_toggles ^= CHAT_OOC
if (!(client.prefs.chat_toggles & CHAT_OOC) && isdead(new_mob))
client.prefs.chat_toggles ^= CHAT_OOC
new_mob.ckey = ckey
if(send_signal)
SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src)
@@ -26,10 +26,9 @@ Contents:
/obj/item/clothing/suit/space/space_ninja/proc/enable_signals()
if(!affecting)
return
RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth)
RegisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE), .proc/reduce_stealth)
RegisterSignal(affecting, COMSIG_MOVABLE_BUMP, .proc/bumping_stealth)
/obj/item/clothing/suit/space/space_ninja/proc/reduce_stealth(datum/source)
affecting.alpha = min(affecting.alpha + 40, 100)
@@ -42,7 +41,7 @@ Contents:
return FALSE
stealth = !stealth
stealth_cooldown = world.time + 5 SECONDS
UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE))
UnregisterSignal(affecting, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_MOB_ATTACK_RANGED, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_MOB_ATTACK_HAND, COMSIG_MOB_THROW, COMSIG_PARENT_ATTACKBY, COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_TELEPORTED, COMSIG_LIVING_GUN_PROCESS_FIRE))
animate(affecting, alpha = 255, time = 3 SECONDS)
affecting.visible_message("<span class='warning'>[affecting.name] appears from thin air!</span>", \
"<span class='notice'>You are now visible.</span>")
+1 -1
View File
@@ -102,7 +102,7 @@
/obj/item/paperplane/throw_impact(atom/hit_atom)
if(iscarbon(hit_atom))
var/mob/living/carbon/C = hit_atom
if(C.can_catch_item(TRUE))
if(!C.get_active_held_item() && !C.restrained())
var/datum/action/innate/origami/origami_action = locate() in C.actions
if(origami_action?.active) //if they're a master of origami and have the ability turned on, force throwmode on so they'll automatically catch the plane.
C.throw_mode_on()
@@ -260,7 +260,7 @@
if(!amount)
return
vol_each = min(reagents.total_volume / amount, 50)
var/name = stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/pill/P
@@ -287,7 +287,7 @@
adjust_item_drop_location(P)
reagents.trans_to(P,vol_each)
else
var/name = stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location())
@@ -313,7 +313,7 @@
if(!amount)
return
vol_each = min(reagents.total_volume / amount, 40)
var/name = stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/pill/P
@@ -331,7 +331,7 @@
return
if(condi)
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/food/condiment/P = new(drop_location())
@@ -344,7 +344,7 @@
if(text2num(many))
amount_full = round(reagents.total_volume / 30)
vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals.
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
@@ -372,7 +372,7 @@
if(text2num(many))
amount_full = round(reagents.total_volume / 60)
vol_part = reagents.total_volume % 60
var/name = stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
@@ -407,7 +407,7 @@
return
vol_each = min(reagents.total_volume / amount, 20)
var/name = stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
var/name = html_decode(stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
@@ -230,6 +230,22 @@
. = 1
..()
/datum/reagent/consumable/coconutmilk
name = "Coconut Milk"
description = "A transparent white liquid extracted from coconuts. Rich in taste."
color = "#DFDFDF" // rgb: 223, 223, 223
taste_description = "sweet milk"
quality = DRINK_GOOD
glass_icon_state = "glass_white"
glass_name = "glass of coconut milk"
glass_desc = "White and nutritious goodness!"
/datum/reagent/consumable/coconutmilk/on_mob_life(mob/living/carbon/M)
if(M.getBruteLoss() && prob(20))
M.heal_bodypart_damage(2,0, 0)
. = 1
..()
/datum/reagent/consumable/cream
name = "Cream"
description = "The fatty, still liquid part of milk. Why don't you mix this with sum scotch, eh?"
@@ -152,6 +152,16 @@
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/telescopiciv
name = "Telescopic IV Drip"
desc = "An IV drip with an advanced infusion pump that can both drain blood into and inject liquids from attached containers. Blood packs are processed at an accelerated rate. This one is telescopic, and can be picked up and put down."
id = "telescopiciv"
build_type = PROTOLATHE
materials = list(MAT_METAL = 5000, MAT_GLASS = 3500, MAT_SILVER = 1000)
build_path = /obj/item/tele_iv
category = list("Medical Designs")
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
/datum/design/holobarrier_med
name = "PENLITE holobarrier projector"
desc = "PENLITE holobarriers, a device that halts individuals with malicious diseases."
@@ -25,6 +25,20 @@
program_type = /datum/nanite_program/viral
category = list("Utility Nanites")
/datum/design/nanites/research
name = "Distributed Computing"
desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
id = "research_nanites"
program_type = /datum/nanite_program/research
category = list("Utility Nanites")
/datum/design/nanites/researchplus
name = "Neural Network"
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts. Can be overloaded to increase research output."
id = "researchplus_nanites"
program_type = /datum/nanite_program/researchplus
category = list("Utility Nanites")
/datum/design/nanites/monitoring
name = "Monitoring"
desc = "The nanites monitor the host's vitals and location, sending them to the suit sensor network."
@@ -39,6 +53,13 @@
program_type = /datum/nanite_program/triggered/self_scan
category = list("Utility Nanites")
/datum/design/nanites/dermal_button
name = "Dermal Button"
desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
id = "dermal_button_nanites"
program_type = /datum/nanite_program/dermal_button
category = list("Utility Nanites")
/datum/design/nanites/stealth
name = "Stealth"
desc = "The nanites hide their activity and programming from superficial scans."
@@ -46,6 +67,15 @@
program_type = /datum/nanite_program/stealth
category = list("Utility Nanites")
/datum/design/nanites/reduced_diagnostics
name = "Reduced Diagnostics"
desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
Doing so saves some power, slightly increasing their replication speed."
id = "red_diag_nanites"
program_type = /datum/nanite_program/reduced_diagnostics
category = list("Utility Nanites")
/datum/design/nanites/access
name = "Subdermal ID"
desc = "The nanites store the host's ID access rights in a subdermal magnetic strip. Updates when triggered, copying the host's current access."
@@ -130,7 +130,7 @@
/datum/nanite_program/stealth
name = "Stealth"
desc = "The nanites hide their activity and programming from superficial scans."
desc = "The nanites mask their activity from superficial scans, becoming undetectable by HUDs and non-specialized scanners."
rogue_types = list(/datum/nanite_program/toxic)
use_rate = 0.2
@@ -142,6 +142,22 @@
. = ..()
nanites.stealth = FALSE
/datum/nanite_program/reduced_diagnostics
name = "Reduced Diagnostics"
desc = "Disables some high-cost diagnostics in the nanites, making them unable to communicate their program list to portable scanners. \
Doing so saves some power, slightly increasing their replication speed."
rogue_types = list(/datum/nanite_program/toxic)
use_rate = -0.1
/datum/nanite_program/reduced_diagnostics/enable_passive_effect()
. = ..()
nanites.diagnostics = FALSE
/datum/nanite_program/reduced_diagnostics/disable_passive_effect()
. = ..()
nanites.diagnostics = TRUE
/datum/nanite_program/relay
name = "Relay"
desc = "The nanites receive and relay long-range nanite signals."
@@ -271,3 +287,138 @@
if(fault == src)
return
fault.software_error()
/datum/nanite_program/dermal_button
name = "Dermal Button"
desc = "Displays a button on the host's skin, which can be used to send a signal to the nanites."
extra_settings = list("Sent Code","Button Name","Icon","Color")
unique = FALSE
var/datum/action/innate/nanite_button/button
var/button_name = "Button"
var/icon = "power"
var/color = "green"
var/sent_code = 0
/datum/nanite_program/dermal_button/set_extra_setting(user, setting)
if(setting == "Sent Code")
var/new_code = input(user, "Set the sent code (1-9999):", name, null) as null|num
if(isnull(new_code))
return
sent_code = CLAMP(round(new_code, 1), 1, 9999)
if(setting == "Button Name")
var/new_button_name = stripped_input(user, "Choose the name for the button.", "Button Name", button_name, MAX_NAME_LEN)
if(!new_button_name)
return
button_name = new_button_name
if(setting == "Icon")
var/new_icon = input("Select the icon to display on the button:", name) as null|anything in list("one","two","three","four","five","plus","minus","power")
if(!new_icon)
return
icon = new_icon
if(setting == "Color")
var/new_color = input("Select the color of the button's icon:", name) as null|anything in list("green","red","yellow","blue")
if(!new_color)
return
color = new_color
/datum/nanite_program/dermal_button/get_extra_setting(setting)
if(setting == "Sent Code")
return sent_code
if(setting == "Button Name")
return button_name
if(setting == "Icon")
return capitalize(icon)
if(setting == "Color")
return capitalize(color)
/datum/nanite_program/dermal_button/copy_extra_settings_to(datum/nanite_program/dermal_button/target)
target.sent_code = sent_code
target.button_name = button_name
target.icon = icon
target.color = color
/datum/nanite_program/dermal_button/enable_passive_effect()
. = ..()
if(!button)
button = new(src, button_name, icon, color)
button.target = host_mob
button.Grant(host_mob)
/datum/nanite_program/dermal_button/disable_passive_effect()
. = ..()
if(button)
button.Remove(host_mob)
/datum/nanite_program/dermal_button/on_mob_remove()
. = ..()
qdel(button)
/datum/nanite_program/dermal_button/proc/press()
if(activated)
host_mob.visible_message("<span class='notice'>[host_mob] presses a button on [host_mob.p_their()] forearm.</span>",
"<span class='notice'>You press the nanite button on your forearm.</span>", null, 2)
SEND_SIGNAL(host_mob, COMSIG_NANITE_SIGNAL, sent_code, "a [name] program")
/datum/action/innate/nanite_button
name = "Button"
icon_icon = 'icons/mob/actions/actions_items.dmi'
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
button_icon_state = "power_green"
var/datum/nanite_program/dermal_button/program
/datum/action/innate/nanite_button/New(datum/nanite_program/dermal_button/_program, _name, _icon, _color)
..()
program = _program
name = _name
button_icon_state = "[_icon]_[_color]"
/datum/action/innate/nanite_button/Activate()
program.press()
/datum/nanite_program/research
name = "Distributed Computing"
desc = "The nanites aid the research servers by performing a portion of its calculations, increasing research point generation."
use_rate = 0.2
rogue_types = list(/datum/nanite_program/toxic)
/datum/nanite_program/research/active_effect()
if(!iscarbon(host_mob))
return
var/points = 1
if(!host_mob.client) //less brainpower
points *= 0.25
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
/datum/nanite_program/researchplus
name = "Neural Network"
desc = "The nanites link the host's brains together forming a neural research network, that becomes more efficient with the amount of total hosts."
use_rate = 0.3
rogue_types = list(/datum/nanite_program/brain_decay)
/datum/nanite_program/researchplus/enable_passive_effect()
. = ..()
if(!iscarbon(host_mob))
return
if(host_mob.client)
SSnanites.neural_network_count++
else
SSnanites.neural_network_count += 0.25
/datum/nanite_program/researchplus/disable_passive_effect()
. = ..()
if(!iscarbon(host_mob))
return
if(host_mob.client)
SSnanites.neural_network_count--
else
SSnanites.neural_network_count -= 0.25
/datum/nanite_program/researchplus/active_effect()
if(!iscarbon(host_mob))
return
var/mob/living/carbon/C = host_mob
var/points = round(SSnanites.neural_network_count / 12, 0.1)
if(!C.client) //less brainpower
points *= 0.25
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = points))
+13 -1
View File
@@ -130,4 +130,16 @@
program_type = /datum/nanite_program/pacifying
/obj/item/disk/nanite_program/stun
program_type = /datum/nanite_program/triggered/stun
program_type = /datum/nanite_program/triggered/stun
/obj/item/disk/nanite_program/dermal_button
program_type = /datum/nanite_program/dermal_button
/obj/item/disk/nanite_program/research
program_type = /datum/nanite_program/research
/obj/item/disk/nanite_program/researchplus
program_type = /datum/nanite_program/researchplus
/obj/item/disk/nanite_program/reduced_diagnostics
program_type = /datum/nanite_program/reduced_diagnostics
+5 -5
View File
@@ -71,7 +71,7 @@
display_name = "Biological Technology"
description = "What makes us tick." //the MC, silly!
prereq_ids = list("base")
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen")
design_ids = list("medicalkit", "chem_heater", "chem_master", "chem_dispenser", "sleeper", "vr_sleeper", "pandemic", "defibmount", "operating", "soda_dispenser", "beer_dispenser", "healthanalyzer", "blood_bag", "bloodbankgen", "telescopiciv")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -960,7 +960,7 @@
prereq_ids = list("datatheory","robotics")
design_ids = list("nanite_disk","nanite_remote","nanite_scanner",\
"nanite_chamber","public_nanite_chamber","nanite_chamber_control","nanite_programmer","nanite_program_hub","nanite_cloud_control",\
"relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites")
"relay_nanites", "monitoring_nanites", "access_nanites", "repairing_nanites","sensor_nanite_volume", "repeater_nanites", "relay_repeater_nanites","red_diag_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -969,7 +969,7 @@
display_name = "Smart Nanite Programming"
description = "Nanite programs that require nanites to perform complex actions, act independently, roam or seek targets."
prereq_ids = list("nanite_base","adv_robotics")
design_ids = list("purging_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
design_ids = list("purging_nanites", "research_nanites", "metabolic_nanites", "stealth_nanites", "memleak_nanites","sensor_voice_nanites", "voice_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2000)
export_price = 4000
@@ -978,7 +978,7 @@
display_name = "Mesh Nanite Programming"
description = "Nanite programs that require static structures and membranes."
prereq_ids = list("nanite_base","engineering")
design_ids = list("hardening_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
design_ids = list("hardening_nanites", "dermal_button_nanites", "refractive_nanites", "cryo_nanites", "conductive_nanites", "shock_nanites", "emp_nanites", "temperature_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
export_price = 5000
@@ -1015,7 +1015,7 @@
display_name = "Harmonic Nanite Programming"
description = "Nanite programs that require seamless integration between nanites and biology."
prereq_ids = list("nanite_bio","nanite_smart","nanite_mesh")
design_ids = list("fakedeath_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
design_ids = list("fakedeath_nanites","researchplus_nanites","aggressive_nanites","defib_nanites","regenerative_plus_nanites","brainheal_plus_nanites","purging_plus_nanites","adrenaline_nanites")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 4000)
export_price = 8000
+1
View File
@@ -14,6 +14,7 @@
/obj/item/seeds/chanter = 3,
/obj/item/seeds/chili = 3,
/obj/item/seeds/cocoapod = 3,
/obj/item/seeds/coconut = 3,
/obj/item/seeds/coffee = 3,
/obj/item/seeds/cotton = 3,
/obj/item/seeds/corn = 3,
+322
View File
@@ -50,6 +50,328 @@
-->
<div class="commit sansserif">
<h2 class="date">30 December 2019</h2>
<h3 class="author">AnturK updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed ranged syndicate mobs stormtrooper training.</li>
</ul>
<h3 class="author">Arturlang updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds Bloodsuckers, beware.</li>
</ul>
<h3 class="author">BlueWildrose updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed stargazers being unable to link to themselves if mindshielded or if holding psionic shielding devices (tinfoil hats) when the species is set.</li>
<li class="bugfix">Fixes non-roundstart slimes being unable to wag their tail.</li>
</ul>
<h3 class="author">Commandersand updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">added two words to clown filter</li>
<li class="rscadd">Added new things to loadouts, check em</li>
</ul>
<h3 class="author">DeltaFire15 updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Clock cult kindle no longer cares about oxygen damage</li>
<li class="tweak">changed mecha internals access for some special mechs.</li>
<li class="tweak">no more mech maintenance access for engineers.</li>
<li class="tweak">All heads of staff can now message CC</li>
<li class="code_imp">Removes a magicnumber</li>
<li class="balance">Rebalanced cult vs cult stun effects to debuff instead of stun</li>
</ul>
<h3 class="author">Detective-Google updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">short hair 80's is no longer jank</li>
</ul>
<h3 class="author">Fermis updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">tweaked how super bases/acids work but limiting them</li>
</ul>
<h3 class="author">Fikou updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">the windup toolbox now has some more "realistic" sounds</li>
<li class="bugfix">the windup toolbox now rumbles again</li>
</ul>
<h3 class="author">Ghommie updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed hulks, sleeping carp users, pacifists and people with chunky fingers being able to unrestrictly use gun and pneumatic cannon circuit assemblies.</li>
<li class="bugfix">Fixed gun circuit assemblies being only usable by human mobs.</li>
<li class="balance">Doubled the locomotion circuit external cooldown, thus halving the movable assemblies' movespeed.</li>
<li class="tweak">Made wooden cabinet/closets... actually made of wood.</li>
<li class="tweak">Wooden cabinets are now deconstructable with a screwdriver.</li>
<li class="tweak">Deconstruction of large crates and other closet subtypes deconstructable with tools other than the welder is no longer instant.</li>
<li class="tweak">You shouldn't be able to target objects you can't see (excluding darkness) with the ARCD and RLD</li>
<li class="tweak">The admin RCD is ranged too, just like the ARCD.</li>
<li class="bugfix">Fixed welding, thirteen loko, welding and wraith spectacles not blinding people as expected. Thank you all whomst reported this issue in the suggestions box channel instead of the github repository's issues section, very smart!</li>
<li class="bugfix">Fixed on_mob eyes overlays not updating properly in certain cases.</li>
<li class="bugfix">Fixed deconversion from bloodshot eyes blood cult resetting your eyes' color to pitch black instead of their previous color, more or less.</li>
<li class="balance">Spinfusor nerf: Upped the casing and ammo box size by one step, removed the projectile's dismemberment value (explosions can still rip a limb or two off), halved the ammo box capacity, reduced the spinfusor ammo supply pack contents from 32 to 8, removed the casing's ability to explode when thrown.</li>
<li class="bugfix">Fixes bubblegum's death not unlocking the arena shuttle buyment.</li>
<li class="bugfix">Fixed alien tech node not being unlockable with subtypes of the accepted items.</li>
<li class="bugfix">Fixed reactive armor onmob overlays not updating when toggled and reactive teleport armor still using forceMove() instead of do_teleport()</li>
<li class="bugfix">Fixed space hermit asteroid rocks unintendedly spawning airless asteroid turf when mined, save for the perimeter.</li>
<li class="bugfix">Fixes reviver implant having been a crapshot ever since soft-crit was introduced years ago.</li>
<li class="tweak">Added a "convalescence" time (about 15 seconds) after the user is out of unconsciousbess/crit to ensure they are properly stabilized.</li>
<li class="tweak">Added a 15 minutes hardcap for accumulated revive cooldown (equivalent to 150 points of brute or burn healed) above which the implant starts cooling down regardless of user's conditions.</li>
<li class="bugfix">Fixed AI core displays I may have broken with my coding extravaganza.</li>
<li class="soundadd">Blue, Amber and Red security alert sounds should be half as loud now.</li>
<li class="balance">Buffed clown ops by removing their clumsiness and adding a new trait to be used in place of several clown role checks.</li>
<li class="tweak">Clown ops too also suffer from not holding or wearing clown shoes now.</li>
<li class="bugfix">Fixed a few holo barriers lacking transparency.</li>
<li class="bugfix">Fixed character setup preview bodyparts not displaying correctly most of times.</li>
<li class="bugfix">Fixed character appearance preview displaying the mannequin in job attire instead of undergarments.</li>
<li class="bugfix">Fixed raven's shuttle computer not being of the emergency shuttle type.</li>
<li class="tweak">Blood bank generators can now be anchored and unanchored now.</li>
<li class="admin">Ghost mentors can now orbit around the target instead of setting their view to theirs'.</li>
<li class="bugfix">Fixes a ghostchat eavesdropping exploit concerning VR.</li>
<li class="bugfix">Fixes VR deaths being broadcasted in deadchat.</li>
<li class="bugfix">Fixed a few pill bottle issues with the ChemMaster.</li>
<li class="bugfix">Fixes a few negative quirks not being properly removed when deleted.</li>
<li class="tweak">Phobia and mute quirks are no longer cheesed by brain surgery grade healing or medicines.</li>
<li class="bugfix">Fixed double-flavour (and bland custom) ice creams.</li>
<li class="bugfix">Fixed Pubbystation's wall Nanomeds being inconsistent with other stations'.</li>
<li class="bugfix">dextrous simplemobs can now swap action intent with 1, 2, 3, 4 now. Just like humies, ayys and monkys.</li>
<li class="bugfix">Stops humanoids whose skin_tone variable is set to "albino" from showing up as pale when examined should their species not use skintones anyway.</li>
<li class="rscdel">Removed the old (almost) unused roboticist encryption key and headset.</li>
<li class="bugfix">Fixed goose meat.</li>
<li class="bugfix">Fixed a little door assembly glass dupe exploit</li>
<li class="bugfix">Fixed AI holopad speech text being small and whispers that in multiple exclamation marks echo through multiple areas.</li>
<li class="rscdel">Removed literally atrocious polka dotted accessories. They were even more atrocious than the yellow horrible tie.</li>
</ul>
<h3 class="author">Ghommie (also porting PRs by AnturK and Arkatos) updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed light eaters not burning out borg lamplights and flashes. fix Fixed light eater not affecting open turfs emitting lights such as light tiles and fairy grass.</li>
<li class="bugfix">Fixed an empty reference about light eater armblade disintegration after Heart of Darkness removal.</li>
</ul>
<h3 class="author">Ghommie, Skogol updated:</h3>
<ul class="changes bgimages16">
<li class="refactor">refactored altclick interaction to allow alt-click interactable objects to parent call without forcing the turf contents stat menu open.</li>
<li class="tweak">Alt clicking will no longer show turf contents for items inside bags etc.</li>
<li class="tweak">Alt clicking the source of your turf contents stat menu will now close said menu.</li>
</ul>
<h3 class="author">GrayRachnid updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">fixes consistency</li>
</ul>
<h3 class="author">Hatterhat updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Regenerative nanites, a "chemical" used in the combat stimulant injector. Actually quite stimulating, and not bad in a pinch for a nuclear operative. Check the Combat Medic Kit!</li>
<li class="tweak">The Combat Medic Kit now has an advanced health analyzer and medisprays instead of patches and a chloral syringe.</li>
<li class="balance">The Advanced Syndicate Surgery Duffelbag or whatever it was doesn't get the better injector, because nobody uses it and so nobody's bothered to update it.</li>
<li class="rscadd">.357 speedloaders can now be printed with the Advanced Illegal Ballistics node on the tech tree!</li>
<li class="balance">okay so i may have given the .357 an extra speedloader at the same cost but it comes in a box now</li>
</ul>
<h3 class="author">ItzGabby updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed AltClick on polychromic collars so they actually work now.</li>
</ul>
<h3 class="author">KeRSedChaplain updated:</h3>
<ul class="changes bgimages16">
<li class="soundadd">Extends the file "deltakalaxon.ogg" to a 38 second .ogg.</li>
</ul>
<h3 class="author">Linzolle updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">neck slice. harm intent someone's head while they are unconscious or in a neck grab to make them bleed uncontrollably.</li>
<li class="bugfix">officer's sabre now properly makes the unsheating and resheating noise</li>
<li class="bugfix">fireman failure has a different message depending on the circumstance</li>
<li class="rscadd">Abductor chem dispenser, and added it to the abductor console.</li>
<li class="rscadd">"Superlingual matrix" to the abductor console. It's the abductor's tongue. Can be used to link it to your abductor communication channel and then implanted into a test subject.</li>
<li class="rscadd">Shrink ray and added it to the abductor console.</li>
<li class="soundadd">Shrink ray sound effect (its the fucking mega man death sound)</li>
<li class="rscadd">special jumpsuit for abductors</li>
<li class="imageadd">abductor jumpsuit, including digi version if a digitigrade person somehow manages to get their hands on it. sprites for the shrink ray and chem dispenser.</li>
<li class="rscadd">new glands to play with, including the all-access gland, the quantum gland, and the blood type randomiser.</li>
<li class="code_imp">split every gland into its own file instead of all being in one file</li>
<li class="tweak">cosmic coat crafting recipe changed to coat + cosmic bedsheet</li>
</ul>
<h3 class="author">Mickyan, nemvar, RaveRadbury, AnturK, SpaceManiac updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Certain incompatible quirks can no longer be taken together.</li>
<li class="bugfix">If an admin sends a ghost back to the lobby, they can now choose a different set of quirks.</li>
<li class="spellcheck">the quirk menu went through some minor formatting changes.</li>
<li class="bugfix">Podcloning now lets you keep your quirks.</li>
<li class="rscadd">Quirks have flavor text in medical records.</li>
<li class="spellcheck">All quirk medical records refer to "Patient", removing a few instances of "Subject".</li>
<li class="tweak">Quirks no longer apply to off-station roundstart antagonists.</li>
<li class="code_imp">Mood quirks are now only processed by the quirk holders</li>
</ul>
<h3 class="author">Narcissisko (ported by Hatterhat) updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Luxury Bar Capsule, at 10,000 points. Comes with no medical supplies, a bar, and a bunch of cigars. Ported from tgstation/tgstation#45547.</li>
</ul>
<h3 class="author">Nervere and subject217, Militaires, py01, nemvar updated:</h3>
<ul class="changes bgimages16">
<li class="balance">The cook's CQC now only works when in the kitchen or the kitchen backroom.</li>
<li class="spellcheck">corrected CQC help instructions</li>
<li class="bugfix">CQC and Sleeping Carp are properly logged.</li>
<li class="tweak">CQC can passively grab targets when not on grab intent. Passive grabs do not count towards combos for CQC or Sleeping carp.</li>
<li class="code_imp">Martial Art and NOGUN cleanup.</li>
</ul>
<h3 class="author">PersianXerxes updated:</h3>
<ul class="changes bgimages16">
<li class="rscdel">Removed night vision quirk</li>
</ul>
<h3 class="author">Putnam updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">acute hepatic pharmacokinesis now works if you already have relevant genitals</li>
<li class="balance">Contamination is no longer an infinitely spreading deadly contagion causing mass panic</li>
<li class="tweak">Dynamic rulesets have lower weight if a round recently featured them (except traitor).</li>
</ul>
<h3 class="author">Putnam3145 updated:</h3>
<ul class="changes bgimages16">
<li class="balance">Buffed HE pipes by making them realistically radiate away heat.</li>
<li class="bugfix">Dynamic has a (totally unused for any relevant purpose) roundstart report now.</li>
<li class="admin">A whole bunch of dynamic data is now available for statbus</li>
<li class="bugfix">Dynamic from-ghost antags no longer double dip on threat refunds when the mode fails due to not enough applications.</li>
<li class="bugfix">whoops broke quirks</li>
<li class="bugfix">quirks work</li>
<li class="rscadd">New tab in preferences screen: "ERP preferences"</li>
<li class="rscadd">New opt-outs for individual effects of incubus draught, succubus milk</li>
<li class="rscdel">Acute hepatic pharmacokinesis has been removed, replaced with above</li>
<li class="tweak">Renamed "Toggle Lewdchem" to "Toggle Lewd MKUltra", since that's what it actually means, and made it toggle the "hypno" setting (rename it again if more hypno mechanics are added).</li>
<li class="tweak">Made MKUltra's lewd messages require both people involved to have hypno opted-in.</li>
<li class="config">Buncha dynamic config tweaks</li>
<li class="bugfix">Ghost cafe spawns are actual ghost roles by the game's reckoning now</li>
<li class="bugfix">a runtime in radioactive contamination</li>
<li class="balance">Bomb armor now acts like other armor types.</li>
<li class="balance">Devastation-level explosions on armorless people no longer destroys everything in their bags.</li>
</ul>
<h3 class="author">Seris02 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">the clowns headset</li>
<li class="bugfix">distance checks</li>
<li class="bugfix">the sprites</li>
<li class="rscadd">added the runed and brass winter coats (cosmetic ratvarian/narsian)</li>
<li class="tweak">how the narsian/ratvarian coats can be made</li>
<li class="bugfix">fixes some ghost roles from dying of stupid shit</li>
<li class="bugfix">pandoras attacking their owners</li>
<li class="rscadd">Added Rising Bass and the shifting scroll.</li>
<li class="tweak">Changes the martial arts scroll in the uplink to "Sleeping Carp Scroll"</li>
</ul>
<h3 class="author">ShizCalev updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">Fixed floodlights not turning off properly when they're underpowered.</li>
<li class="bugfix">Fixed emitters not changing icons properly when they're underpowered.</li>
</ul>
<h3 class="author">Sishen1542 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Clicking a pack of seeds with a pen allows you to set the plant's name, description and the pack of seeds' description. Useful for differentiating genetically modified plants. These changes will persist through different generations of the plant.</li>
<li class="rscadd">Hydroponics trays update their name and description to reflect the plant inside them. They revert to default when emptied.</li>
</ul>
<h3 class="author">Toriate updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Polychromic shorts now have a digitigrade state</li>
</ul>
<h3 class="author">Trilbyspaceclone updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">ports all the new donuts, burgars, and chicken stuff from RG</li>
<li class="rscadd">ports new snowcone</li>
<li class="rscadd">ports grill</li>
<li class="rscadd">ports beakfeast tag/mood lit as TG has it</li>
<li class="rscadd">ports all the amazing new sprites</li>
<li class="tweak">ports crafting for many things like snowcones needing water</li>
<li class="balance">ports of many craftings</li>
<li class="soundadd">lowers fryers sound</li>
<li class="imageadd">ported icons for new food/grill</li>
<li class="imagedel">ports the deletion of some icons and images</li>
<li class="spellcheck">ports a spell check for the snowcones</li>
<li class="code_imp">ports fixes for stuff I didnt know were even broken with snowcones</li>
<li class="bugfix">coder cat failers to push the last commit from year(s) ago</li>
<li class="admin">Updates the changlogs</li>
<li class="tweak">meat hook from HUGE to bulky</li>
<li class="tweak">CE hardsuit is now more rad-proof</li>
<li class="bugfix">Wrong icon names, missing dog fashion with telegram hat</li>
<li class="rscadd">New softdrink that comes in its own vender!</li>
<li class="rscadd">Honey now has a reaction with plants</li>
<li class="tweak">Buzz fuzz now only has a 5% to give honey and will now give 1u of sugar not 2</li>
<li class="rscadd">Blaster shotguns back into armory</li>
<li class="rscdel">Removed Lighters in thunderdomes</li>
<li class="rscadd">Silicons now know what a slime is saying!</li>
<li class="balance">honey now will not kill slimes. Honey slimepeople can be a thing now, go sci.</li>
<li class="rscadd">Added insulin into many of the borg hypo's</li>
</ul>
<h3 class="author">Useroth updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">bamboo which can be used to build punji sticks/ blowguns available as a sugarcane mutation or in exotic seed crate</li>
<li class="tweak">changed the sugar cane growth stages because fuck if I know why, but it was in the PR</li>
<li class="rscadd">New lavaland ruin: Pulsating tumor</li>
<li class="rscadd">New class of lavaland mobs, a bit weaker than megafauna but still stronger than most of what you normally see</li>
<li class="rscadd">Ghost cafe spawner. For letting people spawn as their own character in the ninja holding facility. It bypasses the usual check, so people who have suicided/ghosted/cryod may use it.</li>
<li class="rscadd">Dorms in the ninja holding facility.</li>
</ul>
<h3 class="author">Xantholne updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Santa Hats to Loadout and Clothesmate</li>
<li class="rscadd">Christmas Wintercoats to Loadout and Clothesmate</li>
<li class="rscadd">Christmas male and female uniforms to loadout and Clothesmate</li>
<li class="rscadd">Red, Green, and Traditional Santa boots to loadout and Clothesmate</li>
<li class="rscadd">Christmas Socks, Red candycane socks, Green candycane socks to sock selection</li>
</ul>
<h3 class="author">kappa-sama updated:</h3>
<ul class="changes bgimages16">
<li class="balance">legion drops more crates now</li>
<li class="balance">.357 speedloaders in autolathes are now individual bullets instead, speedloaders are now illegal tech, costs less total metal to make 7 bullets than a previous speedloader. 7.62mm bullets in autolathe when hacked and costs more metal to make 5 7.62mm bullets than getting a clip from the seclathe.</li>
<li class="tweak">mentions that you can refill speedloaders on .357 uplink description</li>
<li class="bugfix">you can now strip people while aggrograbbing or higher</li>
<li class="rscadd">plasmafist to wizard</li>
<li class="code_imp">modular is gone</li>
<li class="rscadd">martial apprentices for the local Chinese wizard</li>
<li class="bugfix">broodmother baby lag</li>
<li class="balance">you can no longer get 100k credits by spending 4k roundstart</li>
<li class="balance">cooking oil in sunflowers instead of corn oil</li>
<li class="bugfix">throats are no longer slit happy</li>
</ul>
<h3 class="author">keronshb updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds reflector blobs to shield blob upgrades</li>
</ul>
<h3 class="author">kevinz000 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Launchpads can now take number inputs for offsets rather than just buttons.</li>
<li class="balance">nanites no longer spread through air blocking objects</li>
<li class="rscadd">Night vision readded as a darkness dampening effect rather than darksight.</li>
<li class="rscdel">conveyors can only stack items on tiles to 150 now.</li>
<li class="rscadd">added 8 character save slots</li>
<li class="rscadd">Cargo shuttle now silently ignores slaughter demons/revenants instead of being blocked even while they are jaunted. A drawback is that manifested ones can't block it either, any more.</li>
<li class="balance">flashbangs process light/sound separately and uses viewers(), so xray users beware.</li>
<li class="tweak">Stat() slowed down for anti-lag measures.</li>
<li class="bugfix">sprint/stamina huds now work again</li>
<li class="balance">Combat defibs now instant stun on disarm rather than 1 second again</li>
<li class="balance">Defibs are now always emagged when emagged with an emag rather than EMP.</li>
<li class="bugfix">aooc toggling now only broadcasts to antagonists</li>
<li class="code_imp">Antag rep proc is now easier to read and supports returning a list.</li>
<li class="balance">Clockwork marauders are now on a configured summon cooldown if being summoned on station. They also rapidly bleed health while in or next to space. And they glow brighter.</li>
</ul>
<h3 class="author">lolman360 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added ability to pick up certain simplemobs.</li>
</ul>
<h3 class="author">nemvar updated:</h3>
<ul class="changes bgimages16">
<li class="bugfix">The brains of roundstart borgs no longer decay.</li>
<li class="code_imp">Refactored the visibility of reagents for mobs.</li>
</ul>
<h3 class="author">nicbn, Kevinz000, ShizCalev updated:</h3>
<ul class="changes bgimages16">
<li class="tweak">Fire alarm is now simpler. Touch it to activate, touch it to deactivate. When activated, it will blink inconsistently if it is emagged.</li>
<li class="bugfix">You can no longer spam fire alarms. Also, they're logged again.</li>
<li class="bugfix">Fixed fire alarms not updating icons properly after being emagged and hacked by Malf AI's.</li>
</ul>
<h3 class="author">r4d6 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Added a N2O pressure tank</li>
<li class="rscdel">Removed a AM Shielding from the crate</li>
<li class="rscadd">Added Handshakes</li>
<li class="rscadd">Added Nose booping</li>
<li class="rscadd">Added submaps for the SM, Tesla and Singulo</li>
<li class="rscadd">Added a placeholder on Boxstation for the Engines</li>
<li class="bugfix">fixed Nose boops not triggering</li>
</ul>
<h3 class="author">shellspeed1 updated:</h3>
<ul class="changes bgimages16">
<li class="rscadd">Adds Insect markings</li>
<li class="rscadd">Adds three new moth wings.</li>
</ul>
<h2 class="date">07 December 2019</h2>
<h3 class="author">AffectedArc07 updated:</h3>
<ul class="changes bgimages16">
+324
View File
@@ -23656,3 +23656,327 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
- tweak: Supply ordered looms are unanchored. Bring a wrench.
r4d6:
- rscadd: Added Departements Winter Coats to the loadout list.
2019-12-30:
AnturK:
- bugfix: Fixed ranged syndicate mobs stormtrooper training.
Arturlang:
- rscadd: Adds Bloodsuckers, beware.
BlueWildrose:
- bugfix: Fixed stargazers being unable to link to themselves if mindshielded or
if holding psionic shielding devices (tinfoil hats) when the species is set.
- bugfix: Fixes non-roundstart slimes being unable to wag their tail.
Commandersand:
- tweak: added two words to clown filter
- rscadd: Added new things to loadouts, check em
DeltaFire15:
- balance: Clock cult kindle no longer cares about oxygen damage
- tweak: changed mecha internals access for some special mechs.
- tweak: no more mech maintenance access for engineers.
- tweak: All heads of staff can now message CC
- code_imp: Removes a magicnumber
- balance: Rebalanced cult vs cult stun effects to debuff instead of stun
Detective-Google:
- bugfix: short hair 80's is no longer jank
Fermis:
- tweak: tweaked how super bases/acids work but limiting them
Fikou:
- tweak: the windup toolbox now has some more "realistic" sounds
- bugfix: the windup toolbox now rumbles again
Ghommie:
- bugfix: Fixed hulks, sleeping carp users, pacifists and people with chunky fingers
being able to unrestrictly use gun and pneumatic cannon circuit assemblies.
- bugfix: Fixed gun circuit assemblies being only usable by human mobs.
- balance: Doubled the locomotion circuit external cooldown, thus halving the movable
assemblies' movespeed.
- tweak: Made wooden cabinet/closets... actually made of wood.
- tweak: Wooden cabinets are now deconstructable with a screwdriver.
- tweak: Deconstruction of large crates and other closet subtypes deconstructable
with tools other than the welder is no longer instant.
- tweak: You shouldn't be able to target objects you can't see (excluding darkness)
with the ARCD and RLD
- tweak: The admin RCD is ranged too, just like the ARCD.
- bugfix: Fixed welding, thirteen loko, welding and wraith spectacles not blinding
people as expected. Thank you all whomst reported this issue in the suggestions
box channel instead of the github repository's issues section, very smart!
- bugfix: Fixed on_mob eyes overlays not updating properly in certain cases.
- bugfix: Fixed deconversion from bloodshot eyes blood cult resetting your eyes'
color to pitch black instead of their previous color, more or less.
- balance: 'Spinfusor nerf: Upped the casing and ammo box size by one step, removed
the projectile''s dismemberment value (explosions can still rip a limb or two
off), halved the ammo box capacity, reduced the spinfusor ammo supply pack contents
from 32 to 8, removed the casing''s ability to explode when thrown.'
- bugfix: Fixes bubblegum's death not unlocking the arena shuttle buyment.
- bugfix: Fixed alien tech node not being unlockable with subtypes of the accepted
items.
- bugfix: Fixed reactive armor onmob overlays not updating when toggled and reactive
teleport armor still using forceMove() instead of do_teleport()
- bugfix: Fixed space hermit asteroid rocks unintendedly spawning airless asteroid
turf when mined, save for the perimeter.
- bugfix: Fixes reviver implant having been a crapshot ever since soft-crit was
introduced years ago.
- tweak: Added a "convalescence" time (about 15 seconds) after the user is out of
unconsciousbess/crit to ensure they are properly stabilized.
- tweak: Added a 15 minutes hardcap for accumulated revive cooldown (equivalent
to 150 points of brute or burn healed) above which the implant starts cooling
down regardless of user's conditions.
- bugfix: Fixed AI core displays I may have broken with my coding extravaganza.
- soundadd: Blue, Amber and Red security alert sounds should be half as loud now.
- balance: Buffed clown ops by removing their clumsiness and adding a new trait
to be used in place of several clown role checks.
- tweak: Clown ops too also suffer from not holding or wearing clown shoes now.
- bugfix: Fixed a few holo barriers lacking transparency.
- bugfix: Fixed character setup preview bodyparts not displaying correctly most
of times.
- bugfix: Fixed character appearance preview displaying the mannequin in job attire
instead of undergarments.
- bugfix: Fixed raven's shuttle computer not being of the emergency shuttle type.
- tweak: Blood bank generators can now be anchored and unanchored now.
- admin: Ghost mentors can now orbit around the target instead of setting their
view to theirs'.
- bugfix: Fixes a ghostchat eavesdropping exploit concerning VR.
- bugfix: Fixes VR deaths being broadcasted in deadchat.
- bugfix: Fixed a few pill bottle issues with the ChemMaster.
- bugfix: Fixes a few negative quirks not being properly removed when deleted.
- tweak: Phobia and mute quirks are no longer cheesed by brain surgery grade healing
or medicines.
- bugfix: Fixed double-flavour (and bland custom) ice creams.
- bugfix: Fixed Pubbystation's wall Nanomeds being inconsistent with other stations'.
- bugfix: dextrous simplemobs can now swap action intent with 1, 2, 3, 4 now. Just
like humies, ayys and monkys.
- bugfix: Stops humanoids whose skin_tone variable is set to "albino" from showing
up as pale when examined should their species not use skintones anyway.
- rscdel: Removed the old (almost) unused roboticist encryption key and headset.
- bugfix: Fixed goose meat.
- bugfix: Fixed a little door assembly glass dupe exploit
- bugfix: Fixed AI holopad speech text being small and whispers that in multiple
exclamation marks echo through multiple areas.
- rscdel: Removed literally atrocious polka dotted accessories. They were even more
atrocious than the yellow horrible tie.
Ghommie (also porting PRs by AnturK and Arkatos):
- bugfix: Fixed light eaters not burning out borg lamplights and flashes. fix Fixed
light eater not affecting open turfs emitting lights such as light tiles and
fairy grass.
- bugfix: Fixed an empty reference about light eater armblade disintegration after
Heart of Darkness removal.
Ghommie, Skogol:
- refactor: refactored altclick interaction to allow alt-click interactable objects
to parent call without forcing the turf contents stat menu open.
- tweak: Alt clicking will no longer show turf contents for items inside bags etc.
- tweak: Alt clicking the source of your turf contents stat menu will now close
said menu.
GrayRachnid:
- bugfix: fixes consistency
Hatterhat:
- rscadd: Regenerative nanites, a "chemical" used in the combat stimulant injector.
Actually quite stimulating, and not bad in a pinch for a nuclear operative.
Check the Combat Medic Kit!
- tweak: The Combat Medic Kit now has an advanced health analyzer and medisprays
instead of patches and a chloral syringe.
- balance: The Advanced Syndicate Surgery Duffelbag or whatever it was doesn't get
the better injector, because nobody uses it and so nobody's bothered to update
it.
- rscadd: .357 speedloaders can now be printed with the Advanced Illegal Ballistics
node on the tech tree!
- balance: okay so i may have given the .357 an extra speedloader at the same cost
but it comes in a box now
ItzGabby:
- bugfix: Fixed AltClick on polychromic collars so they actually work now.
KeRSedChaplain:
- soundadd: Extends the file "deltakalaxon.ogg" to a 38 second .ogg.
Linzolle:
- rscadd: neck slice. harm intent someone's head while they are unconscious or in
a neck grab to make them bleed uncontrollably.
- bugfix: officer's sabre now properly makes the unsheating and resheating noise
- bugfix: fireman failure has a different message depending on the circumstance
- rscadd: Abductor chem dispenser, and added it to the abductor console.
- rscadd: '"Superlingual matrix" to the abductor console. It''s the abductor''s
tongue. Can be used to link it to your abductor communication channel and then
implanted into a test subject.'
- rscadd: Shrink ray and added it to the abductor console.
- soundadd: Shrink ray sound effect (its the fucking mega man death sound)
- rscadd: special jumpsuit for abductors
- imageadd: abductor jumpsuit, including digi version if a digitigrade person somehow
manages to get their hands on it. sprites for the shrink ray and chem dispenser.
- rscadd: new glands to play with, including the all-access gland, the quantum gland,
and the blood type randomiser.
- code_imp: split every gland into its own file instead of all being in one file
- tweak: cosmic coat crafting recipe changed to coat + cosmic bedsheet
Mickyan, nemvar, RaveRadbury, AnturK, SpaceManiac:
- bugfix: Certain incompatible quirks can no longer be taken together.
- bugfix: If an admin sends a ghost back to the lobby, they can now choose a different
set of quirks.
- spellcheck: the quirk menu went through some minor formatting changes.
- bugfix: Podcloning now lets you keep your quirks.
- rscadd: Quirks have flavor text in medical records.
- spellcheck: All quirk medical records refer to "Patient", removing a few instances
of "Subject".
- tweak: Quirks no longer apply to off-station roundstart antagonists.
- code_imp: Mood quirks are now only processed by the quirk holders
Narcissisko (ported by Hatterhat):
- rscadd: Luxury Bar Capsule, at 10,000 points. Comes with no medical supplies,
a bar, and a bunch of cigars. Ported from tgstation/tgstation#45547.
Nervere and subject217, Militaires, py01, nemvar:
- balance: The cook's CQC now only works when in the kitchen or the kitchen backroom.
- spellcheck: corrected CQC help instructions
- bugfix: CQC and Sleeping Carp are properly logged.
- tweak: CQC can passively grab targets when not on grab intent. Passive grabs do
not count towards combos for CQC or Sleeping carp.
- code_imp: Martial Art and NOGUN cleanup.
PersianXerxes:
- rscdel: Removed night vision quirk
Putnam:
- bugfix: acute hepatic pharmacokinesis now works if you already have relevant genitals
- balance: Contamination is no longer an infinitely spreading deadly contagion causing
mass panic
- tweak: Dynamic rulesets have lower weight if a round recently featured them (except
traitor).
Putnam3145:
- balance: Buffed HE pipes by making them realistically radiate away heat.
- bugfix: Dynamic has a (totally unused for any relevant purpose) roundstart report
now.
- admin: A whole bunch of dynamic data is now available for statbus
- bugfix: Dynamic from-ghost antags no longer double dip on threat refunds when
the mode fails due to not enough applications.
- bugfix: whoops broke quirks
- bugfix: quirks work
- rscadd: 'New tab in preferences screen: "ERP preferences"'
- rscadd: New opt-outs for individual effects of incubus draught, succubus milk
- rscdel: Acute hepatic pharmacokinesis has been removed, replaced with above
- tweak: Renamed "Toggle Lewdchem" to "Toggle Lewd MKUltra", since that's what it
actually means, and made it toggle the "hypno" setting (rename it again if more
hypno mechanics are added).
- tweak: Made MKUltra's lewd messages require both people involved to have hypno
opted-in.
- config: Buncha dynamic config tweaks
- bugfix: Ghost cafe spawns are actual ghost roles by the game's reckoning now
- bugfix: a runtime in radioactive contamination
- balance: Bomb armor now acts like other armor types.
- balance: Devastation-level explosions on armorless people no longer destroys everything
in their bags.
Seris02:
- rscadd: the clowns headset
- bugfix: distance checks
- bugfix: the sprites
- rscadd: added the runed and brass winter coats (cosmetic ratvarian/narsian)
- tweak: how the narsian/ratvarian coats can be made
- bugfix: fixes some ghost roles from dying of stupid shit
- bugfix: pandoras attacking their owners
- rscadd: Added Rising Bass and the shifting scroll.
- tweak: Changes the martial arts scroll in the uplink to "Sleeping Carp Scroll"
ShizCalev:
- bugfix: Fixed floodlights not turning off properly when they're underpowered.
- bugfix: Fixed emitters not changing icons properly when they're underpowered.
Sishen1542:
- rscadd: Clicking a pack of seeds with a pen allows you to set the plant's name,
description and the pack of seeds' description. Useful for differentiating genetically
modified plants. These changes will persist through different generations of
the plant.
- rscadd: Hydroponics trays update their name and description to reflect the plant
inside them. They revert to default when emptied.
Toriate:
- rscadd: Polychromic shorts now have a digitigrade state
Trilbyspaceclone:
- rscadd: ports all the new donuts, burgars, and chicken stuff from RG
- rscadd: ports new snowcone
- rscadd: ports grill
- rscadd: ports beakfeast tag/mood lit as TG has it
- rscadd: ports all the amazing new sprites
- tweak: ports crafting for many things like snowcones needing water
- balance: ports of many craftings
- soundadd: lowers fryers sound
- imageadd: ported icons for new food/grill
- imagedel: ports the deletion of some icons and images
- spellcheck: ports a spell check for the snowcones
- code_imp: ports fixes for stuff I didnt know were even broken with snowcones
- bugfix: coder cat failers to push the last commit from year(s) ago
- admin: Updates the changlogs
- tweak: meat hook from HUGE to bulky
- tweak: CE hardsuit is now more rad-proof
- bugfix: Wrong icon names, missing dog fashion with telegram hat
- rscadd: New softdrink that comes in its own vender!
- rscadd: Honey now has a reaction with plants
- tweak: Buzz fuzz now only has a 5% to give honey and will now give 1u of sugar
not 2
- rscadd: Blaster shotguns back into armory
- rscdel: Removed Lighters in thunderdomes
- rscadd: Silicons now know what a slime is saying!
- balance: honey now will not kill slimes. Honey slimepeople can be a thing now,
go sci.
- rscadd: Added insulin into many of the borg hypo's
Useroth:
- rscadd: bamboo which can be used to build punji sticks/ blowguns available as
a sugarcane mutation or in exotic seed crate
- tweak: changed the sugar cane growth stages because fuck if I know why, but it
was in the PR
- rscadd: 'New lavaland ruin: Pulsating tumor'
- rscadd: New class of lavaland mobs, a bit weaker than megafauna but still stronger
than most of what you normally see
- rscadd: Ghost cafe spawner. For letting people spawn as their own character in
the ninja holding facility. It bypasses the usual check, so people who have
suicided/ghosted/cryod may use it.
- rscadd: Dorms in the ninja holding facility.
Xantholne:
- rscadd: Santa Hats to Loadout and Clothesmate
- rscadd: Christmas Wintercoats to Loadout and Clothesmate
- rscadd: Christmas male and female uniforms to loadout and Clothesmate
- rscadd: Red, Green, and Traditional Santa boots to loadout and Clothesmate
- rscadd: Christmas Socks, Red candycane socks, Green candycane socks to sock selection
kappa-sama:
- balance: legion drops more crates now
- balance: .357 speedloaders in autolathes are now individual bullets instead, speedloaders
are now illegal tech, costs less total metal to make 7 bullets than a previous
speedloader. 7.62mm bullets in autolathe when hacked and costs more metal to
make 5 7.62mm bullets than getting a clip from the seclathe.
- tweak: mentions that you can refill speedloaders on .357 uplink description
- bugfix: you can now strip people while aggrograbbing or higher
- rscadd: plasmafist to wizard
- code_imp: modular is gone
- rscadd: martial apprentices for the local Chinese wizard
- bugfix: broodmother baby lag
- balance: you can no longer get 100k credits by spending 4k roundstart
- balance: cooking oil in sunflowers instead of corn oil
- bugfix: throats are no longer slit happy
keronshb:
- rscadd: Adds reflector blobs to shield blob upgrades
kevinz000:
- rscadd: Launchpads can now take number inputs for offsets rather than just buttons.
- balance: nanites no longer spread through air blocking objects
- rscadd: Night vision readded as a darkness dampening effect rather than darksight.
- rscdel: conveyors can only stack items on tiles to 150 now.
- rscadd: added 8 character save slots
- rscadd: Cargo shuttle now silently ignores slaughter demons/revenants instead
of being blocked even while they are jaunted. A drawback is that manifested
ones can't block it either, any more.
- balance: flashbangs process light/sound separately and uses viewers(), so xray
users beware.
- tweak: Stat() slowed down for anti-lag measures.
- bugfix: sprint/stamina huds now work again
- balance: Combat defibs now instant stun on disarm rather than 1 second again
- balance: Defibs are now always emagged when emagged with an emag rather than EMP.
- bugfix: aooc toggling now only broadcasts to antagonists
- code_imp: Antag rep proc is now easier to read and supports returning a list.
- balance: Clockwork marauders are now on a configured summon cooldown if being
summoned on station. They also rapidly bleed health while in or next to space.
And they glow brighter.
lolman360:
- rscadd: Added ability to pick up certain simplemobs.
nemvar:
- bugfix: The brains of roundstart borgs no longer decay.
- code_imp: Refactored the visibility of reagents for mobs.
nicbn, Kevinz000, ShizCalev:
- tweak: Fire alarm is now simpler. Touch it to activate, touch it to deactivate.
When activated, it will blink inconsistently if it is emagged.
- bugfix: You can no longer spam fire alarms. Also, they're logged again.
- bugfix: Fixed fire alarms not updating icons properly after being emagged and
hacked by Malf AI's.
r4d6:
- rscadd: Added a N2O pressure tank
- rscdel: Removed a AM Shielding from the crate
- rscadd: Added Handshakes
- rscadd: Added Nose booping
- rscadd: Added submaps for the SM, Tesla and Singulo
- rscadd: Added a placeholder on Boxstation for the Engines
- bugfix: fixed Nose boops not triggering
shellspeed1:
- rscadd: Adds Insect markings
- rscadd: Adds three new moth wings.
@@ -1,4 +0,0 @@
author: "Linzolle"
delete-after: True
changes:
- rscadd: "neck slice. harm intent someone's head while they are unconscious or in a neck grab to make them bleed uncontrollably."
@@ -1,6 +0,0 @@
author: "Ghommie"
delete-after: True
changes:
- bugfix: "Fixed hulks, sleeping carp users, pacifists and people with chunky fingers being able to unrestrictly use gun and pneumatic cannon circuit assemblies."
- bugfix: "Fixed gun circuit assemblies being only usable by human mobs."
- balance: "Doubled the locomotion circuit external cooldown, thus halving the movable assemblies' movespeed."
@@ -1,6 +0,0 @@
author: "Ghommie"
delete-after: True
changes:
- tweak: "Made wooden cabinet/closets... actually made of wood."
- tweak: "Wooden cabinets are now deconstructable with a screwdriver."
- tweak: "Deconstruction of large crates and other closet subtypes deconstructable with tools other than the welder is no longer instant."
@@ -1,5 +0,0 @@
author: "Ghommie"
delete-after: True
changes:
- tweak: "You shouldn't be able to target objects you can't see (excluding darkness) with the ARCD and RLD"
- tweak: "The admin RCD is ranged too, just like the ARCD."
@@ -1,4 +0,0 @@
author: "kappa-sama"
delete-after: True
changes:
- balance: "legion drops more crates now"
@@ -1,4 +0,0 @@
author: "Ghommie"
delete-after: True
changes:
- bugfix: "Fixed welding, thirteen loko, welding and wraith spectacles not blinding people as expected. Thank you all whomst reported this issue in the suggestions box channel instead of the github repository's issues section, very smart!"
@@ -1,5 +0,0 @@
author: "kappa-sama"
delete-after: True
changes:
- balance: ".357 speedloaders in autolathes are now individual bullets instead, speedloaders are now illegal tech, costs less total metal to make 7 bullets than a previous speedloader. 7.62mm bullets in autolathe when hacked and costs more metal to make 5 7.62mm bullets than getting a clip from the seclathe."
- tweak: "mentions that you can refill speedloaders on .357 uplink description"
@@ -1,5 +0,0 @@
author: "Ghommie"
delete-after: True
changes:
- bugfix: "Fixed on_mob eyes overlays not updating properly in certain cases."
- bugfix: "Fixed deconversion from bloodshot eyes blood cult resetting your eyes' color to pitch black instead of their previous color, more or less."
@@ -1,4 +0,0 @@
author: "Ghommie"
delete-after: True
changes:
- balance: "Spinfusor nerf: Upped the casing and ammo box size by one step, removed the projectile's dismemberment value (explosions can still rip a limb or two off), halved the ammo box capacity, reduced the spinfusor ammo supply pack contents from 32 to 8, removed the casing's ability to explode when thrown."
@@ -1,4 +0,0 @@
author: "lolman360"
delete-after: True
changes:
- rscadd: "Added ability to pick up certain simplemobs."
@@ -1,5 +0,0 @@
author: "Sishen1542"
delete-after: True
changes:
- rscadd: "Clicking a pack of seeds with a pen allows you to set the plant's name, description and the pack of seeds' description. Useful for differentiating genetically modified plants. These changes will persist through different generations of the plant."
- rscadd: "Hydroponics trays update their name and description to reflect the plant inside them. They revert to default when emptied."
@@ -1,5 +0,0 @@
author: "Fikou"
delete-after: True
changes:
- tweak: "the windup toolbox now has some more \"realistic\" sounds"
- bugfix: "the windup toolbox now rumbles again"
@@ -1,4 +0,0 @@
author: "Ghommie"
delete-after: True
changes:
- bugfix: "Fixes bubblegum's death not unlocking the arena shuttle buyment."

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