Merge remote-tracking branch 'upstream/master'
This commit is contained in:
+128296
-128296
File diff suppressed because it is too large
Load Diff
@@ -101,6 +101,7 @@
|
||||
#define NO_AUTO_WAG (1<<12)
|
||||
#define GENITAL_EXAMINE (1<<13)
|
||||
#define VORE_EXAMINE (1<<14)
|
||||
#define TRASH_FORCEFEED (1<<15)
|
||||
#define TOGGLES_CITADEL 0
|
||||
|
||||
//belly sound pref things
|
||||
|
||||
@@ -81,7 +81,6 @@
|
||||
#define CAT_AMMO "Ammunition"
|
||||
#define CAT_PARTS "Weapon Parts"
|
||||
#define CAT_ROBOT "Robots"
|
||||
#define CAT_MISC "Misc"
|
||||
#define CAT_MISCELLANEOUS "Miscellaneous"
|
||||
#define CAT_TOOL "Tools & Storage"
|
||||
#define CAT_FURNITURE "Furniture"
|
||||
|
||||
@@ -159,6 +159,18 @@
|
||||
#define TINT_DARKENED 2 //Threshold of tint level to apply weld mask overlay
|
||||
#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully
|
||||
|
||||
// defines for AFK theft
|
||||
/// How many messages you can remember while logged out before you stop remembering new ones
|
||||
#define AFK_THEFT_MAX_MESSAGES 10
|
||||
/// If someone logs back in and there are entries older than this, just tell them they can't remember who it was or when
|
||||
#define AFK_THEFT_FORGET_DETAILS_TIME 5 MINUTES
|
||||
/// The index of the entry in 'afk_thefts' with the person's visible name at the time
|
||||
#define AFK_THEFT_NAME 1
|
||||
/// The index of the entry in 'afk_thefts' with the text
|
||||
#define AFK_THEFT_MESSAGE 2
|
||||
/// The index of the entry in 'afk_thefts' with the time it happened
|
||||
#define AFK_THEFT_TIME 3
|
||||
|
||||
//Allowed equipment lists for security vests and hardsuits.
|
||||
|
||||
GLOBAL_LIST_INIT(advanced_hardsuit_allowed, typecacheof(list(
|
||||
|
||||
@@ -221,6 +221,7 @@
|
||||
#define TRAIT_LIVING_NO_DENSITY "living_no_density"
|
||||
/// forces us to not render our overlays
|
||||
#define TRAIT_HUMAN_NO_RENDER "human_no_render"
|
||||
#define TRAIT_TRASHCAN "trashcan"
|
||||
|
||||
// mobility flag traits
|
||||
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
|
||||
|
||||
@@ -8,17 +8,22 @@
|
||||
#define DM_UNABSORB "Un-absorb"
|
||||
|
||||
#define DIGESTABLE (1<<0)
|
||||
#define SHOW_VORE_PREFS (1<<1)
|
||||
#define DEVOURABLE (1<<2)
|
||||
#define FEEDING (1<<3)
|
||||
#define NO_VORE (1<<4)
|
||||
#define OPEN_PANEL (1<<5)
|
||||
#define ABSORBED (1<<6)
|
||||
#define VORE_INIT (1<<7)
|
||||
#define VOREPREF_INIT (1<<8)
|
||||
#define LICKABLE (1<<9)
|
||||
#define DEVOURABLE (1<<1)
|
||||
#define FEEDING (1<<2)
|
||||
#define NO_VORE (1<<3)
|
||||
#define ABSORBED (1<<4)
|
||||
#define VORE_INIT (1<<5)
|
||||
#define VOREPREF_INIT (1<<6)
|
||||
#define LICKABLE (1<<7)
|
||||
/// Can be smelled?
|
||||
#define SMELLABLE (1<<8)
|
||||
/// Can get absorbed?
|
||||
#define ABSORBABLE (1<<9)
|
||||
/// Can get simplemob vored?
|
||||
#define MOBVORE (1<<10)
|
||||
|
||||
#define MAX_VORE_FLAG (1<<10)-1 // change this whenever you add a vore flag, must be largest vore flag*2-1
|
||||
/// Change this whenever you add a vore flag, must be largest vore flag*2-1
|
||||
#define MAX_VORE_FLAG (1<<11)-1
|
||||
|
||||
#define isbelly(A) istype(A, /obj/belly)
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
|
||||
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
|
||||
#define LAZYLEN(L) length(L)
|
||||
//Sets a list to null
|
||||
#define LAZYNULL(L) L = null
|
||||
#define LAZYCLEARLIST(L) if(L) L.Cut()
|
||||
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
|
||||
#define reverseList(L) reverseRange(L.Copy())
|
||||
|
||||
@@ -112,6 +112,7 @@ GLOBAL_LIST_INIT(maintenance_loot, list(
|
||||
/obj/item/storage/box/marshmallow = 2,
|
||||
/obj/item/clothing/gloves/tackler/offbrand = 1,
|
||||
/obj/item/stack/sticky_tape = 1,
|
||||
/obj/effect/spawner/lootdrop/grille_or_trash = 15,
|
||||
"" = 3
|
||||
))
|
||||
|
||||
|
||||
@@ -1,491 +0,0 @@
|
||||
/datum/component/personal_crafting/Initialize()
|
||||
if(!ismob(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
|
||||
|
||||
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
|
||||
var/datum/hud/H = user.hud_used
|
||||
var/obj/screen/craft/C = new()
|
||||
C.icon = H.ui_style
|
||||
H.static_inventory += C
|
||||
if(!CL.prefs.widescreenpref)
|
||||
C.screen_loc = ui_boxcraft
|
||||
CL.screen += C
|
||||
RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact)
|
||||
|
||||
/datum/component/personal_crafting
|
||||
var/busy
|
||||
var/viewing_category = 1
|
||||
var/viewing_subcategory = 1
|
||||
var/list/categories = list(
|
||||
CAT_WEAPONRY = list(
|
||||
CAT_WEAPON,
|
||||
CAT_AMMO,
|
||||
),
|
||||
CAT_ROBOT = CAT_NONE,
|
||||
CAT_MISC = list(
|
||||
CAT_MISCELLANEOUS,
|
||||
CAT_TOOL,
|
||||
CAT_FURNITURE,
|
||||
),
|
||||
CAT_PRIMAL = CAT_NONE,
|
||||
CAT_FOOD = list(
|
||||
CAT_BREAD,
|
||||
CAT_BURGER,
|
||||
CAT_CAKE,
|
||||
CAT_DONUT,
|
||||
CAT_EGG,
|
||||
CAT_ICE,
|
||||
CAT_MEAT,
|
||||
CAT_MEXICAN,
|
||||
CAT_MISCFOOD,
|
||||
CAT_PASTRY,
|
||||
CAT_PIE,
|
||||
CAT_PIZZA,
|
||||
CAT_SEAFOOD,
|
||||
CAT_SALAD,
|
||||
CAT_SANDWICH,
|
||||
CAT_SOUP,
|
||||
CAT_SPAGHETTI,
|
||||
),
|
||||
CAT_DRINK = CAT_NONE,
|
||||
CAT_CLOTHING = CAT_NONE,
|
||||
)
|
||||
|
||||
var/cur_category = CAT_NONE
|
||||
var/cur_subcategory = CAT_NONE
|
||||
var/datum/action/innate/crafting/button
|
||||
var/display_craftable_only = FALSE
|
||||
var/display_compact = TRUE
|
||||
|
||||
|
||||
|
||||
|
||||
/* This is what procs do:
|
||||
get_environment - gets a list of things accessable for crafting by user
|
||||
get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
|
||||
check_contents - takes a recipe and a key-type list and checks if said recipe can be done with available stuff
|
||||
check_tools - takes recipe, a key-type list, and a user and checks if there are enough tools to do the stuff, checks bugs one level deep
|
||||
construct_item - takes a recipe and a user, call all the checking procs, calls do_after, checks all the things again, calls del_reqs, creates result, calls CheckParts of said result with argument being list returned by deel_reqs
|
||||
del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check that the contents of the recipe meet the requirements.
|
||||
*
|
||||
* user: The /mob that initated the crafting.
|
||||
* R: The /datum/crafting_recipe being attempted.
|
||||
* contents: List of items to search for R's reqs.
|
||||
*/
|
||||
/datum/component/personal_crafting/proc/check_contents(mob/user, datum/crafting_recipe/R, list/contents)
|
||||
var/list/item_instances = contents["instances"]
|
||||
contents = contents["other"]
|
||||
|
||||
var/list/requirements_list = list()
|
||||
|
||||
// Process all requirements
|
||||
for(var/requirement_path in R.reqs)
|
||||
// Check we have the appropriate amount available in the contents list
|
||||
var/needed_amount = R.reqs[requirement_path]
|
||||
for(var/content_item_path in contents)
|
||||
// Right path and not blacklisted
|
||||
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(requirement_path))
|
||||
continue
|
||||
|
||||
needed_amount -= contents[content_item_path]
|
||||
if(needed_amount <= 0)
|
||||
break
|
||||
|
||||
if(needed_amount > 0)
|
||||
return FALSE
|
||||
|
||||
// Store the instances of what we will use for R.check_requirements() for requirement_path
|
||||
var/list/instances_list = list()
|
||||
for(var/instance_path in item_instances)
|
||||
if(ispath(instance_path, requirement_path))
|
||||
instances_list += item_instances[instance_path]
|
||||
|
||||
requirements_list[requirement_path] = instances_list
|
||||
|
||||
for(var/requirement_path in R.chem_catalysts)
|
||||
if(contents[requirement_path] < R.chem_catalysts[requirement_path])
|
||||
return FALSE
|
||||
|
||||
return R.check_requirements(user, requirements_list)
|
||||
|
||||
/datum/component/personal_crafting/proc/get_environment(mob/user)
|
||||
. = list()
|
||||
for(var/obj/item/I in user.held_items)
|
||||
. += I
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
var/list/L = block(get_step(user, SOUTHWEST), get_step(user, NORTHEAST))
|
||||
for(var/A in L)
|
||||
var/turf/T = A
|
||||
if(T.Adjacent(user))
|
||||
for(var/B in T)
|
||||
var/atom/movable/AM = B
|
||||
if(AM.flags_1 & HOLOGRAM_1)
|
||||
continue
|
||||
. += AM
|
||||
for(var/slot in list(SLOT_R_STORE, SLOT_L_STORE))
|
||||
. += user.get_item_by_slot(slot)
|
||||
|
||||
/datum/component/personal_crafting/proc/get_surroundings(mob/user)
|
||||
. = list()
|
||||
.["tool_behaviour"] = list()
|
||||
.["other"] = list()
|
||||
.["instances"] = list()
|
||||
for(var/obj/item/I in get_environment(user))
|
||||
if(I.flags_1 & HOLOGRAM_1)
|
||||
continue
|
||||
if(.["instances"][I.type])
|
||||
.["instances"][I.type] += I
|
||||
else
|
||||
.["instances"][I.type] = list(I)
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/obj/item/stack/S = I
|
||||
.["other"][I.type] += S.amount
|
||||
else if(I.tool_behaviour)
|
||||
.["tool_behaviour"] += I.tool_behaviour
|
||||
.["other"][I.type] += 1
|
||||
else
|
||||
if(istype(I, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/RC = I
|
||||
if(RC.is_drainable())
|
||||
for(var/datum/reagent/A in RC.reagents.reagent_list)
|
||||
.["other"][A.type] += A.volume
|
||||
.["other"][I.type] += 1
|
||||
|
||||
/datum/component/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents)
|
||||
if(!R.tools.len)
|
||||
return TRUE
|
||||
var/list/possible_tools = list()
|
||||
var/list/present_qualities = list()
|
||||
present_qualities |= contents["tool_behaviour"]
|
||||
for(var/obj/item/I in user.contents)
|
||||
if(istype(I, /obj/item/storage))
|
||||
for(var/obj/item/SI in I.contents)
|
||||
possible_tools += SI.type
|
||||
if(SI.tool_behaviour)
|
||||
present_qualities.Add(SI.tool_behaviour)
|
||||
|
||||
possible_tools += I.type
|
||||
|
||||
if(I.tool_behaviour)
|
||||
present_qualities.Add(I.tool_behaviour)
|
||||
|
||||
possible_tools |= contents["other"]
|
||||
|
||||
main_loop:
|
||||
for(var/A in R.tools)
|
||||
if(A in present_qualities)
|
||||
continue
|
||||
else
|
||||
for(var/I in possible_tools)
|
||||
if(ispath(I, A))
|
||||
continue main_loop
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R)
|
||||
var/list/contents = get_surroundings(user)
|
||||
var/send_feedback = TRUE
|
||||
if(check_contents(user, R, contents))
|
||||
if(check_tools(user, R, contents))
|
||||
if(do_after(user, R.time, target = user))
|
||||
contents = get_surroundings(user)
|
||||
if(!check_contents(user, R, contents))
|
||||
return ", missing component."
|
||||
if(!check_tools(user, R, contents))
|
||||
return ", missing tool."
|
||||
var/list/parts = del_reqs(R, user)
|
||||
var/atom/movable/I = new R.result (get_turf(user.loc))
|
||||
I.CheckParts(parts, R)
|
||||
if(isitem(I))
|
||||
if(isfood(I))
|
||||
var/obj/item/reagent_containers/food/food_result = I
|
||||
var/total_quality = 0
|
||||
var/total_items = 0
|
||||
for(var/obj/item/reagent_containers/food/ingredient in parts)
|
||||
total_items += 1
|
||||
total_quality += ingredient.food_quality
|
||||
if(total_items == 0)
|
||||
food_result.adjust_food_quality(50)
|
||||
else
|
||||
food_result.adjust_food_quality(total_quality / total_items)
|
||||
user.put_in_hands(I)
|
||||
if(send_feedback)
|
||||
SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
|
||||
log_craft("[I] crafted by [user] at [loc_name(I.loc)]")
|
||||
return FALSE
|
||||
return "."
|
||||
return ", missing tool."
|
||||
return ", missing component."
|
||||
|
||||
|
||||
/*Del reqs works like this:
|
||||
|
||||
Loop over reqs var of the recipe
|
||||
Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
|
||||
Get var/surroundings list of things accessable to crafting by get_environment()
|
||||
Check the type of the current cycle req
|
||||
If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isnt remove thing from surroundings
|
||||
If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
|
||||
If there isnt enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
|
||||
While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
|
||||
If its stack check if it has enough amount
|
||||
If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
|
||||
If no put all of the stack in the deletion list, substract its amount from amt and keep searching
|
||||
While doing above stuff check deletion list if it already has such stack type, if yes try to merge them instead of adding new one
|
||||
If its anything else just locate() in in the list in a while loop, each find --s the amt var and puts the found stuff in deletion loop
|
||||
|
||||
Then do a loop over parts var of the recipe
|
||||
Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
|
||||
|
||||
After its done loop over deletion list and delete all the shit that wasnt taken by parts loop
|
||||
|
||||
del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
|
||||
*/
|
||||
|
||||
/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, mob/user)
|
||||
var/list/surroundings
|
||||
var/list/Deletion = list()
|
||||
. = list()
|
||||
var/data
|
||||
var/amt
|
||||
main_loop:
|
||||
for(var/A in R.reqs)
|
||||
amt = R.reqs[A]
|
||||
surroundings = get_environment(user)
|
||||
surroundings -= Deletion
|
||||
if(ispath(A, /datum/reagent))
|
||||
var/datum/reagent/RG = new A
|
||||
var/datum/reagent/RGNT
|
||||
while(amt > 0)
|
||||
var/obj/item/reagent_containers/RC = locate() in surroundings
|
||||
RG = RC.reagents.get_reagent(A)
|
||||
if(RG)
|
||||
if(!locate(RG.type) in Deletion)
|
||||
Deletion += new RG.type()
|
||||
if(RG.volume > amt)
|
||||
RG.volume -= amt
|
||||
data = RG.data
|
||||
RC.reagents.conditional_update(RC)
|
||||
RG = locate(RG.type) in Deletion
|
||||
RG.volume = amt
|
||||
RG.data += data
|
||||
continue main_loop
|
||||
else
|
||||
surroundings -= RC
|
||||
amt -= RG.volume
|
||||
RC.reagents.reagent_list -= RG
|
||||
RC.reagents.conditional_update(RC)
|
||||
RGNT = locate(RG.type) in Deletion
|
||||
RGNT.volume += RG.volume
|
||||
RGNT.data += RG.data
|
||||
qdel(RG)
|
||||
RC.on_reagent_change()
|
||||
else
|
||||
surroundings -= RC
|
||||
else if(ispath(A, /obj/item/stack))
|
||||
var/obj/item/stack/S
|
||||
var/obj/item/stack/SD
|
||||
while(amt > 0)
|
||||
S = locate(A) in surroundings
|
||||
if(S.amount >= amt)
|
||||
if(!locate(S.type) in Deletion)
|
||||
SD = new S.type()
|
||||
Deletion += SD
|
||||
S.use(amt)
|
||||
SD = locate(S.type) in Deletion
|
||||
SD.amount += amt
|
||||
continue main_loop
|
||||
else
|
||||
amt -= S.amount
|
||||
if(!locate(S.type) in Deletion)
|
||||
Deletion += S
|
||||
else
|
||||
data = S.amount
|
||||
S = locate(S.type) in Deletion
|
||||
S.add(data)
|
||||
surroundings -= S
|
||||
else
|
||||
var/atom/movable/I
|
||||
while(amt > 0)
|
||||
I = locate(A) in surroundings
|
||||
Deletion += I
|
||||
surroundings -= I
|
||||
amt--
|
||||
var/list/partlist = list(R.parts.len)
|
||||
for(var/M in R.parts)
|
||||
partlist[M] = R.parts[M]
|
||||
for(var/A in R.parts)
|
||||
if(istype(A, /datum/reagent))
|
||||
var/datum/reagent/RG = locate(A) in Deletion
|
||||
if(RG.volume > partlist[A])
|
||||
RG.volume = partlist[A]
|
||||
. += RG
|
||||
Deletion -= RG
|
||||
continue
|
||||
else if(istype(A, /obj/item/stack))
|
||||
var/obj/item/stack/ST = locate(A) in Deletion
|
||||
if(ST.amount > partlist[A])
|
||||
ST.amount = partlist[A]
|
||||
. += ST
|
||||
Deletion -= ST
|
||||
continue
|
||||
else
|
||||
while(partlist[A] > 0)
|
||||
var/atom/movable/AM = locate(A) in Deletion
|
||||
. += AM
|
||||
Deletion -= AM
|
||||
partlist[A] -= 1
|
||||
while(Deletion.len)
|
||||
var/DL = Deletion[Deletion.len]
|
||||
Deletion.Cut(Deletion.len)
|
||||
qdel(DL)
|
||||
|
||||
/datum/component/personal_crafting/proc/component_ui_interact(obj/screen/craft/image, location, control, params, user)
|
||||
if(user == parent)
|
||||
ui_interact(user)
|
||||
|
||||
/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
cur_category = categories[1]
|
||||
if(islist(categories[cur_category]))
|
||||
var/list/subcats = categories[cur_category]
|
||||
cur_subcategory = subcats[1]
|
||||
else
|
||||
cur_subcategory = CAT_NONE
|
||||
ui = new(user, src, ui_key, "personal_crafting", "Crafting Menu", 700, 800, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
|
||||
/datum/component/personal_crafting/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["busy"] = busy
|
||||
data["category"] = cur_category
|
||||
data["subcategory"] = cur_subcategory
|
||||
data["display_craftable_only"] = display_craftable_only
|
||||
data["display_compact"] = display_compact
|
||||
|
||||
var/list/surroundings = get_surroundings(user)
|
||||
var/list/craftability = list()
|
||||
for(var/rec in GLOB.crafting_recipes)
|
||||
var/datum/crafting_recipe/R = rec
|
||||
|
||||
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
|
||||
continue
|
||||
|
||||
if((R.category != cur_category) || (R.subcategory != cur_subcategory))
|
||||
continue
|
||||
|
||||
craftability["[REF(R)]"] = check_contents(user, R, surroundings)
|
||||
|
||||
data["craftability"] = craftability
|
||||
return data
|
||||
|
||||
/datum/component/personal_crafting/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/list/crafting_recipes = list()
|
||||
for(var/rec in GLOB.crafting_recipes)
|
||||
var/datum/crafting_recipe/R = rec
|
||||
|
||||
if(R.name == "") //This is one of the invalid parents that sneaks in
|
||||
continue
|
||||
|
||||
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
|
||||
continue
|
||||
|
||||
if(isnull(crafting_recipes[R.category]))
|
||||
crafting_recipes[R.category] = list()
|
||||
|
||||
if(R.subcategory == CAT_NONE)
|
||||
crafting_recipes[R.category] += list(build_recipe_data(R))
|
||||
else
|
||||
if(isnull(crafting_recipes[R.category][R.subcategory]))
|
||||
crafting_recipes[R.category][R.subcategory] = list()
|
||||
crafting_recipes[R.category]["has_subcats"] = TRUE
|
||||
crafting_recipes[R.category][R.subcategory] += list(build_recipe_data(R))
|
||||
|
||||
data["crafting_recipes"] = crafting_recipes
|
||||
return data
|
||||
|
||||
|
||||
/datum/component/personal_crafting/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("make")
|
||||
var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
|
||||
ui_interact(usr)
|
||||
if(busy)
|
||||
to_chat(usr, "<span class='warning'>You are already making something!</span>")
|
||||
return
|
||||
busy = TRUE
|
||||
var/fail_msg = construct_item(usr, TR)
|
||||
if(!fail_msg)
|
||||
to_chat(usr, "<span class='notice'>[TR.name] constructed.</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Construction failed[fail_msg]</span>")
|
||||
busy = FALSE
|
||||
if("toggle_recipes")
|
||||
display_craftable_only = !display_craftable_only
|
||||
. = TRUE
|
||||
if("toggle_compact")
|
||||
display_compact = !display_compact
|
||||
. = TRUE
|
||||
if("set_category")
|
||||
if(!isnull(params["category"]))
|
||||
cur_category = params["category"]
|
||||
if(!isnull(params["subcategory"]))
|
||||
if(params["subcategory"] == "0")
|
||||
cur_subcategory = ""
|
||||
else
|
||||
cur_subcategory = params["subcategory"]
|
||||
. = TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
|
||||
var/list/data = list()
|
||||
data["name"] = R.name
|
||||
data["ref"] = "[REF(R)]"
|
||||
var/req_text = ""
|
||||
var/tool_text = ""
|
||||
var/catalyst_text = ""
|
||||
|
||||
for(var/a in R.reqs)
|
||||
//We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var)
|
||||
//Also these are typepaths so sadly we can't just do "[a]"
|
||||
var/atom/A = a
|
||||
req_text += " [R.reqs[A]] [initial(A.name)],"
|
||||
req_text = replacetext(req_text,",","",-1)
|
||||
data["req_text"] = req_text
|
||||
|
||||
for(var/a in R.chem_catalysts)
|
||||
var/atom/A = a //cheat-typecast
|
||||
catalyst_text += " [R.chem_catalysts[A]] [initial(A.name)],"
|
||||
catalyst_text = replacetext(catalyst_text,",","",-1)
|
||||
data["catalyst_text"] = catalyst_text
|
||||
|
||||
for(var/a in R.tools)
|
||||
if(ispath(a, /obj/item))
|
||||
var/obj/item/b = a
|
||||
tool_text += " [initial(b.name)],"
|
||||
else
|
||||
tool_text += " [a],"
|
||||
tool_text = replacetext(tool_text,",","",-1)
|
||||
data["tool_text"] = tool_text
|
||||
|
||||
return data
|
||||
|
||||
//Mind helpers
|
||||
|
||||
/datum/mind/proc/teach_crafting_recipe(R)
|
||||
if(!learned_recipes)
|
||||
learned_recipes = list()
|
||||
learned_recipes |= R
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
|
||||
var/datum/hud/H = user.hud_used
|
||||
for(var/huds in H.static_inventory)
|
||||
if(istype(huds, /obj/screen/craft))
|
||||
return
|
||||
//We don't want to be stacking multiple crafting huds on relogs
|
||||
var/obj/screen/craft/C = new()
|
||||
C.icon = H.ui_style
|
||||
H.static_inventory += C
|
||||
@@ -20,7 +24,7 @@
|
||||
CAT_AMMO,
|
||||
),
|
||||
CAT_ROBOT = CAT_NONE,
|
||||
CAT_MISC = list(
|
||||
CAT_MISCELLANEOUS = list(
|
||||
CAT_MISCELLANEOUS,
|
||||
CAT_TOOL,
|
||||
CAT_FURNITURE,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/sheet/plastic = 1,
|
||||
/obj/item/stack/sheet/mineral/wood = 1)
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_TOOL
|
||||
|
||||
/datum/crafting_recipe/showercurtain
|
||||
@@ -18,7 +18,7 @@
|
||||
/obj/item/stack/rods = 1)
|
||||
result = /obj/structure/curtain
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/guillotine
|
||||
name = "Guillotine"
|
||||
@@ -29,7 +29,7 @@
|
||||
/obj/item/stack/cable_coil = 10)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/femur_breaker
|
||||
name = "Femur Breaker"
|
||||
@@ -39,7 +39,7 @@
|
||||
/obj/item/stack/cable_coil = 30)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
// Blood Sucker stuff //
|
||||
/datum/crafting_recipe/bloodsucker/blackcoffin
|
||||
@@ -54,7 +54,7 @@
|
||||
///obj/item/pipe = 2)
|
||||
time = 150
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
always_availible = TRUE
|
||||
|
||||
/datum/crafting_recipe/bloodsucker/meatcoffin
|
||||
@@ -66,7 +66,7 @@
|
||||
/obj/item/restraints/handcuffs/cable = 1)
|
||||
time = 150
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
always_availible = TRUE
|
||||
|
||||
/datum/crafting_recipe/bloodsucker/metalcoffin
|
||||
@@ -77,7 +77,7 @@
|
||||
reqs = list(/obj/item/stack/sheet/metal = 5)
|
||||
time = 100
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
always_availible = TRUE
|
||||
|
||||
/datum/crafting_recipe/bloodsucker/vassalrack
|
||||
@@ -100,7 +100,7 @@
|
||||
// )
|
||||
time = 150
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
always_availible = FALSE // Disabled until learned
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
)
|
||||
time = 100
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
always_availible = FALSE // Disabled til learned
|
||||
|
||||
/datum/crafting_recipe/furnace
|
||||
@@ -129,7 +129,7 @@
|
||||
/obj/item/stack/rods = 2)
|
||||
tools = list(TOOL_CROWBAR)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/tableanvil
|
||||
name = "Table Anvil"
|
||||
@@ -139,7 +139,7 @@
|
||||
/obj/item/stack/rods = 2)
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WRENCH, TOOL_WELDER)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/sandvil
|
||||
name = "Sandstone Anvil"
|
||||
@@ -148,7 +148,7 @@
|
||||
reqs = list(/obj/item/stack/sheet/mineral/sandstone = 24)
|
||||
tools = list(TOOL_CROWBAR)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/basaltblock
|
||||
name = "Sintered Basalt Block"
|
||||
@@ -157,7 +157,7 @@
|
||||
reqs = list(/obj/item/stack/ore/glass/basalt = 50)
|
||||
tools = list(TOOL_WELDER)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/basaltanvil
|
||||
name = "Basalt Anvil"
|
||||
@@ -166,7 +166,7 @@
|
||||
reqs = list(/obj/item/basaltblock = 5)
|
||||
tools = list(TOOL_CROWBAR)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
///////////////////
|
||||
//Tools & Storage//
|
||||
///////////////////
|
||||
@@ -177,7 +177,7 @@
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/medical/gauze = 1,
|
||||
/datum/reagent/space_cleaner/sterilizine = 5)
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_TOOL
|
||||
|
||||
/datum/crafting_recipe/brute_pack
|
||||
@@ -186,7 +186,7 @@
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/medical/gauze/adv = 1,
|
||||
/datum/reagent/medicine/styptic_powder = 10)
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_TOOL
|
||||
|
||||
/datum/crafting_recipe/burn_pack
|
||||
@@ -195,7 +195,7 @@
|
||||
time = 1
|
||||
reqs = list(/obj/item/stack/medical/gauze/adv = 1,
|
||||
/datum/reagent/medicine/silver_sulfadiazine = 10)
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_TOOL
|
||||
|
||||
/datum/crafting_recipe/ghettojetpack
|
||||
@@ -206,7 +206,7 @@
|
||||
/obj/item/extinguisher = 1,
|
||||
/obj/item/pipe = 3,
|
||||
/obj/item/stack/cable_coil = 30)
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
subcategory = CAT_TOOL
|
||||
tools = list(TOOL_WRENCH, TOOL_WELDER, TOOL_WIRECUTTER)
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/toolboxhammer
|
||||
name = "Toolbox Hammer"
|
||||
@@ -231,7 +231,7 @@
|
||||
/obj/item/stack/rods = 2)
|
||||
time = 40
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/papersack
|
||||
name = "Paper Sack"
|
||||
@@ -239,7 +239,7 @@
|
||||
time = 10
|
||||
reqs = list(/obj/item/paper = 5)
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/smallcarton
|
||||
name = "Small Carton"
|
||||
@@ -247,7 +247,7 @@
|
||||
time = 10
|
||||
reqs = list(/obj/item/stack/sheet/cardboard = 1)
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/bronze_driver
|
||||
name = "Bronze Plated Screwdriver"
|
||||
@@ -259,7 +259,7 @@
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/bronze_welder
|
||||
name = "Bronze Plated Welding Tool"
|
||||
@@ -271,7 +271,7 @@
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/bronze_wirecutters
|
||||
name = "Bronze Plated Wirecutters"
|
||||
@@ -283,7 +283,7 @@
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/bronze_crowbar
|
||||
name = "Bronze Plated Crowbar"
|
||||
@@ -295,7 +295,7 @@
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/bronze_wrench
|
||||
name = "Bronze Plated Wrench"
|
||||
@@ -307,7 +307,7 @@
|
||||
/datum/reagent/water = 15)
|
||||
time = 40
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/rcl
|
||||
name = "Makeshift Rapid Cable Layer"
|
||||
@@ -316,7 +316,7 @@
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
|
||||
reqs = list(/obj/item/stack/sheet/metal = 15)
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/picket_sign
|
||||
name = "Picket Sign"
|
||||
@@ -325,7 +325,7 @@
|
||||
/obj/item/stack/sheet/cardboard = 2)
|
||||
time = 80
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/electrochromatic_kit
|
||||
name = "Electrochromatic Kit"
|
||||
@@ -334,7 +334,7 @@
|
||||
/obj/item/stack/cable_coil = 1)
|
||||
time = 5
|
||||
subcategory = CAT_TOOL
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/blackmarket_uplink
|
||||
name = "Black Market Uplink"
|
||||
@@ -346,7 +346,7 @@
|
||||
/obj/item/radio = 1,
|
||||
/obj/item/analyzer = 1)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/heretic/codex
|
||||
name = "Codex Cicatrix"
|
||||
@@ -358,7 +358,7 @@
|
||||
/obj/item/stack/sheet/animalhide/human = 1)
|
||||
time = 150
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
always_availible = FALSE
|
||||
|
||||
////////////
|
||||
@@ -372,7 +372,7 @@
|
||||
/obj/item/stack/rods = 8)
|
||||
time = 100
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/motorized_wheelchair
|
||||
name = "Hoverchair"
|
||||
@@ -386,7 +386,7 @@
|
||||
tools = list(TOOL_WELDER, TOOL_SCREWDRIVER, TOOL_WRENCH)
|
||||
time = 200
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/skateboard
|
||||
name = "Skateboard"
|
||||
@@ -395,7 +395,7 @@
|
||||
reqs = list(/obj/item/stack/sheet/metal = 5,
|
||||
/obj/item/stack/rods = 10)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/scooter
|
||||
name = "Scooter"
|
||||
@@ -404,7 +404,7 @@
|
||||
reqs = list(/obj/item/stack/sheet/metal = 5,
|
||||
/obj/item/stack/rods = 12)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/////////
|
||||
//Toys///
|
||||
@@ -415,28 +415,28 @@
|
||||
reqs = list(/obj/item/light/bulb = 1, /obj/item/stack/cable_coil = 1, /obj/item/stack/sheet/plastic = 4)
|
||||
result = /obj/item/toy/sword
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/extendohand
|
||||
name = "Extendo-Hand"
|
||||
reqs = list(/obj/item/bodypart/r_arm/robot = 1, /obj/item/clothing/gloves/boxing = 1)
|
||||
result = /obj/item/extendohand
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/toyneb
|
||||
name = "Non-Euplastic Blade"
|
||||
reqs = list(/obj/item/light/tube = 1, /obj/item/stack/cable_coil = 1, /obj/item/stack/sheet/plastic = 4)
|
||||
result = /obj/item/toy/sword/cx
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/catgirlplushie
|
||||
name = "Catgirl Plushie"
|
||||
reqs = list(/obj/item/toy/plush/hairball = 3)
|
||||
result = /obj/item/toy/plush/catgirl
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
////////////
|
||||
//Unsorted//
|
||||
@@ -450,7 +450,7 @@
|
||||
reqs = list(/obj/item/stack/sheet/mineral/wood = 1)
|
||||
result = /obj/item/stick
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
|
||||
/datum/crafting_recipe/swordhilt
|
||||
@@ -459,14 +459,14 @@
|
||||
reqs = list(/obj/item/stack/sheet/mineral/wood = 2)
|
||||
result = /obj/item/swordhandle
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/blackcarpet
|
||||
name = "Black Carpet"
|
||||
reqs = list(/obj/item/stack/tile/carpet = 50, /obj/item/toy/crayon/black = 1)
|
||||
result = /obj/item/stack/tile/carpet/black/fifty
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/paperframes
|
||||
name = "Paper Frames"
|
||||
@@ -474,7 +474,7 @@
|
||||
time = 10
|
||||
reqs = list(/obj/item/stack/sheet/mineral/wood = 5, /obj/item/paper = 20)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/naturalpaper
|
||||
name = "Hand-Pressed Paper"
|
||||
@@ -483,7 +483,7 @@
|
||||
tools = list(/obj/item/hatchet)
|
||||
result = /obj/item/paper_bin/bundlenatural
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/bluespacehonker
|
||||
name = "Bluespace Bike horn"
|
||||
@@ -493,7 +493,7 @@
|
||||
/obj/item/toy/crayon/blue = 1,
|
||||
/obj/item/bikehorn = 1)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/mousetrap
|
||||
name = "Mouse Trap"
|
||||
@@ -502,7 +502,7 @@
|
||||
reqs = list(/obj/item/stack/sheet/cardboard = 1,
|
||||
/obj/item/stack/rods = 1)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/flashlight_eyes
|
||||
name = "Flashlight Eyes"
|
||||
@@ -513,7 +513,7 @@
|
||||
/obj/item/restraints/handcuffs/cable = 1
|
||||
)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/pressureplate
|
||||
name = "Pressure Plate"
|
||||
@@ -524,7 +524,7 @@
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/obj/item/assembly/igniter = 1)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/gold_horn
|
||||
name = "Golden Bike Horn"
|
||||
@@ -533,7 +533,7 @@
|
||||
reqs = list(/obj/item/stack/sheet/mineral/bananium = 5,
|
||||
/obj/item/bikehorn = 1)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/spooky_camera
|
||||
name = "Camera Obscura"
|
||||
@@ -543,7 +543,7 @@
|
||||
/datum/reagent/water/holywater = 10)
|
||||
parts = list(/obj/item/camera = 1)
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/coconut_bong
|
||||
name = "Coconut Bong"
|
||||
@@ -552,7 +552,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/grown/coconut = 1)
|
||||
time = 70
|
||||
subcategory = CAT_MISCELLANEOUS
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
//////////////
|
||||
//Banners/////
|
||||
@@ -565,7 +565,7 @@
|
||||
reqs = list(/obj/item/stack/rods = 2,
|
||||
/obj/item/clothing/under/rank/captain/parade = 1)
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/engineering_banner
|
||||
name = "Engitopia Banner"
|
||||
@@ -574,7 +574,7 @@
|
||||
reqs = list(/obj/item/stack/rods = 2,
|
||||
/obj/item/clothing/under/rank/engineering/engineer = 1)
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/cargo_banner
|
||||
name = "Cargonia Banner"
|
||||
@@ -583,7 +583,7 @@
|
||||
reqs = list(/obj/item/stack/rods = 2,
|
||||
/obj/item/clothing/under/rank/cargo/tech = 1)
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/science_banner
|
||||
name = "Sciencia Banner"
|
||||
@@ -592,7 +592,7 @@
|
||||
reqs = list(/obj/item/stack/rods = 2,
|
||||
/obj/item/clothing/under/rank/rnd/scientist = 1)
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/medical_banner
|
||||
name = "Meditopia Banner"
|
||||
@@ -601,7 +601,7 @@
|
||||
reqs = list(/obj/item/stack/rods = 2,
|
||||
/obj/item/clothing/under/rank/medical/doctor = 1)
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
/datum/crafting_recipe/security_banner
|
||||
name = "Securistan Banner"
|
||||
@@ -610,4 +610,4 @@
|
||||
reqs = list(/obj/item/stack/rods = 2,
|
||||
/obj/item/clothing/under/rank/security/officer = 1)
|
||||
subcategory = CAT_FURNITURE
|
||||
category = CAT_MISC
|
||||
category = CAT_MISCELLANEOUS
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
var/mob/living/L = AM
|
||||
if(L.stat == DEAD)
|
||||
continue
|
||||
if(light_nutrition_gain)
|
||||
if(light_nutrition_gain && L.nutrition < NUTRITION_LEVEL_WELL_FED)
|
||||
L.adjust_nutrition(light_amount * light_nutrition_gain * attached_atoms[AM], NUTRITION_LEVEL_WELL_FED)
|
||||
if(light_amount > bonus_lum || light_amount < malus_lum)
|
||||
var/mult = ((light_amount > bonus_lum) ? 1 : -1) * attached_atoms[AM]
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/datum/element/trash
|
||||
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
|
||||
|
||||
/datum/element/trash/Attach(datum/target)
|
||||
. = ..()
|
||||
RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/UseFromHand)
|
||||
|
||||
/datum/element/trash/proc/UseFromHand(obj/item/source, mob/living/M, mob/living/user)
|
||||
if((M == user || user.vore_flags & TRASH_FORCEFEED) && ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(HAS_TRAIT(H, TRAIT_TRASHCAN))
|
||||
playsound(H.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
|
||||
if(H.vore_selected)
|
||||
H.visible_message("<span class='notice'>[H] [H.vore_selected.vore_verb]s the [source] into their [H.vore_selected]</span>",
|
||||
"<span class='notice'>You [H.vore_selected.vore_verb]s the [source] into your [H.vore_selected]</span>")
|
||||
source.forceMove(H.vore_selected)
|
||||
else
|
||||
H.visible_message("<span class='notice'>[H] consumes the [source].")
|
||||
qdel(source)
|
||||
@@ -154,3 +154,11 @@
|
||||
/datum/quirk/longtimer/on_spawn()
|
||||
var/mob/living/carbon/C = quirk_holder
|
||||
C.generate_fake_scars(rand(min_scars, max_scars))
|
||||
|
||||
/datum/quirk/trashcan
|
||||
name = "Trashcan"
|
||||
desc = "You are able to consume and digest trash."
|
||||
value = 0
|
||||
gain_text = "<span class='notice'>You feel like munching on a can of soda.</span>"
|
||||
lose_text = "<span class='notice'>You no longer feel like you should be eating trash.</span>"
|
||||
mob_trait = TRAIT_TRASHCAN
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
line = null
|
||||
if(qdel_in)
|
||||
QDEL_IN(PB, qdel_in)
|
||||
d
|
||||
|
||||
/obj/effect/projectile/tracer
|
||||
name = "beam"
|
||||
icon = 'icons/obj/projectiles_tracer.dmi'
|
||||
|
||||
@@ -387,6 +387,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
throwforce = 0
|
||||
grind_results = list(/datum/reagent/carbon = 2)
|
||||
|
||||
/obj/item/cigbutt/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/trash)
|
||||
|
||||
/obj/item/cigbutt/cigarbutt
|
||||
name = "cigar butt"
|
||||
desc = "A manky old cigar butt."
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
GLOBAL_LIST_INIT(human_recipes, list( \
|
||||
new/datum/stack_recipe("bloated human costume", /obj/item/clothing/suit/hooded/bloated_human, 5), \
|
||||
new/datum/stack_recipe("human skin hat", /obj/item/clothing/head/human_leather, 1), \
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/animalhide/human/get_main_recipes()
|
||||
|
||||
@@ -179,6 +179,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
|
||||
GLOBAL_LIST_INIT(plasteel_recipes, list ( \
|
||||
new/datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = TRUE), \
|
||||
new/datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50), \
|
||||
new/datum/stack_recipe("plasteel keg", /obj/structure/custom_keg, 10, time = 50), \
|
||||
new/datum/stack_recipe("micro powered fan assembly", /obj/machinery/fan_assembly, 5, time = 50, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
new /datum/stack_recipe_list("crates", list( \
|
||||
new /datum/stack_recipe("gray crate", /obj/structure/closet/crate, 5, time = 50, one_per_turf = 1, on_floor = 1), \
|
||||
|
||||
@@ -7,6 +7,10 @@
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/trash/Initialize()
|
||||
. = ..()
|
||||
AddElement(/datum/element/trash)
|
||||
|
||||
/obj/item/trash/raisins
|
||||
name = "\improper 4no raisins"
|
||||
icon_state= "4no_raisins"
|
||||
@@ -80,6 +84,3 @@
|
||||
name = "boritos bag"
|
||||
icon_state = "boritos"
|
||||
grind_results = list(/datum/reagent/aluminium = 1) //from the mylar bag
|
||||
|
||||
/obj/item/trash/attack(mob/M, mob/living/user)
|
||||
return
|
||||
|
||||
@@ -48,14 +48,34 @@
|
||||
return // no message spam
|
||||
..()
|
||||
|
||||
/obj/structure/mirror/attacked_by(obj/item/I, mob/living/user)
|
||||
if(broken || !istype(user) || !I.force)
|
||||
return ..()
|
||||
|
||||
. = ..()
|
||||
if(broken) // breaking a mirror truly gets you bad luck!
|
||||
to_chat(user, "<span class='warning'>A chill runs down your spine as [src] shatters...</span>")
|
||||
user.AddComponent(/datum/component/omen, silent=TRUE) // we have our own message
|
||||
|
||||
/obj/structure/mirror/bullet_act(obj/item/projectile/P)
|
||||
if(broken || !isliving(P.firer) || !P.damage)
|
||||
return ..()
|
||||
|
||||
. = ..()
|
||||
if(broken) // breaking a mirror truly gets you bad luck!
|
||||
var/mob/living/unlucky_dude = P.firer
|
||||
to_chat(unlucky_dude, "<span class='warning'>A chill runs down your spine as [src] shatters...</span>")
|
||||
unlucky_dude.AddComponent(/datum/component/omen, silent=TRUE) // we have our own message
|
||||
|
||||
/obj/structure/mirror/obj_break(damage_flag, mapload)
|
||||
if(!broken && !(flags_1 & NODECONSTRUCT_1))
|
||||
icon_state = "mirror_broke"
|
||||
if(!mapload)
|
||||
playsound(src, "shatter", 70, 1)
|
||||
if(desc == initial(desc))
|
||||
desc = "Oh no, seven years of bad luck!"
|
||||
broken = TRUE
|
||||
if(broken || (flags_1 & NODECONSTRUCT_1))
|
||||
return
|
||||
icon_state = "mirror_broke"
|
||||
if(!mapload)
|
||||
playsound(src, "shatter", 70, TRUE)
|
||||
if(desc == initial(desc))
|
||||
desc = "Oh no, seven years of bad luck!"
|
||||
broken = TRUE
|
||||
|
||||
/obj/structure/mirror/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
|
||||
@@ -72,7 +72,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
|
||||
// basic doesn't initialize and this will cause issues
|
||||
// no warning though because this can happen naturaly as a result of it being built on top of
|
||||
path = /turf/open/space
|
||||
if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP)) // Don't no-op if the map loader requires it to be reconstructed
|
||||
if(!GLOB.use_preloader && path == type && !(flags & CHANGETURF_FORCEOP) && (baseturfs == new_baseturfs)) // Don't no-op if the map loader requires it to be reconstructed, or if this is a new set of baseturfs
|
||||
return src
|
||||
if(flags & CHANGETURF_SKIP)
|
||||
return new path(src)
|
||||
|
||||
@@ -187,6 +187,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
var/vore_flags = 0
|
||||
var/list/belly_prefs = list()
|
||||
var/vore_taste = "nothing in particular"
|
||||
var/vore_smell = null
|
||||
var/toggleeatingnoise = TRUE
|
||||
var/toggledigestionnoise = TRUE
|
||||
var/hound_sleeper = TRUE
|
||||
@@ -1068,6 +1069,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Voracious MediHound sleepers:</b> <a href='?_src_=prefs;preference=hound_sleeper'>[(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Sounds:</b> <a href='?_src_=prefs;preference=toggleeatingnoise'>[(cit_toggles & EATING_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Hear Vore Digestion Sounds:</b> <a href='?_src_=prefs;preference=toggledigestionnoise'>[(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Allow trash forcefeeding (requires Trashcan quirk)</b> <a href='?_src_=prefs;preference=toggleforcefeedtrash'>[(cit_toggles & TRASH_FORCEFEED) ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Forced Feminization:</b> <a href='?_src_=prefs;preference=feminization'>[(cit_toggles & FORCED_FEM) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Forced Masculinization:</b> <a href='?_src_=prefs;preference=masculinization'>[(cit_toggles & FORCED_MASC) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
dat += "<b>Lewd Hypno:</b> <a href='?_src_=prefs;preference=hypno'>[(cit_toggles & HYPNO) ? "Allowed" : "Disallowed"]</a><br>"
|
||||
@@ -2800,6 +2802,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("toggledigestionnoise")
|
||||
cit_toggles ^= DIGESTION_NOISES
|
||||
|
||||
if("toggleforcefeedtrash")
|
||||
cit_toggles ^= TRASH_FORCEFEED
|
||||
|
||||
if("breast_enlargement")
|
||||
cit_toggles ^= BREAST_ENLARGEMENT
|
||||
|
||||
|
||||
@@ -821,6 +821,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
S["vore_flags"] >> vore_flags
|
||||
S["vore_taste"] >> vore_taste
|
||||
S["vore_smell"] >> vore_smell
|
||||
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
|
||||
if(fexists(char_vr_path))
|
||||
var/list/json_from_file = json_decode(file2text(char_vr_path))
|
||||
@@ -994,6 +995,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
vore_flags = sanitize_integer(vore_flags, 0, MAX_VORE_FLAG, 0)
|
||||
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
|
||||
vore_smell = copytext(vore_smell, 1, MAX_TASTE_LEN)
|
||||
belly_prefs = SANITIZE_LIST(belly_prefs)
|
||||
|
||||
cit_character_pref_load(S)
|
||||
@@ -1147,6 +1149,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
WRITE_FILE(S["vore_flags"] , vore_flags)
|
||||
WRITE_FILE(S["vore_taste"] , vore_taste)
|
||||
WRITE_FILE(S["vore_smell"] , vore_smell)
|
||||
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
|
||||
var/belly_prefs_json = safe_json_encode(list("belly_prefs" = belly_prefs))
|
||||
if(fexists(char_vr_path))
|
||||
|
||||
@@ -482,3 +482,9 @@
|
||||
icon_state = "kabuto"
|
||||
item_state = "kabuto"
|
||||
flags_inv = HIDEHAIR|HIDEEARS
|
||||
|
||||
/obj/item/clothing/head/human_leather
|
||||
name = "human skin hat"
|
||||
desc = "This will scare them. All will know my power."
|
||||
icon_state = "human_leather"
|
||||
item_state = "human_leather"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
weight = 8
|
||||
|
||||
/datum/round_event/cat_surgeon/announce(fake)
|
||||
priority_announce("One of our... ahem... 'special' cases has escaped. Our sensors now show their tracker implant on your station. On an unrelated note, has anyone seen our cats?",
|
||||
priority_announce("One of our... ahem... 'special' cases has escaped. As it happens their last known location before their tracker went dead is your station so keep an eye out for them. On an unrelated note, has anyone seen our cats?",
|
||||
sender_override = "Nanotrasen Psych Ward")
|
||||
|
||||
/datum/round_event/cat_surgeon/start()
|
||||
|
||||
@@ -73,3 +73,40 @@
|
||||
icon_state = "barrel_open"
|
||||
else
|
||||
icon_state = "barrel"
|
||||
|
||||
/obj/structure/custom_keg
|
||||
name = "Plasteel Keg"
|
||||
desc = "A large plasteel keg. You can use it to hold liquids. You may wanna label this, too."
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "keg"
|
||||
density = TRUE
|
||||
anchored = FALSE
|
||||
pressure_resistance = 2 * ONE_ATMOSPHERE
|
||||
max_integrity = 300
|
||||
var/open = FALSE
|
||||
|
||||
/obj/structure/custom_keg/Initialize()
|
||||
create_reagents(1000, DRAINABLE | AMOUNT_VISIBLE)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/custom_keg/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>It is currently [open?"open, letting you pour liquids in.":"closed, letting you draw liquids from the tap."]</span>"
|
||||
|
||||
/obj/structure/custom_keg/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
open = !open
|
||||
if(open)
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
|
||||
ENABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
|
||||
to_chat(user, "<span class='notice'>You open [src], letting you fill it.</span>")
|
||||
else
|
||||
DISABLE_BITFIELD(reagents.reagents_holder_flags, REFILLABLE)
|
||||
ENABLE_BITFIELD(reagents.reagents_holder_flags, DRAINABLE)
|
||||
to_chat(user, "<span class='notice'>You close [src], letting you draw from its tap.</span>")
|
||||
update_icon()
|
||||
|
||||
/obj/structure/custom_keg/update_icon_state()
|
||||
if(open)
|
||||
icon_state = "keg_open"
|
||||
else
|
||||
icon_state = "keg"
|
||||
|
||||
@@ -679,7 +679,7 @@
|
||||
icon_state = "crow"
|
||||
matrixed_sections = MATRIX_RED
|
||||
|
||||
/datum/sprite_accessory/tails/mam_tail/cow
|
||||
/datum/sprite_accessory/tails/mam_tails/cow
|
||||
name = "Cow"
|
||||
icon_state = "cow"
|
||||
matrixed_sections = MATRIX_RED
|
||||
|
||||
@@ -51,6 +51,9 @@
|
||||
var/obj/item/l_store = null
|
||||
var/obj/item/s_store = null
|
||||
|
||||
/// When an braindead player has their equipment fiddled with, we log that info here for when they come back so they know who took their ID while they were DC'd for 30 seconds
|
||||
var/list/afk_thefts
|
||||
|
||||
var/special_voice = "" // For changing our voice. Used by a symptom.
|
||||
|
||||
var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding
|
||||
|
||||
@@ -2,3 +2,33 @@
|
||||
..()
|
||||
if(dna?.species?.has_field_of_vision && CONFIG_GET(flag/use_field_of_vision))
|
||||
LoadComponent(/datum/component/field_of_vision, field_of_vision_type)
|
||||
|
||||
if(!LAZYLEN(afk_thefts))
|
||||
return
|
||||
|
||||
var/list/print_msg = list()
|
||||
print_msg += "<span class='info'>*---------*</span>"
|
||||
print_msg += "<span class='userdanger'>As you snap back to consciousness, you recall people messing with your stuff...</span>"
|
||||
|
||||
afk_thefts = reverseRange(afk_thefts)
|
||||
|
||||
for(var/list/iter_theft as anything in afk_thefts)
|
||||
if(!islist(iter_theft) || LAZYLEN(iter_theft) != AFK_THEFT_TIME)
|
||||
stack_trace("[src] ([ckey]) returned to their body and had a null/malformed afk_theft entry. Contents: [json_encode(iter_theft)]")
|
||||
continue
|
||||
|
||||
var/thief_name = iter_theft[AFK_THEFT_NAME]
|
||||
var/theft_message = iter_theft[AFK_THEFT_MESSAGE]
|
||||
var/time_since = world.time - iter_theft[AFK_THEFT_TIME]
|
||||
|
||||
if(time_since > AFK_THEFT_FORGET_DETAILS_TIME)
|
||||
print_msg += "\t<span class='danger'><b>Someone [theft_message], but it was at least [DisplayTimeText(AFK_THEFT_FORGET_DETAILS_TIME)] ago.</b></span>"
|
||||
else
|
||||
print_msg += "\t<span class='danger'><b>[thief_name] [theft_message] roughly [DisplayTimeText(time_since, 10)] ago.</b></span>"
|
||||
|
||||
if(LAZYLEN(afk_thefts) >= AFK_THEFT_MAX_MESSAGES)
|
||||
print_msg += "<span class='warning'>There may have been more, but that's all you can remember...</span>"
|
||||
print_msg += "<span class='info'>*---------*</span>"
|
||||
|
||||
to_chat(src, print_msg.Join("\n"))
|
||||
LAZYNULL(afk_thefts)
|
||||
|
||||
@@ -911,6 +911,12 @@
|
||||
"<span class='userdanger'>[src] tries to remove your [what.name].</span>", target = src,
|
||||
target_message = "<span class='danger'>You try to remove [who]'s [what.name].</span>")
|
||||
what.add_fingerprint(src)
|
||||
if(ishuman(who))
|
||||
var/mob/living/carbon/human/victim_human = who
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(src.name, "tried unequipping your [what]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
else
|
||||
to_chat(src,"<span class='notice'>You try to remove [who]'s [what.name].</span>")
|
||||
what.add_fingerprint(src)
|
||||
@@ -957,6 +963,13 @@
|
||||
to_chat(src, "<span class='warning'>\The [what.name] doesn't fit in that place!</span>")
|
||||
return
|
||||
|
||||
if(ishuman(who))
|
||||
var/mob/living/carbon/human/victim_human = who
|
||||
if(victim_human.key && !victim_human.client) // AKA braindead
|
||||
if(victim_human.stat <= SOFT_CRIT && LAZYLEN(victim_human.afk_thefts) <= AFK_THEFT_MAX_MESSAGES)
|
||||
var/list/new_entry = list(list(src.name, "tried equipping you with [what]", world.time))
|
||||
LAZYADD(victim_human.afk_thefts, new_entry)
|
||||
|
||||
who.visible_message("<span class='notice'>[src] tries to put [what] on [who].</span>",
|
||||
"<span class='notice'>[src] tries to put [what] on you.</span>", target = src,
|
||||
target_message = "<span class='notice'>You try to put [what] on [who].</span>")
|
||||
|
||||
@@ -364,11 +364,10 @@
|
||||
/mob/living/simple_animal/hostile/proc/AttackingTarget()
|
||||
SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
|
||||
in_melee = TRUE
|
||||
/* sorry for the simplemob vore fans
|
||||
if(vore_active)
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags,DEVOURABLE)) // aggressive check to ensure vore attacks can be made
|
||||
if(!client && L.Adjacent(src) && CHECK_BITFIELD(L.vore_flags, DEVOURABLE) && CHECK_BITFIELD(L.vore_flags, MOBVORE)) // aggressive check to ensure vore attacks can be made
|
||||
if(prob(voracious_chance))
|
||||
vore_attack(src,L,src)
|
||||
else
|
||||
@@ -379,7 +378,6 @@
|
||||
return target.attack_animal(src)
|
||||
else
|
||||
return target.attack_animal(src)
|
||||
*/
|
||||
return target.attack_animal(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/proc/Aggro()
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* tgui state: vorepanel_state
|
||||
*
|
||||
* Only checks that the user and src_object are the same.
|
||||
**/
|
||||
|
||||
GLOBAL_DATUM_INIT(ui_vorepanel_state, /datum/ui_state/vorepanel_state, new)
|
||||
|
||||
/datum/ui_state/vorepanel_state/can_use_topic(src_object, mob/user)
|
||||
if(src_object != user)
|
||||
// Note, in order to allow others to look at others vore panels, change this to
|
||||
// UI_UPDATE
|
||||
return UI_CLOSE
|
||||
if(!user.client)
|
||||
return UI_CLOSE
|
||||
if(user.stat == DEAD)
|
||||
return UI_DISABLED
|
||||
return UI_INTERACTIVE
|
||||
@@ -9,7 +9,7 @@
|
||||
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
|
||||
*/
|
||||
/proc/tgui_alert(mob/user, message, title, list/buttons, timeout = 60 SECONDS)
|
||||
/proc/tgui_alert(mob/user, message = null, title = null, list/buttons = list("Ok"), timeout = 0)
|
||||
if (!user)
|
||||
user = usr
|
||||
if (!istype(user))
|
||||
@@ -35,9 +35,9 @@
|
||||
* * title - The of the alert modal, shown on the top of the TGUI window.
|
||||
* * buttons - The options that can be chosen by the user, each string is assigned a button on the UI.
|
||||
* * callback - The callback to be invoked when a choice is made.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Set to zero for no timeout.
|
||||
* * timeout - The timeout of the alert, after which the modal will close and qdel itself. Disabled by default, can be set to seconds otherwise.
|
||||
*/
|
||||
/proc/tgui_alert_async(mob/user, message, title, list/buttons, datum/callback/callback, timeout = 60 SECONDS)
|
||||
/proc/tgui_alert_async(mob/user, message = null, title = null, list/buttons = list("Ok"), datum/callback/callback, timeout = 0)
|
||||
if (!user)
|
||||
user = usr
|
||||
if (!istype(user))
|
||||
@@ -90,7 +90,7 @@
|
||||
* the window was closed by the user.
|
||||
*/
|
||||
/datum/tgui_modal/proc/wait()
|
||||
while (!choice && !closed)
|
||||
while (!choice && !closed && !QDELETED(src))
|
||||
stoplag(1)
|
||||
|
||||
/datum/tgui_modal/ui_interact(mob/user, datum/tgui/ui)
|
||||
@@ -124,10 +124,13 @@
|
||||
if("choose")
|
||||
if (!(params["choice"] in buttons))
|
||||
return
|
||||
choice = params["choice"]
|
||||
set_choice(params["choice"])
|
||||
SStgui.close_uis(src)
|
||||
return TRUE
|
||||
|
||||
/datum/tgui_modal/proc/set_choice(choice)
|
||||
src.choice = choice
|
||||
|
||||
/**
|
||||
* # async tgui_modal
|
||||
*
|
||||
@@ -138,23 +141,17 @@
|
||||
var/datum/callback/callback
|
||||
|
||||
/datum/tgui_modal/async/New(mob/user, message, title, list/buttons, callback, timeout)
|
||||
..(user, title, message, buttons, timeout)
|
||||
..(user, message, title, buttons, timeout)
|
||||
src.callback = callback
|
||||
|
||||
/datum/tgui_modal/async/Destroy(force, ...)
|
||||
QDEL_NULL(callback)
|
||||
. = ..()
|
||||
|
||||
/datum/tgui_modal/async/ui_close(mob/user)
|
||||
/datum/tgui_modal/async/set_choice(choice)
|
||||
. = ..()
|
||||
qdel(src)
|
||||
|
||||
/datum/tgui_modal/async/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if (!. || choice == null)
|
||||
return
|
||||
callback.InvokeAsync(choice)
|
||||
qdel(src)
|
||||
if(!isnull(src.choice))
|
||||
callback?.InvokeAsync(src.choice)
|
||||
|
||||
/datum/tgui_modal/async/wait()
|
||||
return
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
SEND_SOUND(M,prey_digest)
|
||||
play_sound = pick(pred_digest)
|
||||
|
||||
if(M.vore_flags & ABSORBED)
|
||||
if(M.vore_flags & ABSORBED || !(M.vore_flags & ABSORBABLE)) //Negative.
|
||||
continue
|
||||
|
||||
if(M.nutrition >= 100) //Drain them until there's no nutrients left. Slowly "absorb" them.
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
///////////////////// Mob Living /////////////////////
|
||||
/mob/living
|
||||
var/vore_flags = 0
|
||||
var/showvoreprefs = TRUE // Determines if the mechanical vore preferences button will be displayed on the mob or not.
|
||||
var/obj/belly/vore_selected // Default to no vore capability.
|
||||
var/list/vore_organs = list() // List of vore containers inside a mob
|
||||
var/vore_taste = null // What the character tastes like
|
||||
// Determines if the mechanical vore preferences button will be displayed on the mob or not.
|
||||
var/showvoreprefs = TRUE
|
||||
/// Default to no vore capability.
|
||||
var/obj/belly/vore_selected
|
||||
/// List of vore containers inside a mob
|
||||
var/list/vore_organs = list()
|
||||
/// What the character tastes like
|
||||
var/vore_taste = null
|
||||
/// What the character smells like
|
||||
var/vore_smell = null
|
||||
/// Next time vore sounds get played for the prey, do not change manually as it is intended to be set automatically
|
||||
var/next_preyloop
|
||||
|
||||
//
|
||||
// Hook for generic creation of stuff on new creatures
|
||||
//
|
||||
/hook/living_new/proc/vore_setup(mob/living/M)
|
||||
add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/escapeOOC))
|
||||
add_verb(M, list(/mob/living/proc/preyloop_refresh, /mob/living/proc/lick, /mob/living/proc/smell, /mob/living/proc/escapeOOC))
|
||||
|
||||
if(M.vore_flags & NO_VORE) //If the mob isn't supposed to have a stomach, let's not give it an insidepanel so it can make one for itself, or a stomach.
|
||||
return TRUE
|
||||
@@ -256,6 +263,7 @@
|
||||
|
||||
client.prefs.vore_flags = vore_flags // there's garbage data in here, but it doesn't matter
|
||||
client.prefs.vore_taste = vore_taste
|
||||
client.prefs.vore_smell = vore_smell
|
||||
|
||||
var/list/serialized = list()
|
||||
for(var/belly in vore_organs)
|
||||
@@ -264,6 +272,8 @@
|
||||
|
||||
client.prefs.belly_prefs = serialized
|
||||
|
||||
client.prefs.save_character()
|
||||
|
||||
return TRUE
|
||||
|
||||
//
|
||||
@@ -274,8 +284,9 @@
|
||||
to_chat(src,"<span class='warning'>You attempted to apply your vore prefs but somehow you're in this character without a client.prefs variable. Tell a dev.</span>")
|
||||
return FALSE
|
||||
ENABLE_BITFIELD(vore_flags,VOREPREF_INIT)
|
||||
COPY_SPECIFIC_BITFIELDS(vore_flags,client.prefs.vore_flags,DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE)
|
||||
COPY_SPECIFIC_BITFIELDS(vore_flags, client.prefs.vore_flags, DIGESTABLE | DEVOURABLE | FEEDING | LICKABLE | SMELLABLE | ABSORBABLE | MOBVORE)
|
||||
vore_taste = client.prefs.vore_taste
|
||||
vore_smell = client.prefs.vore_smell
|
||||
|
||||
release_vore_contents(silent = TRUE)
|
||||
QDEL_LIST(vore_organs)
|
||||
@@ -379,6 +390,56 @@
|
||||
else
|
||||
taste_message += "a plain old normal [src]"
|
||||
return taste_message
|
||||
|
||||
//
|
||||
// Equally important as the above
|
||||
//
|
||||
/mob/living/proc/smell()
|
||||
set name = "Smell Someone"
|
||||
set category = "Vore"
|
||||
set desc = "Smell someone nearby!"
|
||||
|
||||
if(incapacitated(ignore_restraints = TRUE))
|
||||
to_chat(src, "<span class='warning'>You can't do that while incapacitated.</span>")
|
||||
return
|
||||
if(!CheckActionCooldown())
|
||||
to_chat(src, "<span class='warning'>You can't do that so fast, slow down.</span>")
|
||||
return
|
||||
|
||||
DelayNextAction(CLICK_CD_MELEE, flush = TRUE)
|
||||
|
||||
var/list/smellable = list()
|
||||
for(var/mob/living/L in view(1))
|
||||
if(L != src && (!L.ckey || L.client?.prefs.vore_flags & SMELLABLE) && Adjacent(L))
|
||||
LAZYADD(smellable, L)
|
||||
for(var/mob/living/listed in smellable)
|
||||
smellable[listed] = new /mutable_appearance(listed)
|
||||
|
||||
if(!smellable)
|
||||
return
|
||||
|
||||
var/mob/living/sniffed = show_radial_menu(src, src, smellable, radius = 40, require_near = TRUE)
|
||||
|
||||
if(QDELETED(sniffed) || (sniffed.ckey && !(sniffed.client?.prefs.vore_flags & SMELLABLE)) || !Adjacent(sniffed) || incapacitated(ignore_restraints = TRUE))
|
||||
return
|
||||
|
||||
visible_message("<span class='warning'>[src] smells [sniffed]!</span>","<span class='notice'>You smell [sniffed]. They smell like [sniffed.get_smell_message()].</span>","<b>Sniff!</b>")
|
||||
|
||||
/mob/living/proc/get_smell_message(allow_generic = TRUE, datum/species/mrace)
|
||||
if(!vore_smell && !allow_generic)
|
||||
return FALSE
|
||||
|
||||
var/smell_message = ""
|
||||
if(vore_smell && (vore_smell != ""))
|
||||
smell_message += "[vore_smell]"
|
||||
else
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H = src
|
||||
smell_message += "a normal [H.custom_species ? H.custom_species : H.dna.species]"
|
||||
else
|
||||
smell_message += "a plain old normal [src]"
|
||||
return smell_message
|
||||
|
||||
// Check if an object is capable of eating things, based on vore_organs
|
||||
//
|
||||
/proc/has_vore_belly(var/mob/living/O)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+50
-20
@@ -50,6 +50,56 @@
|
||||
-->
|
||||
<div class="commit sansserif">
|
||||
|
||||
<h2 class="date">19 July 2021</h2>
|
||||
<h3 class="author">Arturlang updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">The crafting button should no longer silently make more copies of itself on reconects</li>
|
||||
<li class="code_imp">There are no longer two copies of the crafting component.</li>
|
||||
<li class="code_imp">There is no longer a rogue d in tracer.dm tweak: Everything in Misc was moved to Miscelanious in the crafting menu, and Misc was nuked from orbit. Nobody will miss you.</li>
|
||||
</ul>
|
||||
<h3 class="author">MrJWhit updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixes a memory leak, there's a good chance that it's the same one that killed kilo.</li>
|
||||
</ul>
|
||||
<h3 class="author">SandPoot updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Put back mob vore with a pref.</li>
|
||||
<li class="code_imp">Taken some stuff from tg for tgui_alert.</li>
|
||||
<li class="refactor">Refactored a lot of code on vore panel.</li>
|
||||
</ul>
|
||||
<h3 class="author">WanderingFox95 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">custom plasteel kegs</li>
|
||||
</ul>
|
||||
<h3 class="author">YakumoChen updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">You can now wear the suffering of others on your head with just a sheet of human skin!</li>
|
||||
<li class="imageadd">Human skin hats</li>
|
||||
</ul>
|
||||
<h3 class="author">keronshb updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Stripping/equipping things to a conscious braindead person (AKA a human owned by a disconnected player) will now give them a message with your visible name and roughly how long ago you touched their stuff when they login again. Touching someone's pockets or adjusting their gear other than equipping/unequipping is not logged. After 5 minutes, you'll have forgotten both their name and exactly how long ago past those 5 minutes it happened. (Credit to Ryll-Ryll)</li>
|
||||
<li class="rscadd">LAZYNULL</li>
|
||||
<li class="rscadd">Breaking mirrors now gives you a bad omen</li>
|
||||
</ul>
|
||||
<h3 class="author">timothyteakettle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">anthros can now select the cow tail</li>
|
||||
<li class="rscadd">new quirk that allows you to eat trash</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">18 July 2021</h2>
|
||||
<h3 class="author">timothyteakettle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixes photosynthesis stopping nutrition going past well fed from non-photosynthesis means</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">17 July 2021</h2>
|
||||
<h3 class="author">cadyn updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="server">precompile.sh updated</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">15 July 2021</h2>
|
||||
<h3 class="author">Putnam3145 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
@@ -559,26 +609,6 @@
|
||||
<li class="rscadd">more drink mixture flavortext</li>
|
||||
<li class="soundadd">you're going to Baystation</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">15 May 2021</h2>
|
||||
<h3 class="author">bunny232 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Corrects the bot pathing by engineering on meta station</li>
|
||||
</ul>
|
||||
<h3 class="author">timothyteakettle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="balance">borg spraycans have a five second delay before being able to knock someone down again</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">14 May 2021</h2>
|
||||
<h3 class="author">keronshb updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="balance">Removes VOG sleep command since it was an undocumented readd.</li>
|
||||
</ul>
|
||||
<h3 class="author">zeroisthebiggay updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="spellcheck">consealed</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<b>GoonStation 13 Development Team</b>
|
||||
|
||||
@@ -29662,3 +29662,43 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
|
||||
2021-07-15:
|
||||
Putnam3145:
|
||||
- bugfix: fixes a major source of lag
|
||||
2021-07-17:
|
||||
cadyn:
|
||||
- server: precompile.sh updated
|
||||
2021-07-18:
|
||||
timothyteakettle:
|
||||
- bugfix: fixes photosynthesis stopping nutrition going past well fed from non-photosynthesis
|
||||
means
|
||||
2021-07-19:
|
||||
Arturlang:
|
||||
- bugfix: The crafting button should no longer silently make more copies of itself
|
||||
on reconects
|
||||
- code_imp: There are no longer two copies of the crafting component.
|
||||
- code_imp: 'There is no longer a rogue d in tracer.dm tweak: Everything in Misc
|
||||
was moved to Miscelanious in the crafting menu, and Misc was nuked from orbit.
|
||||
Nobody will miss you.'
|
||||
MrJWhit:
|
||||
- bugfix: Fixes a memory leak, there's a good chance that it's the same one that
|
||||
killed kilo.
|
||||
SandPoot:
|
||||
- rscadd: Put back mob vore with a pref.
|
||||
- code_imp: Taken some stuff from tg for tgui_alert.
|
||||
- refactor: Refactored a lot of code on vore panel.
|
||||
WanderingFox95:
|
||||
- rscadd: custom plasteel kegs
|
||||
YakumoChen:
|
||||
- rscadd: You can now wear the suffering of others on your head with just a sheet
|
||||
of human skin!
|
||||
- imageadd: Human skin hats
|
||||
keronshb:
|
||||
- rscadd: Stripping/equipping things to a conscious braindead person (AKA a human
|
||||
owned by a disconnected player) will now give them a message with your visible
|
||||
name and roughly how long ago you touched their stuff when they login again.
|
||||
Touching someone's pockets or adjusting their gear other than equipping/unequipping
|
||||
is not logged. After 5 minutes, you'll have forgotten both their name and exactly
|
||||
how long ago past those 5 minutes it happened. (Credit to Ryll-Ryll)
|
||||
- rscadd: LAZYNULL
|
||||
- rscadd: Breaking mirrors now gives you a bad omen
|
||||
timothyteakettle:
|
||||
- bugfix: anthros can now select the cow tail
|
||||
- rscadd: new quirk that allows you to eat trash
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 228 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 111 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 105 KiB |
@@ -639,6 +639,7 @@
|
||||
#include "code\datums\elements\swimming.dm"
|
||||
#include "code\datums\elements\sword_point.dm"
|
||||
#include "code\datums\elements\tactical.dm"
|
||||
#include "code\datums\elements\trash.dm"
|
||||
#include "code\datums\elements\turf_transparency.dm"
|
||||
#include "code\datums\elements\update_icon_blocker.dm"
|
||||
#include "code\datums\elements\update_icon_updates_onmob.dm"
|
||||
@@ -3593,6 +3594,7 @@
|
||||
#include "code\modules\tgui\states\observer.dm"
|
||||
#include "code\modules\tgui\states\physical.dm"
|
||||
#include "code\modules\tgui\states\self.dm"
|
||||
#include "code\modules\tgui\states\vorepanel.dm"
|
||||
#include "code\modules\tgui\states\zlevel.dm"
|
||||
#include "code\modules\tgui_panel\audio.dm"
|
||||
#include "code\modules\tgui_panel\external.dm"
|
||||
|
||||
@@ -0,0 +1,591 @@
|
||||
/* eslint-disable max-len */
|
||||
import { Fragment } from 'inferno';
|
||||
import { useBackend, useLocalState } from "../backend";
|
||||
import { Box, Button, Flex, Collapsible, Icon, LabeledList, NoticeBox, Section, Tabs } from "../components";
|
||||
import { Window } from "../layouts";
|
||||
|
||||
const stats = [
|
||||
null,
|
||||
'average',
|
||||
'bad',
|
||||
];
|
||||
|
||||
const digestModeToColor = {
|
||||
"Hold": null,
|
||||
"Dragon": "blue",
|
||||
"Digest": "red",
|
||||
"Absorb": "purple",
|
||||
"Unabsorb": "purple",
|
||||
};
|
||||
|
||||
const digestModeToPreyMode = {
|
||||
"Hold": "being held.",
|
||||
"Digest": "being digested.",
|
||||
"Absorb": "being absorbed.",
|
||||
"Unabsorb": "being unabsorbed.",
|
||||
"Dragon": "being digested by a powerful creature.",
|
||||
};
|
||||
|
||||
/**
|
||||
* There are three main sections to this UI.
|
||||
* - The Inside Panel, where all relevant data for interacting with a belly you're in is located.
|
||||
* - The Belly Selection Panel, where you can select what belly people will go into and customize the active one.
|
||||
* - User Preferences, where you can adjust all of your vore preferences on the fly.
|
||||
*/
|
||||
export const VorePanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
return (
|
||||
<Window width={700} height={660} theme="abstract" resizable>
|
||||
<Window.Content scrollable>
|
||||
{data.unsaved_changes && (
|
||||
<NoticeBox danger>
|
||||
<Flex>
|
||||
<Flex.Item basis="90%">
|
||||
Warning: Unsaved Changes!
|
||||
</Flex.Item>
|
||||
<Flex.Item>
|
||||
<Button
|
||||
content="Save Prefs"
|
||||
icon="save"
|
||||
onClick={() => act("saveprefs")} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</NoticeBox>
|
||||
) || null}
|
||||
<VoreInsidePanel />
|
||||
<VoreBellySelectionAndCustomization />
|
||||
<VoreUserPreferences />
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreInsidePanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
absorbed,
|
||||
belly_name,
|
||||
belly_mode,
|
||||
desc,
|
||||
pred,
|
||||
contents,
|
||||
ref,
|
||||
} = data.inside;
|
||||
|
||||
if (!belly_name) {
|
||||
return (
|
||||
<Section title="Inside">
|
||||
You aren't inside anyone.
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Section title="Inside">
|
||||
<Box color="green" inline>You are currently {absorbed ? "absorbed into" : "inside"}</Box>
|
||||
<Box color="yellow" inline>{pred}'s</Box>
|
||||
<Box color="red" inline>{belly_name}</Box>
|
||||
<Box color="yellow" inline>and you are</Box>
|
||||
<Box color={digestModeToColor[belly_mode]} inline>{digestModeToPreyMode[belly_mode]}</Box>
|
||||
<Box color="label">
|
||||
{desc}
|
||||
</Box>
|
||||
{contents.length && (
|
||||
<Collapsible title="Belly Contents">
|
||||
<VoreContentsPanel contents={contents} belly={ref} />
|
||||
</Collapsible>
|
||||
) || "There is nothing else around you."}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreBellySelectionAndCustomization = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
our_bellies,
|
||||
selected,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Section title="My Bellies">
|
||||
<Tabs>
|
||||
{our_bellies.map(belly => (
|
||||
<Tabs.Tab
|
||||
key={belly.name}
|
||||
selected={belly.selected}
|
||||
textColor={digestModeToColor[belly.digest_mode]}
|
||||
onClick={() => act("bellypick", { bellypick: belly.ref })}>
|
||||
<Box inline textColor={belly.selected && digestModeToColor[belly.digest_mode] || null}>
|
||||
{belly.name} ({belly.contents})
|
||||
</Box>
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
<Tabs.Tab onClick={() => act("newbelly")}>
|
||||
New
|
||||
<Icon name="plus" ml={0.5} />
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{selected && <VoreSelectedBelly belly={selected} />}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Subtemplate of VoreBellySelectionAndCustomization
|
||||
*/
|
||||
const VoreSelectedBelly = (props, context) => {
|
||||
const { act } = useBackend(context);
|
||||
|
||||
const { belly } = props;
|
||||
const {
|
||||
belly_name,
|
||||
is_wet,
|
||||
wet_loop,
|
||||
mode,
|
||||
verb,
|
||||
desc,
|
||||
sound,
|
||||
release_sound,
|
||||
can_taste,
|
||||
bulge_size,
|
||||
escapable,
|
||||
interacts,
|
||||
contents,
|
||||
} = belly;
|
||||
|
||||
const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Tabs>
|
||||
<Tabs.Tab selected={tabIndex === 0} onClick={() => setTabIndex(0)}>
|
||||
Controls
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab selected={tabIndex === 1} onClick={() => setTabIndex(1)}>
|
||||
Options
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab selected={tabIndex === 2} onClick={() => setTabIndex(2)}>
|
||||
Contents ({contents.length})
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab selected={tabIndex === 3} onClick={() => setTabIndex(3)}>
|
||||
Interactions
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{tabIndex === 0 && (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Name" buttons={
|
||||
<Fragment>
|
||||
<Button
|
||||
icon="arrow-left"
|
||||
tooltipPosition="left"
|
||||
tooltip="Move this belly tab left."
|
||||
onClick={() => act("move_belly", { dir: -1 })} />
|
||||
<Button
|
||||
icon="arrow-right"
|
||||
tooltipPosition="left"
|
||||
tooltip="Move this belly tab right."
|
||||
onClick={() => act("move_belly", { dir: 1 })} />
|
||||
</Fragment>
|
||||
}>
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_name" })}
|
||||
content={belly_name} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Mode">
|
||||
<Button
|
||||
color={digestModeToColor[mode]}
|
||||
onClick={() => act("set_attribute", { attribute: "b_mode" })}
|
||||
content={mode} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Flavor Text" buttons={
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_desc" })}
|
||||
icon="pen" />
|
||||
}>
|
||||
{desc}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Vore Verb">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_verb" })}
|
||||
content={verb} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Belly Messages">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "dmp" })}
|
||||
content="Digest Message (to prey)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "dmo" })}
|
||||
content="Digest Message (to you)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "smo" })}
|
||||
content="Struggle Message (outside)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "smi" })}
|
||||
content="Struggle Message (inside)" />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "em" })}
|
||||
content="Examine Message (when full)" />
|
||||
<Button
|
||||
color="red"
|
||||
onClick={() => act("set_attribute", { attribute: "b_msgs", msgtype: "reset" })}
|
||||
content="Reset Messages" />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) || tabIndex === 1 && (
|
||||
<Flex wrap="wrap">
|
||||
<Flex.Item basis="49%" grow={1}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Can Taste">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_tastes" })}
|
||||
icon={can_taste ? "toggle-on" : "toggle-off"}
|
||||
selected={can_taste}
|
||||
content={can_taste ? "Yes" : "No"} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Fleshy Belly">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_wetness" })}
|
||||
icon={is_wet ? "toggle-on" : "toggle-off"}
|
||||
selected={is_wet}
|
||||
content={is_wet ? "Yes" : "No"} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Internal Loop">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_wetloop" })}
|
||||
icon={wet_loop ? "toggle-on" : "toggle-off"}
|
||||
selected={wet_loop}
|
||||
content={wet_loop ? "Yes" : "No"} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="49%" grow={1}>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Vore Sound">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_sound" })}
|
||||
content={sound} />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_soundtest" })}
|
||||
icon="volume-up" />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Release Sound">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_release" })}
|
||||
content={release_sound} />
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_releasesoundtest" })}
|
||||
icon="volume-up" />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Required Examine Size">
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_bulge_size" })}
|
||||
content={bulge_size * 100 + "%"} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="100%" mt={1}>
|
||||
<Button.Confirm
|
||||
fluid
|
||||
icon="exclamation-triangle"
|
||||
confirmIcon="trash"
|
||||
color="red"
|
||||
content="Delete Belly"
|
||||
confirmContent="This is irreversable!"
|
||||
onClick={() => act("set_attribute", { attribute: "b_del" })} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
) || tabIndex === 2 && (
|
||||
<VoreContentsPanel outside contents={contents} />
|
||||
) || tabIndex === 3 && (
|
||||
<Section title="Belly Interactions" buttons={
|
||||
<Button
|
||||
onClick={() => act("set_attribute", { attribute: "b_escapable" })}
|
||||
icon={escapable ? "toggle-on" : "toggle-off"}
|
||||
selected={escapable}
|
||||
content={escapable ? "Interactions On" : "Interactions Off"} />
|
||||
}>
|
||||
{escapable ? (
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Escape Chance">
|
||||
<Button
|
||||
content={interacts.escapechance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_escapechance" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Escape Time">
|
||||
<Button
|
||||
content={interacts.escapetime / 10 + "s"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_escapetime" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Divider />
|
||||
<LabeledList.Item label="Transfer Chance">
|
||||
<Button
|
||||
content={interacts.transferchance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_transferchance" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Transfer Location">
|
||||
<Button
|
||||
content={interacts.transferlocation ? interacts.transferlocation : "Disabled"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_transferlocation" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Divider />
|
||||
<LabeledList.Item label="Absorb Chance">
|
||||
<Button
|
||||
content={interacts.absorbchance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_absorbchance" })} />
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Digest Chance">
|
||||
<Button
|
||||
content={interacts.digestchance + "%"}
|
||||
onClick={() => act("set_attribute", { attribute: "b_digestchance" })} />
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
) : "These options only display while interactions are turned on."}
|
||||
</Section>
|
||||
) || "Error"}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreContentsPanel = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
show_pictures,
|
||||
} = data;
|
||||
const {
|
||||
contents,
|
||||
belly,
|
||||
outside = false,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{outside && (
|
||||
<Button
|
||||
textAlign="center"
|
||||
fluid
|
||||
mb={1}
|
||||
onClick={() => act("pick_from_outside", { "pickall": true })}>
|
||||
All
|
||||
</Button>
|
||||
) || null}
|
||||
{show_pictures && (
|
||||
<Flex wrap="wrap" justify="center" align="center">
|
||||
{contents.map(thing => (
|
||||
<Flex.Item key={thing.name} basis="33%">
|
||||
<Button
|
||||
width="64px"
|
||||
color={thing.absorbed ? "purple" : stats[thing.stat]}
|
||||
style={{
|
||||
'vertical-align': 'middle',
|
||||
'margin-right': '5px',
|
||||
'border-radius': '20px',
|
||||
}}
|
||||
onClick={() => act(thing.outside ? "pick_from_outside" : "pick_from_inside", {
|
||||
"pick": thing.ref,
|
||||
"belly": belly,
|
||||
})}>
|
||||
<img
|
||||
src={"data:image/jpeg;base64, " + thing.icon}
|
||||
width="64px"
|
||||
height="64px"
|
||||
style={{
|
||||
'-ms-interpolation-mode': 'nearest-neighbor',
|
||||
'margin-left': '-5px',
|
||||
}} />
|
||||
</Button>
|
||||
{thing.name}
|
||||
</Flex.Item>
|
||||
))}
|
||||
</Flex>
|
||||
) || (
|
||||
<LabeledList>
|
||||
{contents.map(thing => (
|
||||
<LabeledList.Item key={thing.ref} label={thing.name}>
|
||||
<Button
|
||||
fluid
|
||||
mt={-1}
|
||||
mb={-1}
|
||||
color={thing.absorbed ? "purple" : stats[thing.stat]}
|
||||
onClick={() => act(thing.outside ? "pick_from_outside" : "pick_from_inside", {
|
||||
"pick": thing.ref,
|
||||
"belly": belly,
|
||||
})}>
|
||||
Interact
|
||||
</Button>
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const VoreUserPreferences = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
|
||||
const {
|
||||
digestable,
|
||||
devourable,
|
||||
feeding,
|
||||
absorbable,
|
||||
allowmobvore,
|
||||
vore_sounds,
|
||||
digestion_sounds,
|
||||
lickable,
|
||||
smellable,
|
||||
} = data.prefs;
|
||||
|
||||
const {
|
||||
show_pictures,
|
||||
} = data;
|
||||
|
||||
return (
|
||||
<Section title="Preferences" buttons={
|
||||
<Button icon="eye" selected={show_pictures} onClick={() => act("show_pictures")}>
|
||||
Contents Preference: {show_pictures ? "Show Pictures" : "Show List"}
|
||||
</Button>
|
||||
}>
|
||||
<Flex spacing={1} wrap="wrap" justify="center">
|
||||
<Flex.Item basis="33%">
|
||||
<Button
|
||||
onClick={() => act("toggle_devour")}
|
||||
icon={devourable ? "toggle-on" : "toggle-off"}
|
||||
selected={devourable}
|
||||
fluid
|
||||
tooltip={"This button is to toggle your ability to be devoured by others. "
|
||||
+ (devourable ? "Click here to prevent being devoured." : "Click here to allow being devoured.")}
|
||||
content={devourable ? "Devouring Allowed" : "No Devouring"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="33%">
|
||||
<Button
|
||||
onClick={() => act("toggle_mobvore")}
|
||||
icon={allowmobvore ? "toggle-on" : "toggle-off"}
|
||||
selected={allowmobvore}
|
||||
fluid
|
||||
tooltip={"This button is for those who don't like being eaten by mobs. "
|
||||
+ (allowmobvore
|
||||
? "Click here to prevent being eaten by mobs."
|
||||
: "Click here to allow being eaten by mobs.")}
|
||||
tooltipPosition="bottom-right"
|
||||
content={allowmobvore ? "Mobs eating you allowed" : "No Mobs eating you"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="33%" grow={1}>
|
||||
<Button
|
||||
onClick={() => act("toggle_feed")}
|
||||
icon={feeding ? "toggle-on" : "toggle-off"}
|
||||
selected={feeding}
|
||||
fluid
|
||||
tooltip={"This button is to toggle your ability to be fed to or by others vorishly. "
|
||||
+ (feeding
|
||||
? "Click here to prevent being fed to/by other people."
|
||||
: "Click here to allow being fed to/by other people.")}
|
||||
content={feeding ? "Feeding Allowed" : "No Feeding"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_digest")}
|
||||
icon={digestable ? "toggle-on" : "toggle-off"}
|
||||
selected={digestable}
|
||||
fluid
|
||||
tooltip={"This button is for those who don't like being digested. It can make you undigestable."
|
||||
+ (digestable ? " Click here to prevent digestion." : " Click here to allow digestion.")}
|
||||
tooltipPosition="bottom-right"
|
||||
content={digestable ? "Digestion Allowed" : "No Digestion"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_absorbable")}
|
||||
icon={absorbable ? "toggle-on" : "toggle-off"}
|
||||
selected={absorbable}
|
||||
fluid
|
||||
tooltip={"This button allows preds to know whether you prefer or don't prefer to be absorbed. "
|
||||
+ (absorbable ? "Click here to disallow being absorbed." : "Click here to allow being absorbed.")}
|
||||
content={absorbable ? "Absorption Allowed" : "No Absorption"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_vore_sounds")}
|
||||
icon={vore_sounds ? "volume-up" : "volume-mute"}
|
||||
selected={vore_sounds}
|
||||
fluid
|
||||
tooltip={"Be able to hear vore sounds. "
|
||||
+ (vore_sounds
|
||||
? "Click here to turn off vore sounds."
|
||||
: "Click here to turn on vore sounds.")}
|
||||
content={vore_sounds ? "Vore Sounds Enabled" : "Vore Sounds Disabled"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="50%">
|
||||
<Button
|
||||
onClick={() => act("toggle_digestion_sounds")}
|
||||
icon={digestion_sounds ? "volume-up" : "volume-mute"}
|
||||
selected={digestion_sounds}
|
||||
fluid
|
||||
tooltip={"Be able to hear digestion sounds. "
|
||||
+ (digestion_sounds
|
||||
? "Click here to turn off digestion sounds."
|
||||
: "Click here to turn on digestion sounds.")}
|
||||
content={digestion_sounds ? "Digestion Sounds Enabled" : "Digestion Sounds Disabled"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
onClick={() => act("toggle_lickable")}
|
||||
icon={lickable ? "toggle-on" : "toggle-off"}
|
||||
selected={lickable}
|
||||
fluid
|
||||
tooltip={"Be able to be licked by others. "
|
||||
+ (lickable
|
||||
? "Click here to turn off being able to be licked."
|
||||
: "Click here to turn on being able to be licked.")}
|
||||
tooltipPosition="bottom-right"
|
||||
content={lickable ? "Lickable" : "Unlickable"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
fluid
|
||||
content="Set Taste"
|
||||
icon="grin-tongue"
|
||||
onClick={() => act("setflavor")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
onClick={() => act("toggle_smellable")}
|
||||
icon={smellable ? "toggle-on" : "toggle-off"}
|
||||
selected={smellable}
|
||||
fluid
|
||||
tooltip={"Be able to be smelled by others. "
|
||||
+ (smellable
|
||||
? "Click here to turn off being able to be smelled."
|
||||
: "Click here to turn on being able to be smelled.")}
|
||||
content={smellable ? "Smellable" : "Unsmellable"} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="25%">
|
||||
<Button
|
||||
fluid
|
||||
content="Set Smell"
|
||||
icon="wind"
|
||||
onClick={() => act("setsmell")} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
<Section>
|
||||
<Flex spacing={1}>
|
||||
<Flex.Item basis="49%">
|
||||
<Button
|
||||
fluid
|
||||
content="Save Prefs"
|
||||
icon="save"
|
||||
onClick={() => act("saveprefs")} />
|
||||
</Flex.Item>
|
||||
<Flex.Item basis="49%" grow={1}>
|
||||
<Button
|
||||
fluid
|
||||
content="Reload Prefs"
|
||||
icon="undo"
|
||||
onClick={() => act("reloadprefs")} />
|
||||
</Flex.Item>
|
||||
</Flex>
|
||||
</Section>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@@ -67,7 +67,7 @@ mv target/i686-unknown-linux-gnu/release/librust_g.so "$1/librust_g.so"
|
||||
cd ..
|
||||
|
||||
# Auxtools dependencies
|
||||
apt-get install build-essential g++-multilib libc6-i386 libstdc++6:i386
|
||||
apt-get install -y build-essential g++-multilib libc6-i386 libstdc++6:i386
|
||||
|
||||
# Update auxmos
|
||||
if [ ! -d "auxmos" ]; then
|
||||
|
||||
Reference in New Issue
Block a user