Skip to content

Commit

Permalink
[MIRROR] Fixes some issues with paper planes (#1011)
Browse files Browse the repository at this point in the history
* Fixes some issues with paper planes

* Modularize this (better better paper planes)

---------

Co-authored-by: John Willard <[email protected]>
Co-authored-by: Mal <[email protected]>
  • Loading branch information
3 people authored and StealsThePRs committed Feb 17, 2024
1 parent e3578ab commit 7635158
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 105 deletions.
3 changes: 3 additions & 0 deletions code/__DEFINES/traits/declarations.dm
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_NO_EXTINGUISH "no_extinguish"
/// Indicates if the mob is currently speaking with sign language
#define TRAIT_SIGN_LANG "sign_language"
/// Trait given to mobs to indicate that they can catch papers thrown at them midair without trying,
/// and make syndicate airplanes when folding paper up.
#define TRAIT_PAPER_MASTER "paper_master"
/// This mob is able to use sign language over the radio.
#define TRAIT_CAN_SIGN_ON_COMMS "can_sign_on_comms"
/// nobody can use martial arts on this mob
Expand Down
3 changes: 3 additions & 0 deletions code/__DEFINES/traits/sources.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
/// Trait from light debugging
#define LIGHT_DEBUG_TRAIT "light-debug"

/// Trait given by an Action datum
#define ACTION_TRAIT "action"

#define CLOTHING_TRAIT "clothing"
#define HELMET_TRAIT "helmet"
/// inherited from the mask
Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/traits/_traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE,
"TRAIT_SHOVE_KNOCKDOWN_BLOCKED" = TRAIT_SHOVE_KNOCKDOWN_BLOCKED,
"TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG,
"TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
"TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE,
"TRAIT_SKITTISH" = TRAIT_SKITTISH,
Expand Down
1 change: 1 addition & 0 deletions code/_globalvars/traits/admin_tooling.dm
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_SHIFTY_EYES" = TRAIT_SHIFTY_EYES,
"TRAIT_SHOCKIMMUNE" = TRAIT_SHOCKIMMUNE,
"TRAIT_SIGN_LANG" = TRAIT_SIGN_LANG,
"TRAIT_PAPER_MASTER" = TRAIT_PAPER_MASTER,
"TRAIT_SILENT_FOOTSTEPS" = TRAIT_SILENT_FOOTSTEPS,
"TRAIT_SIXTHSENSE" = TRAIT_SIXTHSENSE,
"TRAIT_SKITTISH" = TRAIT_SKITTISH,
Expand Down
4 changes: 2 additions & 2 deletions code/datums/actions/mobs/assume_form.dm
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

// important: do this at the very end because we might have SIGNAL_ADDTRAIT for this on the mob that's dependent on the above logic
SEND_SIGNAL(owner, COMSIG_ACTION_DISGUISED_APPEARANCE, target_atom)
ADD_TRAIT(owner, TRAIT_DISGUISED, REF(src))
ADD_TRAIT(owner, TRAIT_DISGUISED, ACTION_TRAIT)

/// Resets the appearances of the mob to the default.
/datum/action/cooldown/mob_cooldown/assume_form/proc/reset_appearances()
Expand All @@ -85,4 +85,4 @@
owner.cut_overlays()

// important: do this very end because we might have SIGNAL_REMOVETRAIT for this on the mob that's dependent on the above logic
REMOVE_TRAIT(owner, TRAIT_DISGUISED, REF(src))
REMOVE_TRAIT(owner, TRAIT_DISGUISED, ACTION_TRAIT)
4 changes: 2 additions & 2 deletions code/datums/actions/mobs/lava_swoop.dm
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@

/datum/action/cooldown/mob_cooldown/lava_swoop/Grant(mob/M)
. = ..()
M.add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE), REF(src))
M.add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE), ACTION_TRAIT)

/datum/action/cooldown/mob_cooldown/lava_swoop/Remove(mob/M)
. = ..()
M.remove_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE), REF(src))
M.remove_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_NOFIRE), ACTION_TRAIT)

/datum/action/cooldown/mob_cooldown/lava_swoop/Activate(atom/target_atom)
disable_cooldown_actions()
Expand Down
6 changes: 3 additions & 3 deletions code/datums/actions/mobs/sign_language.dm
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,17 @@
SIGNAL_ADDTRAIT(TRAIT_MUTE),
SIGNAL_REMOVETRAIT(TRAIT_MUTE)
))
REMOVE_TRAIT(grant_to, TRAIT_SIGN_LANG, TRAIT_GENERIC)
REMOVE_TRAIT(grant_to, TRAIT_SIGN_LANG, ACTION_TRAIT)

