Skip to content

Commit

Permalink
Merge upstream 10.11.24 (#678)
Browse files Browse the repository at this point in the history
## About The Pull Request
Апстриме
  • Loading branch information
larentoun authored Nov 10, 2024
2 parents 0bef13a + 995716e commit d2540da
Show file tree
Hide file tree
Showing 34 changed files with 276 additions and 141 deletions.
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,15 @@ Space Station 13 is a paranoia-laden round-based roleplaying game set against th

**[How to compile in VSCode and other build options](tools/build/README.md).**

## Contributors
[Guides for Contributors](.github/CONTRIBUTING.md)
## Getting started

[/tg/station HACKMD account](https://hackmd.io/@tgstation) - Design documentation here
For contribution guidelines refer to the [Guides for Contributors](.github/CONTRIBUTING.md).

[Interested in some starting lore?](https://github.com/tgstation/common_core)
For getting started (dev env, compilation) see the HackMD document [here](https://hackmd.io/@tgstation/HJ8OdjNBc#tgstation-Development-Guide).

For overall design documentation see [HackMD](https://hackmd.io/@tgstation).

For lore, [see Common Core](https://github.com/tgstation/common_core).

## LICENSE

Expand Down
3 changes: 2 additions & 1 deletion code/__DEFINES/mobs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,8 @@
#define GRADIENT_APPLIES_TO_FACIAL_HAIR (1<<1)

// Hair masks
#define HAIR_MASK_HIDE_ABOVE_45_DEG_MEDIUM "hide_above_45deg"
#define HAIR_MASK_HIDE_ABOVE_45_DEG_MEDIUM "hide_above_45deg_medium"
#define HAIR_MASK_HIDE_ABOVE_45_DEG_LOW "hide_above_45deg_low"

// Height defines
// - They are numbers so you can compare height values (x height < y height)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@
candidates -= player
else if(is_centcom_level(player.z))
candidates -= player // We don't autotator people in CentCom
else if(player.mind && (player.mind.special_role || player.mind.can_roll_midround()))
else if(player.mind && (player.mind.special_role || !player.mind.can_roll_midround()))
candidates -= player // We don't autotator people with roles already

/datum/dynamic_ruleset/midround/from_living/autotraitor/execute()
Expand Down Expand Up @@ -310,7 +310,7 @@
continue
if(isnull(player.mind))
continue
if(player.mind.special_role || player.mind.can_roll_midround())
if(player.mind.special_role || !player.mind.can_roll_midround())
continue
candidates += player

Expand Down Expand Up @@ -479,7 +479,7 @@
candidates -= player
continue

if(player.mind && (player.mind.special_role || player.mind.can_roll_midround()))
if(player.mind && (player.mind.special_role || !player.mind.can_roll_midround()))
candidates -= player

/datum/dynamic_ruleset/midround/from_living/blob_infection/execute()
Expand Down
1 change: 1 addition & 0 deletions code/datums/components/blob_minion.dm
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
/// We only speak telepathically to blobs
/datum/component/blob_minion/proc/on_try_speech(mob/living/minion, message, ignore_spam, forced)
SIGNAL_HANDLER
minion.log_talk(message, LOG_SAY, tag = "blob hivemind telepathy")
var/spanned_message = minion.say_quote(message)
var/rendered = span_blob("<b>\[Blob Telepathy\] [minion.real_name]</b> [spanned_message]")
relay_to_list_and_observers(rendered, GLOB.blob_telepathy_mobs, minion)
Expand Down
33 changes: 27 additions & 6 deletions code/datums/helper_datums/teleport.dm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

// argument handling
// if the precision is not specified, default to 0, but apply BoH penalties
if (isnull(precision))
if(isnull(precision))
precision = 0

switch(channel)
Expand All @@ -40,7 +40,7 @@
to_chat(MM, span_warning("The bluespace interface on your bag of holding interferes with the teleport!"))

// if effects are not specified and not explicitly disabled, sparks
if ((!effectin || !effectout) && !no_effects)
if((!effectin || !effectout) && !no_effects)
var/datum/effect_system/spark_spread/sparks = new
sparks.set_up(5, 1, teleatom)
if (!effectin)
Expand Down Expand Up @@ -78,10 +78,16 @@
return TRUE

tele_play_specials(teleatom, curturf, effectin, asoundin)

var/success = teleatom.forceMove(destturf)
if(success)
log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]")
tele_play_specials(teleatom, destturf, effectout, asoundout)
if(!success)
return FALSE

. = TRUE
/* Past this point, the teleport is successful and you can assume that they're already there */

log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]")
tele_play_specials(teleatom, destturf, effectout, asoundout)

if(ismob(teleatom))
var/mob/M = teleatom
Expand All @@ -90,7 +96,22 @@

SEND_SIGNAL(teleatom, COMSIG_MOVABLE_POST_TELEPORT, destination, channel)

return TRUE
//We need to be sure that the buckled mobs can teleport too
if(teleatom.has_buckled_mobs())
for(var/mob/living/rider in teleatom.buckled_mobs)
//just in case it fails, but the mob gets unbuckled anyways even if it passes
teleatom.unbuckle_mob(rider, TRUE, FALSE)

var/rider_success = do_teleport(rider, destturf, precision, channel=channel, no_effects=TRUE)
if(!rider_success)
continue

if(get_turf(rider) != destturf) //precision made them teleport somewhere else
to_chat(rider, span_warning("As you reorient your senses, you realize you aren't riding [teleatom] anymore!"))
continue

// [mob/living].forceMove() forces mobs to unbuckle, so we need to buckle them again
teleatom.buckle_mob(rider, force=TRUE)

/proc/tele_play_specials(atom/movable/teleatom, atom/location, datum/effect_system/effect, sound)
if(!location)
Expand Down
24 changes: 13 additions & 11 deletions code/game/objects/buckling.dm
Original file line number Diff line number Diff line change
Expand Up @@ -215,23 +215,25 @@
if(target == src)
return FALSE

// Check if the target to buckle isn't INSIDE OF A WALL
if(!isopenturf(loc) || !isopenturf(target.loc))
return FALSE

// Check if the target to buckle isn't A SOLID OBJECT (not including vehicles)
var/turf/ground = get_turf(src)
if(ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
return FALSE
// If we're not already on the same turf as our target...
if(get_turf(target) != ground)
// Check if the target to buckle isn't INSIDE OF A WALL
if(!isopenturf(loc) || !isopenturf(target.loc))
return FALSE

// Check if the target to buckle isn't INSIDE A SOLID OBJECT (not including vehicles)
if(ground.is_blocked_turf(exclude_mobs = TRUE, source_atom = src))
return FALSE

// If we're checking the loc, make sure the target is on the thing we're bucking them to.
if(check_loc && !target.Adjacent(src))
return FALSE

// Check if this atom can have things buckled to it.
if(!can_buckle && !force)
return FALSE

// If we're checking the loc, make sure the target is on the thing we're bucking them to.
if(check_loc && !target.Adjacent(src))
return FALSE

// Make sure the target isn't already buckled to something.
if(target.buckled)
return FALSE
Expand Down
71 changes: 64 additions & 7 deletions code/game/objects/items.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1027,36 +1027,93 @@

///Called BEFORE the object is ground up - use this to change grind results based on conditions. Return "-1" to prevent the grinding from occurring
/obj/item/proc/on_grind()
PROTECTED_PROC(TRUE)

return SEND_SIGNAL(src, COMSIG_ITEM_ON_GRIND)

///Grind item, adding grind_results to item's reagents and transfering to target_holder if specified
/obj/item/proc/grind(datum/reagents/target_holder, mob/user)
/obj/item/proc/grind(datum/reagents/target_holder, mob/user, atom/movable/grinder = loc)
SHOULD_NOT_OVERRIDE(TRUE)

. = FALSE
if(on_grind() == -1)
if(on_grind() == -1 || target_holder.holder_full())
return

. = grind_atom(target_holder, user)

//reccursive grinding to get all them juices
var/result
for(var/obj/item/ingredient as anything in get_all_contents_type(/obj/item))
if(ingredient == src)
continue

result = ingredient.grind(target_holder, user)
if(!.)
. = result

if(. && istype(grinder))
return grinder.blended(src, grinded = TRUE)

///Subtypes override his proc for custom grinding
/obj/item/proc/grind_atom(datum/reagents/target_holder, mob/user)
PROTECTED_PROC(TRUE)

. = FALSE
if(length(grind_results))
target_holder.add_reagent_list(grind_results)
. = TRUE
if(reagents?.total_volume)
reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user)
if(reagents?.trans_to(target_holder, reagents.total_volume, transferred_by = user))
. = TRUE

///Called BEFORE the object is ground up - use this to change grind results based on conditions. Return "-1" to prevent the grinding from occurring
/obj/item/proc/on_juice()
PROTECTED_PROC(TRUE)

if(!juice_typepath)
return -1

return SEND_SIGNAL(src, COMSIG_ITEM_ON_JUICE)

///Juice item, converting nutriments into juice_typepath and transfering to target_holder if specified
/obj/item/proc/juice(datum/reagents/target_holder, mob/user)
/obj/item/proc/juice(datum/reagents/target_holder, mob/user, atom/movable/juicer = loc)
SHOULD_NOT_OVERRIDE(TRUE)

. = FALSE
if(on_juice() == -1 || !reagents?.total_volume)
return FALSE
return

. = juice_atom(target_holder, user)

//reccursive juicing to get all them juices
var/result
for(var/obj/item/ingredient as anything in get_all_contents_type(/obj/item))
if(ingredient == src)
continue

result = ingredient.juice(target_holder, user)
if(!.)
. = result

if(. && istype(juicer))
return juicer.blended(src, grinded = FALSE)

///Subtypes override his proc for custom juicing
/obj/item/proc/juice_atom(datum/reagents/target_holder, mob/user)
PROTECTED_PROC(TRUE)

. = FALSE

if(ispath(juice_typepath))
reagents.convert_reagent(/datum/reagent/consumable/nutriment, juice_typepath, include_source_subtypes = FALSE)
reagents.convert_reagent(/datum/reagent/consumable/nutriment/vitamin, juice_typepath, include_source_subtypes = FALSE)
reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user)
. = TRUE

if(!QDELETED(target_holder))
reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user)

///What should The atom that blended an object do with it afterwards? Default behaviour is to delete it
/atom/movable/proc/blended(obj/item/blended_item, grinded)
qdel(blended_item)

return TRUE

Expand Down
13 changes: 5 additions & 8 deletions code/game/objects/items/cigarettes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,6 @@ CIGARETTE PACKETS ARE IN FANCY.DM

/obj/item/cigarette/Initialize(mapload)
. = ..()
create_reagents(chem_volume, INJECTABLE | NO_REACT)
if(list_reagents)
reagents.add_reagent_list(list_reagents)
if(starts_lit)
light()
AddComponent(/datum/component/knockoff, 90, list(BODY_ZONE_PRECISE_MOUTH), slot_flags) //90% to knock off when wearing a mask
AddElement(/datum/element/update_icon_updates_onmob)
RegisterSignal(src, COMSIG_ATOM_TOUCHED_SPARKS, PROC_REF(sparks_touched))
Expand All @@ -201,15 +196,17 @@ CIGARETTE PACKETS ARE IN FANCY.DM
initial_reagents = list_reagents,\
food_flags = FOOD_NO_EXAMINE,\
foodtypes = JUNKFOOD,\
volume = 50,\
volume = chem_volume,\
eat_time = 0 SECONDS,\
tastes = list("a never before experienced flavour.", "finally sitting down after standing your entire life"),\
tastes = list("a never before experienced flavour", "finally sitting down after standing your entire life"),\
eatverbs = list("taste"),\
bite_consumption = 50,\
bite_consumption = chem_volume,\
junkiness = 0,\
reagent_purity = null,\
on_consume = CALLBACK(src, PROC_REF(on_consume)),\
)
if(starts_lit)
light()

/obj/item/cigarette/Destroy()
STOP_PROCESSING(SSobj, src)
Expand Down
6 changes: 1 addition & 5 deletions code/game/objects/items/stacks/stack.dm
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,10 @@
return
return TRUE

/obj/item/stack/grind(datum/reagents/target_holder, mob/user)
/obj/item/stack/grind_atom(datum/reagents/target_holder, mob/user)
var/current_amount = get_amount()
if(current_amount <= 0 || QDELETED(src)) //just to get rid of this 0 amount/deleted stack we return success
return TRUE
if(on_grind() == -1)
return FALSE
if(isnull(target_holder))
return TRUE

if(reagents)
reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user)
Expand Down
12 changes: 12 additions & 0 deletions code/game/objects/items/theft_tools.dm
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@
pulseicon = "supermatter_sliver_pulse"
layer = ABOVE_MOB_LAYER

