From 60b9e9dafe2113808d1c1885cdfada9f672c2270 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 10 Jul 2020 21:06:53 +0100 Subject: [PATCH 01/14] trader event/mob --- code/modules/events/travelling_trader.dm | 115 +++++++++++++++++++++++ tgstation.dme | 1 + 2 files changed, 116 insertions(+) create mode 100644 code/modules/events/travelling_trader.dm diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm new file mode 100644 index 0000000000..918bc94029 --- /dev/null +++ b/code/modules/events/travelling_trader.dm @@ -0,0 +1,115 @@ +/datum/round_event_control/travelling_trader + name = "Travelling Trader" + typepath = /datum/round_event/travelling_trader + weight = 10 + max_occurrences = 3 + earliest_start = 0 MINUTES + +/datum/round_event/travelling_trader + startWhen = 0 + endWhen = 600 //you effectively have 10 minutes to complete the traders request, before they disappear + var/mob/living/carbon/human/dummy/travelling_trader/trader + var/atom/spawn_location //where the trader appears + +/datum/round_event/travelling_trader/setup() + //find position to place trader at, same as how jacq works for poofing + var/list/targets = list() + for(var/H in GLOB.network_holopads) + var/area/A = get_area(H) + if(!A || findtextEx(A.name, "AI") || !is_station_level(H)) + continue + targets += H + + if(!targets) + targets = GLOB.generic_event_spawns + + spawn_location = pick(targets) + +/datum/round_event/travelling_trader/start() + //spawn a type of trader + trader = pick(subtypesof(/mob/living/carbon/human/dummy/travelling_trader)) + var/datum/effect_system/smoke_spread/smoke = new + smoke.set_up(1, spawn_location) + smoke.start() + trader.visible_message("[src] suddenly appears in a puff of smoke!") + +/datum/round_event/travelling_trader/announce(fake) + priority_announce("A mysterious figure has been detected on sensors at [get_area(spawn_location)]", "Mysterious Figure") + +/datum/round_event/travelling_trader/end() + if(trader) + trader.visible_message("The [src] has given up on waiting!") + qdel(trader) + +//the actual trader mob +/mob/living/carbon/human/dummy/travelling_trader //subtype of dummy because we want to be resource-efficient + real_name = "Debug Travelling Trader" + status_flags = GODMODE //avoid scenarios of people trying to kill the trader + move_resist = MOVE_FORCE_VERY_STRONG //you can't bluespace bodybag them! + var/datum/outfit/trader_outfit + var/list/possible_wanted_items //weighted list of possible things to request + var/list/possible_rewards //weighted list of possible things to give in return for the requested item + var/atom/requested_item //the thing they chose from possible_wanted_items + var/last_speech //last time someone tried interacting with them using their hand + var/last_refusal //last time they vocally refused an item given to them + var/initial_speech = "It looks like the coders did a mishap!" //first thing they say when interacted with, like a description + var/speech_verb = "says" + var/request_speech = "Please bring me a requested_item you shall be greatly rewarded!" //second thing they say when interacted with + var/acceptance_speech = "This is exactly what I wanted! I shall be on my way now, thank you.!" + var/refusal_speech = "A given_item? I wanted a requested_item!" //what they say when refusing an item + var/active = TRUE + +/mob/living/carbon/human/dummy/travelling_trader/proc/setup_speech(var/input_speech, var/obj/item/given_item) + if(requested_item) + input_speech = replacetext(input_speech, "requested_item", requested_item.name) + if(given_item) + input_speech = replacetext(input_speech, "given_item", given_item.name) + return input_speech + +/mob/living/carbon/human/dummy/travelling_trader/attack_hand(mob/living/carbon/human/H) + if(active && last_speech + 3 SECONDS < world.realtime) //can only talk once per 3 seconds, to avoid spam + last_speech = world.realtime + if(initial_speech) + visible_message("[src] [speech_verb] \"[setup_speech(initial_speech)]\"") + sleep(15) + if(active && request_speech) //they might not be active anymore because of the prior sleep! + visible_message("[src] [speech_verb] \"[setup_speech(request_speech)]\"") + +/mob/living/carbon/human/dummy/travelling_trader/attackby(obj/item/I, mob/user) + if(active) + if(check_item(I)) + active = FALSE + visible_message("[src] [speech_verb] \"[setup_speech(acceptance_speech, I)]\"") + qdel(I) + sleep(20) + give_reward() + qdel(src) + else + if(last_refusal + 3 SECONDS < world.realtime) + last_refusal = world.realtime + visible_message("[src] [speech_verb] \"[setup_speech(refusal_speech, I)]\"") + +/mob/living/carbon/human/dummy/travelling_trader/proc/check_item(var/obj/item/supplied_item) //sometimes we might want to care about the properties of the item, etc + return istype(supplied_item, requested_item) + +/mob/living/carbon/human/dummy/travelling_trader/proc/give_reward() + var/reward = pickweight(possible_rewards) + new reward(get_turf(src)) + +/mob/living/carbon/human/dummy/travelling_trader/Initialize() + ADD_TRAIT(src,TRAIT_PIERCEIMMUNE, "trader_pierce_immune") //don't let people take their blood + trader_outfit.equip(src, TRUE) + for(var/obj/item/item in src.get_equipped_items()) + ADD_TRAIT(item, TRAIT_NODROP, "trader_no_drop") //don't let people steal the travellers clothes! + item.resistance_flags |= INDESTRUCTIBLE //don't let people burn their clothes off, either. + requested_item = pickweight(possible_wanted_items) + ..() + +/mob/living/carbon/human/dummy/travelling_trader/Destroy() + var/datum/effect_system/smoke_spread/smoke = new + smoke.set_up(1, loc) + smoke.start() + visible_message("[src] disappears in a puff of smoke, leaving something on the ground!") + ..() + +//travelling trader subtypes (the types that can actually spawn) \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index 8be5ae2a46..78a665a033 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1954,6 +1954,7 @@ #include "code\modules\events\spider_infestation.dm" #include "code\modules\events\spontaneous_appendicitis.dm" #include "code\modules\events\stray_cargo.dm" +#include "code\modules\events\travelling_trader.dm" #include "code\modules\events\vent_clog.dm" #include "code\modules\events\wisdomcow.dm" #include "code\modules\events\wormholes.dm" From 045169e1ee60b5da419cb344419f42b825222d01 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 10 Jul 2020 22:50:22 +0100 Subject: [PATCH 02/14] actual trader subtypes --- code/modules/events/travelling_trader.dm | 103 +++++++++++++++++++++-- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index 918bc94029..e6cbb28f30 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -7,7 +7,7 @@ /datum/round_event/travelling_trader startWhen = 0 - endWhen = 600 //you effectively have 10 minutes to complete the traders request, before they disappear + endWhen = 900 //you effectively have 15 minutes to complete the traders request, before they disappear var/mob/living/carbon/human/dummy/travelling_trader/trader var/atom/spawn_location //where the trader appears @@ -27,7 +27,8 @@ /datum/round_event/travelling_trader/start() //spawn a type of trader - trader = pick(subtypesof(/mob/living/carbon/human/dummy/travelling_trader)) + var/trader_type = pick(subtypesof(/mob/living/carbon/human/dummy/travelling_trader)) + trader = new trader_type(spawn_location) var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(1, spawn_location) smoke.start() @@ -81,7 +82,7 @@ active = FALSE visible_message("[src] [speech_verb] \"[setup_speech(acceptance_speech, I)]\"") qdel(I) - sleep(20) + sleep(15) give_reward() qdel(src) else @@ -102,7 +103,8 @@ for(var/obj/item/item in src.get_equipped_items()) ADD_TRAIT(item, TRAIT_NODROP, "trader_no_drop") //don't let people steal the travellers clothes! item.resistance_flags |= INDESTRUCTIBLE //don't let people burn their clothes off, either. - requested_item = pickweight(possible_wanted_items) + if(!requested_item) //sometimes we already picked one + requested_item = pickweight(possible_wanted_items) ..() /mob/living/carbon/human/dummy/travelling_trader/Destroy() @@ -112,4 +114,95 @@ visible_message("[src] disappears in a puff of smoke, leaving something on the ground!") ..() -//travelling trader subtypes (the types that can actually spawn) \ No newline at end of file +//travelling trader subtypes (the types that can actually spawn) +//so far there's: cook / botanist / animal hunter + +//cook +/mob/living/carbon/human/dummy/travelling_trader/cook + name = "Otherworldly Chef" + trader_outfit = /datum/outfit/job/cook + initial_speech = "Mama-mia! I have came to this plane of existence, searching the greatest of foods!" + request_speech = "Can you fetch me the delicacy known as requested_item? I would pay you for your service!" + acceptance_speech = "Grazie! You have done me a service, my friend." + refusal_speech = "A given_item? Surely you must be joking!" + possible_rewards = list() + + +/mob/living/carbon/human/dummy/travelling_trader/cook/Initialize() + //pick a random crafted food item as the requested item + requested_item = pick(subtypesof(/datum/crafting_recipe/food)).result + ..() + +//botanist +/mob/living/carbon/human/dummy/travelling_trader/gardener + name = "Otherworldly Gardener" + trader_outfit = /datum/outfit/job/botanist + initial_speech = "I have come across this realm in search of rare plants and believe this station may be able to help me.." + request_speech = "Are you able to bring me a requested_item? I could see that you get some reward for this task." + acceptance_speech = "Amazing! Ill finally be able to make that salad. Goodbye for now!" + refusal_speech = "A given_item? Did nobody ever teach you the basics of gardening?" + possible_rewards = list() + + +/mob/living/carbon/human/dummy/travelling_trader/gardener/Initialize() + requested_item = pick(subtypesof(/obj/item/reagent_containers/food/snacks/grown)) + ..() + +//animal hunter +/mob/living/carbon/human/dummy/travelling_trader/animal_hunter + name = "Otherworldly Animal Specialist" + trader_outfit = /datum/outfit/synthetic + initial_speech = "Greetings, lifeform. I am here to locate a special creature aboard your station." + request_speech = "Find me the creature known as 'requested_item' and you shall be rewarded for your efforts." + refusal_speech = "Do you think me to be a fool, lifeform? I know a requested_item when I see one." + possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi/Ian = 1, /mob/living/simple_animal/sloth/paperwork = 1, /mob/living/carbon/monkey/punpun = 1, /mob/living/simple_animal/pet/fox/Renault = 1, /mob/living/simple_animal/hostile/carp/cayenne = 1) + +mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() + acceptance_speech = pick(list("This lifeform shall make for a great stew, thank you.", "This lifeform shall be of a true use to our cause, thank you.", "The lifeform is adequate. Goodbye.", "This lifeform shall make a great addition to my collection.")) + ..() + +/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(var/obj/item/supplied_item) //item is likely to be in contents of whats supplied + if(supplied_item.contents[requested_item]) + //delete the contents, item given is correct, but we don't want the contents to spill out when the parent is deleted + for(var/atom/thing in supplied_item.contents) + qdel(thing) + return TRUE + return FALSE + +//bartender +/mob/living/carbon/human/dummy/travelling_trader/bartender + name = "Otherworldly Bartender" + trader_outfit = /datum/outfit/job/bartender + initial_speech = "Greetings, station inhabitor. I came to this dimension in the pursuit of a particular drink." + request_speech = "Bring me thirty units of the beverage known as 'requested_item'." + acceptance_speech = "This is truly the drink I have been seeking. Thank you." + refusal_speech = "Do not mess with me, simpleton, I do not wish for that which you are trying to give me." + +/mob/living/carbon/human/dummy/travelling_trader/bartender/Initialize() //pick a subtype of ethanol that isn't found in the default set of the booze dispensers reagents + requested_item = pick(subtypesof(/datum/reagent/consumable/ethanol) - list(/datum/reagent/consumable/ethanol/beer, + /datum/reagent/consumable/ethanol/kahlua, + /datum/reagent/consumable/ethanol/whiskey, + /datum/reagent/consumable/ethanol/wine, + /datum/reagent/consumable/ethanol/vodka, + /datum/reagent/consumable/ethanol/gin, + /datum/reagent/consumable/ethanol/rum, + /datum/reagent/consumable/ethanol/tequila, + /datum/reagent/consumable/ethanol/vermouth, + /datum/reagent/consumable/ethanol/cognac, + /datum/reagent/consumable/ethanol/ale, + /datum/reagent/consumable/ethanol/absinthe, + /datum/reagent/consumable/ethanol/hcider, + /datum/reagent/consumable/ethanol/creme_de_menthe, + /datum/reagent/consumable/ethanol/creme_de_cacao, + /datum/reagent/consumable/ethanol/creme_de_coconut, + /datum/reagent/consumable/ethanol/triple_sec, + /datum/reagent/consumable/ethanol/sake, + /datum/reagent/consumable/ethanol/applejack)) + ..() + +/mob/living/carbon/human/dummy/travelling_trader/bartender/check_item(var/obj/item/supplied_item) //you need to check its reagents + var/obj/item/reagent_container/container = supplied_item + if(container) + if(container.reagents.has_reagent(requested_item, 30)) + return TRUE + return FALSE From 75b9eef74ef42add0872f89ad73aeeb6e660b8fc Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 10 Jul 2020 22:52:08 +0100 Subject: [PATCH 03/14] bug fixes --- code/modules/events/travelling_trader.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index e6cbb28f30..16533a0108 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -201,8 +201,8 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() ..() /mob/living/carbon/human/dummy/travelling_trader/bartender/check_item(var/obj/item/supplied_item) //you need to check its reagents - var/obj/item/reagent_container/container = supplied_item - if(container) - if(container.reagents.has_reagent(requested_item, 30)) + var/obj/item/reagent_container/supplied_container = supplied_item + if(supplied_container) + if(supplied_container.reagents.has_reagent(requested_item, 30)) return TRUE return FALSE From e571400b1bdb50bbbb95105b41b9216ffeb39006 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 11 Jul 2020 03:35:15 +0100 Subject: [PATCH 04/14] lots of bug fixes --- code/modules/events/travelling_trader.dm | 39 ++++++++++-------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index 16533a0108..d7eece79d1 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -12,23 +12,13 @@ var/atom/spawn_location //where the trader appears /datum/round_event/travelling_trader/setup() - //find position to place trader at, same as how jacq works for poofing - var/list/targets = list() - for(var/H in GLOB.network_holopads) - var/area/A = get_area(H) - if(!A || findtextEx(A.name, "AI") || !is_station_level(H)) - continue - targets += H - - if(!targets) - targets = GLOB.generic_event_spawns - - spawn_location = pick(targets) + spawn_location = pick(GLOB.generic_event_spawns) /datum/round_event/travelling_trader/start() //spawn a type of trader var/trader_type = pick(subtypesof(/mob/living/carbon/human/dummy/travelling_trader)) - trader = new trader_type(spawn_location) + message_admins("we picked trader [trader_type] at location [spawn_location]") + trader = new trader_type(get_turf(spawn_location)) var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(1, spawn_location) smoke.start() @@ -43,7 +33,7 @@ qdel(trader) //the actual trader mob -/mob/living/carbon/human/dummy/travelling_trader //subtype of dummy because we want to be resource-efficient +/mob/living/carbon/human/dummy/travelling_trader //similar to a dummy because we want to be resource-efficient real_name = "Debug Travelling Trader" status_flags = GODMODE //avoid scenarios of people trying to kill the trader move_resist = MOVE_FORCE_VERY_STRONG //you can't bluespace bodybag them! @@ -62,13 +52,15 @@ /mob/living/carbon/human/dummy/travelling_trader/proc/setup_speech(var/input_speech, var/obj/item/given_item) if(requested_item) - input_speech = replacetext(input_speech, "requested_item", requested_item.name) + var/atom/temp_requested = new requested_item + input_speech = replacetext(input_speech, "requested_item", temp_requested.name) + qdel(temp_requested) if(given_item) input_speech = replacetext(input_speech, "given_item", given_item.name) return input_speech /mob/living/carbon/human/dummy/travelling_trader/attack_hand(mob/living/carbon/human/H) - if(active && last_speech + 3 SECONDS < world.realtime) //can only talk once per 3 seconds, to avoid spam + if(active && last_speech + 3 < world.realtime) //can only talk once per 3 seconds, to avoid spam last_speech = world.realtime if(initial_speech) visible_message("[src] [speech_verb] \"[setup_speech(initial_speech)]\"") @@ -86,7 +78,7 @@ give_reward() qdel(src) else - if(last_refusal + 3 SECONDS < world.realtime) + if(last_refusal + 3 < world.realtime) last_refusal = world.realtime visible_message("[src] [speech_verb] \"[setup_speech(refusal_speech, I)]\"") @@ -98,14 +90,14 @@ new reward(get_turf(src)) /mob/living/carbon/human/dummy/travelling_trader/Initialize() + ..() ADD_TRAIT(src,TRAIT_PIERCEIMMUNE, "trader_pierce_immune") //don't let people take their blood - trader_outfit.equip(src, TRUE) + equipOutfit(trader_outfit, TRUE) for(var/obj/item/item in src.get_equipped_items()) ADD_TRAIT(item, TRAIT_NODROP, "trader_no_drop") //don't let people steal the travellers clothes! item.resistance_flags |= INDESTRUCTIBLE //don't let people burn their clothes off, either. if(!requested_item) //sometimes we already picked one requested_item = pickweight(possible_wanted_items) - ..() /mob/living/carbon/human/dummy/travelling_trader/Destroy() var/datum/effect_system/smoke_spread/smoke = new @@ -130,7 +122,8 @@ /mob/living/carbon/human/dummy/travelling_trader/cook/Initialize() //pick a random crafted food item as the requested item - requested_item = pick(subtypesof(/datum/crafting_recipe/food)).result + var/category = pick(list(/obj/item/reagent_containers/food/snacks/burger,/obj/item/reagent_containers/food/snacks/pie,/obj/item/reagent_containers/food/snacks/pizza,/obj/item/reagent_containers/food/snacks/soup,/obj/item/reagent_containers/food/snacks/store/bread)) + requested_item = pick(subtypesof(category)) ..() //botanist @@ -162,7 +155,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() ..() /mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(var/obj/item/supplied_item) //item is likely to be in contents of whats supplied - if(supplied_item.contents[requested_item]) + if(requested_item in supplied_item.contents) //delete the contents, item given is correct, but we don't want the contents to spill out when the parent is deleted for(var/atom/thing in supplied_item.contents) qdel(thing) @@ -201,8 +194,8 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() ..() /mob/living/carbon/human/dummy/travelling_trader/bartender/check_item(var/obj/item/supplied_item) //you need to check its reagents - var/obj/item/reagent_container/supplied_container = supplied_item - if(supplied_container) + if(istype(supplied_item, /obj/item/reagent_containers)) + var/obj/item/reagent_containers/supplied_container = supplied_item if(supplied_container.reagents.has_reagent(requested_item, 30)) return TRUE return FALSE From c1592ad162f3e428781beba144ba0a7329e274d0 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 11 Jul 2020 23:27:29 +0100 Subject: [PATCH 05/14] more rewards --- code/game/objects/items/kitchen.dm | 6 + code/game/objects/items/pet_carrier.dm | 5 +- code/game/objects/items/stacks/tape.dm | 13 +- code/game/objects/items/storage/boxes.dm | 6 + code/modules/events/travelling_trader.dm | 156 +++++++++++++++--- code/modules/mining/money_bag.dm | 6 +- .../living/simple_animal/friendly/bumbles.dm | 1 + .../simple_animal/friendly/farm_animals.dm | 9 + code/modules/reagents/reagent_dispenser.dm | 39 +++++ 9 files changed, 213 insertions(+), 28 deletions(-) diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index dda41494ff..1d4610488d 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -54,6 +54,12 @@ else return ..() +/obj/item/kitchen/fork/throwing + name = "throwing fork" + desc = "A fork, sharpened to perfection, making it a great weapon for throwing." + throwforce = 15 + embedding = list("pain_mult" = 2, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 100) + sharpness = IS_SHARP_ACCURATE /obj/item/kitchen/knife name = "kitchen knife" diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index 8b322d20cb..8ebb497fe1 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -106,7 +106,7 @@ if(user == target) to_chat(user, "Why would you ever do that?") return - if(ishostile(target) && !allows_hostiles && target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers + if(ishostile(target) && (!allows_hostiles || istype(target, /mob/living/simple_animal/hostile/carp/cayenne))) || target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers, but let cayenne in! to_chat(user, "You have a feeling you shouldn't keep this as a pet.") load_occupant(user, target) @@ -253,7 +253,8 @@ occupant_gas_supply = new if(isanimal(occupant)) var/mob/living/simple_animal/animal = occupant - occupant_gas_supply.set_temperature(animal.minbodytemp) //simple animals only care about temperature when their turf isnt a location + occupant_gas_supply[/datum/gas/oxygen] = 0.0064 //make sure it has some gas in so it isn't depressurized + occupant_gas_supply.set_temperature(animal.minbodytemp) //simple animals only care about temperature/pressure when their turf isnt a location else if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist") diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm index 177260febb..8e8e2eaf52 100644 --- a/code/game/objects/items/stacks/tape.dm +++ b/code/game/objects/items/stacks/tape.dm @@ -15,6 +15,8 @@ var/list/conferred_embed = EMBED_HARMLESS var/overwrite_existing = FALSE + var/apply_time = 30 + /obj/item/stack/sticky_tape/afterattack(obj/item/I, mob/living/user) if(!istype(I)) return @@ -25,17 +27,24 @@ user.visible_message("[user] begins wrapping [I] with [src].", "You begin wrapping [I] with [src].") - if(do_after(user, 30, target=I)) + if(do_after(user, apply_time, target=I)) I.embedding = conferred_embed I.updateEmbedding() to_chat(user, "You finish wrapping [I] with [src].") - use(1) + if(max_amount > 0) + use(1) I.name = "[prefix] [I.name]" if(istype(I, /obj/item/grenade)) var/obj/item/grenade/sticky_bomb = I sticky_bomb.sticky = TRUE +/obj/item/stack/sticky_tape/infinite //endless tape that applies far faster, for maximum honks + name = "endless sticky tape" + desc = "This roll of sticky tape somehow has no end." + max_amount = 0 + apply_time = 10 + /obj/item/stack/sticky_tape/super name = "super sticky tape" singular_name = "super sticky tape" diff --git a/code/game/objects/items/storage/boxes.dm b/code/game/objects/items/storage/boxes.dm index cdd3781748..02ae867240 100644 --- a/code/game/objects/items/storage/boxes.dm +++ b/code/game/objects/items/storage/boxes.dm @@ -1418,3 +1418,9 @@ obj/item/storage/box/stingbangs new /obj/item/reagent_containers/glass/beaker/meta(src) new /obj/item/reagent_containers/glass/beaker/noreact(src) new /obj/item/reagent_containers/glass/beaker/bluespace(src) + +/obj/item/storage/box/strange_seeds_5pack + +/obj/item/storage/box/strange_seeds_5pack/PopulateContents() + for(var/i in 1 to 5) + new /obj/item/seeds/random(src) \ No newline at end of file diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index d7eece79d1..e19b2bfdee 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -12,12 +12,15 @@ var/atom/spawn_location //where the trader appears /datum/round_event/travelling_trader/setup() - spawn_location = pick(GLOB.generic_event_spawns) + if(GLOB.generic_event_spawns) + spawn_location = pick(GLOB.generic_event_spawns) + else + message_admins("No event spawn landmarks exist on the map while placing a travelling trader, resorting to random station turf. (go yell at a mapper)") + spawn_location = get_random_station_turf() /datum/round_event/travelling_trader/start() //spawn a type of trader var/trader_type = pick(subtypesof(/mob/living/carbon/human/dummy/travelling_trader)) - message_admins("we picked trader [trader_type] at location [spawn_location]") trader = new trader_type(get_turf(spawn_location)) var/datum/effect_system/smoke_spread/smoke = new smoke.set_up(1, spawn_location) @@ -34,7 +37,7 @@ //the actual trader mob /mob/living/carbon/human/dummy/travelling_trader //similar to a dummy because we want to be resource-efficient - real_name = "Debug Travelling Trader" + var/trader_name = "Debug Travelling Trader" status_flags = GODMODE //avoid scenarios of people trying to kill the trader move_resist = MOVE_FORCE_VERY_STRONG //you can't bluespace bodybag them! var/datum/outfit/trader_outfit @@ -75,7 +78,7 @@ visible_message("[src] [speech_verb] \"[setup_speech(acceptance_speech, I)]\"") qdel(I) sleep(15) - give_reward() + give_reward(user) qdel(src) else if(last_refusal + 3 < world.realtime) @@ -98,6 +101,7 @@ item.resistance_flags |= INDESTRUCTIBLE //don't let people burn their clothes off, either. if(!requested_item) //sometimes we already picked one requested_item = pickweight(possible_wanted_items) + name = trader_name //gets changed in humans initialisation so we set it here /mob/living/carbon/human/dummy/travelling_trader/Destroy() var/datum/effect_system/smoke_spread/smoke = new @@ -107,69 +111,113 @@ ..() //travelling trader subtypes (the types that can actually spawn) -//so far there's: cook / botanist / animal hunter +//so far there's: cook / botanist / bartender / animal hunter / artifact dealer / surgeon (6 types!) //cook /mob/living/carbon/human/dummy/travelling_trader/cook - name = "Otherworldly Chef" + trader_name = "Otherworldly Chef" trader_outfit = /datum/outfit/job/cook initial_speech = "Mama-mia! I have came to this plane of existence, searching the greatest of foods!" request_speech = "Can you fetch me the delicacy known as requested_item? I would pay you for your service!" acceptance_speech = "Grazie! You have done me a service, my friend." refusal_speech = "A given_item? Surely you must be joking!" - possible_rewards = list() - + possible_rewards = list(/obj/item/paper/secretrecipe = 1, + /obj/item/pizzabox/infinite = 1, + /obj/item/kitchen/fork/throwing = 1, + /mob/living/simple_animal/cow/random = 1) /mob/living/carbon/human/dummy/travelling_trader/cook/Initialize() //pick a random crafted food item as the requested item - var/category = pick(list(/obj/item/reagent_containers/food/snacks/burger,/obj/item/reagent_containers/food/snacks/pie,/obj/item/reagent_containers/food/snacks/pizza,/obj/item/reagent_containers/food/snacks/soup,/obj/item/reagent_containers/food/snacks/store/bread)) - requested_item = pick(subtypesof(category)) + requested_item = GLOB.crafting_recipes[pick(subtypesof( /datum/crafting_recipe/food))].result ..() //botanist /mob/living/carbon/human/dummy/travelling_trader/gardener - name = "Otherworldly Gardener" + trader_name = "Otherworldly Gardener" trader_outfit = /datum/outfit/job/botanist initial_speech = "I have come across this realm in search of rare plants and believe this station may be able to help me.." request_speech = "Are you able to bring me a requested_item? I could see that you get some reward for this task." acceptance_speech = "Amazing! Ill finally be able to make that salad. Goodbye for now!" refusal_speech = "A given_item? Did nobody ever teach you the basics of gardening?" - possible_rewards = list() + possible_rewards = list(/obj/item/seeds/cherry/bomb = 1, + /obj/item/storage/box/strange_seeds_5pack = 6, + /obj/item/clothing/suit/hooded/bee_costume = 2, + /obj/item/seeds/gatfruit = 1) //overall you have less chance of seeing them than a lifebringer just bringing the seeds to you directly /mob/living/carbon/human/dummy/travelling_trader/gardener/Initialize() - requested_item = pick(subtypesof(/obj/item/reagent_containers/food/snacks/grown)) + requested_item = pick(subtypesof(/obj/item/reagent_containers/food/snacks/grown) - list(/obj/item/reagent_containers/food/snacks/grown/shell, + /obj/item/reagent_containers/food/snacks/grown/shell/gatfruit, + /obj/item/reagent_containers/food/snacks/grown/cherry_bomb)) ..() //animal hunter /mob/living/carbon/human/dummy/travelling_trader/animal_hunter - name = "Otherworldly Animal Specialist" - trader_outfit = /datum/outfit/synthetic + trader_name = "Otherworldly Animal Specialist" + trader_outfit = /datum/outfit/job/doctor initial_speech = "Greetings, lifeform. I am here to locate a special creature aboard your station." - request_speech = "Find me the creature known as 'requested_item' and you shall be rewarded for your efforts." + request_speech = "Find me the creature known as 'requested_item' and you shall be rewarded for your efforts." refusal_speech = "Do you think me to be a fool, lifeform? I know a requested_item when I see one." - possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi/Ian = 1, /mob/living/simple_animal/sloth/paperwork = 1, /mob/living/carbon/monkey/punpun = 1, /mob/living/simple_animal/pet/fox/Renault = 1, /mob/living/simple_animal/hostile/carp/cayenne = 1) + possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi/Ian = 1, + /mob/living/simple_animal/sloth/paperwork = 1, + /mob/living/carbon/monkey/punpun = 1, + /mob/living/simple_animal/pet/fox/Renault = 1, + /mob/living/simple_animal/hostile/carp/cayenne = 1, + /mob/living/simple_animal/pet/bumbles = 1, + /mob/living/simple_animal/parrot/Poly = 1) + possible_rewards = list(/mob/living/simple_animal/pet/dog/corgi/exoticcorgi = 1, //rewards are animals, friendly to only the person who handed the reward in! + /mob/living/simple_animal/cockroach = 1, + /mob/living/simple_animal/hostile/skeleton = 1, + /mob/living/simple_animal/hostile/stickman = 1, + /mob/living/simple_animal/hostile/stickman/dog = 1, + /mob/living/simple_animal/hostile/asteroid/fugu = 1, + /mob/living/simple_animal/hostile/bear = 1, + /mob/living/simple_animal/hostile/retaliate/clown/fleshclown = 1, + /mob/living/simple_animal/hostile/tree = 1, + /mob/living/simple_animal/hostile/mimic = 1 + /mob/living/simple_animal/hostile/shark/laser = 1 + ) mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() acceptance_speech = pick(list("This lifeform shall make for a great stew, thank you.", "This lifeform shall be of a true use to our cause, thank you.", "The lifeform is adequate. Goodbye.", "This lifeform shall make a great addition to my collection.")) + //make sure they only ask for animals that are still alive + for(var/mob/living/animal in possible_wanted_items) + if(!(animal in GLOB.mob_living_list)) + possible_wanted_items -= animal + if(!possible_wanted_items) + //all the pets are dead, so ask for a monkey, or sometimes a corgi (corgis are more annoying to get a hold of) + possible_wanted_items = list(/mob/living/simple_animal/pet/dog/corgi = 1, /mob/living/carbon/monkey = 3) ..() /mob/living/carbon/human/dummy/travelling_trader/animal_hunter/check_item(var/obj/item/supplied_item) //item is likely to be in contents of whats supplied - if(requested_item in supplied_item.contents) - //delete the contents, item given is correct, but we don't want the contents to spill out when the parent is deleted - for(var/atom/thing in supplied_item.contents) - qdel(thing) - return TRUE + for(var/atom/something in supplied_item.contents) + if(istype(something, requested_item)) + qdel(something) //typically things holding mobs release the mob when the container is deleted, so delete the mob first here + return TRUE return FALSE +/mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(var/mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea + var/mob/living/animal = pickweight(possible_rewards) + if(giver && giver.tag) + animal.faction += "/[[giver.tag]/]" + var/obj/item/pet_carrier/bluespace/jar = new(get_turf(src)) + jar.add_occupant(animal) + jar.name = "WARNING: [animal] INSIDE" + //bartender /mob/living/carbon/human/dummy/travelling_trader/bartender - name = "Otherworldly Bartender" + trader_name = "Otherworldly Bartender" trader_outfit = /datum/outfit/job/bartender initial_speech = "Greetings, station inhabitor. I came to this dimension in the pursuit of a particular drink." request_speech = "Bring me thirty units of the beverage known as 'requested_item'." acceptance_speech = "This is truly the drink I have been seeking. Thank you." refusal_speech = "Do not mess with me, simpleton, I do not wish for that which you are trying to give me." + possible_rewards = list(/obj/structure/reagent_dispensers/keg/neurotoxin = 1, //all kegs have 250u aside from neurotoxin/hearty punch which have 100u + /obj/structure/reagent_dispensers/keg/hearty_punch = 3, + /obj/structure/reagent_dispensers/keg/red_queen = 3, + /obj/structure/reagent_dispensers/keg/narsour = 3 + /obj/structure/reagent_dispensers/keg/quintuple_sec = 3) + /mob/living/carbon/human/dummy/travelling_trader/bartender/Initialize() //pick a subtype of ethanol that isn't found in the default set of the booze dispensers reagents requested_item = pick(subtypesof(/datum/reagent/consumable/ethanol) - list(/datum/reagent/consumable/ethanol/beer, @@ -199,3 +247,65 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() if(supplied_container.reagents.has_reagent(requested_item, 30)) return TRUE return FALSE + +//artifact dealer +/mob/living/carbon/human/dummy/travelling_trader/artifact_dealer + trader_name = "Otherworldly Artifact Dealer" + trader_outfit = /datum/outfit/artifact_dealer //he's cool enough to get his own outfit + inital_speech = "I have come here due to sensing the existence of an object of great power and importance." + request_speech = "Give to me a requested_item and I shall make it worth your while, traveller." + acceptance_speech = "This is truly an artifact worthy of my collection, thank you." + refusal_speech = "A given_item? Hah! Worthless." + possible_wanted_items = list(/obj/item/pen/fountain/captain = 1, //various rare things and high risk but not useful things (i.e. champion belt, bedsheet, pen) + /obj/item/storage/belt/champion = 1 + /obj/item/clothing/shoes/wheelys = 1 + /obj/item/relic = 1 + /obj/item/flashlight/lamp/bananalamp = 1 + /obj/item/storage/box/hug = 1 + /obj/item/clothing/gloves/color/yellow = 1 + /obj/item/instrument/saxophone = 1, + /obj/item/bedsheet/captain = 1, + /obj/item/slime_extract/green = 1, + /obj/item/chainsaw = 1, + /obj/item/clothing/head/crown = 1) + possible_rewards = list(/obj/item/storage/bag/money/c5000 = 5, + /obj/item/circuitboard/computer/arcade/amputation = 2, + /obj/item/stack/sticky_tape/infinite = 2, + /obj/item/clothing/suit/hooded/wintercoat/cosmic = 2) + +/mob/living/carbon/human/dummy/travelling_trader/artifact_dealer/Initialize() + possible_rewards[pick(subtypesof(/obj/item/clothing/head/collectable)) = 1] //this is slightly lower because it's absolutely useless + ..() + +/datum/outfit/artifact_dealer + uniform = /obj/item/clothing/under/suit/black_really + shoes = /obj/item/clothing/shoes/combat + head = /obj/item/clothing/head/that + glasses = /obj/item/clothing/glasses/monocle + +//surgeon +/mob/living/carbon/human/dummy/travelling_trader/surgeon + trader_name = "Otherworldly Surgeon" + trader_outfit = /datum/outfit/otherworldly_surgeon + initial_speech = "Hello there, meatbag. You can provide me with something I want." + request_speech = "Find me a requested_item. I shall make sure it's worth your efforts." + acceptance_speech = "This shall do. Goodbye, meatbag." + refusal_speech = "That is not what I wish for. Give me a requested_item, or I shall take one by force." + possible_wanted_items = list(/obj/item/bodypart/l_arm = 4, //limbs are the most common, with brain/head being the least so, organs in the middle + /obj/item/bodypart/r_arm = 4, + /obj/item/bodypart/l_leg = 4, + /obj/item/bodypart/r_leg = 4, + /obj/item/organ/tongue = 2, + /obj/item/organ/liver = 2, + /obj/item/organ/lungs = 2, + /obj/item/organ/heart = 2, + /obj/item/bodypart/eyes = 1. + /obj/item/organ/brain = 1, + /obj/item/bodypart/head = 1) + +/datum/outfit/otherworldly_surgeon + uniform = /obj/item/clothing/under/pants/white + shoes = /obj/item/clothing/shoes/sneakers/white + gloves = /obj/item/clothing/gloves/color/latex + mask = /obj/item/clothing/mask/surgical + suit = /obj/item/clothing/suit/apron/surgical \ No newline at end of file diff --git a/code/modules/mining/money_bag.dm b/code/modules/mining/money_bag.dm index 66f99ec40c..7dd13a6fc1 100644 --- a/code/modules/mining/money_bag.dm +++ b/code/modules/mining/money_bag.dm @@ -24,4 +24,8 @@ new /obj/item/coin/silver(src) new /obj/item/coin/gold(src) new /obj/item/coin/gold(src) - new /obj/item/coin/adamantine(src) \ No newline at end of file + new /obj/item/coin/adamantine(src) + +/obj/item/storage/bag/money/c5000/PopulateContents() + for(var/i = 0, i < 5, i++) + new /obj/item/stack/spacecash/c1000(src) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/bumbles.dm b/code/modules/mob/living/simple_animal/friendly/bumbles.dm index 2d236a4327..3707aa33f8 100644 --- a/code/modules/mob/living/simple_animal/friendly/bumbles.dm +++ b/code/modules/mob/living/simple_animal/friendly/bumbles.dm @@ -30,6 +30,7 @@ verb_yell = "buzzes intensely" emote_see = list("buzzes.", "makes a loud buzz.", "rolls several times.", "buzzes happily.") speak_chance = 1 + unique_name = TRUE /mob/living/simple_animal/pet/bumbles/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index ba9cdfda64..b42216c2cc 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -192,6 +192,15 @@ else ..() +//a cow that produces a random reagent in its udder +/mob/living/simple_animal/cow/random + name = "strange cow" + desc = "Something seems off about the milk this cow is producing." + +/mob/living/simple_animal/cow/random/Initialize() + milk_reagent = get_random_reagent_id() //this has a blacklist so don't worry about romerol cows, etc + + //Wisdom cow, speaks and bestows great wisdoms /mob/living/simple_animal/cow/wisdom name = "wisdom cow" diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index bc4e214161..927da6d625 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -247,3 +247,42 @@ icon_state = "bluekeg" reagent_id = /datum/reagent/consumable/ethanol/gargle_blaster tank_volume = 100 + +//kegs given by the travelling trader's bartender subtype + +/obj/structure/reagent_dispensers/keg/quintuple_sec + name = "keg of quintuple sec" + desc = "A keg of pure justice." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/ethanol/quintuple_sec + tank_volume = 250 + +/obj/structure/reagent_dispensers/keg/narsour + name = "keg of narsour" + desc = "A keg of eldritch terrors." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/ethanol/narsour + tank_volume = 250 + +/obj/structure/reagent_dispensers/keg/red_queen + name = "keg of red queen" + desc = "A strange keg, filled with a kind of tea." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/red_queen + tank_volume = 250 + +/obj/structure/reagent_dispensers/keg/hearty_punch + name = "keg of hearty punch" + desc = "A keg that will get you right back on your feet." + icon_state = "redkeg" + reagent_id = /datum/reagent/consumable/hearty_punch + tank_volume = 100 //this usually has a 15:1 ratio when being made, so we provide less of it + +/obj/structure/reagent_dispensers/keg/neurotoxin + name = "keg of neurotoxin" + desc = "A keg of the sickly substance known as 'neurotoxin'." + icon_state = "bluekeg" + reagent_id = /datum/reagent/consumable/ethanol/neurotoxin + tank_volume = 100 //2.5x less than the other kegs because it's harder to get + + From 8712dd6de49c4423d1b19b10396397f016b18414 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 00:31:45 +0100 Subject: [PATCH 06/14] bugfixes --- code/game/objects/items/pet_carrier.dm | 2 +- code/modules/events/travelling_trader.dm | 42 ++++++++++++++-------- code/modules/reagents/reagent_dispenser.dm | 2 +- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index 8ebb497fe1..a60aa02ce1 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -106,7 +106,7 @@ if(user == target) to_chat(user, "Why would you ever do that?") return - if(ishostile(target) && (!allows_hostiles || istype(target, /mob/living/simple_animal/hostile/carp/cayenne))) || target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers, but let cayenne in! + if(ishostile(target) && (!allows_hostiles || istype(target, /mob/living/simple_animal/hostile/carp/cayenne)) || target.move_resist < MOVE_FORCE_VERY_STRONG) //don't allow goliaths into pet carriers, but let cayenne in! to_chat(user, "You have a feeling you shouldn't keep this as a pet.") load_occupant(user, target) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index e19b2bfdee..6c2692dc65 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -174,7 +174,7 @@ /mob/living/simple_animal/hostile/bear = 1, /mob/living/simple_animal/hostile/retaliate/clown/fleshclown = 1, /mob/living/simple_animal/hostile/tree = 1, - /mob/living/simple_animal/hostile/mimic = 1 + /mob/living/simple_animal/hostile/mimic = 1, /mob/living/simple_animal/hostile/shark/laser = 1 ) @@ -199,7 +199,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() /mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(var/mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea var/mob/living/animal = pickweight(possible_rewards) if(giver && giver.tag) - animal.faction += "/[[giver.tag]/]" + animal.faction += "\[[giver.tag]\]" var/obj/item/pet_carrier/bluespace/jar = new(get_turf(src)) jar.add_occupant(animal) jar.name = "WARNING: [animal] INSIDE" @@ -215,7 +215,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() possible_rewards = list(/obj/structure/reagent_dispensers/keg/neurotoxin = 1, //all kegs have 250u aside from neurotoxin/hearty punch which have 100u /obj/structure/reagent_dispensers/keg/hearty_punch = 3, /obj/structure/reagent_dispensers/keg/red_queen = 3, - /obj/structure/reagent_dispensers/keg/narsour = 3 + /obj/structure/reagent_dispensers/keg/narsour = 3, /obj/structure/reagent_dispensers/keg/quintuple_sec = 3) @@ -252,17 +252,17 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() /mob/living/carbon/human/dummy/travelling_trader/artifact_dealer trader_name = "Otherworldly Artifact Dealer" trader_outfit = /datum/outfit/artifact_dealer //he's cool enough to get his own outfit - inital_speech = "I have come here due to sensing the existence of an object of great power and importance." + initial_speech = "I have come here due to sensing the existence of an object of great power and importance." request_speech = "Give to me a requested_item and I shall make it worth your while, traveller." acceptance_speech = "This is truly an artifact worthy of my collection, thank you." refusal_speech = "A given_item? Hah! Worthless." possible_wanted_items = list(/obj/item/pen/fountain/captain = 1, //various rare things and high risk but not useful things (i.e. champion belt, bedsheet, pen) - /obj/item/storage/belt/champion = 1 - /obj/item/clothing/shoes/wheelys = 1 - /obj/item/relic = 1 - /obj/item/flashlight/lamp/bananalamp = 1 - /obj/item/storage/box/hug = 1 - /obj/item/clothing/gloves/color/yellow = 1 + /obj/item/storage/belt/champion = 1, + /obj/item/clothing/shoes/wheelys = 1, + /obj/item/relic = 1, + /obj/item/flashlight/lamp/bananalamp = 1, + /obj/item/storage/box/hug = 1, + /obj/item/clothing/gloves/color/yellow = 1, /obj/item/instrument/saxophone = 1, /obj/item/bedsheet/captain = 1, /obj/item/slime_extract/green = 1, @@ -274,7 +274,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() /obj/item/clothing/suit/hooded/wintercoat/cosmic = 2) /mob/living/carbon/human/dummy/travelling_trader/artifact_dealer/Initialize() - possible_rewards[pick(subtypesof(/obj/item/clothing/head/collectable)) = 1] //this is slightly lower because it's absolutely useless + possible_rewards += list(pick(subtypesof(/obj/item/clothing/head/collectable)) = 1) //this is slightly lower because it's absolutely useless ..() /datum/outfit/artifact_dealer @@ -291,7 +291,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() request_speech = "Find me a requested_item. I shall make sure it's worth your efforts." acceptance_speech = "This shall do. Goodbye, meatbag." refusal_speech = "That is not what I wish for. Give me a requested_item, or I shall take one by force." - possible_wanted_items = list(/obj/item/bodypart/l_arm = 4, //limbs are the most common, with brain/head being the least so, organs in the middle + possible_wanted_items = list(/obj/item/bodypart/l_arm = 4, /obj/item/bodypart/r_arm = 4, /obj/item/bodypart/l_leg = 4, /obj/item/bodypart/r_leg = 4, @@ -299,13 +299,27 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() /obj/item/organ/liver = 2, /obj/item/organ/lungs = 2, /obj/item/organ/heart = 2, - /obj/item/bodypart/eyes = 1. + /obj/item/organ/eyes = 1, /obj/item/organ/brain = 1, /obj/item/bodypart/head = 1) + possible_rewards = list(/obj/item/organ/cyberimp/mouth/breathing_tube = 1, + /obj/item/organ/eyes/robotic/thermals = 1, + /obj/item/organ/cyberimp/arm/toolset = 1, + /obj/item/organ/cyberimp/arm/surgery = 1, + /obj/item/organ/cyberimp/arm/janitor = 1, + /obj/item/organ/cyberimp/arm/flash = 1, + /obj/item/organ/cyberimp/arm/shield = 1, + /obj/item/organ/cyberimp/eyes/hud/medical = 1, + /obj/item/organ/cyberimp/arm/baton = 1) + +/mob/living/carbon/human/dummy/travelling_trader/surgeon/give_reward() + var/obj/item/organ/implant = pickweight(possible_rewards) + var/obj/item/autosurgeon/reward = new(get_turf(src)) + reward.insert_organ(implant) /datum/outfit/otherworldly_surgeon uniform = /obj/item/clothing/under/pants/white shoes = /obj/item/clothing/shoes/sneakers/white gloves = /obj/item/clothing/gloves/color/latex mask = /obj/item/clothing/mask/surgical - suit = /obj/item/clothing/suit/apron/surgical \ No newline at end of file + suit = /obj/item/clothing/suit/apron/surgical diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 927da6d625..2b79533e31 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -275,7 +275,7 @@ name = "keg of hearty punch" desc = "A keg that will get you right back on your feet." icon_state = "redkeg" - reagent_id = /datum/reagent/consumable/hearty_punch + reagent_id = /datum/reagent/consumable/ethanol/hearty_punch tank_volume = 100 //this usually has a 15:1 ratio when being made, so we provide less of it /obj/structure/reagent_dispensers/keg/neurotoxin From ab01a69c1ff06e7de5eca410b8e1f2645941b1f4 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 00:53:31 +0100 Subject: [PATCH 07/14] bugfix --- code/modules/events/travelling_trader.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index 6c2692dc65..2dd2c80b00 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -313,7 +313,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() /obj/item/organ/cyberimp/arm/baton = 1) /mob/living/carbon/human/dummy/travelling_trader/surgeon/give_reward() - var/obj/item/organ/implant = pickweight(possible_rewards) + var/obj/item/organ/implant = new pickweight(possible_rewards) var/obj/item/autosurgeon/reward = new(get_turf(src)) reward.insert_organ(implant) From cff2e3d680ddcaddbdd0e59fc68be3990417e2e1 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 00:58:34 +0100 Subject: [PATCH 08/14] never set max amount to 0 --- code/game/objects/items/stacks/tape.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/stacks/tape.dm b/code/game/objects/items/stacks/tape.dm index 8e8e2eaf52..d33d106d11 100644 --- a/code/game/objects/items/stacks/tape.dm +++ b/code/game/objects/items/stacks/tape.dm @@ -15,6 +15,7 @@ var/list/conferred_embed = EMBED_HARMLESS var/overwrite_existing = FALSE + var/endless = FALSE var/apply_time = 30 /obj/item/stack/sticky_tape/afterattack(obj/item/I, mob/living/user) @@ -31,7 +32,7 @@ I.embedding = conferred_embed I.updateEmbedding() to_chat(user, "You finish wrapping [I] with [src].") - if(max_amount > 0) + if(!endless) use(1) I.name = "[prefix] [I.name]" @@ -42,7 +43,7 @@ /obj/item/stack/sticky_tape/infinite //endless tape that applies far faster, for maximum honks name = "endless sticky tape" desc = "This roll of sticky tape somehow has no end." - max_amount = 0 + endless = TRUE apply_time = 10 /obj/item/stack/sticky_tape/super From 8e31e3c5340fbfc824101c73f9d353931f25857b Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 01:56:24 +0100 Subject: [PATCH 09/14] a tonne of fixes --- code/modules/events/travelling_trader.dm | 33 ++++++++++++++---------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index 2dd2c80b00..9de8f75fd3 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -128,7 +128,10 @@ /mob/living/carbon/human/dummy/travelling_trader/cook/Initialize() //pick a random crafted food item as the requested item - requested_item = GLOB.crafting_recipes[pick(subtypesof( /datum/crafting_recipe/food))].result + var/recipe = pick(subtypesof(/datum/crafting_recipe/food)) + var/datum/crafting_recipe/food/new_recipe = new recipe + requested_item = new_recipe.result + qdel(new_recipe) //we don't need it anymore ..() //botanist @@ -136,7 +139,7 @@ trader_name = "Otherworldly Gardener" trader_outfit = /datum/outfit/job/botanist initial_speech = "I have come across this realm in search of rare plants and believe this station may be able to help me.." - request_speech = "Are you able to bring me a requested_item? I could see that you get some reward for this task." + request_speech = "Are you able to bring me the plant known to you as: 'requested_item'? I could see that you get some reward for this task." acceptance_speech = "Amazing! Ill finally be able to make that salad. Goodbye for now!" refusal_speech = "A given_item? Did nobody ever teach you the basics of gardening?" possible_rewards = list(/obj/item/seeds/cherry/bomb = 1, @@ -175,8 +178,9 @@ /mob/living/simple_animal/hostile/retaliate/clown/fleshclown = 1, /mob/living/simple_animal/hostile/tree = 1, /mob/living/simple_animal/hostile/mimic = 1, - /mob/living/simple_animal/hostile/shark/laser = 1 - ) + /mob/living/simple_animal/hostile/shark = 1, + /mob/living/simple_animal/hostile/netherworld/blankbody = 1, + /mob/living/simple_animal/hostile/retaliate/goose = 1) mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() acceptance_speech = pick(list("This lifeform shall make for a great stew, thank you.", "This lifeform shall be of a true use to our cause, thank you.", "The lifeform is adequate. Goodbye.", "This lifeform shall make a great addition to my collection.")) @@ -197,12 +201,13 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() return FALSE /mob/living/carbon/human/dummy/travelling_trader/animal_hunter/give_reward(var/mob/giver) //the reward is actually given in a jar, because releasing it onto the station might be a bad idea - var/mob/living/animal = pickweight(possible_rewards) - if(giver && giver.tag) - animal.faction += "\[[giver.tag]\]" var/obj/item/pet_carrier/bluespace/jar = new(get_turf(src)) - jar.add_occupant(animal) - jar.name = "WARNING: [animal] INSIDE" + var/chosen_animal = pickweight(possible_rewards) + var/mob/living/new_animal = new chosen_animal(jar) + if(giver && giver.tag) + new_animal.faction += "\[[giver.tag]\]" + jar.add_occupant(new_animal) + jar.name = "WARNING: [new_animal]" //bartender /mob/living/carbon/human/dummy/travelling_trader/bartender @@ -218,7 +223,6 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() /obj/structure/reagent_dispensers/keg/narsour = 3, /obj/structure/reagent_dispensers/keg/quintuple_sec = 3) - /mob/living/carbon/human/dummy/travelling_trader/bartender/Initialize() //pick a subtype of ethanol that isn't found in the default set of the booze dispensers reagents requested_item = pick(subtypesof(/datum/reagent/consumable/ethanol) - list(/datum/reagent/consumable/ethanol/beer, /datum/reagent/consumable/ethanol/kahlua, @@ -253,7 +257,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() trader_name = "Otherworldly Artifact Dealer" trader_outfit = /datum/outfit/artifact_dealer //he's cool enough to get his own outfit initial_speech = "I have come here due to sensing the existence of an object of great power and importance." - request_speech = "Give to me a requested_item and I shall make it worth your while, traveller." + request_speech = "Give to me the great object known as: requested_item and I shall make it worth your while, traveller." acceptance_speech = "This is truly an artifact worthy of my collection, thank you." refusal_speech = "A given_item? Hah! Worthless." possible_wanted_items = list(/obj/item/pen/fountain/captain = 1, //various rare things and high risk but not useful things (i.e. champion belt, bedsheet, pen) @@ -288,7 +292,7 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() trader_name = "Otherworldly Surgeon" trader_outfit = /datum/outfit/otherworldly_surgeon initial_speech = "Hello there, meatbag. You can provide me with something I want." - request_speech = "Find me a requested_item. I shall make sure it's worth your efforts." + request_speech = "Find me the appendage you call 'requested_item'. I shall make sure it's worth your efforts." acceptance_speech = "This shall do. Goodbye, meatbag." refusal_speech = "That is not what I wish for. Give me a requested_item, or I shall take one by force." possible_wanted_items = list(/obj/item/bodypart/l_arm = 4, @@ -313,9 +317,10 @@ mob/living/carbon/human/dummy/travelling_trader/animal_hunter/Initialize() /obj/item/organ/cyberimp/arm/baton = 1) /mob/living/carbon/human/dummy/travelling_trader/surgeon/give_reward() - var/obj/item/organ/implant = new pickweight(possible_rewards) + var/chosen_implant = pickweight(possible_rewards) + var/new_implant = new chosen_implant var/obj/item/autosurgeon/reward = new(get_turf(src)) - reward.insert_organ(implant) + reward.insert_organ(new_implant) /datum/outfit/otherworldly_surgeon uniform = /obj/item/clothing/under/pants/white From fbb9fe2d9cba7e9ec548950c3f5a4c39a355373b Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 02:14:50 +0100 Subject: [PATCH 10/14] better fork --- code/game/objects/items/kitchen.dm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 1d4610488d..a06461180c 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -58,7 +58,9 @@ name = "throwing fork" desc = "A fork, sharpened to perfection, making it a great weapon for throwing." throwforce = 15 - embedding = list("pain_mult" = 2, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 100) + throw_speed = 3 + throw_range = 6 + embedding = list("pain_mult" = 2, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) sharpness = IS_SHARP_ACCURATE /obj/item/kitchen/knife From 3e5f98182521e36e051d2289f0de273113d8022a Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 03:17:50 +0100 Subject: [PATCH 11/14] speed 4 for embeds --- code/game/objects/items/kitchen.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index a06461180c..2c00265ce8 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -58,10 +58,10 @@ name = "throwing fork" desc = "A fork, sharpened to perfection, making it a great weapon for throwing." throwforce = 15 - throw_speed = 3 + throw_speed = 4 throw_range = 6 embedding = list("pain_mult" = 2, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) - sharpness = IS_SHARP_ACCURATE + sharpness = IS_SHARP /obj/item/kitchen/knife name = "kitchen knife" From 070513044844c2c0611b27dbb8a47d36d168f6d4 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 17:31:37 +0100 Subject: [PATCH 12/14] small edgecase --- code/modules/events/travelling_trader.dm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index 9de8f75fd3..b3cd8cecaa 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -130,7 +130,10 @@ //pick a random crafted food item as the requested item var/recipe = pick(subtypesof(/datum/crafting_recipe/food)) var/datum/crafting_recipe/food/new_recipe = new recipe - requested_item = new_recipe.result + if(istype(new_recipe.result, /obj/item/reagent_containers/food)) //not all food recipes make food objects (like cak/butterbear) + requested_item = new_recipe.result + else + requested_item = /obj/item/reagent_containers/food/snacks/copypasta qdel(new_recipe) //we don't need it anymore ..() From c0687886e4f5e4efd3b6de848ae4a2d0bded884f Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 21:38:09 +0100 Subject: [PATCH 13/14] using initial is better practice --- code/modules/events/travelling_trader.dm | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index b3cd8cecaa..b7afc3440e 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -55,9 +55,7 @@ /mob/living/carbon/human/dummy/travelling_trader/proc/setup_speech(var/input_speech, var/obj/item/given_item) if(requested_item) - var/atom/temp_requested = new requested_item - input_speech = replacetext(input_speech, "requested_item", temp_requested.name) - qdel(temp_requested) + input_speech = replacetext(input_speech, "requested_item", initial(requested_item.name)) if(given_item) input_speech = replacetext(input_speech, "given_item", given_item.name) return input_speech @@ -128,13 +126,12 @@ /mob/living/carbon/human/dummy/travelling_trader/cook/Initialize() //pick a random crafted food item as the requested item - var/recipe = pick(subtypesof(/datum/crafting_recipe/food)) - var/datum/crafting_recipe/food/new_recipe = new recipe - if(istype(new_recipe.result, /obj/item/reagent_containers/food)) //not all food recipes make food objects (like cak/butterbear) - requested_item = new_recipe.result + var/datum/crafting_recipe/food_recipe = pick(subtypesof(/datum/crafting_recipe/food)) + var/result = initial(food_recipe.result) + if(ispath(result, /obj/item/reagent_containers/food)) //not all food recipes make food objects (like cak/butterbear) + requested_item = result else requested_item = /obj/item/reagent_containers/food/snacks/copypasta - qdel(new_recipe) //we don't need it anymore ..() //botanist From 29628dd82a08b2a917b43686a5fcd42bf2d67f91 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 12 Jul 2020 21:40:16 +0100 Subject: [PATCH 14/14] cows --- code/modules/mob/living/simple_animal/friendly/farm_animals.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index b42216c2cc..6749c771be 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -199,7 +199,7 @@ /mob/living/simple_animal/cow/random/Initialize() milk_reagent = get_random_reagent_id() //this has a blacklist so don't worry about romerol cows, etc - + ..() //Wisdom cow, speaks and bestows great wisdoms /mob/living/simple_animal/cow/wisdom