mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-22 03:27:05 +01:00
Adds a new rock-paper-scissors emote (#25300)
* adds rock paper scissors mechanics * better icon * Cleans up the last bit of the implementation * use barber scissors instead * minor cleanups * Apply suggestions from code review Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com> Signed-off-by: Luc <89928798+lewcc@users.noreply.github.com> * Update code/datums/status_effects/neutral.dm Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Signed-off-by: Luc <89928798+lewcc@users.noreply.github.com> --------- Signed-off-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com> Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com>
This commit is contained in:
+21
-9
@@ -147,16 +147,16 @@
|
||||
*
|
||||
* Arguments:
|
||||
* * user - Person that is trying to send the emote.
|
||||
* * params - Parameters added after the emote.
|
||||
* * emote_arg - String parameter added after the emote.
|
||||
* * type_override - Override to the current emote_type.
|
||||
* * intentional - Bool that says whether the emote was forced (FALSE) or not (TRUE).
|
||||
*
|
||||
* Returns TRUE if it was able to run the emote, FALSE otherwise.
|
||||
*/
|
||||
/datum/emote/proc/run_emote(mob/user, params, type_override, intentional = FALSE)
|
||||
/datum/emote/proc/run_emote(mob/user, emote_arg, type_override, intentional = FALSE)
|
||||
. = TRUE
|
||||
var/msg = select_message_type(user, message, intentional)
|
||||
if(params && message_param)
|
||||
if(emote_arg && message_param)
|
||||
// In this case, we did make some changes to the message that will be used, and we want to add the postfix on with the new parameters.
|
||||
// This is applicable to things like mimes, who this lets have a target on their canned emote responses.
|
||||
// Note that we only do this if we would otherwise have a message param, meaning there should be some target by default.
|
||||
@@ -164,17 +164,17 @@
|
||||
if(message_param == EMOTE_PARAM_USE_POSTFIX || (msg != message && message_postfix))
|
||||
if(!message_postfix)
|
||||
CRASH("Emote was specified to use postfix but message_postfix is empty.")
|
||||
msg = select_param(user, params, "[remove_ending_punctuation(msg)] [message_postfix]", msg)
|
||||
msg = select_param(user, emote_arg, "[remove_ending_punctuation(msg)] [message_postfix]", msg)
|
||||
else if(msg == message)
|
||||
// In this case, we're not making any substitutions in select_message_type, but we do have some params we want to sub in.
|
||||
msg = select_param(user, params, message_param, message)
|
||||
msg = select_param(user, emote_arg, message_param, message)
|
||||
|
||||
// If this got propogated up, jump out.
|
||||
if(msg == EMOTE_ACT_STOP_EXECUTION)
|
||||
return TRUE
|
||||
|
||||
if(isnull(msg))
|
||||
to_chat(user, "<span class='warning'>'[params]' isn't a valid parameter for [key].</span>")
|
||||
to_chat(user, "<span class='warning'>'[emote_arg]' isn't a valid parameter for [key].</span>")
|
||||
return TRUE
|
||||
|
||||
msg = replace_pronoun(user, msg)
|
||||
@@ -230,13 +230,13 @@
|
||||
* Try to run an emote, checking can_run_emote once before executing the emote itself.
|
||||
*
|
||||
* * user - User of the emote
|
||||
* * params - Params of the emote to be passed to run_emote
|
||||
* * params - An optional extra argument included after the emote key.
|
||||
* * type_override - emote type to override the existing one with, if given.
|
||||
* * intentional - Whether or not the emote was triggered intentionally (if false, the emote was forced by code).
|
||||
*
|
||||
* Returns TRUE if the emote was able to be run (or failed successfully), or FALSE if the emote is unusable.
|
||||
*/
|
||||
/datum/emote/proc/try_run_emote(mob/user, params, type_override, intentional = FALSE)
|
||||
/datum/emote/proc/try_run_emote(mob/user, emote_arg, type_override, intentional = FALSE)
|
||||
// You can use this signal to block execution of emotes from components/other sources.
|
||||
var/sig_res = SEND_SIGNAL(user, COMSIG_MOB_PREEMOTE, key, intentional)
|
||||
switch(sig_res)
|
||||
@@ -245,9 +245,18 @@
|
||||
if(COMPONENT_BLOCK_EMOTE_SILENT)
|
||||
return TRUE
|
||||
|
||||
. = run_emote(user, params, type_override, intentional)
|
||||
. = run_emote(user, emote_arg, type_override, intentional)
|
||||
|
||||
// safeguard in case these get modified
|
||||
reset_emote()
|
||||
|
||||
/**
|
||||
* Reset the emote back to its original state.
|
||||
* Necessary if you've made modifications to the emote itself over the course of its
|
||||
* execution, as emotes are singletons, and changes would be reflected on every usage of the emote.
|
||||
*/
|
||||
/datum/emote/proc/reset_emote()
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
message = initial(message)
|
||||
message_param = initial(message_param)
|
||||
|
||||
@@ -421,6 +430,9 @@
|
||||
*/
|
||||
/datum/emote/proc/select_param(mob/user, params, substitution, base_message)
|
||||
|
||||
if(target_behavior == EMOTE_TARGET_BHVR_IGNORE)
|
||||
return base_message
|
||||
|
||||
if(target_behavior == EMOTE_TARGET_BHVR_RAW)
|
||||
return replacetext(substitution, "%t", params)
|
||||
|
||||
|
||||
@@ -69,6 +69,20 @@
|
||||
user.remove_status_effect(type)
|
||||
highfived.remove_status_effect(type)
|
||||
|
||||
/datum/status_effect/high_five/proc/wiz_effect(mob/living/carbon/user, mob/living/carbon/highfived)
|
||||
user.status_flags |= GODMODE
|
||||
highfived.status_flags |= GODMODE
|
||||
explosion(get_turf(user), 5, 2, 1, 3, cause = id)
|
||||
// explosions have a spawn so this makes sure that we don't get gibbed
|
||||
addtimer(CALLBACK(src, PROC_REF(wiz_cleanup), user, highfived), 0.3 SECONDS) // I want to be sure this lasts long enough, with lag.
|
||||
add_attack_logs(user, highfived, "caused a wizard [id] explosion")
|
||||
|
||||
/datum/status_effect/high_five/proc/post_start()
|
||||
return
|
||||
|
||||
/datum/status_effect/high_five/proc/regular_effect(mob/living/carbon/user, mob/living/carbon/highfived)
|
||||
user.visible_message("<span class='notice'><b>[user.name]</b> and <b>[highfived.name]</b> [success]</span>")
|
||||
|
||||
/datum/status_effect/high_five/on_apply()
|
||||
if(!iscarbon(owner))
|
||||
return FALSE
|
||||
@@ -82,25 +96,23 @@
|
||||
continue
|
||||
if(is_wiz && iswizard(C))
|
||||
user.visible_message("<span class='biggerdanger'><b>[user.name]</b> and <b>[C.name]</b> [critical_success]</span>")
|
||||
user.status_flags |= GODMODE
|
||||
C.status_flags |= GODMODE
|
||||
explosion(get_turf(user), 5, 2, 1, 3, cause = id)
|
||||
// explosions have a spawn so this makes sure that we don't get gibbed
|
||||
addtimer(CALLBACK(src, PROC_REF(wiz_cleanup), user, C), 0.3 SECONDS) //I want to be sure this lasts long enough, with lag.
|
||||
add_attack_logs(user, C, "caused a wizard [id] explosion")
|
||||
wiz_effect(user, C)
|
||||
both_wiz = TRUE
|
||||
user.do_attack_animation(C, no_effect = TRUE)
|
||||
C.do_attack_animation(user, no_effect = TRUE)
|
||||
playsound(user, sound_effect, 80)
|
||||
if(!both_wiz)
|
||||
user.visible_message("<span class='notice'><b>[user.name]</b> and <b>[C.name]</b> [success]</span>")
|
||||
regular_effect(user, C)
|
||||
user.remove_status_effect(type)
|
||||
C.remove_status_effect(type)
|
||||
return FALSE
|
||||
// We can return to break out of the loop here so we don't auto-remove (which causes the timer on the wizard highfive to break)
|
||||
// This is safe because we only pass the continue if we don't have the status effect
|
||||
return TRUE // DO NOT AUTOREMOVE
|
||||
|
||||
owner.custom_emote(EMOTE_VISIBLE, request)
|
||||
owner.create_point_bubble_from_path(item_path, FALSE)
|
||||
post_start()
|
||||
|
||||
/datum/status_effect/high_five/on_timeout()
|
||||
owner.visible_message("[owner] [get_missed_message()]")
|
||||
@@ -144,6 +156,96 @@
|
||||
|
||||
return pick(missed_messages)
|
||||
|
||||
/datum/status_effect/high_five/rps
|
||||
id = "rps"
|
||||
critical_success = "both play rock -- THEY'RE GOING IN FOR THE FISTBUMP!"
|
||||
success = "play rock-paper-scissors!"
|
||||
sound_effect = 'sound/effects/glassknock.ogg'
|
||||
request = "wants to play rock-paper-scissors!"
|
||||
item_path = /obj/item/claymore // it's time to d-d-d-d-d-d-d-duel!
|
||||
/// The move that you'll be making.
|
||||
var/move
|
||||
|
||||
/datum/status_effect/high_five/rps/get_missed_message()
|
||||
var/list/missed_messages = list(
|
||||
"just seems to be practicing against [owner.p_themselves()]. [owner.p_are(TRUE)] [owner.p_they()] losing?",
|
||||
"seems more interested in a thumb war."
|
||||
)
|
||||
|
||||
return pick(missed_messages)
|
||||
|
||||
/datum/status_effect/high_five/rps/proc/get_move_status(my_move, their_move)
|
||||
if(my_move == their_move)
|
||||
return RPS_EMOTE_TIE
|
||||
switch(my_move)
|
||||
if(RPS_EMOTE_ROCK)
|
||||
return their_move == RPS_EMOTE_SCISSORS ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN
|
||||
|
||||
if(RPS_EMOTE_PAPER)
|
||||
return their_move == RPS_EMOTE_ROCK ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN
|
||||
|
||||
if(RPS_EMOTE_SCISSORS)
|
||||
return their_move == RPS_EMOTE_PAPER ? RPS_EMOTE_WE_WIN : RPS_EMOTE_THEY_WIN
|
||||
|
||||
else
|
||||
CRASH("Unknown emote rock type")
|
||||
|
||||
/datum/status_effect/high_five/rps/post_start()
|
||||
playsound(owner, 'sound/effects/glassknock.ogg', 50, FALSE)
|
||||
|
||||
/datum/status_effect/high_five/rps/regular_effect(mob/living/carbon/user, mob/living/carbon/highfived)
|
||||
var/datum/status_effect/high_five/rps/their_status_effect = highfived.has_status_effect(type)
|
||||
var/outcome = get_move_status(move, their_status_effect.move)
|
||||
var/outcome_msg
|
||||
switch(outcome)
|
||||
if(RPS_EMOTE_TIE)
|
||||
outcome_msg = "It's a tie!"
|
||||
if(RPS_EMOTE_WE_WIN)
|
||||
outcome_msg = "[user] wins!"
|
||||
if(RPS_EMOTE_THEY_WIN)
|
||||
outcome_msg = "[highfived] wins!"
|
||||
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] plays <b>[move]</b>, and [highfived] plays <b>[their_status_effect.move]</b>.</span>",
|
||||
"<span class='notice'>[highfived] plays <b>[their_status_effect.move]</b>.</span>",
|
||||
"<span class='notice'>It sounds like rock-paper-scissors.</span>"
|
||||
)
|
||||
|
||||
user.visible_message(
|
||||
"<span class='warning'>[outcome_msg]</span>",
|
||||
blind_message = "<span class='notice'>It sounds like [pick(user, highfived)] won!</span>" // you're blind how are you supposed to know
|
||||
)
|
||||
|
||||
/datum/status_effect/high_five/rps/on_creation(mob/living/new_owner, made_move)
|
||||
if(made_move)
|
||||
if(!(made_move in list(RPS_EMOTE_ROCK, RPS_EMOTE_PAPER, RPS_EMOTE_SCISSORS)))
|
||||
stack_trace("RPS emote was given an invalid move type on creation.")
|
||||
else
|
||||
move = made_move
|
||||
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/high_five/rps/on_apply()
|
||||
if(!isnull(move))
|
||||
to_chat(owner, "<span class='notice'>You prepare to play <b>[move]</b>.</span>")
|
||||
return ..() // we already have the move, probably from the emote passing it in
|
||||
|
||||
move = get_rock_paper_scissors_move(owner)
|
||||
if(move == null)
|
||||
return FALSE // make it auto-remove itself
|
||||
|
||||
to_chat(owner, "<span class='notice'>You prepare to play <b>[move]</b>.</span>")
|
||||
return ..()
|
||||
|
||||
|
||||
/proc/get_rock_paper_scissors_move(mob/living/carbon/user)
|
||||
var/list/move_icons = list(
|
||||
RPS_EMOTE_SCISSORS = image(icon = 'icons/obj/items.dmi', icon_state = "bscissor"),
|
||||
RPS_EMOTE_PAPER = image(icon = 'icons/obj/bureaucracy.dmi', icon_state = "paper"),
|
||||
RPS_EMOTE_ROCK = image(icon = 'icons/obj/toy.dmi', icon_state = "pet_rock")
|
||||
)
|
||||
return show_radial_menu(user, user, move_icons)
|
||||
|
||||
/// A status effect that can have a certain amount of "bonus" duration added, which extends the duration every tick,
|
||||
/// although there is a maximum amount of bonus time that can be active at any given time.
|
||||
/datum/status_effect/limited_bonus
|
||||
|
||||
Reference in New Issue
Block a user