Skip to content

Commit

Permalink
Merge branch 'SPLURT-Station:master' into Lambda-and-meta-fixin
Browse files Browse the repository at this point in the history
  • Loading branch information
SaraSayomi authored Sep 14, 2024
2 parents 5bb7358 + ada3d2e commit a8d0602
Show file tree
Hide file tree
Showing 21 changed files with 239 additions and 86 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci_suite.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
run_linters:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
name: Run Linters
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: Restore SpacemanDMM cache
Expand Down Expand Up @@ -54,7 +54,7 @@ jobs:
compile_all_maps:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
name: Compile Maps
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- name: Restore BYOND cache
Expand Down
Empty file added .gitmodules
Empty file.
1 change: 1 addition & 0 deletions code/datums/elements/mob_holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
I.layer = FLOAT_LAYER //So it doesn't get screwed up by layer overrides.
I.plane = FLOAT_PLANE //Same as above but for planes.
I.override = TRUE
I.transform = null
add_overlay(I)
name = target.name
desc = target.desc
Expand Down
81 changes: 75 additions & 6 deletions code/modules/client/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -483,17 +483,25 @@ GLOBAL_LIST_EMPTY(preferences_datums)
dat += "<HR>"

dat += "<center>"
var/client_file = user.client.Import()
var/savefile/client_file = new(user.client.Import())
var/savefile_name
if(client_file)
var/savefile/cache_savefile = new(user.client.Import())
if(!cache_savefile["deleted"] || savefile_needs_update(cache_savefile) != -2)
cache_savefile["real_name"] >> savefile_name
if(istype(client_file, /savefile))
if(!client_file["deleted"] || savefile_needs_update(client_file) != -2)
client_file["real_name"] >> savefile_name
dat += "Local storage: [savefile_name ? savefile_name : "Empty"]"
dat += "<br />"
dat += "<a href='?_src_=prefs;preference=export_slot'>Export current slot</a>"
dat += "<a [savefile_name ? "href='?_src_=prefs;preference=import_slot' style='white-space:normal;'" : "class='linkOff'"]>Import into current slot</a>"
dat += "<a href='?_src_=prefs;preference=delete_local_copy' style='white-space:normal;background:#eb2e2e;'>Delete locally saved character</a>"
dat += "<br />"
dat += "<a href='?_src_=prefs;preference=give_slot' [offer ? "style='white-space:normal;background:#eb2e2e;'" : ""]>[offer ? "Cancel offer" : "Offer slot"]</a>"
dat += "<a href='?_src_=prefs;preference=retrieve_slot'>Retrieve offered character</a>"
if(offer)
dat += "<br />"
dat += "The redemption code is <b>[offer.redemption_code]</b>"
dat += "<br />"
dat += "The offer will automatically be cancelled if there is an error, or if someone takes it"

dat += "</center>"

dat += "<HR>"
Expand Down Expand Up @@ -4065,8 +4073,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if("import_slot")
var/savefile/S = new(user.client.Import())
if(istype(S, /savefile))
if(load_character(provided = S) == TRUE)
if(load_character(provided = S))
tgui_alert_async(user, "Successfully loaded character slot.")
save_character(TRUE)
else
tgui_alert_async(user, "Failed loading character slot")
return
Expand All @@ -4078,6 +4087,66 @@ GLOBAL_LIST_EMPTY(preferences_datums)
user.client.clear_export()
tgui_alert_async(user, "Local save data erased.")

if("give_slot")
if(!QDELETED(offer))
var/datum/character_offer_instance/offer_datum = LAZYACCESS(GLOB.character_offers, offer.redemption_code)
if(!offer_datum)
return
qdel(offer_datum)
else
var/savefile/S = save_character(export = TRUE)
if(istype(S, /savefile))
var/datum/character_offer_instance/offer_datum = new(usr.ckey, S)
if(QDELETED(offer_datum))
tgui_alert_async(usr, "Could not set up offer, try again later")
return
offer_datum.RegisterSignal(usr, COMSIG_MOB_CLIENT_LOGOUT, TYPE_PROC_REF(/datum/character_offer_instance, on_quit))
offer = offer_datum
tgui_alert_async(usr, "The redemption code is [offer_datum.redemption_code], give it to the receiver")

