mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-23 03:57:48 +01:00
Merge branch 'master' into dogborg-end
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
Landmark to be spawned by GMs and admins when running events.
|
||||
Do NOT directly spawn "" or buildmode spawn this.
|
||||
Use the "Manage Event Triggers" verb under "Eventkit" category.
|
||||
Admin verb is called by code\modules\admin\verbs\event_triggers.dm
|
||||
*/
|
||||
/obj/effect/landmark/event_trigger
|
||||
name = "ONLY FOR EVENTS. DO NOT USE WHEN MAPPING"
|
||||
desc = "Please notify staff if you see this!"
|
||||
var/creator_ckey = ""
|
||||
var/isTeamwork = FALSE //Whether to notify creator or whole team.
|
||||
var/isRepeating = FALSE
|
||||
var/coordinates = ""
|
||||
var/cooldown = 0 //Given in seconds in set_vars() but stored in ticks
|
||||
var/last_trigger = 0
|
||||
var/isLoud = FALSE
|
||||
var/isNarrate = FALSE
|
||||
|
||||
/obj/effect/landmark/event_trigger/New()
|
||||
..()
|
||||
coordinates = "(X:[loc.x];Y:[loc.y];Z:[loc.z])"
|
||||
|
||||
/obj/effect/landmark/event_trigger/proc/set_vars(mob/M)
|
||||
var/new_name = sanitize(tgui_input_text(M, "Input Name for the trigger", "Naming", "Event Trigger"))
|
||||
if(!new_name)
|
||||
return
|
||||
name = new_name
|
||||
creator_ckey = M.ckey
|
||||
if(!event_triggers[creator_ckey])
|
||||
event_triggers[creator_ckey] = list()
|
||||
event_triggers[creator_ckey] |= list(src)
|
||||
isTeamwork = (tgui_alert(M, "Notify rest of team?", "Teamwork", list("No", "Yes")) == "Yes" ? TRUE : FALSE)
|
||||
if(!isTeamwork)
|
||||
isLoud = (tgui_alert(M, "Should it make a bwoink when triggered for YOU?", "bwoink", list("No", "Yes")) == "Yes" ? TRUE : FALSE)
|
||||
isRepeating = (tgui_alert(M, "Make it fire repeatedly?", "Repetition", list("No", "Yes")) == "Yes" ? TRUE : FALSE)
|
||||
if(isRepeating)
|
||||
cooldown = tgui_input_number(M, "Set cooldown in seconds. Minimum 5 seconds!", "Cooldown", 60, min_value = 5)
|
||||
cooldown = cooldown SECONDS
|
||||
else
|
||||
delete_me = TRUE
|
||||
log_admin("[M.ckey] has created a [isNarrate ? "Narrtion" : "Notification"] landmark trigger at [coordinates]")
|
||||
|
||||
/obj/effect/landmark/event_trigger/Destroy()
|
||||
if(event_triggers[creator_ckey])
|
||||
event_triggers[creator_ckey] -= src
|
||||
..()
|
||||
|
||||
/obj/effect/landmark/event_trigger/Crossed(var/atom/movable/AM)
|
||||
if(!isliving(AM))
|
||||
return FALSE
|
||||
var/mob/living/L = AM
|
||||
if(!L.ckey) return FALSE
|
||||
|
||||
if(world.time < (last_trigger + cooldown))
|
||||
return FALSE
|
||||
if(!isRepeating && last_trigger) //Used to avoid spam if qdel(src) fires too slowly
|
||||
return FALSE
|
||||
last_trigger = world.time
|
||||
|
||||
if(!creator_ckey) //For some reason, the user didn't have a ckey. Let's clean up
|
||||
qdel(src)
|
||||
return FALSE
|
||||
var/mob/creator_reference = GLOB.directory[creator_ckey]
|
||||
if(!creator_reference || isTeamwork) //If logged/crashed, we default to teamwork mode
|
||||
message_admins("Player [L.name] ([L.ckey]) has triggered event narrate landmark [name] of type \
|
||||
[isNarrate ? "Narration" : "Notification"]. \n \
|
||||
The landmark was created by [creator_ckey], and it [isRepeating ? \
|
||||
"will be possible to trigger after [cooldown / (1 SECOND)] seconds" : "has self-deleted"]\n \
|
||||
COORDINATES: [coordinates]")
|
||||
else
|
||||
if(isLoud)
|
||||
creator_reference << 'sound/effects/adminhelp.ogg'
|
||||
to_chat(creator_reference, SPAN_WARNING("Player [L.name] ([L.ckey]) has triggered event \
|
||||
narrate landmark [name] of type [isNarrate ? "Narration" : "Notification"]. \n \
|
||||
It [isRepeating ? "will be possible to trigger after [cooldown / (1 SECOND)] seconds" : "has self-deleted"] \n \
|
||||
COORDINATES: [coordinates]"))
|
||||
if(!isNarrate)
|
||||
if(!isRepeating)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
else
|
||||
return L
|
||||
|
||||
|
||||
/obj/effect/landmark/event_trigger/auto_narrate
|
||||
var/message
|
||||
var/isPersonal_orVis_orAud = 0 //0 for personal, 1 for vis, 2 for aud
|
||||
var/message_range //Leave at 0 for world.view
|
||||
var/isWarning = FALSE //For personal messages
|
||||
isNarrate = TRUE
|
||||
|
||||
/obj/effect/landmark/event_trigger/auto_narrate/New()
|
||||
message_range = world.view
|
||||
..()
|
||||
|
||||
/obj/effect/landmark/event_trigger/auto_narrate/set_vars(mob/M)
|
||||
..()
|
||||
message = encode_html_emphasis(sanitize(tgui_input_text(M, "What should the automatic narration say?", "Message"), encode = FALSE))
|
||||
isPersonal_orVis_orAud = (tgui_alert(M, "Should it send directly to the player, or send to the turf?", "Target", list("Player", "Turf")) == "Player" ? 0 : 1)
|
||||
if(isPersonal_orVis_orAud == 0)
|
||||
isWarning = (tgui_alert(M, "Should it be a normal message or a big scary red text?", "Scary Red", list("Big Red", "Normal")) == "Big Red" ? TRUE : FALSE)
|
||||
else
|
||||
isPersonal_orVis_orAud = (tgui_alert(M, "Should it be visible or audible?", "Mode", list("Visible", "Audible")) == "Audible" ? 2 : 1)
|
||||
var/range = tgui_input_number(M, "Give narration range! Input value over 10 to use world.view", "Range",default = 11, min_value = 0)
|
||||
if(range <= 10)
|
||||
message_range = range
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/effect/landmark/event_trigger/auto_narrate/Crossed(var/atom/movable/AM)
|
||||
. = ..() //Checks if AM is mob/living and notifies admin(s)
|
||||
if(!.)
|
||||
return
|
||||
var/mob/living/L = .
|
||||
var/turf/T = get_turf(src)
|
||||
switch(isPersonal_orVis_orAud)
|
||||
if(0)
|
||||
if(isWarning)
|
||||
to_chat(L, SPAN_DANGER(message))
|
||||
else
|
||||
to_chat(L, message)
|
||||
if(1)
|
||||
T.visible_message(message, range = message_range, runemessage = message)
|
||||
if(2)
|
||||
T.audible_message(message, hearing_distance = message_range, runemessage= message)
|
||||
if(!isRepeating)
|
||||
qdel(src)
|
||||
@@ -76,3 +76,7 @@
|
||||
name = "steam emitter"
|
||||
icon_state = "smoke_emitter"
|
||||
effect_system_type = /datum/effect/effect/system/steam_spread
|
||||
|
||||
/obj/effect/map_effect/interval/effect_emitter/steam/less_frequent
|
||||
interval_lower_bound = 10 SECONDS
|
||||
interval_upper_bound = 30 SECONDS
|
||||
|
||||
@@ -4,6 +4,11 @@ var/global/list/active_radio_jammers = list()
|
||||
var/turf/Tr = get_turf(radio)
|
||||
if(!Tr) return 0 //Nullspace radios don't get jammed.
|
||||
|
||||
var/area/our_area = get_area(Tr)
|
||||
|
||||
if(our_area.no_comms)
|
||||
return TRUE
|
||||
|
||||
for(var/obj/item/device/radio_jammer/J as anything in active_radio_jammers)
|
||||
var/turf/Tj = get_turf(J)
|
||||
|
||||
@@ -111,4 +116,3 @@ var/global/list/active_radio_jammers = list()
|
||||
cut_overlays()
|
||||
add_overlay("jammer_overlay_[overlay_percent]")
|
||||
last_overlay_percent = overlay_percent
|
||||
|
||||
|
||||
@@ -490,7 +490,12 @@ GLOBAL_DATUM(autospeaker, /mob/living/silicon/ai/announcer)
|
||||
else if(subspace_transmission)
|
||||
var/list/jamming = is_jammed(src)
|
||||
if(jamming)
|
||||
var/distance = jamming["distance"]
|
||||
var/distance = 0
|
||||
var/area/our_area = get_area(src)
|
||||
if(our_area.no_comms)
|
||||
distance = 99
|
||||
else
|
||||
distance = jamming["distance"]
|
||||
to_chat(M, "<span class='danger'>\icon[src][bicon(src)] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.</span>")
|
||||
return FALSE
|
||||
|
||||
|
||||
@@ -217,8 +217,10 @@ This device records all warnings given and teleport events for admin review in c
|
||||
|
||||
//No, you can't teleport if there's a jammer.
|
||||
if(is_jammed(src) || is_jammed(destination))
|
||||
to_chat(user,"<span class='warning'>\The [src] refuses to teleport you, due to strong interference!</span>")
|
||||
return FALSE
|
||||
var/area/our_area = get_area(src)
|
||||
if(!our_area.no_comms) //I don't actually want this to block teleporters, just comms
|
||||
to_chat(user,"<span class='warning'>\The [src] refuses to teleport you, due to strong interference!</span>")
|
||||
return FALSE
|
||||
|
||||
//No, you can't port to or from away missions. Stupidly complicated check.
|
||||
var/turf/uT = get_turf(user)
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
edge = TRUE
|
||||
sharp = TRUE
|
||||
|
||||
|
||||
/obj/item/weapon/material/twohanded/saber/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
if (src.wielded == 1)
|
||||
if(unique_parry_check(user, attacker, damage_source) && prob(50))
|
||||
@@ -34,3 +33,49 @@
|
||||
playsound(src, 'sound/weapons/punchmiss.ogg', 50, 1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/material/twohanded/staff
|
||||
w_class = ITEMSIZE_LARGE
|
||||
default_material = MAT_WOOD
|
||||
name = "staff"
|
||||
desc = "A sturdy length of metal or wood. A common traveler's aid mostly used for support or probing unstable ground, but also a fairly effective weapon in a pinch."
|
||||
description_info = "When wielded with two hands, staves can be used to parry incoming melee attacks. Being on disarm intent also grants them an added chance to stun or knock down opponents, and increases your chances of parrying an attack."
|
||||
icon = 'icons/obj/weapons_vr.dmi'
|
||||
icon_state = "mat_staff"
|
||||
base_icon = "mat_staff"
|
||||
item_state = "mat_staff"
|
||||
item_icons = list(
|
||||
slot_l_hand_str = 'icons/mob/items/lefthand_melee_vr.dmi',
|
||||
slot_r_hand_str = 'icons/mob/items/righthand_melee_vr.dmi',
|
||||
)
|
||||
force_wielded = 18 //a bit stronger than a stun baton
|
||||
force_divisor = 0.45
|
||||
unwielded_force_divisor = 0.1
|
||||
var/base_parry_chance = 20
|
||||
var/disarm_defense = 1.5 //bonus multiplier to parry rate when in disarm stance
|
||||
var/stun_chance = 25 //chance to weaken an opponent when used in disarm stance only, remembering that disarm also halves damage dealt
|
||||
var/stun_duration = 2
|
||||
attack_verb = list("struck","smashed","thumped","thrashed","beaten","slammed","battered")
|
||||
edge = FALSE
|
||||
sharp = FALSE
|
||||
|
||||
/obj/item/weapon/material/twohanded/staff/handle_shield(mob/user, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
var/parry_chance
|
||||
if(istype(damage_source, /obj/item/projectile)) //can't block ranged attacks, only melee!
|
||||
return 0
|
||||
if(src.wielded == 1)
|
||||
if(user.a_intent == I_DISARM)
|
||||
parry_chance = base_parry_chance * disarm_defense
|
||||
else
|
||||
parry_chance = base_parry_chance
|
||||
if(unique_parry_check(user, attacker, damage_source) && prob(parry_chance))
|
||||
user.visible_message("<span class='danger'>\The [user] parries [attack_text] with \the [src]!</span>")
|
||||
playsound(src, 'sound/weapons/punchmiss.ogg', 50, 1)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/material/twohanded/staff/apply_hit_effect(mob/living/target, mob/living/user, var/hit_zone)
|
||||
. = ..()
|
||||
if(src.wielded == 1 && user.a_intent == I_DISARM && prob(stun_chance))
|
||||
target.Weaken(stun_duration)
|
||||
user.visible_message("<span class='danger'>\The [user] trips [target] with \the [src]!</span>")
|
||||
@@ -21,6 +21,16 @@
|
||||
/obj/structure/prop/rock/small/alt
|
||||
icon_state = "lavarocks2"
|
||||
|
||||
// Warm rocks used as atoms retention fields outside!
|
||||
|
||||
/obj/structure/prop/warmrocks
|
||||
name = "warm rocks"
|
||||
desc = "A number of small rocks that are warm to the touch."
|
||||
icon = 'icons/obj/flora/rocks.dmi'
|
||||
icon_state = "warmrocks"
|
||||
density = FALSE
|
||||
can_atmos_pass = ATMOS_PASS_NO
|
||||
|
||||
//Water-trim versions for placing in water
|
||||
|
||||
/obj/structure/prop/rock/water
|
||||
|
||||
Reference in New Issue
Block a user