mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 07:48:55 +00:00
156 lines
5.0 KiB
Plaintext
156 lines
5.0 KiB
Plaintext
/**
|
|
# Interactions code by HONKERTRON feat TestUnit
|
|
- Contains a lot ammount of ERP and MEHANOYEBLYA
|
|
- CREDIT TO ATMTA STATION FOR MOST OF THIS CODE, I ONLY MADE IT WORK IN /vg/ - Matt
|
|
- Rewritten 30/08/16 by Zuhayr, sry if I removed anything important.
|
|
- I removed ERP and replaced it with handholding. Nothing of worth was lost. - Vic
|
|
- Fuck you, Vic. ERP is back. - TT
|
|
- >using var/ on everything, also TRUE
|
|
- "TGUIzes" the panel because yes - SandPoot
|
|
- Makes all the code good because yes as well - SandPoot
|
|
**/
|
|
|
|
/mob/proc/list_interaction_attributes()
|
|
return list()
|
|
|
|
/mob/living/list_interaction_attributes()
|
|
. = ..()
|
|
if(has_hands())
|
|
. += "...have hands."
|
|
if(has_mouth())
|
|
. += "...have a mouth, which is [mouth_is_free() ? "uncovered" : "covered"]."
|
|
|
|
/// The base of all interactions
|
|
/datum/interaction
|
|
var/description
|
|
var/simple_message
|
|
var/simple_style = "notice"
|
|
var/write_log_user
|
|
var/write_log_target
|
|
|
|
var/interaction_sound
|
|
|
|
var/max_distance = 1
|
|
|
|
var/interaction_flags = INTERACTION_FLAG_ADJACENT
|
|
|
|
var/required_from_user = NONE
|
|
var/required_from_user_exposed = NONE
|
|
var/required_from_user_unexposed = NONE
|
|
|
|
var/required_from_target = NONE
|
|
var/required_from_target_exposed = NONE
|
|
var/required_from_target_unexposed = NONE
|
|
|
|
/// Additional details to be shown in the interaction menu, accepts more than one entry
|
|
var/list/additional_details
|
|
|
|
/// Checks if user can do an interaction, action_check is for whether you're actually doing it or not (useful for the menu and not removing the buttons)
|
|
/datum/interaction/proc/evaluate_user(mob/living/user, silent = TRUE, action_check = TRUE)
|
|
if(SSinteractions.is_blacklisted(user))
|
|
return FALSE
|
|
|
|
if(required_from_user & INTERACTION_REQUIRE_MOUTH)
|
|
if(!user.has_mouth())
|
|
if(!silent)
|
|
to_chat(user, span_warning("You don't have a mouth."))
|
|
return FALSE
|
|
|
|
if(!user.mouth_is_free())
|
|
if(!silent)
|
|
to_chat(user, span_warning("Your mouth is covered."))
|
|
return FALSE
|
|
|
|
if(required_from_user & INTERACTION_REQUIRE_HANDS)
|
|
if(!user.has_hands())
|
|
if(!silent)
|
|
to_chat(user, span_warning("You don't have hands."))
|
|
return FALSE
|
|
|
|
if(COOLDOWN_FINISHED(user, last_interaction_time))
|
|
return TRUE
|
|
|
|
if(action_check)
|
|
return FALSE
|
|
else
|
|
return TRUE
|
|
|
|
/// Same as evaluate_user, but for target
|
|
/datum/interaction/proc/evaluate_target(mob/living/user, mob/living/target, silent = TRUE)
|
|
if(SSinteractions.is_blacklisted(target))
|
|
return FALSE
|
|
|
|
if(!(interaction_flags & INTERACTION_FLAG_USER_IS_TARGET))
|
|
if(user == target)
|
|
if(!silent)
|
|
to_chat(user, span_warning("You can't do that to yourself."))
|
|
return FALSE
|
|
|
|
if(required_from_target & INTERACTION_REQUIRE_MOUTH)
|
|
if(!target.has_mouth())
|
|
if(!silent)
|
|
to_chat(user, span_warning("They don't have a mouth."))
|
|
return FALSE
|
|
|
|
if(!target.mouth_is_free())
|
|
if(!silent)
|
|
to_chat(user, span_warning("Their mouth is covered."))
|
|
return FALSE
|
|
|
|
if(required_from_target & INTERACTION_REQUIRE_HANDS)
|
|
if(!target.has_hands())
|
|
if(!silent)
|
|
to_chat(user, span_warning("They don't have hands."))
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
/// Actually doing the action, has a few checks to see if it's valid, usually overwritten to be make things actually happen and what-not
|
|
/datum/interaction/proc/do_action(mob/living/user, mob/living/target)
|
|
if(!(interaction_flags & INTERACTION_FLAG_USER_IS_TARGET))
|
|
if(user == target) //tactical href fix
|
|
to_chat(user, span_warning("You cannot target yourself."))
|
|
return
|
|
if(get_dist(user, target) > max_distance)
|
|
to_chat(user, span_warning("They are too far away."))
|
|
return
|
|
if(interaction_flags & INTERACTION_FLAG_ADJACENT && !(user.Adjacent(target) && target.Adjacent(user)))
|
|
to_chat(user, span_warning("You cannot get to them."))
|
|
return
|
|
if(!evaluate_user(user, silent = FALSE))
|
|
return
|
|
if(!evaluate_target(user, target, silent = FALSE))
|
|
return
|
|
|
|
if(write_log_user)
|
|
user.log_message("[write_log_user] [target]", LOG_ATTACK)
|
|
if(write_log_target)
|
|
target.log_message("[write_log_target] [user]", LOG_VICTIM, log_globally = FALSE)
|
|
|
|
display_interaction(user, target)
|
|
post_interaction(user, target)
|
|
|
|
/// Display the message
|
|
/datum/interaction/proc/display_interaction(mob/living/user, mob/living/target)
|
|
if(simple_message)
|
|
var/use_message = replacetext(simple_message, "USER", "\the [user]")
|
|
use_message = replacetext(use_message, "TARGET", "\the [target]")
|
|
user.visible_message("<span class='[simple_style]'>[capitalize(use_message)]</span>")
|
|
|
|
/// After the interaction, the base only plays the sound and only if it has one
|
|
/datum/interaction/proc/post_interaction(mob/living/user, mob/living/target)
|
|
COOLDOWN_START(user, last_interaction_time, 0.6 SECONDS)
|
|
if(interaction_sound)
|
|
var/soundfile_to_play
|
|
|
|
// pickweight so you can make a certain sound play
|
|
// more times. This does NOT mean you are forced to
|
|
// use the system. If you do not make the list
|
|
// associative, all options will have the same chances!
|
|
if(islist(interaction_sound))
|
|
soundfile_to_play = pickweight(interaction_sound)
|
|
else
|
|
soundfile_to_play = interaction_sound
|
|
playsound(get_turf(user), soundfile_to_play, 50, 1, -1)
|
|
return
|