mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-25 04:57:12 +01:00
Added the Combat Bakery Kit (#21901)
* QUASO * Apply suggestions from code review Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> * blame lewc for giving me spaces * Update code/datums/uplink_items/uplink_traitor.dm Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> * Update code/datums/components/boomerang.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com> * Update code/game/objects/items/granters/_granters.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> * purge that --------- Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>
This commit is contained in:
co-authored by
Luc
Burzah
Henri215
parent
0e371e1b93
commit
d42d2f647d
@@ -281,6 +281,8 @@
|
||||
#define COMPONENT_CANCEL_THROW (1<<0)
|
||||
///from base of atom/movable/throw_at(): (datum/thrownthing, spin)
|
||||
#define COMSIG_MOVABLE_POST_THROW "movable_post_throw"
|
||||
///from base of datum/thrownthing/finalize(): (obj/thrown_object, datum/thrownthing) used for when a throw is finished
|
||||
#define COMSIG_MOVABLE_THROW_LANDED "movable_throw_landed"
|
||||
///from base of atom/movable/onTransitZ(): (old_z, new_z)
|
||||
#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit"
|
||||
///called when the movable is placed in an unaccessible area, used for stationloving: ()
|
||||
|
||||
@@ -142,6 +142,7 @@ SUBSYSTEM_DEF(throwing)
|
||||
|
||||
if(callback)
|
||||
callback.Invoke()
|
||||
SEND_SIGNAL(thrownthing, COMSIG_MOVABLE_THROW_LANDED, src)
|
||||
thrownthing.end_throw()
|
||||
|
||||
/datum/thrownthing/proc/hit_atom(atom/A)
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
///The cooldown period between last_boomerang_throw and it's methods of implementing a rebound proc.
|
||||
#define BOOMERANG_REBOUND_INTERVAL (1 SECONDS)
|
||||
|
||||
/**
|
||||
* If an object is given the boomerang component, it should be thrown back to the thrower after either hitting it's target, or landing on the thrown tile.
|
||||
* Thrown objects should be thrown back to the original thrower with this component, a number of tiles defined by boomerang_throw_range.
|
||||
*/
|
||||
/datum/component/boomerang
|
||||
///How far should the boomerang try to travel to return to the thrower?
|
||||
var/boomerang_throw_range = 3
|
||||
///If this boomerang is thrown, does it re-enable the throwers throw mode?
|
||||
var/thrower_easy_catch_enabled = FALSE
|
||||
///This cooldown prevents our 2 throwing signals from firing too often based on how we implement those signals within thrown impacts.
|
||||
var/last_boomerang_throw = 0
|
||||
|
||||
/datum/component/boomerang/Initialize(boomerang_throw_range, thrower_easy_catch_enabled)
|
||||
. = ..()
|
||||
if(!isitem(parent)) //Only items support being thrown around like a boomerang, feel free to make this apply to humans later on.
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
//Assignments
|
||||
src.boomerang_throw_range = boomerang_throw_range
|
||||
src.thrower_easy_catch_enabled = thrower_easy_catch_enabled
|
||||
|
||||
/datum/component/boomerang/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, PROC_REF(prepare_throw)) //Collect data on current thrower and the throwing datum
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(return_missed_throw))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT, PROC_REF(return_hit_throw))
|
||||
|
||||
/datum/component/boomerang/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(COMSIG_MOVABLE_POST_THROW, COMSIG_MOVABLE_THROW_LANDED, COMSIG_MOVABLE_IMPACT))
|
||||
|
||||
/**
|
||||
* Proc'd before the first thrown is performed in order to gather information regarding each throw as well as handle throw_mode as necessary.
|
||||
* * source: Datum src from original signal call.
|
||||
* * thrown_thing: The thrownthing datum from the parent object's latest throw. Updates thrown_boomerang.
|
||||
* * spin: Carry over from POST_THROW, the speed of rotation on the boomerang when thrown.
|
||||
*/
|
||||
/datum/component/boomerang/proc/prepare_throw(datum/source, datum/thrownthing/thrown_thing, spin)
|
||||
SIGNAL_HANDLER
|
||||
if(thrower_easy_catch_enabled && iscarbon(thrown_thing?.thrower))
|
||||
var/mob/living/carbon/C = thrown_thing.thrower
|
||||
C.throw_mode_on()
|
||||
|
||||
/**
|
||||
* Proc that triggers when the thrown boomerang hits an object.
|
||||
* * source: Datum src from original signal call.
|
||||
* * hit_atom: The atom that has been hit by the boomerang component.
|
||||
* * init_throwing_datum: The thrownthing datum that originally impacted the object, that we use to build the new throwing datum for the rebound.
|
||||
*/
|
||||
/datum/component/boomerang/proc/return_hit_throw(datum/source, atom/hit_atom, datum/thrownthing/init_throwing_datum)
|
||||
SIGNAL_HANDLER
|
||||
if(world.time <= last_boomerang_throw)
|
||||
return
|
||||
var/obj/item/true_parent = parent
|
||||
aerodynamic_swing(init_throwing_datum, true_parent)
|
||||
|
||||
/**
|
||||
* Proc that triggers when the thrown boomerang does not hit a target.
|
||||
* * source: Datum src from original signal call.
|
||||
* * throwing_datum: The thrownthing datum that originally impacted the object, that we use to build the new throwing datum for the rebound.
|
||||
*/
|
||||
/datum/component/boomerang/proc/return_missed_throw(datum/source, datum/thrownthing/throwing_datum)
|
||||
SIGNAL_HANDLER
|
||||
if(world.time <= last_boomerang_throw)
|
||||
return
|
||||
var/obj/item/true_parent = parent
|
||||
aerodynamic_swing(throwing_datum, true_parent)
|
||||
|
||||
/**
|
||||
* Proc that triggers when the thrown boomerang has been fully thrown, rethrowing the boomerang back to the thrower, and producing visible feedback.
|
||||
* * throwing_datum: The thrownthing datum that originally impacted the object, that we use to build the new throwing datum for the rebound.
|
||||
* * hit_atom: The atom that has been hit by the boomerang'd object.
|
||||
*/
|
||||
/datum/component/boomerang/proc/aerodynamic_swing(datum/thrownthing/throwing_datum, obj/item/true_parent)
|
||||
var/mob/thrown_by = locateUID(true_parent.thrownby)
|
||||
if(istype(thrown_by))
|
||||
var/dir = get_dir(true_parent, thrown_by)
|
||||
var/turf/T = get_ranged_target_turf(thrown_by, dir, 2)
|
||||
addtimer(CALLBACK(true_parent, TYPE_PROC_REF(/atom/movable, throw_at), T, boomerang_throw_range, throwing_datum.speed, null, TRUE), 1)
|
||||
last_boomerang_throw = world.time + BOOMERANG_REBOUND_INTERVAL
|
||||
true_parent.visible_message("<span class='danger'>[true_parent] is flying back at [throwing_datum.thrower]!</span>", \
|
||||
"<span class='danger'>You see [true_parent] fly back at you!</span>", \
|
||||
"<span class='hear'>You hear an aerodynamic woosh!</span>")
|
||||
|
||||
#undef BOOMERANG_REBOUND_INTERVAL
|
||||
@@ -47,6 +47,16 @@
|
||||
to_chat(L, "<span class='caution'>Glowing red letters appear on the front cover...</span>")
|
||||
to_chat(L, "<span class='warning'>[pick("NICE TRY BUT NO!","CLEVER BUT NOT CLEVER ENOUGH!", "SUCH FLAGRANT CHEESING IS WHY WE ACCEPTED YOUR APPLICATION!", "CUTE!", "YOU DIDN'T THINK IT'D BE THAT EASY, DID YOU?")]</span>")
|
||||
burnt_out = TRUE
|
||||
else if(istype(item, /obj/item/book/granter))
|
||||
var/obj/item/book/granter/I = item
|
||||
if(prob(80))
|
||||
L.visible_message("<span class='warning'>[I] catches fire!</span>")
|
||||
qdel(I)
|
||||
else
|
||||
I.uses += 1
|
||||
charged_item = I
|
||||
break
|
||||
|
||||
else if(istype(item, /obj/item/gun/magic))
|
||||
var/obj/item/gun/magic/I = item
|
||||
if(prob(80) && !I.can_charge)
|
||||
|
||||
@@ -67,6 +67,15 @@
|
||||
cost = 50
|
||||
job = list("Mime")
|
||||
|
||||
/datum/uplink_item/jobspecific/combat_baking
|
||||
name = "Combat Bakery Kit"
|
||||
desc = "A kit of clandestine baked weapons. Contains a baguette which a skilled mime could use as a sword, \
|
||||
a pair of throwing croissants, and the recipe to make more on demand. Once the job is done, eat the evidence."
|
||||
reference = "CBK"
|
||||
item = /obj/item/storage/box/syndie_kit/combat_baking
|
||||
cost = 25 //A chef can get a knife that sharp easily, though it won't block. While you can get endless boomerang, they are less deadly than a stech, and slower / more predictable.
|
||||
job = list("Mime", "Chef")
|
||||
|
||||
/datum/uplink_item/jobspecific/pressure_mod
|
||||
name = "Kinetic Accelerator Pressure Mod"
|
||||
desc = "A modification kit which allows Kinetic Accelerators to do greatly increased damage while indoors. Occupies 35% mod capacity."
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Books that teach things.
|
||||
*
|
||||
* (Intrinsic actions like bar flinging, spells like fireball or smoke, or martial arts)
|
||||
*/
|
||||
/obj/item/book/granter
|
||||
/// Flavor messages displayed to mobs reading the granter
|
||||
var/list/remarks = list()
|
||||
/// Controls how long a mob must keep the book in his hand to actually successfully learn
|
||||
var/pages_to_mastery = 3
|
||||
/// Sanity, whether it's currently being read
|
||||
var/reading = FALSE
|
||||
/// The amount of uses on the granter.
|
||||
var/uses = 1
|
||||
/// The time it takes to read the book
|
||||
var/reading_time = 5 SECONDS
|
||||
/// The sounds played as the user's reading the book.
|
||||
var/list/book_sounds = list(
|
||||
'sound/effects/pageturn1.ogg',
|
||||
'sound/effects/pageturn2.ogg',
|
||||
'sound/effects/pageturn3.ogg'
|
||||
)
|
||||
|
||||
/obj/item/book/granter/attack_self(mob/living/user)
|
||||
if(reading)
|
||||
to_chat(user, "<span class='warning'>You're already reading this!</span>")
|
||||
return FALSE
|
||||
if(!user.has_vision())
|
||||
to_chat(user, "<span class='warning'>You are blind and can't read anything!</span>")
|
||||
return FALSE
|
||||
if(!isliving(user))
|
||||
return FALSE
|
||||
if(!can_learn(user))
|
||||
return FALSE
|
||||
|
||||
if(uses <= 0)
|
||||
recoil(user)
|
||||
return FALSE
|
||||
|
||||
on_reading_start(user)
|
||||
reading = TRUE
|
||||
for(var/i in 1 to pages_to_mastery)
|
||||
if(!turn_page(user))
|
||||
on_reading_stopped()
|
||||
reading = FALSE
|
||||
return
|
||||
if(do_after(user, reading_time, src))
|
||||
uses--
|
||||
on_reading_finished(user)
|
||||
reading = FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Called when the user starts to read the granter.
|
||||
/obj/item/book/granter/proc/on_reading_start(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You start reading [name]...</span>")
|
||||
|
||||
/// Called when the reading is interrupted without finishing.
|
||||
/obj/item/book/granter/proc/on_reading_stopped(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You stop reading...</span>")
|
||||
|
||||
/// Called when the reading is completely finished. This is where the actual granting should happen.
|
||||
/obj/item/book/granter/proc/on_reading_finished(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You finish reading [name]!</span>")
|
||||
|
||||
/// The actual "turning over of the page" flavor bit that happens while someone is reading the granter.
|
||||
/obj/item/book/granter/proc/turn_page(mob/living/user)
|
||||
playsound(user, pick(book_sounds), 30, TRUE)
|
||||
|
||||
if(!do_after(user, reading_time, src))
|
||||
return FALSE
|
||||
|
||||
to_chat(user, "<span class='notice'>[length(remarks) ? pick(remarks) : "You keep reading..."]</span>")
|
||||
return TRUE
|
||||
|
||||
/// Effects that occur whenever the book is read when it has no uses left.
|
||||
/obj/item/book/granter/proc/recoil(mob/living/user)
|
||||
return
|
||||
|
||||
/// Checks if the user can learn whatever this granter... grants
|
||||
/obj/item/book/granter/proc/can_learn(mob/living/user)
|
||||
return TRUE
|
||||
|
||||
// Generic action giver
|
||||
/obj/item/book/granter/action
|
||||
/// The typepath of action that is given
|
||||
var/datum/action/granted_action
|
||||
/// The name of the action, formatted in a more text-friendly way.
|
||||
var/action_name = ""
|
||||
|
||||
/obj/item/book/granter/action/can_learn(mob/living/user)
|
||||
if(!granted_action)
|
||||
CRASH("Someone attempted to learn [type], which did not have an action set.")
|
||||
if(locate(granted_action) in user.actions)
|
||||
to_chat(user, "<span class='warning'>You already know all about [action_name]!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/book/granter/action/on_reading_start(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You start reading about [action_name]...</span>")
|
||||
|
||||
/obj/item/book/granter/action/on_reading_finished(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You feel like you've got a good handle on [action_name]!</span>")
|
||||
// Action goes on the mind as the user actually learns the thing in your brain
|
||||
var/datum/action/new_action = new granted_action(user.mind || user)
|
||||
new_action.Grant(user)
|
||||
@@ -0,0 +1,18 @@
|
||||
/obj/item/book/granter/crafting_recipe
|
||||
/// A list of all recipe types we grant on learn
|
||||
var/list/crafting_recipe_types = list()
|
||||
|
||||
/obj/item/book/granter/crafting_recipe/on_reading_finished(mob/user)
|
||||
..()
|
||||
if(!user.mind)
|
||||
return
|
||||
for(var/datum/crafting_recipe/crafting_recipe_type as anything in crafting_recipe_types)
|
||||
user.mind.teach_crafting_recipe(crafting_recipe_type)
|
||||
to_chat(user, "<span class='notice'>You learned how to make [initial(crafting_recipe_type.name)].</span>")
|
||||
|
||||
/obj/item/book/granter/crafting_recipe/dusting
|
||||
icon_state = "book1"
|
||||
|
||||
/obj/item/book/granter/crafting_recipe/dusting/recoil(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>The book turns to dust in your hands.</span>")
|
||||
qdel(src)
|
||||
@@ -0,0 +1,19 @@
|
||||
/obj/item/book/granter/crafting_recipe/combat_baking
|
||||
name = "the anarchist's cookbook"
|
||||
desc = "A widely illegal recipe book which will teach you how to bake croissants to die for."
|
||||
crafting_recipe_types = list(
|
||||
/datum/crafting_recipe/throwing_croissant
|
||||
)
|
||||
icon_state = "cooking_learing_illegal"
|
||||
remarks = list(
|
||||
"\"Austrian? Not French?\"",
|
||||
"\"Got to get the butter ratio right...\"",
|
||||
"\"This is the greatest thing since sliced bread!\"",
|
||||
"\"I'll leave no trace except crumbs!\"",
|
||||
"\"Who knew that bread could hurt a man so badly?\""
|
||||
)
|
||||
|
||||
/obj/item/book/granter/crafting_recipe/combat_baking/recoil(mob/living/user)
|
||||
to_chat(user, "<span class='warning'>The book dissolves into burnt flour!</span>")
|
||||
new /obj/effect/decal/cleanable/ash(get_turf(src))
|
||||
qdel(src)
|
||||
@@ -282,6 +282,11 @@
|
||||
new /obj/item/spellbook/oneuse/mime/greaterwall(src)
|
||||
new /obj/item/spellbook/oneuse/mime/fingergun(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/combat_baking/populate_contents()
|
||||
new /obj/item/reagent_containers/food/snacks/baguette/combat(src)
|
||||
for(var/i in 1 to 2)
|
||||
new /obj/item/reagent_containers/food/snacks/croissant/throwing(src)
|
||||
new /obj/item/book/granter/crafting_recipe/combat_baking(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/atmosn2ogrenades
|
||||
name = "atmos N2O grenades"
|
||||
|
||||
@@ -67,6 +67,17 @@
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/throwing_croissant
|
||||
name = "Throwing croissant"
|
||||
reqs = list(
|
||||
/obj/item/reagent_containers/food/snacks/croissant = 1,
|
||||
/obj/item/stack/rods = 1
|
||||
)
|
||||
result = list(/obj/item/reagent_containers/food/snacks/croissant)
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
always_availible = FALSE
|
||||
|
||||
/datum/crafting_recipe/advancedegun
|
||||
name = "Advanced Energy Gun"
|
||||
tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
|
||||
@@ -551,5 +551,15 @@
|
||||
list_reagents = list("nutriment" = 4, "sugar" = 2)
|
||||
tastes = list("croissant" = 1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/croissant/throwing
|
||||
throwforce = 20
|
||||
throw_range = 9 //now with extra throwing action
|
||||
tastes = list("croissant" = 2, "butter" = 1, "metal" = 1)
|
||||
list_reagents = list("nutriment" = 4, "sugar" = 2, "iron" = 1)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/croissant/throwing/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/boomerang, throw_range, TRUE)
|
||||
|
||||
#undef DONUT_NORMAL
|
||||
#undef DONUT_FROSTED
|
||||
|
||||
@@ -170,6 +170,14 @@
|
||||
list_reagents = list("nutriment" = 6, "vitamin" = 1)
|
||||
tastes = list("bread" = 2)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/baguette/combat
|
||||
sharp = TRUE
|
||||
force = 20
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/baguette/combat/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/parry, _stamina_constant = 2, _stamina_coefficient = 0.5, _parryable_attack_types = ALL_ATTACK_TYPES)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/twobread
|
||||
name = "two bread"
|
||||
desc = "It is very bitter and winy."
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@@ -363,6 +363,7 @@
|
||||
#include "code\datums\cache\crew.dm"
|
||||
#include "code\datums\cache\powermonitor.dm"
|
||||
#include "code\datums\components\_component.dm"
|
||||
#include "code\datums\components\boomerang.dm"
|
||||
#include "code\datums\components\caltrop.dm"
|
||||
#include "code\datums\components\deadchat_control.dm"
|
||||
#include "code\datums\components\decal.dm"
|
||||
@@ -987,6 +988,9 @@
|
||||
#include "code\game\objects\items\devices\radio\headset.dm"
|
||||
#include "code\game\objects\items\devices\radio\intercom.dm"
|
||||
#include "code\game\objects\items\devices\radio\radio_objects.dm"
|
||||
#include "code\game\objects\items\granters\_granters.dm"
|
||||
#include "code\game\objects\items\granters\crafting_granters\_crafting_granter.dm"
|
||||
#include "code\game\objects\items\granters\crafting_granters\combat_baking.dm"
|
||||
#include "code\game\objects\items\mountable_frames\air_alarm_frame.dm"
|
||||
#include "code\game\objects\items\mountable_frames\apc_frame.dm"
|
||||
#include "code\game\objects\items\mountable_frames\buttons_switches.dm"
|
||||
|
||||
Reference in New Issue
Block a user