diff --git a/.github/workflows/autochangelog.yml b/.github/workflows/autochangelog.yml
index 0a939f29918..45303ec0c92 100644
--- a/.github/workflows/autochangelog.yml
+++ b/.github/workflows/autochangelog.yml
@@ -15,10 +15,22 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
+
+ - name: Generate App Token
+ id: app-token-generation
+ uses: actions/create-github-app-token@v1
+ if: env.APP_PRIVATE_KEY != '' && env.APP_ID != ''
+ with:
+ app-id: ${{ secrets.APP_ID }}
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
+ env:
+ APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
+ APP_ID: ${{ secrets.APP_ID }}
+
- name: Run auto changelog
uses: actions/github-script@v7
with:
script: |
const { processAutoChangelog } = await import('${{ github.workspace }}/tools/pull_request_hooks/autoChangelog.js')
await processAutoChangelog({ github, context })
- github-token: ${{ secrets.COMFY_ORANGE_PAT || secrets.GITHUB_TOKEN }}
+ github-token: ${{ steps.app-token-generation.outputs.token || secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/compile_changelogs.yml b/.github/workflows/compile_changelogs.yml
index 478251f25db..6e46dc4b16d 100644
--- a/.github/workflows/compile_changelogs.yml
+++ b/.github/workflows/compile_changelogs.yml
@@ -18,37 +18,54 @@ jobs:
# unset SECRET_EXISTS
# if [ -n "$ENABLER_SECRET" ]; then SECRET_EXISTS=true ; fi
# echo "ACTIONS_ENABLED=$SECRET_EXISTS" >> $GITHUB_OUTPUT
+
- name: "Setup python"
#if: steps.value_holder.outputs.ACTIONS_ENABLED
uses: actions/setup-python@v5
with:
python-version: '3.x'
+
- name: "Install deps"
#if: steps.value_holder.outputs.ACTIONS_ENABLED
run: |
python -m pip install --upgrade pip
python -m pip install pyyaml
sudo apt-get install dos2unix
+
- name: "Checkout"
#if: steps.value_holder.outputs.ACTIONS_ENABLED
uses: actions/checkout@v4
with:
fetch-depth: 25
persist-credentials: false
+
- name: "Compile"
#if: steps.value_holder.outputs.ACTIONS_ENABLED
run: |
python tools/ss13_genchangelog.py html/changelogs
+
- name: Commit
#if: steps.value_holder.outputs.ACTIONS_ENABLED
run: |
- git config --local user.email "action@github.com"
- git config --local user.name "Changelogs"
+ git config --local user.name "vorestation-ci[bot]"
+ git config --local user.email "199609141+vorestation-ci[bot]@users.noreply.github.com"
git pull origin master
git add html/changelogs
git commit -m "Automatic changelog compile [ci skip]" -a || true
+
+ - name: Generate App Token
+ id: app-token-generation
+ uses: actions/create-github-app-token@v1
+ if: env.APP_PRIVATE_KEY != '' && env.APP_ID != ''
+ with:
+ app-id: ${{ secrets.APP_ID }}
+ private-key: ${{ secrets.APP_PRIVATE_KEY }}
+ env:
+ APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
+ APP_ID: ${{ secrets.APP_ID }}
+
- name: "Push"
#if: steps.value_holder.outputs.ACTIONS_ENABLED
uses: ad-m/github-push-action@master
with:
- github_token: ${{ secrets.COMFY_ORANGE_PAT || secrets.GITHUB_TOKEN }}
+ github_token: ${{ steps.app-token-generation.outputs.token || secrets.GITHUB_TOKEN }}
diff --git a/code/_global_vars/configuration.dm b/code/_global_vars/configuration.dm
index 3ab241a8fb7..36c08c45658 100644
--- a/code/_global_vars/configuration.dm
+++ b/code/_global_vars/configuration.dm
@@ -4,4 +4,5 @@ GLOBAL_REAL(config, /datum/controller/configuration) = new
GLOBAL_DATUM_INIT(revdata, /datum/getrev, new)
+GLOBAL_VAR_INIT(game_version, "VOREStation")
GLOBAL_VAR_INIT(changelog_hash, "")
diff --git a/code/datums/components/orbiter.dm b/code/datums/components/orbiter.dm
index 6e6cf9001ff..5b80b16e262 100644
--- a/code/datums/components/orbiter.dm
+++ b/code/datums/components/orbiter.dm
@@ -22,14 +22,14 @@
/datum/component/orbiter/RegisterWithParent()
. = ..()
var/atom/target = parent
- while(ismovable(target))
+ if(ismovable(target))
RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(move_react))
target = target.loc
/datum/component/orbiter/UnregisterFromParent()
. = ..()
var/atom/target = parent
- while(ismovable(target))
+ if(ismovable(target))
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
target = target.loc
@@ -119,12 +119,12 @@
// These are prety rarely activated, how often are you following something in a bag?
if(oldloc && !isturf(oldloc)) // We used to be registered to it, probably
var/atom/target = oldloc
- while(ismovable(target))
+ if(ismovable(target))
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
target = target.loc
if(orbited?.loc && orbited.loc != newturf) // We want to know when anything holding us moves too
var/atom/target = orbited.loc
- while(ismovable(target))
+ if(ismovable(target))
RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(move_react), TRUE)
target = target.loc
diff --git a/code/game/objects/items/devices/scanners/guide.dm b/code/game/objects/items/devices/scanners/guide.dm
index 18405d9c974..ab4e2a8bf4b 100644
--- a/code/game/objects/items/devices/scanners/guide.dm
+++ b/code/game/objects/items/devices/scanners/guide.dm
@@ -1,6 +1,6 @@
/obj/item/healthanalyzer/verb/toggle_guide()
set name = "Toggle Guidance"
- set desc = "Toggles whether or not \the [src] will provide guidance and instruction in addition to scanning."
+ set desc = "Toggles whether or not the health analyzer will provide guidance and instruction in addition to scanning."
set category = "Object"
guide = !guide
to_chat(usr, span_notice("You toggle \the [src]'s guidance system [guide ? "on" : "off"]."))
diff --git a/code/game/objects/items/falling_object_vr.dm b/code/game/objects/items/falling_object_vr.dm
index e51f8790d5e..19d175f1ef2 100644
--- a/code/game/objects/items/falling_object_vr.dm
+++ b/code/game/objects/items/falling_object_vr.dm
@@ -8,8 +8,10 @@
var/falling_type = /obj/item/reagent_containers/food/snacks/sliceable/pizza/margherita
var/crushing = TRUE
-/obj/effect/falling_effect/Initialize(mapload, type)
+/obj/effect/falling_effect/Initialize(mapload, type, var/crushing_type)
..()
+ if(!isnull(crushing_type))
+ crushing = crushing_type
if(type)
falling_type = type
return INITIALIZE_HINT_LATELOAD
diff --git a/code/game/objects/items/lockpicks.dm b/code/game/objects/items/lockpicks.dm
index 843b0608deb..de8f31e29c0 100644
--- a/code/game/objects/items/lockpicks.dm
+++ b/code/game/objects/items/lockpicks.dm
@@ -1,4 +1,5 @@
//For bypassing locked /obj/structure/simple_doors
+//now with added fence gate support
/obj/item/lockpick
name = "set of lockpicks"
@@ -30,6 +31,23 @@
if(do_after(user, pick_time * D.lock_difficulty))
to_chat(user, span_notice("Success!"))
D.locked = FALSE
+ if(istype(A, /obj/structure/fence/door))
+ var/obj/structure/fence/door/D = A
+ if(!D.locked) //you can pick your nose, but you can't pick an unlocked door
+ to_chat(user, span_notice("\The [D] isn't locked."))
+ return
+ else if(D.lock_type != pick_type) //make sure our types match
+ to_chat(user, span_warning("\The [src] can't pick \the [D]. Another tool might work?"))
+ return
+ else if(!D.can_pick) //make sure we're actually allowed to bypass it at all
+ to_chat(user, span_warning("\The [D] can't be [pick_verb]ed."))
+ return
+ else //finally, we can assume that they do match
+ to_chat(user, span_notice("You start to [pick_verb] the lock on \the [D]..."))
+ playsound(src, D.keysound,100, 1)
+ if(do_after(user, pick_time * D.lock_difficulty))
+ to_chat(user, span_notice("Success!"))
+ D.locked = FALSE
else if(ishuman(A)) //you can pick your friends, and you can pick your nose, but you can't pick your friend's nose
var/mob/living/carbon/human/H = A
if(user.zone_sel.selecting == BP_HEAD)
diff --git a/code/game/objects/random/misc.dm b/code/game/objects/random/misc.dm
index 12ca6d276f4..44e85abefff 100644
--- a/code/game/objects/random/misc.dm
+++ b/code/game/objects/random/misc.dm
@@ -269,6 +269,7 @@
prob(1);/obj/item/beartrap,
prob(1);/obj/item/handcuffs,
prob(1);/obj/item/handcuffs/legcuffs,
+ prob(1);/obj/item/lockpick,
prob(2);/obj/item/reagent_containers/syringe/drugs,
prob(1);/obj/item/reagent_containers/syringe/steroid)
diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm
index ee9170953a3..466b591ef58 100644
--- a/code/game/objects/structures/artstuff.dm
+++ b/code/game/objects/structures/artstuff.dm
@@ -71,6 +71,7 @@
/obj/item/canvas/Initialize()
. = ..()
reset_grid()
+ desc += " (Canvas size is [width]x[height].)"
/obj/item/canvas/proc/reset_grid()
grid = new/list(width,height)
diff --git a/code/game/objects/structures/fence.dm b/code/game/objects/structures/fence.dm
index 0237f0c20a9..ca764fa85c4 100644
--- a/code/game/objects/structures/fence.dm
+++ b/code/game/objects/structures/fence.dm
@@ -69,6 +69,7 @@
return ..()
/obj/structure/fence/attackby(obj/item/W, mob/user)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(W.has_tool_quality(TOOL_WIRECUTTER))
if(!cuttable)
to_chat(user, span_warning("This section of the fence can't be cut."))
@@ -122,6 +123,11 @@
cuttable = FALSE
var/open = FALSE
var/locked = FALSE
+ var/lock_id = null //does the door have an associated key?
+ var/lock_type = "simple" //string matched to "pick_type" on /obj/item/lockpick
+ var/can_pick = TRUE //can it be picked/bypassed?
+ var/lock_difficulty = 1 //multiplier to picking/bypassing time
+ var/keysound = 'sound/items/toolbelt_equip.ogg'
/obj/structure/fence/door/Initialize()
update_door_status()
@@ -144,6 +150,23 @@
return TRUE
+/obj/structure/fence/door/attackby(obj/item/W as obj, mob/user as mob)
+ user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
+ if(istype(W,/obj/item/simple_key))
+ var/obj/item/simple_key/key = W
+ if(open)
+ to_chat(user,span_notice("\The [src] must be closed in order for you to lock it."))
+ else if(key.key_id != src.lock_id)
+ to_chat(user,span_warning("The [key] doesn't fit \the [src]'s lock!"))
+ else if(key.key_id == src.lock_id)
+ visible_message(span_notice("[user] [key.keyverb] \the [key] and [locked ? "unlocks" : "locks"] \the [src]."))
+ locked = !locked
+ playsound(src, keysound,100, 1)
+ return
+ else
+ attack_hand(user)
+ return
+
/obj/structure/fence/door/proc/toggle(mob/user)
switch(open)
if(FALSE)
diff --git a/code/game/world.dm b/code/game/world.dm
index 97804b4d774..ebee8ba4b80 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -130,7 +130,7 @@ var/world_topic_spam_protect_time = world.timeofday
else if (copytext(T,1,7) == "status")
var/input[] = params2list(T)
var/list/s = list()
- s["version"] = game_version
+ s["version"] = GLOB.game_version
s["mode"] = master_mode
s["respawn"] = CONFIG_GET(flag/abandon_allowed)
s["persistance"] = CONFIG_GET(flag/persistence_disabled)
@@ -559,7 +559,7 @@ var/world_topic_spam_protect_time = world.timeofday
s += span_bold("[station_name()]");
s += " ("
s += "" //Change this to wherever you want the hub to link to.
-// s += "[game_version]"
+// s += "[GLOB.game_version]"
s += "Default" //Replace this with something else. Or ever better, delete it and uncomment the game version.
s += ""
s += ")"
diff --git a/code/global.dm b/code/global.dm
index 9ca93bfeb1b..4c401f7e396 100644
--- a/code/global.dm
+++ b/code/global.dm
@@ -31,7 +31,6 @@ var/href_logfile = null
// var/const/company_short = "NT"
// var/const/star_name = "Vir"
// var/const/starsys_name = "Vir"
-var/const/game_version = "VOREStation"
var/game_year = (text2num(time2text(world.realtime, "YYYY")) + 300) //VOREStation Edit
var/round_progressing = 1
diff --git a/code/modules/admin/verbs/buildmode.dm b/code/modules/admin/verbs/buildmode.dm
index 97f5539c4a3..2c6fd01e63e 100644
--- a/code/modules/admin/verbs/buildmode.dm
+++ b/code/modules/admin/verbs/buildmode.dm
@@ -658,12 +658,10 @@
return
if(pa.Find("left") && !pa.Find("ctrl"))
if(ispath(holder.buildmode.objholder))
- var/obj/effect/falling_effect/FE = new /obj/effect/falling_effect(get_turf(object), holder.buildmode.objholder)
- FE.crushing = FALSE
+ new /obj/effect/falling_effect(get_turf(object), holder.buildmode.objholder, FALSE)
else if(pa.Find("right"))
if(ispath(holder.buildmode.objholder))
- var/obj/effect/falling_effect/FE = new /obj/effect/falling_effect(get_turf(object), holder.buildmode.objholder)
- FE.crushing = TRUE
+ new /obj/effect/falling_effect(get_turf(object), holder.buildmode.objholder, TRUE)
else if(pa.Find("ctrl"))
holder.buildmode.objholder = object.type
to_chat(user, span_notice("[object]([object.type]) copied to buildmode."))
diff --git a/code/modules/busy_space/organizations.dm b/code/modules/busy_space/organizations.dm
index 002a79e6ba0..c63796ffa77 100644
--- a/code/modules/busy_space/organizations.dm
+++ b/code/modules/busy_space/organizations.dm
@@ -2903,7 +2903,7 @@
acronym = "SAARE"
desc = "SAARE consistently have the worst reputation of any paramilitary group. This is because they specialize in deniability and secrecy. Although publically they work in asset recovery, they have a substantiated reputation for info-theft and piracy that has lead to them butting heads with the law on more than one occasion. Nonetheless, they are an invaluable part of the Solar economy, and other TSCs and small colonial governments keep them in business.\
\
- For the purposes of plausible deniability, SAARE designates their ships using a series of rotating identifiers, with ships on a specific operation or in a particular area all using the same initial designation (e.g. 'Sledgehammer') and having a different numerical identifier, with the most important ships involved bearing a unique additional codename (such as 'Actual' for Command \& Control ships). As ships are shuffled in and out of operating areas, it can be difficult to pin down exactly which ship in SAARE's fleet was responsible for which act. SAARE's misdirection is multilayered, including elements such as extensive use of repainting, false IFFs, bribes, forged documents, intimidation, camouflage, and all manner of other underhanded tactics."
+ For the purposes of plausible deniability, SAARE designates their ships using a series of rotating identifiers, with ships on a specific operation or in a particular area all using the same initial designation (e.g. 'Sledgehammer') and having a different numerical identifier, with the most important ships involved bearing a unique additional codename (such as 'Actual' for Command & Control ships). As ships are shuffled in and out of operating areas, it can be difficult to pin down exactly which ship in SAARE's fleet was responsible for which act. SAARE's misdirection is multilayered, including elements such as extensive use of repainting, false IFFs, bribes, forged documents, intimidation, camouflage, and all manner of other underhanded tactics."
history = ""
work = "mercenary contractors"
headquarters = ""
@@ -3005,4 +3005,4 @@
i--
//ex: "Phalanx One-Niner", "Sledgehammer Actual" (CO/VIP), "Kodiak Seven-Four", "Tomahawk Two-Zero"
- //probably a more elegant (read: fancier) way to do the second part but fuck it, this works just fine
\ No newline at end of file
+ //probably a more elegant (read: fancier) way to do the second part but fuck it, this works just fine
diff --git a/code/modules/client/preference_setup/loadout/loadout_utility.dm b/code/modules/client/preference_setup/loadout/loadout_utility.dm
index d92786e7a00..44157000d98 100644
--- a/code/modules/client/preference_setup/loadout/loadout_utility.dm
+++ b/code/modules/client/preference_setup/loadout/loadout_utility.dm
@@ -316,3 +316,8 @@ modular computers
display_name = "podzu music player"
path = /obj/item/walkpod
cost = 2
+
+/datum/gear/utility/bloodbag //For your vampiric crew!
+ display_name = "blood bag (Randomized)"
+ path = /obj/item/reagent_containers/blood/random_bloodsucker
+ cost = 1
diff --git a/code/modules/clothing/spacesuits/void/event_vr.dm b/code/modules/clothing/spacesuits/void/event_vr.dm
index d9645b94887..57128e8efed 100644
--- a/code/modules/clothing/spacesuits/void/event_vr.dm
+++ b/code/modules/clothing/spacesuits/void/event_vr.dm
@@ -198,7 +198,7 @@
/obj/item/clothing/head/helmet/space/void/aether/verb/select_color()
set name = "Helmet Color"
- set desc = "Change the color of [src]"
+ set desc = "Change the color of the helmet"
set category = "Object"
var/choice = tgui_input_list(usr, "Select a new color:", "[src] Color", list("White", "Blue", "Purple", "Yellow", "Red", "Green"))
diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm
index 88259428618..3ae50352c6c 100644
--- a/code/modules/hydroponics/trays/tray.dm
+++ b/code/modules/hydroponics/trays/tray.dm
@@ -236,6 +236,17 @@
if(prob(mutchance))
yield_mod = min(10,yield_mod+rand(1,2))
return
+ else if(istype(Proj, /obj/item/projectile/energy/floraprune))
+ var/obj/item/projectile/energy/floraprune/GP = Proj
+ mutchance *= GP.lasermod
+ if(prob(mutchance) && seed)
+ var/c = safepick(seed.chems)
+ if(length(seed.chems) > 1 && c)
+ var/turf/T = get_turf(loc)
+ seed = seed.diverge()
+ T.visible_message(span_infoplain(span_bold("\The [seed.display_name]") + " quivers!"))
+ seed.chems -= c
+ return
..()
diff --git a/code/modules/makeup/nailpolish.dm b/code/modules/makeup/nailpolish.dm
index 8fe3e12ac74..a49126186b5 100644
--- a/code/modules/makeup/nailpolish.dm
+++ b/code/modules/makeup/nailpolish.dm
@@ -5,6 +5,7 @@
desc = "to paint your nails with. Or someone else's!"
icon = 'icons/obj/nailpolish_vr.dmi'
icon_state = "nailpolish"
+ w_class = ITEMSIZE_SMALL
var/colour = "#FFFFFF"
var/image/top_underlay
var/image/color_underlay
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 66e23dee715..b6b38246bd7 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -645,7 +645,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(src, span_filter_notice(span_red("You are dead! You have no mind to store memory!")))
/mob/observer/dead/Post_Incorpmove()
- stop_following()
+ if(following) //This wasn't here before. It meant that we would do stop_following repeatedly every movement we made...Resulting in a DOS on our client.
+ stop_following()
/mob/observer/dead/verb/analyze_air()
set name = "Analyze Air"
diff --git a/code/modules/mob/living/carbon/human/species/station/alraune.dm b/code/modules/mob/living/carbon/human/species/station/alraune.dm
index d48a75fd97d..24ba9afa824 100644
--- a/code/modules/mob/living/carbon/human/species/station/alraune.dm
+++ b/code/modules/mob/living/carbon/human/species/station/alraune.dm
@@ -404,7 +404,7 @@
/mob/living/carbon/human/proc/alraune_fruit_pick()
set name = "Pick Fruit"
- set desc = "Pick fruit off of [src]."
+ set desc = "Pick fruit off of the fruit gland."
set category = "Object"
set src in view(1)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm
index a7b9592463b..ffc8b367a1f 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/stardog.dm
@@ -322,7 +322,7 @@
if(!destinations.len)
to_chat(src, span_warning("There is nowhere nearby to land! You need to get closer to somewhere else that you can transition to before you can transition."))
return
- for(var/obj/effect/landmark/stardog/l in destinations)
+ //for(var/obj/effect/landmark/stardog/l in destinations)
var/obj/effect/overmap/visitable/our_dest = tgui_input_list(src, "Where would you like to try to go?", "Transition", destinations, timeout = 15 SECONDS, strict_modern = TRUE)
if(!our_dest)
to_chat(src, span_warning("You decide not to transition."))
diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
index ea33b588bde..7fd294c6955 100644
--- a/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/vore/vore.dm
@@ -11,6 +11,7 @@
. = ..()
add_verb(src, /mob/living/simple_mob/proc/set_name)
add_verb(src, /mob/living/simple_mob/proc/set_desc)
+ add_verb(src, /mob/living/simple_mob/proc/set_gender)
if(copy_prefs_to_mob)
login_prefs()
@@ -73,5 +74,14 @@
if(newdesc)
desc = newdesc
+/mob/living/simple_mob/proc/set_gender()
+ set name = "Set Gender"
+ set desc = "Set your gender."
+ set category = "Abilities.Settings"
+ var/newgender
+ newgender = tgui_input_list(src, "Please select a gender:", "Set Gender", list(FEMALE, MALE, NEUTER, PLURAL))
+ if(newgender)
+ gender = newgender
+
/mob/living/simple_mob/vore/aggressive
mob_bump_flag = HEAVY
diff --git a/code/modules/overmap/sectors.dm b/code/modules/overmap/sectors.dm
index 327cca74ad1..e8f4ad79651 100644
--- a/code/modules/overmap/sectors.dm
+++ b/code/modules/overmap/sectors.dm
@@ -68,7 +68,9 @@
if(!docking_codes)
docking_codes = "[ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))][ascii2text(rand(65,90))]"
+ #ifdef TESTING
testing("Located sector \"[name]\" at [start_x],[start_y], containing Z [english_list(map_z)]")
+ #endif
LAZYADD(SSshuttles.sectors_to_initialize, src) //Queued for further init. Will populate the waypoint lists; waypoints not spawned yet will be added in as they spawn.
SSshuttles.process_init_queues()
diff --git a/code/modules/power/fusion/fusion_reactions.dm b/code/modules/power/fusion/fusion_reactions.dm
index 73c277cc42d..d0617f94dec 100644
--- a/code/modules/power/fusion/fusion_reactions.dm
+++ b/code/modules/power/fusion/fusion_reactions.dm
@@ -17,8 +17,7 @@ var/list/fusion_reactions
/proc/get_fusion_reaction(var/p_react, var/s_react, var/m_energy)
if(!fusion_reactions)
fusion_reactions = list()
- for(var/rtype in subtypesof(/decl/fusion_reaction)
- )
+ for(var/rtype in subtypesof(/decl/fusion_reaction))
var/decl/fusion_reaction/cur_reaction = new rtype()
if(!fusion_reactions[cur_reaction.p_react])
fusion_reactions[cur_reaction.p_react] = list()
diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm
index e66a4ac11ce..c80653d532f 100644
--- a/code/modules/projectiles/guns/energy/special.dm
+++ b/code/modules/projectiles/guns/energy/special.dm
@@ -56,6 +56,7 @@
list(mode_name="induce mutations", projectile_type=/obj/item/projectile/energy/floramut, modifystate="floramut"),
list(mode_name="increase yield", projectile_type=/obj/item/projectile/energy/florayield, modifystate="florayield"),
list(mode_name="induce specific mutations", projectile_type=/obj/item/projectile/energy/floramut/gene, modifystate="floramut"),
+ list(mode_name="prune reagents", projectile_type=/obj/item/projectile/energy/floraprune, modifystate="floramut"),
)
/obj/item/gun/energy/floragun/Initialize()
@@ -121,6 +122,7 @@
var/obj/item/projectile/energy/floramut/gene/G = .
var/obj/item/projectile/energy/florayield/GY = .
var/obj/item/projectile/energy/floramut/GM = .
+ var/obj/item/projectile/energy/floraprune/GP = .
// Inserting the upgrade level of the gun to the projectile as there isn't a better way to do this.
if(istype(G))
G.gene = gene
@@ -129,6 +131,8 @@
GY.lasermod = emitter.rating
else if(istype(GM))
GM.lasermod = emitter.rating
+ else if(istype(GP))
+ GP.lasermod = emitter.rating
/obj/item/gun/energy/meteorgun
name = "meteor gun"
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index 285be34a335..1997e7a2e69 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -221,6 +221,32 @@
else
return 1
+/obj/item/projectile/energy/floraprune
+ name = "delta somatoray"
+ icon_state = "energy2"
+ fire_sound = 'sound/effects/stealthoff.ogg'
+ damage = 0
+ damage_type = TOX
+ nodamage = 1
+ check_armour = "energy"
+ light_range = 2
+ light_power = 0.5
+ light_color = "#FFFFFF"
+ impact_effect_type = /obj/effect/temp_visual/impact_effect/monochrome_laser
+ var/lasermod = 0
+ hud_state = "electrothermal"
+
+/obj/item/projectile/energy/floraprune/on_hit(var/atom/target, var/blocked = 0)
+ var/mob/living/M = target
+ if(ishuman(target)) //Make plantpeople thin, seeing as we're removing reagents from actual plants
+ var/mob/living/carbon/human/H = M
+ if((H.species.flags & IS_PLANT) && (M.nutrition > 30))
+ M.adjust_nutrition(-30)
+ else if (istype(target, /mob/living/carbon/))
+ M.show_message(span_blue("The radiation beam dissipates harmlessly through your body."))
+ else
+ return 1
+
/obj/item/projectile/beam/mindflayer
name = "flayer ray"
diff --git a/code/modules/random_map/automata/caves.dm b/code/modules/random_map/automata/caves.dm
index 9783c77541b..6fb4d8bcb83 100644
--- a/code/modules/random_map/automata/caves.dm
+++ b/code/modules/random_map/automata/caves.dm
@@ -27,7 +27,9 @@
if (CELL_ALIVE(map[tmp_cell]))
ore_turfs += tmp_cell
+ #ifdef TESTING
testing("ASGEN: Found [ore_turfs.len] ore turfs.")
+ #endif
var/ore_count = round(map.len/20)
var/door_count = 0
var/empty_count = 0
@@ -46,8 +48,10 @@
empty_count += 1
ore_count--
+ #ifdef TESTING
testing("ASGEN: Set [door_count] turfs to random minerals.")
testing("ASGEN: Set [empty_count] turfs to high-chance random minerals.")
+ #endif
return 1
/datum/random_map/automata/cave_system/apply_to_turf(var/x,var/y)
diff --git a/code/modules/reagents/machinery/dispenser/cartridge_presets_vr.dm b/code/modules/reagents/machinery/dispenser/cartridge_presets_vr.dm
index 08f50c48985..698ac70d9d7 100644
--- a/code/modules/reagents/machinery/dispenser/cartridge_presets_vr.dm
+++ b/code/modules/reagents/machinery/dispenser/cartridge_presets_vr.dm
@@ -1,17 +1,38 @@
-/obj/item/reagent_containers/chem_disp_cartridge
- //Xenoflora
- ammonia spawn_reagent = REAGENT_ID_AMMONIA
- diethylamine spawn_reagent = REAGENT_ID_DIETHYLAMINE
- plantbgone spawn_reagent = REAGENT_ID_PLANTBGONE
- mutagen spawn_reagent = REAGENT_ID_MUTAGEN
+//Xenoflora
- //Biochem
- nutriment spawn_reagent = REAGENT_ID_NUTRIMENT
- protein spawn_reagent = REAGENT_ID_PROTEIN
+/obj/item/reagent_containers/chem_disp_cartridge/ammonia
+ spawn_reagent = REAGENT_ID_AMMONIA
- //Special Ops
- biomass spawn_reagent = REAGENT_ID_BIOMASS
- carthatoline spawn_reagent = REAGENT_ID_CARTHATOLINE
- corophizine spawn_reagent = REAGENT_ID_COROPHIZINE
- myelamine spawn_reagent = REAGENT_ID_MYELAMINE
- osteodaxon spawn_reagent = REAGENT_ID_OSTEODAXON
+/obj/item/reagent_containers/chem_disp_cartridge/diethylamine
+ spawn_reagent = REAGENT_ID_DIETHYLAMINE
+
+/obj/item/reagent_containers/chem_disp_cartridge/plantbgone
+ spawn_reagent = REAGENT_ID_PLANTBGONE
+
+/obj/item/reagent_containers/chem_disp_cartridge/mutagen
+ spawn_reagent = REAGENT_ID_MUTAGEN
+
+//Biochem
+
+/obj/item/reagent_containers/chem_disp_cartridge/nutriment
+ spawn_reagent = REAGENT_ID_NUTRIMENT
+
+/obj/item/reagent_containers/chem_disp_cartridge/protein
+ spawn_reagent = REAGENT_ID_PROTEIN
+
+//Special Ops
+
+/obj/item/reagent_containers/chem_disp_cartridge/biomass
+ spawn_reagent = REAGENT_ID_BIOMASS
+
+/obj/item/reagent_containers/chem_disp_cartridge/carthatoline
+ spawn_reagent = REAGENT_ID_CARTHATOLINE
+
+/obj/item/reagent_containers/chem_disp_cartridge/corophizine
+ spawn_reagent = REAGENT_ID_COROPHIZINE
+
+/obj/item/reagent_containers/chem_disp_cartridge/myelamine
+ spawn_reagent = REAGENT_ID_MYELAMINE
+
+/obj/item/reagent_containers/chem_disp_cartridge/osteodaxon
+ spawn_reagent = REAGENT_ID_OSTEODAXON
diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm
index cbbb56b8720..32833767b27 100644
--- a/code/modules/reagents/reagent_containers/blood_pack.dm
+++ b/code/modules/reagents/reagent_containers/blood_pack.dm
@@ -109,3 +109,11 @@
desc = "Seems pretty useless... Maybe if there were a way to fill it?"
icon_state = "empty"
item_state = "bloodpack_empty"
+
+/obj/item/reagent_containers/blood/random_bloodsucker
+ name = "Ration BloodPack"
+ desc = "A standard issue BloodPack Ration given to crew that require blood to be sustained!"
+
+/obj/item/reagent_containers/blood/random_bloodsucker/Initialize()
+ blood_type = pick("A+", "A-", "B+", "B-", "O-", "O+", "AB+", "AB-")
+ . = ..()
diff --git a/code/modules/scripting/AST/AST Nodes.dm b/code/modules/scripting/AST/AST Nodes.dm
index ceeacdcdc30..0ab6a901188 100644
--- a/code/modules/scripting/AST/AST Nodes.dm
+++ b/code/modules/scripting/AST/AST Nodes.dm
@@ -12,8 +12,7 @@
Articles:
-
*/
-var
- const
+
/*
Constants: Operator Precedence
OOP_OR - Logical or
@@ -27,16 +26,16 @@ var
OOP_UNARY - Unary Operators
OOP_GROUP - Parentheses
*/
- OOP_OR = 1 //||
- OOP_AND = OOP_OR + 1 //&&
- OOP_BIT = OOP_AND + 1 //&, |
- OOP_EQUAL = OOP_BIT + 1 //==, !=
- OOP_COMPARE = OOP_EQUAL + 1 //>, <, >=, <=
- OOP_ADD = OOP_COMPARE + 1 //+, -
- OOP_MULTIPLY= OOP_ADD + 1 //*, /, %
- OOP_POW = OOP_MULTIPLY+ 1 //^
- OOP_UNARY = OOP_POW + 1 //!
- OOP_GROUP = OOP_UNARY + 1 //()
+var/const/OOP_OR = 1 // ||
+var/const/OOP_AND = OOP_OR + 1 // &&
+var/const/OOP_BIT = OOP_AND + 1 // &, |
+var/const/OOP_EQUAL = OOP_BIT + 1 // ==, !=
+var/const/OOP_COMPARE = OOP_EQUAL + 1 // >, <, >=, <=
+var/const/OOP_ADD = OOP_COMPARE + 1 // +, -
+var/const/OOP_MULTIPLY= OOP_ADD + 1 // *, /, %
+var/const/OOP_POW = OOP_MULTIPLY + 1 // ^
+var/const/OOP_UNARY = OOP_POW + 1 // !
+var/const/OOP_GROUP = OOP_UNARY + 1 // ()
/*
Class: node
diff --git a/code/modules/tgui_input/say_modal/modal.dm b/code/modules/tgui_input/say_modal/modal.dm
index 30f5805f46a..17f229da499 100644
--- a/code/modules/tgui_input/say_modal/modal.dm
+++ b/code/modules/tgui_input/say_modal/modal.dm
@@ -130,4 +130,8 @@
if(type == "entry" || type == "force")
handle_entry(type, payload)
return TRUE
+ if(type == "lenwarn")
+ var/mlen = payload["length"]
+ var/maxlen = payload["maxlength"]
+ to_chat(client, span_warning(span_bold("Warning") + ": Message with [mlen] exceeded the maximum length of [maxlen]."))
return FALSE
diff --git a/html/changelogs/archive/2025-02.yml b/html/changelogs/archive/2025-02.yml
new file mode 100644
index 00000000000..c319ff27437
--- /dev/null
+++ b/html/changelogs/archive/2025-02.yml
@@ -0,0 +1,44 @@
+2025-02-15:
+ ItsSelis:
+ - rscadd: Automatic changelog generation & compilation
+ - code_imp: Changelog buttons now pointing to the autochangelogs instead of opening
+ the wiki
+2025-02-18:
+ ItsSelis:
+ - refactor: moved one global var to a managed global (to test the workflow change)
+ Kashargul:
+ - qol: prevents too long messages from being sent in tgui say
+2025-02-19:
+ TheGreatKitsune:
+ - qol: Adds text to art canvas descriptions indicating their size
+2025-02-20:
+ TheGreatKitsune:
+ - rscadd: Add a button to set gender of simplemobs
+2025-02-21:
+ Cameron-The-Raven:
+ - bugfix: build mode dropped items will no longer always gib
+ KillianKirilenko:
+ - rscadd: lockpick sets can now be found as part of the contraband pool in maint
+ items (useless on station though)
+ - rscadd: lockpick sets can now be used to pick fence gates as well
+ - image: resprited the basic lockpick set
+2025-02-22:
+ NickBelmont:
+ - rscadd: Reagent-removing 'Pruning mode' to the floral somatoray
+ Tost:
+ - qol: Changed nail polish's size to small
+ - code_imp: Added w_class = ITEMSIZE_SMALL to nail polish, which was missing originally.
+2025-02-23:
+ Cameron-The-Raven:
+ - bugfix: Snake tail no longer has a stray white void pixel following you 24/7 when
+ facing south
+ - bugfix: pizza vouchers will no longer land with such speed that they gib any user,
+ even if not emagged.
+ - bugfix: no more crashing as a ghost
+2025-02-24:
+ Cameron-The-Raven:
+ - rscadd: Vampiric crew now have a source of nutrition in the loadout under the
+ Utility tab!
+ ItsSelis:
+ - code_imp: disabled some testing logs by default (now require -DTESTING to be set
+ while compiling)
diff --git a/icons/mob/human_races/sprite_accessories/tails.dmi b/icons/mob/human_races/sprite_accessories/tails.dmi
index d81f83d241c..8ea69813b2b 100644
Binary files a/icons/mob/human_races/sprite_accessories/tails.dmi and b/icons/mob/human_races/sprite_accessories/tails.dmi differ
diff --git a/icons/obj/lockpicks.dmi b/icons/obj/lockpicks.dmi
index 11880cd0f52..13a284098b8 100644
Binary files a/icons/obj/lockpicks.dmi and b/icons/obj/lockpicks.dmi differ
diff --git a/maps/~map_system/_map_selection.dm b/maps/~map_system/_map_selection.dm
index c02812bf5ec..1103735a7d5 100644
--- a/maps/~map_system/_map_selection.dm
+++ b/maps/~map_system/_map_selection.dm
@@ -5,8 +5,8 @@
/* FOR LIVE SERVER */
/*********************/
-//#define USE_MAP_TETHER
-#define USE_MAP_STELLARDELIGHT
+#define USE_MAP_TETHER
+//#define USE_MAP_STELLARDELIGHT
//#define USE_MAP_GROUNDBASE
// Debug
diff --git a/tgui/packages/tgui-say/TguiSay.tsx b/tgui/packages/tgui-say/TguiSay.tsx
index f7a45487613..c2b5cea6909 100644
--- a/tgui/packages/tgui-say/TguiSay.tsx
+++ b/tgui/packages/tgui-say/TguiSay.tsx
@@ -51,7 +51,7 @@ export function TguiSay() {
keyof typeof RADIO_PREFIXES | null
>(null);
const [size, setSize] = useState(WindowSize.Small);
- const [maxLength, setMaxLength] = useState(1024);
+ const [maxLength, setMaxLength] = useState(4096);
const [minimumHeight, setMinimumHeight] = useState(WindowSize.Small);
const [minimumWidth, setMinimumWidth] = useState(WindowSize.Width);
const [lightMode, setLightMode] = useState(false);
@@ -117,14 +117,21 @@ export function TguiSay() {
const iterator = channelIterator.current;
const prefix = currentPrefix ?? '';
- if (value?.length && value.length < maxLength) {
- chatHistory.current.add(value);
- Byond.sendMessage('entry', {
- channel: iterator.current(),
- entry: iterator.isSay() ? prefix + value : value,
- });
+ if (value?.length) {
+ if (value.length < maxLength) {
+ chatHistory.current.add(value);
+ Byond.sendMessage('entry', {
+ channel: iterator.current(),
+ entry: iterator.isSay() ? prefix + value : value,
+ });
+ } else {
+ Byond.sendMessage('lenwarn', {
+ length: value.length,
+ maxlength: maxLength,
+ });
+ return;
+ }
}
-
handleClose();
}
diff --git a/tools/pull_request_hooks/changelogParser.js b/tools/pull_request_hooks/changelogParser.js
index 76e9e216c03..ba572d24b40 100644
--- a/tools/pull_request_hooks/changelogParser.js
+++ b/tools/pull_request_hooks/changelogParser.js
@@ -42,7 +42,7 @@ function parseChangelogBody(lines, openTag) {
const entry = CHANGELOG_KEYS_TO_ENTRY[type] || CHANGELOG_KEYS_TO_ENTRY["rscadd"];
- if (entry.placeholders.includes(description)) {
+ if (!entry || entry.placeholders.includes(description)) {
continue;
}
@@ -64,6 +64,9 @@ function parseChangelogBody(lines, openTag) {
}
export function parseChangelog(text) {
+ if(text == null) {
+ return undefined;
+ }
const lines = text.split("\n").map((line) => line.trim());
for (let index = 0; index < lines.length; index++) {