/datum/action/innate/sign_language/Activate()
active = TRUE
ADD_TRAIT(owner, TRAIT_SIGN_LANG, TRAIT_GENERIC)
ADD_TRAIT(owner, TRAIT_SIGN_LANG, ACTION_TRAIT)
to_chat(owner, span_green("You are now communicating with sign language."))
build_all_button_icons(UPDATE_BUTTON_BACKGROUND)

/datum/action/innate/sign_language/Deactivate()
active = FALSE
REMOVE_TRAIT(owner, TRAIT_SIGN_LANG, TRAIT_GENERIC)
REMOVE_TRAIT(owner, TRAIT_SIGN_LANG, ACTION_TRAIT)
to_chat(owner, span_green("You have stopped using sign language."))
build_all_button_icons(UPDATE_BUTTON_BACKGROUND)

Expand Down
6 changes: 3 additions & 3 deletions code/datums/actions/mobs/sneak.dm
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
/datum/action/cooldown/mob_cooldown/sneak/Remove(mob/living/remove_from)
if(HAS_TRAIT(remove_from, TRAIT_SNEAK))
remove_from.alpha = initial(remove_from.alpha)
REMOVE_TRAIT(remove_from, TRAIT_SNEAK, name)
REMOVE_TRAIT(remove_from, TRAIT_SNEAK, ACTION_TRAIT)

return ..()

Expand All @@ -26,11 +26,11 @@
// Otherwise we get permanent invisbility exploits.
animate(owner, alpha = initial(owner.alpha), time = animation_time)
owner.balloon_alert(owner, "you reveal yourself")
REMOVE_TRAIT(owner, TRAIT_SNEAK, name)
REMOVE_TRAIT(owner, TRAIT_SNEAK, ACTION_TRAIT)

else
animate(owner, alpha = sneak_alpha, time = animation_time)
owner.balloon_alert(owner, "you blend into the environment")
ADD_TRAIT(owner, TRAIT_SNEAK, name)
ADD_TRAIT(owner, TRAIT_SNEAK, ACTION_TRAIT)

return TRUE
2 changes: 2 additions & 0 deletions code/game/objects/items/granters/oragami.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@
check_flags = NONE

/datum/action/innate/origami/Activate()
ADD_TRAIT(owner, TRAIT_PAPER_MASTER, ACTION_TRAIT)
to_chat(owner, span_notice("You will now fold origami planes."))
active = TRUE
build_all_button_icons(UPDATE_BUTTON_ICON)

/datum/action/innate/origami/Deactivate()
REMOVE_TRAIT(owner, TRAIT_PAPER_MASTER, ACTION_TRAIT)
to_chat(owner, span_notice("You will no longer fold origami planes."))
active = FALSE
build_all_button_icons(UPDATE_BUTTON_ICON)
Expand Down
6 changes: 6 additions & 0 deletions code/modules/paperwork/carbonpaper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
return
. += span_notice("Right-click to tear off the carbon-copy (you must use both hands).")

/obj/item/paper/carbon/AltClick(mob/living/user)
if(!copied)
to_chat(user, span_notice("Take off the carbon copy first."))
return
return ..()

/obj/item/paper/carbon/proc/removecopy(mob/living/user)
if(copied)
to_chat(user, span_notice("There are no more carbon copies attached to this paper!"))
Expand Down
26 changes: 26 additions & 0 deletions code/modules/paperwork/paper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@

/obj/item/paper/examine(mob/user)
. = ..()
. += span_notice("Alt-click [src] to fold it into a paper plane.")
if(!in_range(user, src) && !isobserver(user))
. += span_warning("You're too far away to read it!")
return
Expand Down Expand Up @@ -358,6 +359,31 @@
return TRUE
return ..()

/obj/item/paper/AltClick(mob/living/user)
. = ..()
if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS))
return
if(HAS_TRAIT(user, TRAIT_PAPER_MASTER))
return make_plane(user, /obj/item/paperplane/syndicate)
return make_plane(user, /obj/item/paperplane)


/**
* Paper plane folding
* Makes a paperplane depending on args and returns it.
*
* Arguments:
* * mob/living/user - who's folding
* * obj/item/paperplane/plane_type - what it will be folded into (path)
*/
/obj/item/paper/proc/make_plane(mob/living/user, obj/item/paperplane/plane_type = /obj/item/paperplane)
balloon_alert(user, "folded into a plane")
user.temporarilyRemoveItemFromInventory(src)
var/obj/item/paperplane/new_plane = new plane_type(loc, src)
if(user.Adjacent(new_plane))
user.put_in_hands(new_plane)
return new_plane