if("retrieve_slot")
if(!LAZYLEN(GLOB.character_offers))
tgui_alert_async(usr, "There are no active offers")
return
var/retrieve_code = input(usr, "Input the 5 digit redemption code") as text|null
if(!retrieve_code)
return
if(!text2num(retrieve_code))
tgui_alert_async(usr, "Only numbers allowed")
return
if(length(retrieve_code) != 5)
tgui_alert_async(usr, "Exactly 5 digits, no less, no more, try again")
return
var/datum/character_offer_instance/offer_datum = LAZYACCESS(GLOB.character_offers, retrieve_code)
if(!offer_datum)
tgui_alert_async(usr, "This is an invalid code!")
return
if(offer == offer_datum)
tgui_alert_async(usr, "You cannot accept your own offer")
return
var/savefile/savefile = offer_datum.character_savefile
var/mob/living/the_owner = get_mob_by_ckey(offer_datum.owner_ckey)
if(savefile_needs_update(savefile) == -2)
tgui_alert_async(usr, "Something's wrong, this savefile is corrupted.")
to_chat(the_owner, span_boldwarning("Something went wrong with the trade, it's been canceled."))
qdel(offer_datum)
return
var/character_name = savefile["real_name"]
if(alert(usr, "You are overwriting the currently selected slot with the character [character_name]", "Are you sure?", "Yes, load this character deleting the currently selected slot", "No") == "No")
return
if(QDELETED(offer_datum))
tgui_alert_async(usr, "This character is no longer available, such a shame!")
return
to_chat(the_owner, span_boldwarning("[usr.key] has retrieved your character, [character_name]!"))
if(!load_character(provided = savefile))
tgui_alert_async(usr, "Something went wrong loading the savefile, even though it has already been checked, please report this issue!")
to_chat(the_owner, span_boldwarning("Something went wrong at the final step of the trade, report this."))
qdel(offer_datum)
return
tgui_alert_async(usr, "Successfully received [character_name]!")
save_character(TRUE)
qdel(offer_datum)

if(href_list["preference"] == "gear")
if(href_list["clear_loadout"])
loadout_data["SAVE_[loadout_slot]"] = list()
Expand Down
2 changes: 1 addition & 1 deletion dependencies.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export NODE_VERSION_PRECISE=16.13.1
export SPACEMAN_DMM_VERSION=suite-1.8

# Python version for mapmerge and other tools
export PYTHON_VERSION=3.7.9
export PYTHON_VERSION=3.9.0

# Auxmos git tag
export AUXMOS_VERSION=v2.5.1
Expand Down
8 changes: 8 additions & 0 deletions html/changelogs/archive/2024-09.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
2024-09-07:
MosleyTheMalO:
- bugfix: Fixes the overall sprite
- rscadd: adds a new polychromic sprite
- rscadd: donator item
SandPoot:
- rscadd: Added Character offering system, exchange characters with people you want
to!
116 changes: 50 additions & 66 deletions modular_sand/code/datums/elements/holder_micro.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
var/mob/living/living = get_atom_on_turf(micro.loc, /mob/living)
if(living && (COMPARE_SIZES(living, micro)) < (1 / CONFIG_GET(number/max_pick_ratio)))
living.visible_message(span_warning("\The [living] drops [micro] as [micro.p_they()] grow\s too big to carry."),
span_warning("You drop \The [living] as [living.p_they()] grow\s too big to carry."),
target=micro,
target_message=span_notice("\The [living] drops you as you grow too big to carry."))
span_warning("You drop \The [living] as [living.p_they()] grow\s too big to carry."),
target = micro,
target_message = span_notice("\The [living] drops you as you grow too big to carry."))
holder.release()
else if(!istype(living)) // Somehow a inside a mob_holder and the mob_holder isn't inside any livings? release.
holder.release()
Expand Down Expand Up @@ -56,7 +56,7 @@
return

/datum/element/mob_holder/micro/proc/mob_try_pickup_micro(mob/living/carbon/source, mob/living/carbon/user)
if(!(user.a_intent == INTENT_GRAB))
if(user.a_intent != INTENT_GRAB)
return FALSE
if(!ishuman(user) || !user.Adjacent(source) || user.incapacitated())
return FALSE
Expand All @@ -77,7 +77,7 @@
source.balloon_alert(user, "buckled to something!")
return FALSE
source.visible_message(span_warning("[user] starts picking up [source]."), \
span_userdanger("[user] starts picking you up!"))
span_userdanger("[user] starts picking you up!"))
source.balloon_alert(user, "picking up")
var/time_required = COMPARE_SIZES(source, user) * 4 SECONDS //Scale how fast the pickup will be depending on size difference
if(!do_after(user, time_required, source))
Expand All @@ -93,9 +93,9 @@
return FALSE