/obj/item/nuke_core/supermatter_sliver/Initialize(mapload)
. = ..()
RegisterSignal(src, COMSIG_FISHING_ROD_CAST, PROC_REF(on_hook))

/obj/item/nuke_core/supermatter_sliver/proc/on_hook(obj/item/nuke_core/supermatter_sliver/source, obj/item/fishing_rod/rod, mob/user)
SIGNAL_HANDLER

//hook gets dusted but the rod remains intact
attackby(rod.hook, user)

return FISHING_ROD_CAST_HANDLED

/obj/item/nuke_core/supermatter_sliver/attack_tk(mob/user) // no TK dusting memes
return

Expand Down
12 changes: 12 additions & 0 deletions code/modules/clothing/head/helmet.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
drop_sound = 'sound/items/handling/helmet/helmet_drop1.ogg'
visor_toggle_up_sound = SFX_VISOR_UP
visor_toggle_down_sound = SFX_VISOR_DOWN
hair_mask = HAIR_MASK_HIDE_ABOVE_45_DEG_LOW

/obj/item/clothing/head/helmet/sec/Initialize(mapload)
. = ..()
Expand Down Expand Up @@ -68,6 +69,17 @@

return ..()

/obj/item/clothing/head/helmet/sec/attack_self(mob/user)
. = ..()
if(.)
return
balloon_alert(user, "[flags_inv & HIDEHAIR ? "loosening" : "tightening"] straps...")
if(!do_after(user, 3 SECONDS, src))
return
flags_inv ^= HIDEHAIR
balloon_alert(user, "[flags_inv & HIDEHAIR ? "tightened" : "loosened"] straps")
return TRUE