/obj/item/proc/burn_paper_product_attackby_check(obj/item/attacking_item, mob/living/user, bypass_clumsy = FALSE)
//can't be put on fire!
if((resistance_flags & FIRE_PROOF) || !(resistance_flags & FLAMMABLE))
Expand Down
144 changes: 49 additions & 95 deletions code/modules/paperwork/paperplane.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
desc = "Paper, folded in the shape of a plane."
icon = 'icons/obj/service/bureaucracy.dmi'
icon_state = "paperplane"
base_icon_state = "paperplane"
custom_fire_overlay = "paperplane_onfire"
throw_range = 7
throw_speed = 1
Expand All @@ -11,8 +12,10 @@
resistance_flags = FLAMMABLE
max_integrity = 50

var/hit_probability = 2 //%
var/obj/item/paper/internalPaper
///The chance of hitting a mob in the eye when thrown, in percentage.
var/hit_probability = 2
///Reference to the paper that's folded up in this paperplane, which we return when unfolded.
var/obj/item/paper/internal_paper

// NOVA EDIT START - Better paper planes
/// How long does getting shot in the eyes knock you down for?
Expand All @@ -27,38 +30,38 @@

/obj/item/paperplane/syndicate
desc = "Paper, masterfully folded in the shape of a plane."
throwforce = 20 //same as throwing stars, but no chance of embedding.
hit_probability = 100 //guaranteed to cause eye damage when it hits a mob.
throwforce = 20
hit_probability = 100

/obj/item/paperplane/Initialize(mapload, obj/item/paper/newPaper)
/obj/item/paperplane/Initialize(mapload, obj/item/paper/paper_made_of)
. = ..()
pixel_x = base_pixel_x + rand(-9, 9)
pixel_y = base_pixel_y + rand(-8, 8)
if(newPaper)
internalPaper = newPaper
flags_1 = newPaper.flags_1
color = newPaper.color
newPaper.forceMove(src)
if(paper_made_of)
internal_paper = paper_made_of
flags_1 = paper_made_of.flags_1
color = paper_made_of.color
paper_made_of.forceMove(src)
else
internalPaper = new(src)
if(internalPaper.icon_state == "cpaper" || internalPaper.icon_state == "cpaper_words")
icon_state = "paperplane_carbon" // It's the purple carbon copy. Use the purple paper plane
update_appearance()
internal_paper = new(src)
if(istype(internal_paper, /obj/item/paper/carbon_copy))
icon_state = "[base_icon_state]_carbon"
update_appearance(UPDATE_ICON)

/obj/item/paperplane/Exited(atom/movable/gone, direction)
. = ..()
if (internalPaper == gone)
internalPaper = null
if (internal_paper == gone)
internal_paper = null
if(!QDELETED(src))
qdel(src)

/obj/item/paperplane/Destroy()
internalPaper = null
internal_paper = null
return ..()

/obj/item/paperplane/suicide_act(mob/living/user)
var/obj/item/organ/internal/eyes/eyes = user.get_organ_slot(ORGAN_SLOT_EYES)
user.Stun(200)
user.Stun(20 SECONDS)
user.visible_message(span_suicide("[user] jams [src] in [user.p_their()] nose. It looks like [user.p_theyre()] trying to commit suicide!"))
user.adjust_eye_blur(12 SECONDS)
if(eyes)
Expand All @@ -68,103 +71,54 @@

/obj/item/paperplane/update_overlays()
. = ..()
for(var/stamp in internalPaper.stamp_cache)
. += "paperplane_[stamp]"
for(var/stamp in internal_paper.stamp_cache)
. += "[base_icon_state]_[stamp]"

/obj/item/paperplane/attack_self(mob/user)
balloon_alert(user, "unfolded")

var/atom/location = drop_location()
// Need to keep a reference to the internal paper
// when we move it out of the plane, our ref gets set to null
var/obj/item/paper/internal_paper = internalPaper
internal_paper.forceMove(location)
var/obj/item/paper/released_paper = internal_paper
released_paper.forceMove(location)
// This will as a side effect, qdel the paper plane, making the user's hands empty

user.put_in_hands(internal_paper)
user.put_in_hands(released_paper)

/obj/item/paperplane/attackby(obj/item/P, mob/living/carbon/human/user, params)
if(burn_paper_product_attackby_check(P, user))
/obj/item/paperplane/attackby(obj/item/attacking_item, mob/user, params)
if(burn_paper_product_attackby_check(attacking_item, user))
return
if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
if(istype(attacking_item, /obj/item/pen) || istype(attacking_item, /obj/item/toy/crayon))
to_chat(user, span_warning("You should unfold [src] before changing it!"))
return

else if(istype(P, /obj/item/stamp)) //we don't randomize stamps on a paperplane
internalPaper.attackby(P, user) //spoofed attack to update internal paper.
else if(istype(attacking_item, /obj/item/stamp)) //we don't randomize stamps on a paperplane
internal_paper.attackby(attacking_item, user) //spoofed attack to update internal paper.
update_appearance()
add_fingerprint(user)
return