source.visible_message(span_warning("[user] picks up [source]!"),
span_userdanger("[user] picks you up!"),
target = user,
target_message = span_notice("You pick [source] up."))
span_userdanger("[user] picks you up!"),
target = user,
target_message = span_notice("You pick [source] up."))
source.drop_all_held_items()
mob_pickup_micro(source, user)
return TRUE
Expand All @@ -108,57 +108,51 @@
slot_flags = ITEM_SLOT_FEET | ITEM_SLOT_HEAD | ITEM_SLOT_ID | ITEM_SLOT_BACK | ITEM_SLOT_NECK
w_class = null //handled by their size

/obj/item/clothing/head/mob_holder/micro/container_resist(mob/living/user)
if(user.incapacitated())
to_chat(user, span_warning("You can't escape while you're restrained like this!"))
/obj/item/clothing/head/mob_holder/micro/container_resist(mob/living/resisting)
if(resisting.incapacitated())
to_chat(resisting, span_warning("You can't escape while you're restrained like this!"))
return
var/mob/living/L = get_atom_on_turf(src, /mob/living)
visible_message(span_warning("[src] begins to squirm in [L]'s grasp!"))
var/time_required = COMPARE_SIZES(L, user) / 4 SECONDS //Scale how fast the resisting will be depending on size difference
if(!do_after(user, time_required, L, IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM))
if(!user || user.stat != CONSCIOUS || user.loc != src)
return
to_chat(loc, span_warning("[src] stops resisting."))
var/mob/living/carrier = get_atom_on_turf(src, /mob/living)
visible_message(span_warning("[resisting] begins to squirm in [carrier]'s grasp!"))
var/time_required = COMPARE_SIZES(carrier, resisting) / 4 SECONDS //Scale how fast the resisting will be depending on size difference
if(do_after(resisting, time_required, carrier, IGNORE_TARGET_LOC_CHANGE | IGNORE_HELD_ITEM))
visible_message(span_warning("[src] escapes [carrier]!"))
release()
return
visible_message("<span class='warning'>[src] escapes [L]!")
release()

/obj/item/clothing/head/mob_holder/micro/MouseDrop(mob/M as mob)
..()
if(M != usr)
if(QDELETED(resisting) || resisting.loc != src)
return
if(usr == src)
visible_message(span_warning("[src] stops resisting."))

/obj/item/clothing/head/mob_holder/micro/MouseDrop(mob/living/carbon/human/carrier)
. = ..()
if(carrier != usr)
return
if(!Adjacent(usr))
if(usr == held_mob)
return
if(istype(M,/mob/living/silicon/ai))
if(!(src in carrier.held_items))
return
var/mob/living/carbon/human/O = held_mob
if(istype(O))
O.MouseDrop(usr)
held_mob.MouseDrop(usr)

/obj/item/clothing/head/mob_holder/micro/attack_self(mob/living/user)
if(!user.CheckActionCooldown())
/obj/item/clothing/head/mob_holder/micro/attack_self(mob/living/carbon/human/bully)
if(!bully.CheckActionCooldown())
return
user.DelayNextAction(CLICK_CD_MELEE, flush = TRUE)
var/mob/living/carbon/human/M = held_mob
if(istype(M))
if(user.a_intent == "harm") //TO:DO, rework all of these interactions to be a lot more in depth
visible_message(span_danger("[user] slams their fist down on [M]!"), runechat_popup = TRUE, rune_msg = " slams their fist down on [M]!")
playsound(loc, 'sound/weapons/punch1.ogg', 50, 1)
M.adjustBruteLoss(5)
return
if(user.a_intent == "disarm")
visible_message(span_danger("[user] pins [M] down with a finger!"), runechat_popup = TRUE, rune_msg = " pins [M] down with a finger!")
playsound(loc, 'sound/effects/bodyfall1.ogg', 50, 1)
M.adjustStaminaLoss(10)
return
if(user.a_intent == "grab")
visible_message(span_danger("[user] squeezes their fist around [M]!"), runechat_popup = TRUE, rune_msg = " squeezes their fist around [M]!")
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1)
M.adjustOxyLoss(5)
return
M.help_shake_act(user)
bully.DelayNextAction(CLICK_CD_MELEE, flush = TRUE)
var/mob/living/carbon/bullied = held_mob
switch(bully.a_intent)
if(INTENT_HARM) //TO:DO, rework all of these interactions to be a lot more in depth
visible_message(span_danger("[bully] slams their fist down on [bullied]!"), runechat_popup = TRUE, rune_msg = " slams their fist down on [bullied]!")
playsound(drop_location(), 'sound/weapons/punch1.ogg', 50, 1)
bullied.adjustBruteLoss(5)
if(INTENT_DISARM)
visible_message(span_danger("[bully] pins [bullied] down with a finger!"), runechat_popup = TRUE, rune_msg = " pins [bullied] down with a finger!")
playsound(drop_location(), 'sound/effects/bodyfall1.ogg', 50, 1)
bullied.adjustStaminaLoss(10)
if(INTENT_GRAB)
visible_message(span_danger("[bully] squeezes their fist around [bullied]!"), runechat_popup = TRUE, rune_msg = " squeezes their fist around [bullied]!")
playsound(drop_location(), 'sound/weapons/thudswoosh.ogg', 50, 1)
bullied.adjustOxyLoss(5)
else
bullied.help_shake_act(bully)

