diff --git a/code/modules/admin/admin_verb_lists_vr.dm b/code/modules/admin/admin_verb_lists_vr.dm index 7a5b8245d1..cba0101c02 100644 --- a/code/modules/admin/admin_verb_lists_vr.dm +++ b/code/modules/admin/admin_verb_lists_vr.dm @@ -163,7 +163,8 @@ var/list/admin_verbs_fun = list( /client/proc/roll_dices, /datum/admins/proc/call_supply_drop, /datum/admins/proc/call_drop_pod, - /client/proc/smite, +// /client/proc/smite, //Replaced by player_effects + /client/proc/player_effects, /client/proc/admin_lightning_strike, /client/proc/resize, //VOREStation Add, /client/proc/tgui_admin_lists, //CHOMPStation Add diff --git a/code/modules/admin/player_effects.dm b/code/modules/admin/player_effects.dm new file mode 100644 index 0000000000..7501e6c77d --- /dev/null +++ b/code/modules/admin/player_effects.dm @@ -0,0 +1,690 @@ +/client/proc/player_effects(var/mob/target in mob_list) + set name = "Player Effects" + set desc = "Modify a player character with various 'special treatments' from a list." + set category = "Fun" + if(!check_rights(R_FUN)) + return + + var/datum/eventkit/player_effects/spawner = new() + spawner.target = target + spawner.user = src.mob + spawner.tgui_interact(src.mob) + +/datum/eventkit/player_effects + var/mob/target //The target of the effects + var/mob/user + +/datum/eventkit/player_effects/New() + . = ..() + +/datum/eventkit/player_effects/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PlayerEffects", "Player Effects") + ui.open() + +/datum/eventkit/player_effects/Destroy() + . = ..() + +/datum/eventkit/player_effects/tgui_static_data(mob/user) + var/list/data = list() + + data["real_name"] = target.name; + data["player_ckey"] = target.ckey; + data["target_mob"] = target; + + + return data + +/datum/eventkit/player_effects/tgui_state(mob/user) + return GLOB.tgui_admin_state + +/datum/eventkit/player_effects/tgui_act(action) + . = ..() + if(.) + return + if(!check_rights_for(usr.client, R_SPAWN)) + return + + log_and_message_admins("[key_name(user)] used player effect: [action] on [target.ckey] playing [target.name]") + + switch(action) + + ////////////SMITES///////////// + if("break_legs") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/broken_legs = 0 + var/obj/item/organ/external/left_leg = Tar.get_organ(BP_L_LEG) + if(left_leg && left_leg.fracture()) + broken_legs++ + var/obj/item/organ/external/right_leg = Tar.get_organ(BP_R_LEG) + if(right_leg && right_leg.fracture()) + broken_legs++ + if(!broken_legs) + to_chat(user,"[target] didn't have any breakable legs, sorry.") + + if("bluespace_artillery") + bluespace_artillery(target,src) + + if("spont_combustion") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.adjust_fire_stacks(10) + Tar.IgniteMob() + Tar.visible_message(span_danger("[target] bursts into flames!")) + + if("lightning_strike") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/turf/T = get_step(get_step(target, NORTH), NORTH) + T.Beam(target, icon_state="lightning[rand(1,12)]", time = 5) + Tar.electrocute_act(75,def_zone = BP_HEAD) + target.visible_message(span_danger("[target] is struck by lightning!")) + + if("shadekin_attack") + var/turf/Tt = get_turf(target) //Turf for target + + if(target.loc != Tt) + return //Too hard to attack someone in something + + var/turf/Ts //Turf for shadekin + + //Try to find nondense turf + for(var/direction in cardinal) + var/turf/T = get_step(target,direction) + if(T && !T.density) + Ts = T //Found shadekin spawn turf + if(!Ts) + return //Didn't find shadekin spawn turf + + var/mob/living/simple_mob/shadekin/red/shadekin = new(Ts) + //Abuse of shadekin + shadekin.real_name = shadekin.name + shadekin.init_vore() + shadekin.ability_flags |= 0x1 + shadekin.phase_shift() + shadekin.ai_holder.give_target(target) + shadekin.ai_holder.hostile = FALSE + shadekin.ai_holder.mauling = TRUE + shadekin.Life() + //Remove when done + spawn(10 SECONDS) + if(shadekin) + shadekin.death() + + if("shadekin_vore") + var/static/list/kin_types = list( + "Red Eyes (Dark)" = /mob/living/simple_mob/shadekin/red/dark, + "Red Eyes (Light)" = /mob/living/simple_mob/shadekin/red/white, + "Red Eyes (Brown)" = /mob/living/simple_mob/shadekin/red/brown, + "Blue Eyes (Dark)" = /mob/living/simple_mob/shadekin/blue/dark, + "Blue Eyes (Light)" = /mob/living/simple_mob/shadekin/blue/white, + "Blue Eyes (Brown)" = /mob/living/simple_mob/shadekin/blue/brown, + "Purple Eyes (Dark)" = /mob/living/simple_mob/shadekin/purple/dark, + "Purple Eyes (Light)" = /mob/living/simple_mob/shadekin/purple/white, + "Purple Eyes (Brown)" = /mob/living/simple_mob/shadekin/purple/brown, + "Yellow Eyes (Dark)" = /mob/living/simple_mob/shadekin/yellow/dark, + "Yellow Eyes (Light)" = /mob/living/simple_mob/shadekin/yellow/white, + "Yellow Eyes (Brown)" = /mob/living/simple_mob/shadekin/yellow/brown, + "Green Eyes (Dark)" = /mob/living/simple_mob/shadekin/green/dark, + "Green Eyes (Light)" = /mob/living/simple_mob/shadekin/green/white, + "Green Eyes (Brown)" = /mob/living/simple_mob/shadekin/green/brown, + "Orange Eyes (Dark)" = /mob/living/simple_mob/shadekin/orange/dark, + "Orange Eyes (Light)" = /mob/living/simple_mob/shadekin/orange/white, + "Orange Eyes (Brown)" = /mob/living/simple_mob/shadekin/orange/brown, + "Rivyr (Unique)" = /mob/living/simple_mob/shadekin/blue/rivyr) + var/kin_type = tgui_input_list(usr, "Select the type of shadekin for [target] nomf","Shadekin Type Choice", kin_types) + if(!kin_type || !target) + return + + + kin_type = kin_types[kin_type] + + var/myself = tgui_alert(usr, "Control the shadekin yourself or delete pred and prey after?","Control Shadekin?",list("Control","Cancel","Delete")) + if(!myself || myself == "Cancel" || !target) + return + + var/turf/Tt = get_turf(target) + + if(target.loc != Tt) + return //Can't nom when not exposed + + //Begin abuse + target.transforming = TRUE //Cheap hack to stop them from moving + var/mob/living/simple_mob/shadekin/shadekin = new kin_type(Tt) + shadekin.real_name = shadekin.name + shadekin.init_vore() + shadekin.can_be_drop_pred = TRUE + shadekin.dir = SOUTH + shadekin.ability_flags |= 0x1 + shadekin.phase_shift() //Homf + shadekin.energy = initial(shadekin.energy) + //For fun + sleep(1 SECOND) + shadekin.dir = WEST + sleep(1 SECOND) + shadekin.dir = EAST + sleep(1 SECOND) + shadekin.dir = SOUTH + sleep(1 SECOND) + shadekin.audible_message("[shadekin] belches loudly!", runemessage = "URRRRRP") + sleep(2 SECONDS) + shadekin.phase_shift() + target.transforming = FALSE //Undo cheap hack + + if(myself == "Control") //Put admin in mob + shadekin.ckey = target.ckey + + else //Permakin'd + to_chat(target,span_danger("You're carried off into The Dark by the [shadekin]. Who knows if you'll find your way back?")) + target.ghostize() + qdel(target) + qdel(shadekin) + + + if("redspace_abduct") + redspace_abduction(target, src) + + if("autosave") + fake_autosave(target, src) + + if("autosave2") + fake_autosave(target, src, TRUE) + + if("adspam") + if(target.client) + target.client.create_fake_ad_popup_multiple(/obj/screen/popup/default, 15) + + if("peppernade") + var/obj/item/weapon/grenade/chem_grenade/teargas/grenade = new /obj/item/weapon/grenade/chem_grenade/teargas + grenade.loc = target.loc + to_chat(target,span_warning("GRENADE?!")) + grenade.detonate() + + if("spicerequest") + var/obj/item/weapon/reagent_containers/food/condiment/spacespice/spice = new /obj/item/weapon/reagent_containers/food/condiment/spacespice + spice.loc = target.loc + to_chat(target,"A bottle of spices appears at your feet... be careful what you wish for!") + + if("terror") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.fear = 200 + + if("terror_aoe") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + for(var/mob/living/carbon/human/L in orange(Tar.client.view, Tar)) + L.fear = 200 + Tar.fear = 200 + + if("spin") + var/speed = tgui_input_number(user, "Spin speed (minimum 0.1):", "Speed") + if(speed < 0.1) + return + var/loops = tgui_input_number(user, "Number of loops (-1 for infinite):", "Loops") + var/direction_ask = tgui_alert(user, "Clockwise or Anti-Clockwise", "Direction", list("Clockwise", "Anti-Clockwise", "Cancel")) + var/direction + if(direction_ask == "Clockwise") + direction = 1 + if(direction_ask == "Anti-Clockwise") + direction = 0 + if(direction_ask == "Cancel") + return + target.SpinAnimation(speed, loops, direction) + + if("squish") + var/is_squished = target.tf_scale_x || target.tf_scale_y + playsound(target, 'sound/items/hooh.ogg', 50, 1) + if(!is_squished) + target.SetTransform(null, (target.size_multiplier * 1.2), (target.size_multiplier * 0.5)) + else + target.ClearTransform() + target.update_transform() + + if("pie_splat") + new/obj/effect/decal/cleanable/pie_smudge(get_turf(target)) + playsound(target, 'sound/effects/slime_squish.ogg', 100, 1, get_rand_frequency(), falloff = 5) + target.Weaken(1) + target.visible_message(span_danger("[target] is struck by pie!")) + + if("spicy_air") + to_chat(target, span_warning("Spice spice baby!")) + target.eye_blurry = max(target.eye_blurry, 25) + target.Blind(10) + target.Stun(5) + target.Weaken(5) + playsound(target, 'sound/effects/spray2.ogg', 100, 1, get_rand_frequency(), falloff = 5) + + if("hot_dog") + playsound(target, 'sound/effects/whistle.ogg', 50, 1, get_rand_frequency(), falloff = 5) + sleep(2 SECONDS) + target.Stun(10) + if(!ishuman(target)) + return + var/mob/living/carbon/human/H = target + if(H.head) + H.unEquip(H.head) + if(H.wear_suit) + H.unEquip(H.wear_suit) + var/obj/item/clothing/suit = new /obj/item/clothing/suit/storage/hooded/foodcostume/hotdog + var/obj/item/clothing/hood = new /obj/item/clothing/head/hood_vr/hotdog_hood + H.equip_to_slot_if_possible(suit, slot_wear_suit, 0, 0, 1) + H.equip_to_slot_if_possible(hood, slot_head, 0, 0, 1) + sleep(5 SECONDS) + qdel(suit) + qdel(hood) + + ////////MEDICAL////////////// + + if("appendicitis") + var/mob/living/carbon/human/Tar = target + if(istype(Tar)) + Tar.appendicitis() + + if("damage_organ") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/list/organs = list() + for(var/obj/item/organ/I in Tar.organs) + organs |= I + for(var/obj/item/organ/I in Tar.internal_organs) + organs |= I + var/obj/item/organ/our_organ = tgui_input_list(user, "Choose an organ to damage:", "Organs", organs) + if(!our_organ) + return + var/effect = tgui_alert(user, "What do you want to do to the Organ", "Effect", list("Damage", "Kill", "Bruise", "Cancel")) + if(effect == "Cancel") + return + if(effect == "Damage") + var/organ_damage = tgui_input_number(user, "Add how much damage? It is currently at [our_organ.damage].", "Damage") + our_organ.damage = max((our_organ.damage - organ_damage), 0) + if(effect == "Kill") + our_organ.die() + if(effect == "Bruise") + our_organ.bruise() + + if("assist_organ") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/list/organs = list() + for(var/obj/item/organ/I in Tar.organs) + organs |= I + for(var/obj/item/organ/I in Tar.internal_organs) + organs |= I + var/obj/item/organ/our_organ = tgui_input_list(user, "Choose an organ to become assisted:", "Organs", organs) + if(!our_organ) + return + our_organ.mechassist() + + if("robot_organ") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/list/organs = list() + for(var/obj/item/organ/I in Tar.organs) + organs |= I + for(var/obj/item/organ/I in Tar.internal_organs) + organs |= I + var/obj/item/organ/our_organ = tgui_input_list(user, "Choose an organ to become robotic:", "Organs", organs) + if(!our_organ) + return + our_organ.robotize() + + if("repair_organ") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/list/organs = list() + for(var/obj/item/organ/I in Tar.organs) + organs |= I + for(var/obj/item/organ/I in Tar.internal_organs) + organs |= I + var/obj/item/organ/our_organ = tgui_input_list(user, "Choose an organ to heal:", "Organs", organs) + if(!our_organ) + return + var/effect = tgui_alert(user, "What do you want to do to the Organ", "Effect", list("Heal", "Rejuvenate", "Cancel")) + if(effect == "Cancel") + return + if(effect == "Heal") + var/organ_damage = tgui_input_number(user, "Add how much damage? It is currently at [our_organ.damage].", "Damage") + our_organ.damage = max((our_organ.damage - organ_damage), 0) + if(effect == "Rejuvenate") + our_organ.rejuvenate() + + if("drop_organ") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/list/organs = list() + for(var/obj/item/organ/I in Tar.organs) + organs |= I + for(var/obj/item/organ/I in Tar.internal_organs) + organs |= I + var/obj/item/organ/our_organ = tgui_input_list(user, "Choose an organ to damage:", "Organs", organs) + if(!our_organ) + return + our_organ.removed() + + if("break_bone") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/list/organs = list() + for(var/obj/item/organ/external/E in Tar.organs) + organs |= E + var/obj/item/organ/external/our_organ = tgui_input_list(user, "Choose an bone to break:", "Organs", organs) + if(!our_organ) + return + our_organ.fracture() + + if("stasis") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + if(Tar.in_stasis) + Tar.Stasis(0) + else + Tar.Stasis(100000) + + ////////ABILITIES////////////// + + if("vent_crawl") + var/mob/living/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/proc/ventcrawl + + if("darksight") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/current_darksight = Tar.species.darksight + var/change_sight = tgui_input_number(user, "What level do you wish to set their darksight to? It is currently [current_darksight].", "Darksight") + if(change_sight) + Tar.species.darksight = change_sight + + if("cocoon") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/carbon/human/proc/enter_cocoon + + if("transformation") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_hair + Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_hair_colors + Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_gender + Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_wings + Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_tail + Tar.verbs |= /mob/living/carbon/human/proc/shapeshifter_select_ears + Tar.verbs |= /mob/living/carbon/human/proc/lleill_select_shape //designed for non-shapeshifter mobs + Tar.verbs |= /mob/living/carbon/human/proc/lleill_select_colour + + if("set_size") + var/mob/living/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/proc/set_size + + if("lleill_energy") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/energy_max = tgui_input_number(user, "What should their max lleill energy be set to? It is currently [Tar.species.lleill_energy_max].", "Max energy") + Tar.species.lleill_energy_max = energy_max + var/energy_new = tgui_input_number(user, "What should their current lleill energy be set to? It is currently [Tar.species.lleill_energy].", "Max energy") + Tar.species.lleill_energy = energy_new + + if("lleill_invisibility") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/carbon/human/proc/lleill_invisibility + + if("beast_form") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/carbon/human/proc/lleill_beast_form + + if("lleill_transmute") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/carbon/human/proc/lleill_transmute + + if("lleill_alchemy") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/carbon/human/proc/lleill_alchemy + + if("lleill_drain") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/carbon/human/proc/lleill_contact + + if("brutal_pred") + var/mob/living/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/proc/shred_limb + + if("trash_eater") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.verbs |= /mob/living/proc/eat_trash + Tar.verbs |= /mob/living/proc/toggle_trash_catching + + + ////////INVENTORY////////////// + + if("drop_all") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/confirm = tgui_alert(user, "Make [Tar] drop everything?", "Message", list("Yes", "No")) + if(confirm != "Yes") + return + + for(var/obj/item/W in Tar) + if(istype(W, /obj/item/weapon/implant/backup) || istype(W, /obj/item/device/nif)) //VOREStation Edit - There's basically no reason to remove either of these + continue //VOREStation Edit + Tar.drop_from_inventory(W) + + if("drop_specific") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + + var/list/items = Tar.get_equipped_items() + var/item_to_drop = tgui_input_list(user, "Choose item to force drop:", "Drop Specific Item", items) + if(item_to_drop) + Tar.drop_from_inventory(item_to_drop) + + if("drop_held") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.drop_l_hand() + Tar.drop_r_hand() + + if("list_all") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + Tar.get_equipped_items() + + if("give_item") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + if(!user.client.holder) + return + var/obj/item/X = user.client.holder.marked_datum + if(!istype(X)) + return + Tar.put_in_hands(X) + + if("equip_item") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + if(!user.client.holder) + return + var/obj/item/X = user.client.holder.marked_datum + if(!istype(X)) + return + if(Tar.equip_to_appropriate_slot(X)) + return + else + Tar.equip_to_storage(X) + + ////////ADMIN////////////// + + if("quick_nif") + var/mob/living/carbon/human/Tar = target + if(!istype(Tar)) + return + var/input_NIF + if(!Tar.get_organ(BP_HEAD)) + to_chat(user,span_warning("Target is unsuitable.")) + return + if(Tar.nif) + to_chat(user,span_warning("Target already has a NIF.")) + return + if(Tar.species.flags & NO_SCAN) + var/obj/item/device/nif/S = /obj/item/device/nif/bioadap + input_NIF = initial(S.name) + new /obj/item/device/nif/bioadap(Tar) + else + var/list/NIF_types = typesof(/obj/item/device/nif) + var/list/NIFs = list() + + for(var/NIF_type in NIF_types) + var/obj/item/device/nif/S = NIF_type + NIFs[capitalize(initial(S.name))] = NIF_type + + var/list/show_NIFs = sortList(NIFs) // the list that will be shown to the user to pick from + + input_NIF = tgui_input_list(user, "Pick the NIF type","Quick NIF", show_NIFs) + var/chosen_NIF = NIFs[capitalize(input_NIF)] + + if(chosen_NIF) + new chosen_NIF(Tar) + else + new /obj/item/device/nif(Tar) + log_and_message_admins("[key_name(user)] Quick NIF'd [Tar.real_name] with a [input_NIF].") + + if("resize") + user.client.resize(target) + + if("teleport") + var/where = tgui_alert(user, "Where to teleport?", "Where?", list("To Me", "To Mob", "To Area", "Cancel")) + if(where == "Cancel") + return + if(where == "To Me") + user.client.Getmob(target) + if(where == "To Mob") + var/mob/selection = tgui_input_list(usr, "Select a mob to jump [target] to:", "Jump to mob", mob_list) + target.on_mob_jump() + target.forceMove(get_turf(selection)) + log_admin("[key_name(user)] jumped [target] to [selection]") + if(where == "To Area") + var/area/A + A = tgui_input_list(user, "Pick an area to teleport [target] to:", "Jump to Area", return_sorted_areas()) + target.on_mob_jump() + target.forceMove(pick(get_area_turfs(A))) + log_admin("[key_name(user)] jumped [target] to [A]") + + if("gib") + var/death = tgui_alert(user, "Are you sure you want to destroy [target]?", "Gib?", list("KILL", "Cancel")) + if(death == "KILL") + target.gib() + + if("dust") + var/death = tgui_alert(user, "Are you sure you want to destroy [target]?", "Dust?", list("KILL", "Cancel")) + if(death == "KILL") + target.dust() + + if("paralyse") + var/mob/living/Tar = target + if(!istype(Tar)) + return + user.client.holder.paralyze_mob(Tar) + + if("subtle_message") + user.client.cmd_admin_subtle_message(target) + + if("direct_narrate") + user.client.cmd_admin_direct_narrate(target) + + if("player_panel") + user.client.holder.show_player_panel(target) + + if("view_variables") + user.client.debug_variables(target) + + if("orbit") + if(!user.client.holder.marked_datum) + return + var/atom/movable/X = user.client.holder.marked_datum + X.orbit(target) + + if("ai") + if(!istype(target, /mob/living)) + to_chat(usr, span_notice("This can only be used on instances of type /mob/living")) + return + var/mob/living/L = target + if(L.client || L.teleop) + to_chat(usr, span_warning("This cannot be used on player mobs!")) + return + + if(L.ai_holder) //Cleaning up the original ai + var/ai_holder_old = L.ai_holder + L.ai_holder = null + qdel(ai_holder_old) //Only way I could make #TESTING - Unable to be GC'd to stop. del() logs show it works. + L.ai_holder_type = tgui_input_list(usr, "Choose AI holder", "AI Type", typesof(/datum/ai_holder/)) + L.initialize_ai_holder() + L.faction = sanitize(tgui_input_text(usr, "Please input AI faction", "AI faction", "neutral")) + L.a_intent = tgui_input_list(usr, "Please choose AI intent", "AI intent", list(I_HURT, I_HELP)) + if(tgui_alert(usr, "Make mob wake up? This is needed for carbon mobs.", "Wake mob?", list("Yes", "No")) == "Yes") + L.AdjustSleeping(-100) + + + ////////FIXES////////////// + + if("rejuvenate") + var/mob/living/Tar = target + if(!istype(Tar)) + return + Tar.rejuvenate() + + if("popup-box") + var/message = tgui_input_text(user, "Write a message to send to the user with a space for them to reply without using the text box:", "Message") + if(!message) + return + log_admin("[key_name(user)] sent message to [target]: [message]") + var/reply = tgui_input_text(target, "An admin has sent you a message: [message]", "Reply") + if(!reply) + return + log_and_message_admins("[key_name(target)] replied to [user]'s message: [reply].") + + if("stop-orbits") + //CHOMPEdit Start + if(target.orbiters) + target.orbiters.stop_all() + //CHOMPEdit End diff --git a/modular_chomp/code/datums/components/orbiter.dm b/modular_chomp/code/datums/components/orbiter.dm index 3a8ab63483..01b51d4a0c 100644 --- a/modular_chomp/code/datums/components/orbiter.dm +++ b/modular_chomp/code/datums/components/orbiter.dm @@ -99,6 +99,13 @@ if(!refreshing && !length(orbiters) && !QDELING(src)) qdel(src) +/datum/component/orbiter/proc/stop_all() + var/atom/master = parent + master.orbiters = null + for(var/i in orbiters) + end_orbit(i) + orbiters = null + // This proc can receive signals by either the thing being directly orbited or anything holding it /datum/component/orbiter/proc/move_react(atom/orbited, atom/oldloc, direction) set waitfor = FALSE // Transfer calls this directly and it doesnt care if the ghosts arent done moving diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlAbilities.tsx b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlAbilities.tsx new file mode 100644 index 0000000000..366c44cb66 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlAbilities.tsx @@ -0,0 +1,50 @@ +import { useBackend } from '../../../backend'; +import { Button, Section } from '../../../components'; + +export const ControlAbilities = (props) => { + const { act } = useBackend(); + + return ( +
+ + + + + + + + + + + + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlAdmin.tsx b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlAdmin.tsx new file mode 100644 index 0000000000..36dbc56161 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlAdmin.tsx @@ -0,0 +1,47 @@ +import { useBackend } from '../../../backend'; +import { Button, Section } from '../../../components'; + +export const ControlAdmin = (props) => { + const { act } = useBackend(); + + return ( +
+ + + + + + + + + + + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlFixes.tsx b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlFixes.tsx new file mode 100644 index 0000000000..5e0d2f9f5d --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlFixes.tsx @@ -0,0 +1,20 @@ +import { useBackend } from '../../../backend'; +import { Button, Section } from '../../../components'; + +export const ControlFixes = (props) => { + const { act } = useBackend(); + + return ( +
+ + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlInventory.tsx b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlInventory.tsx new file mode 100644 index 0000000000..f8b390e8fb --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlInventory.tsx @@ -0,0 +1,29 @@ +import { useBackend } from '../../../backend'; +import { Button, Section } from '../../../components'; + +export const ControlInventory = (props) => { + const { act } = useBackend(); + + return ( +
+ + + + + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlMedical.tsx b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlMedical.tsx new file mode 100644 index 0000000000..b9884384d1 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlMedical.tsx @@ -0,0 +1,38 @@ +import { useBackend } from '../../../backend'; +import { Button, Section } from '../../../components'; + +export const ControlMedical = (props) => { + const { act } = useBackend(); + + return ( +
+ + + + + + + + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlSmites.tsx b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlSmites.tsx new file mode 100644 index 0000000000..bfd83aa3e2 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/PlayerEffectsTabs/ControlSmites.tsx @@ -0,0 +1,68 @@ +import { useBackend } from '../../../backend'; +import { Button, Section } from '../../../components'; + +export const ControlSmites = (props) => { + const { act } = useBackend(); + + return ( +
+ + + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/index.tsx b/tgui/packages/tgui/interfaces/PlayerEffects/index.tsx new file mode 100644 index 0000000000..b4de1f1945 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/index.tsx @@ -0,0 +1,60 @@ +import { useState } from 'react'; + +import { useBackend } from '../../backend'; +import { NoticeBox, Tabs } from '../../components'; +import { Window } from '../../layouts'; +import { ControlAbilities } from './PlayerEffectsTabs/ControlAbilities'; +import { ControlAdmin } from './PlayerEffectsTabs/ControlAdmin'; +import { ControlFixes } from './PlayerEffectsTabs/ControlFixes'; +import { ControlInventory } from './PlayerEffectsTabs/ControlInventory'; +import { ControlMedical } from './PlayerEffectsTabs/ControlMedical'; +import { ControlSmites } from './PlayerEffectsTabs/ControlSmites'; +import { Data } from './types'; + +export const PlayerEffects = (props) => { + const { data } = useBackend(); + + const { real_name, player_ckey } = data; + + const [tab, setTab] = useState(0); + + const tabs: React.JSX.Element[] = []; + + tabs[0] = ; + tabs[1] = ; + tabs[2] = ; + tabs[3] = ; + tabs[4] = ; + tabs[5] = ; + + return ( + + + + setTab(0)}> + Smites + + setTab(1)}> + Medical + + setTab(2)}> + Abilities + + setTab(3)}> + Inventory + + setTab(4)}> + Admin + + setTab(5)}> + Fixes + + + + {real_name} played by {player_ckey}. + + {tabs[tab]} + + + ); +}; diff --git a/tgui/packages/tgui/interfaces/PlayerEffects/types.ts b/tgui/packages/tgui/interfaces/PlayerEffects/types.ts new file mode 100644 index 0000000000..74f9211e4e --- /dev/null +++ b/tgui/packages/tgui/interfaces/PlayerEffects/types.ts @@ -0,0 +1,4 @@ +export type Data = { + real_name: string; + player_ckey: string; +}; diff --git a/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferences.tsx.tsx b/tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferences.tsx similarity index 100% rename from tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferences.tsx.tsx rename to tgui/packages/tgui/interfaces/VorePanel/VoreUserPreferences.tsx diff --git a/tgui/packages/tgui/interfaces/VorePanel/index.tsx b/tgui/packages/tgui/interfaces/VorePanel/index.tsx index 7e5bdfe482..ad2547cf08 100644 --- a/tgui/packages/tgui/interfaces/VorePanel/index.tsx +++ b/tgui/packages/tgui/interfaces/VorePanel/index.tsx @@ -6,7 +6,7 @@ import { Window } from '../../layouts'; import { Data } from './types'; import { VoreBellySelectionAndCustomization } from './VoreBellySelectionAndCustomization'; import { VoreInsidePanel } from './VoreInsidePanel'; -import { VoreUserPreferences } from './VoreUserPreferences.tsx'; +import { VoreUserPreferences } from './VoreUserPreferences'; /** * There are three main sections to this UI. diff --git a/vorestation.dme b/vorestation.dme index b9f949fa5e..2eac9236ce 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1890,6 +1890,7 @@ #include "code\modules\admin\NewBan.dm" #include "code\modules\admin\news.dm" #include "code\modules\admin\persistence.dm" +#include "code\modules\admin\player_effects.dm" #include "code\modules\admin\player_notes.dm" #include "code\modules\admin\player_panel.dm" #include "code\modules\admin\topic.dm"