return ..()


/obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback, gentle, quickstart = TRUE)
. = ..(target, range, speed, thrower, FALSE, diagonals_first, callback, quickstart = quickstart)

/obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
if(iscarbon(hit_atom))
var/mob/living/carbon/C = hit_atom
if(C.can_catch_item(TRUE))
var/datum/action/innate/origami/origami_action = locate() in C.actions
if(origami_action?.active) //if they're a master of origami and have the ability turned on, force throwmode on so they'll automatically catch the plane.
C.throw_mode_on(THROW_MODE_TOGGLE)

if(..() || !ishuman(hit_atom))//if the plane is caught or it hits a nonhuman
// NOVA EDIT START - Better paper planes
if(delete_on_impact)
qdel(src)
// NOVA EDIT END
return
var/mob/living/carbon/human/H = hit_atom
var/obj/item/organ/internal/eyes/eyes = H.get_organ_slot(ORGAN_SLOT_EYES)
if(prob(hit_probability))
if(H.is_eyes_covered())
// NOVA EDIT START - Better paper planes
if(delete_on_impact)
qdel(src)
// NOVA EDIT END
return
visible_message(span_danger("\The [src] hits [H] in the eye[eyes ? "" : " socket"]!"))
H.adjust_eye_blur(12 SECONDS)
eyes?.apply_organ_damage(rand(impact_eye_damage_lower, impact_eye_damage_higher))
H.Knockdown(40)
H.emote("scream")
if(iscarbon(hit_atom) && HAS_TRAIT(hit_atom, TRAIT_PAPER_MASTER))
var/mob/living/carbon/hit_carbon = hit_atom
if(hit_carbon.can_catch_item(TRUE))
hit_carbon.throw_mode_on(THROW_MODE_TOGGLE)

if(delete_on_impact)
qdel(src)
// NOVA EDIT END

/obj/item/paper/examine(mob/user)
. = ..()
. += span_notice("Alt-click [src] to fold it into a paper plane.")

/obj/item/paper/AltClick(mob/living/user, obj/item/I)
if(!user.can_perform_action(src, NEED_DEXTERITY|NEED_HANDS))
if(. || !ishuman(hit_atom)) //if the plane is caught or it hits a nonhuman
return
if(istype(src, /obj/item/paper/carbon))
var/obj/item/paper/carbon/Carbon = src
if(!Carbon.copied)
to_chat(user, span_notice("Take off the carbon copy first."))
return
//Origami Master
var/datum/action/innate/origami/origami_action = locate() in user.actions
if(origami_action?.active)
make_plane(user, I, /obj/item/paperplane/syndicate)
else
make_plane(user, I, /obj/item/paperplane)
var/mob/living/carbon/human/hit_human = hit_atom
var/obj/item/organ/internal/eyes/eyes = hit_human.get_organ_slot(ORGAN_SLOT_EYES)
if(!prob(hit_probability))
return
if(hit_human.is_eyes_covered())
return
visible_message(span_danger("\The [src] hits [hit_human] in the eye[eyes ? "" : " socket"]!"))
hit_human.adjust_eye_blur(12 SECONDS)
eyes?.apply_organ_damage(rand(6, 8))
hit_human.Paralyze(4 SECONDS)
hit_human.emote("scream")

/**
* Paper plane folding
*
* Arguments:
* * mob/living/user - who's folding
* * obj/item/I - what's being folded
* * obj/item/paperplane/plane_type - what it will be folded into (path)
*/
/obj/item/paper/proc/make_plane(mob/living/user, obj/item/I, obj/item/paperplane/plane_type = /obj/item/paperplane)
balloon_alert(user, "folded into a plane")
user.temporarilyRemoveItemFromInventory(src)
I = new plane_type(loc, src)
if(user.Adjacent(I))
user.put_in_hands(I)
/obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback, gentle, quickstart = TRUE)
return ..(target, range, speed, thrower, FALSE, diagonals_first, callback, quickstart = quickstart)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Better paper planes
/obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
. = ..()
if(delete_on_impact)
qdel(src)
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -6505,6 +6505,7 @@
#include "modular_nova\master_files\code\modules\modular_computers\file_system\programs\maintenance\camera.dm"
#include "modular_nova\master_files\code\modules\pai\card.dm"
#include "modular_nova\master_files\code\modules\paperwork\employment_contract.dm"
#include "modular_nova\master_files\code\modules\paperwork\paperplane.dm"
#include "modular_nova\master_files\code\modules\paperwork\stamps.dm"
#include "modular_nova\master_files\code\modules\power\cable.dm"
#include "modular_nova\master_files\code\modules\power\powernet.dm"
Expand Down

0 comments on commit 7635158

Please sign in to comment.