/obj/item/clothing/head/helmet/sec/click_alt(mob/user)
flipped_visor = !flipped_visor
balloon_alert(user, "visor flipped")
Expand Down
9 changes: 2 additions & 7 deletions code/modules/hydroponics/grown.dm
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,7 @@
reagents.add_reagent(/datum/reagent/consumable/ethanol/fruit_wine, reagent.volume, data, added_purity = reagent_purity)
reagents.del_reagent(reagent.type)

/obj/item/food/grown/grind(datum/reagents/target_holder, mob/user)
if(on_grind() == -1)
return FALSE

/obj/item/food/grown/grind_atom(datum/reagents/target_holder, mob/user)
var/grind_results_num = LAZYLEN(grind_results)
if(grind_results_num)
var/average_purity = reagents.get_average_purity()
Expand All @@ -152,9 +149,7 @@
for(var/reagent in grind_results)
reagents.add_reagent(reagent, single_reagent_amount, added_purity = average_purity)

if(reagents && target_holder)
reagents.trans_to(target_holder, reagents.total_volume, transferred_by = user)
return TRUE
return reagents?.trans_to(target_holder, reagents.total_volume, transferred_by = user)

#undef BITE_SIZE_POTENCY_MULTIPLIER
#undef BITE_SIZE_VOLUME_MULTIPLIER
Loading

0 comments on commit d2540da

Please sign in to comment.