/obj/item/clothing/head/mob_holder/micro/attacked_by(obj/item/I, mob/living/user)
return held_mob?.attacked_by(I, user) || ..()
Expand All @@ -173,21 +167,11 @@
user.vore_attack(user, held_mob, pred)
return STOP_ATTACK_PROC_CHAIN

/obj/item/clothing/head/mob_holder/micro/verb/interact_with()
set name = "Interact With"
set desc = "Perform an interaction with someone."
set category = "IC"
set src in view(usr.client)

var/datum/component/interaction_menu_granter/menu = usr.GetComponent(/datum/component/interaction_menu_granter)
if(!menu)
to_chat(usr, span_warning("You must have done something really bad to not have an interaction component."))
return

if(!src)
to_chat(usr, span_warning("Your interaction target is gone!"))
return
menu.open_menu(usr, held_mob)
/obj/item/clothing/head/mob_holder/micro/Exited(mob/living/vored, direction)
if(istype(vored.loc, /obj/belly))
held_mob = null
qdel(src)
return ..()

/obj/item/clothing/head/mob_holder/micro/GetAccess()
. = ..()
Expand Down
41 changes: 41 additions & 0 deletions modular_sand/code/modules/character_giving/character_giving.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#define REDEMPTION_CODE_GENERATION_ATTEMPTS 5

GLOBAL_LIST_INIT(character_offers, list())

/datum/character_offer_instance
var/owner_ckey
var/savefile/character_savefile
var/redemption_code

/datum/character_offer_instance/New(owner_ckey, character_savefile)
. = ..()
if(!owner_ckey || !character_savefile)
qdel(src)
return
src.owner_ckey = owner_ckey
src.character_savefile = character_savefile

// 5 digit number, no fucking way some idiot is guessing this
var/attempts = 0
while(!redemption_code || LAZYFIND(GLOB.character_offers, redemption_code))
if(attempts >= REDEMPTION_CODE_GENERATION_ATTEMPTS)
qdel(src)
return
redemption_code = "[random_nukecode()]"
attempts++

LAZYSET(GLOB.character_offers, redemption_code, src)

/datum/character_offer_instance/Destroy(force, ...)
var/datum/preferences/to_remove = LAZYACCESS(GLOB.preferences_datums, owner_ckey)
to_remove.offer = null
LAZYREMOVE(GLOB.character_offers, redemption_code)
owner_ckey = null
character_savefile = null
redemption_code = null
return ..()

/datum/character_offer_instance/proc/on_quit()
qdel(src)

#undef REDEMPTION_CODE_GENERATION_ATTEMPTS
2 changes: 2 additions & 0 deletions modular_sand/code/modules/client/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
/// Chance of moaning during an interaction
var/moaning_multiplier = 65

var/datum/character_offer_instance/offer

//SANDSTORM EDIT - extra language
/datum/preferences/proc/SetLanguage(mob/user)
var/list/dat = list()
Expand Down
15 changes: 15 additions & 0 deletions modular_splurt/code/datums/elements/holder_micro.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/obj/item/clothing/head/mob_holder/micro/verb/interact_with()
set name = "Interact With"
set desc = "Perform an interaction with someone."
set category = "IC"
set src in view(usr.client)

var/datum/component/interaction_menu_granter/menu = usr.GetComponent(/datum/component/interaction_menu_granter)
if(!menu)
to_chat(usr, span_warning("You must have done something really bad to not have an interaction component."))
return

if(!src)
to_chat(usr, span_warning("Your interaction target is gone!"))
return
menu.open_menu(usr, held_mob)
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,10 @@
path = /obj/item/clothing/shoes/clown_shoes/jester
ckeywhitelist = list()
donator_group_id = DONATOR_GROUP_TIER_1

//Shoes
/datum/gear/donator/shoes/chameleon_suits
name = "Chameleon Shoes"
path = /obj/item/clothing/shoes/chameleon
ckeywhitelist = list()
donator_group_id = DONATOR_GROUP_TIER_1
Loading

0 comments on commit a8d0602

Please sign in to comment.