mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-06-05 14:17:12 +01:00
f9e3b58ecd
* Begin * few fixes * WINDOWS * Update airlock.dm * Update status_display.dm * Fixes plus rusty walls. * Update walls.dm * air alarm, intercom, apc updates, plasma windows, tinted, firealarm(todo) * Update airlock.dm * FINALLY FIXES THE DOORS * Update airlock.dm * firealarm and fixes. * fixes * mining vendor and washing machine * firedoor * blastdoor * firealarm sound, shutters sound, blast door sounds. * Delete window.dm * Revert "Delete window.dm" This reverts commit 4737c539eb9b49a526c784f45161c3189505ac57. * fixes * Update 2.0 newscaster DONE bookshelf DONE disposals chute DONE chairs DONE stools DONE beds - Will upgrade later. requests console DONE light switch DONE roller bed DONE nanomed DONE extinguisher cabnets DONE extinguishers DONE buttons shield generators DONE space heater DONE emitter DONE field generator DONE rad collector DONE cameras DONE morgue units DONE watercooler bench Will upgrade later E-N (corgi) port? Will do later. plastic flaps Done Guns - later * fiox * l o g i c * Update extinguisher.dm * V2.5 * racks and fixws * computer typing noise * gun sprite updates * Update guns.dmi * air alarm light mask * better light overlays * floors! * gaygun, bench * lasergun sounds - remove gun balance. * no decals. * Update intercom.dmi * better directionals * lasercannon, nucgun, * Update laser.dm * aaa * aaa * some sprite updates * aaa * shotgun suppressor+sound * Update airlock.dm * Update shieldgen.dmi * chair fix, tools too. * Update chairs.dmi
521 lines
16 KiB
Plaintext
521 lines
16 KiB
Plaintext
/obj/machinery/power/emitter
|
|
name = "emitter"
|
|
desc = "A heavy-duty industrial laser, often used in containment fields and power generation."
|
|
icon = 'icons/obj/singularity.dmi' //ICON OVERRIDEN IN SKYRAT AESTHETICS - SEE MODULE
|
|
icon_state = "emitter"
|
|
|
|
anchored = FALSE
|
|
density = TRUE
|
|
req_access = list(ACCESS_ENGINE_EQUIP)
|
|
circuit = /obj/item/circuitboard/machine/emitter
|
|
|
|
use_power = NO_POWER_USE
|
|
idle_power_usage = 10
|
|
active_power_usage = 300
|
|
|
|
var/icon_state_on = "emitter_+a"
|
|
var/icon_state_underpowered = "emitter_+u"
|
|
var/active = FALSE
|
|
var/powered = FALSE
|
|
var/fire_delay = 100
|
|
var/maximum_fire_delay = 100 //10 seconds
|
|
var/minimum_fire_delay = 20 // 2 seconds
|
|
var/last_shot = 0
|
|
var/shot_number = 0
|
|
var/welded = FALSE ///if it's welded down to the ground or not. the emitter will not fire while unwelded. if set to true, the emitter will start anchored as well.
|
|
var/locked = FALSE
|
|
var/allow_switch_interact = TRUE
|
|
|
|
var/projectile_type = /obj/projectile/beam/emitter
|
|
var/projectile_sound = 'sound/weapons/emitter.ogg'
|
|
var/datum/effect_system/spark_spread/sparks
|
|
|
|
var/obj/item/gun/energy/gun
|
|
var/list/gun_properties
|
|
var/mode = 0
|
|
|
|
// The following 3 vars are mostly for the prototype
|
|
var/manual = FALSE
|
|
var/charge = 0
|
|
var/last_projectile_params
|
|
|
|
|
|
/obj/machinery/power/emitter/welded/Initialize()
|
|
welded = TRUE
|
|
return ..()
|
|
|
|
/obj/machinery/power/emitter/ctf
|
|
name = "Energy Cannon"
|
|
active = TRUE
|
|
active_power_usage = FALSE
|
|
idle_power_usage = FALSE
|
|
locked = TRUE
|
|
req_access_txt = "100"
|
|
welded = TRUE
|
|
use_power = FALSE
|
|
|
|
/obj/machinery/power/emitter/Initialize()
|
|
. = ..()
|
|
RefreshParts()
|
|
wires = new /datum/wires/emitter(src)
|
|
if(welded)
|
|
if(!anchored)
|
|
set_anchored(TRUE)
|
|
connect_to_network()
|
|
|
|
sparks = new
|
|
sparks.attach(src)
|
|
sparks.set_up(5, TRUE, src)
|
|
|
|
/obj/machinery/power/emitter/ComponentInitialize()
|
|
. = ..()
|
|
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
|
|
|
|
/obj/machinery/power/emitter/set_anchored(anchorvalue)
|
|
. = ..()
|
|
if(!anchored && welded) //make sure they're keep in sync in case it was forcibly unanchored by badmins or by a megafauna.
|
|
welded = FALSE
|
|
|
|
/obj/machinery/power/emitter/RefreshParts()
|
|
var/max_firedelay = 120
|
|
var/firedelay = 120
|
|
var/min_firedelay = 24
|
|
var/power_usage = 350
|
|
for(var/obj/item/stock_parts/micro_laser/L in component_parts)
|
|
max_firedelay -= 20 * L.rating
|
|
min_firedelay -= 4 * L.rating
|
|
firedelay -= 20 * L.rating
|
|
maximum_fire_delay = max_firedelay
|
|
minimum_fire_delay = min_firedelay
|
|
fire_delay = firedelay
|
|
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
|
power_usage -= 50 * M.rating
|
|
active_power_usage = power_usage
|
|
|
|
/obj/machinery/power/emitter/examine(mob/user)
|
|
. = ..()
|
|
if(welded)
|
|
. += "<span class='info'>It's moored firmly to the floor. You can unsecure its moorings with a <b>welder</b>.</span>"
|
|
else if(anchored)
|
|
. += "<span class='info'>It's currently anchored to the floor. You can secure its moorings with a <b>welder</b>, or remove it with a <b>wrench</b>.</span>"
|
|
else
|
|
. += "<span class='info'>It's not anchored to the floor. You can secure it in place with a <b>wrench</b>.</span>"
|
|
|
|
if(in_range(user, src) || isobserver(user))
|
|
if(!active)
|
|
. += "<span class='notice'>Its status display is currently turned off.</span>"
|
|
else if(!powered)
|
|
. += "<span class='notice'>Its status display is glowing faintly.</span>"
|
|
else
|
|
. += "<span class='notice'>Its status display reads: Emitting one beam every <b>[DisplayTimeText(fire_delay)]</b>.</span>"
|
|
. += "<span class='notice'>Power consumption at <b>[DisplayPower(active_power_usage)]</b>.</span>"
|
|
|
|
/obj/machinery/power/emitter/ComponentInitialize()
|
|
. = ..()
|
|
AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated))
|
|
|
|
/obj/machinery/power/emitter/proc/can_be_rotated(mob/user,rotation_type)
|
|
if (anchored)
|
|
to_chat(user, "<span class='warning'>It is fastened to the floor!</span>")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/obj/machinery/power/emitter/should_have_node()
|
|
return welded
|
|
|
|
/obj/machinery/power/emitter/Destroy()
|
|
if(SSticker.IsRoundInProgress())
|
|
var/turf/T = get_turf(src)
|
|
message_admins("Emitter deleted at [ADMIN_VERBOSEJMP(T)]")
|
|
log_game("Emitter deleted at [AREACOORD(T)]")
|
|
investigate_log("<font color='red'>deleted</font> at [AREACOORD(T)]", INVESTIGATE_SINGULO)
|
|
QDEL_NULL(sparks)
|
|
return ..()
|
|
|
|
/obj/machinery/power/emitter/update_icon_state()
|
|
if(active && powernet)
|
|
icon_state = avail(active_power_usage) ? icon_state_on : icon_state_underpowered
|
|
else
|
|
icon_state = initial(icon_state)
|
|
|
|
/obj/machinery/power/emitter/interact(mob/user)
|
|
add_fingerprint(user)
|
|
if(welded)
|
|
if(!powernet)
|
|
to_chat(user, "<span class='warning'>\The [src] isn't connected to a wire!</span>")
|
|
return TRUE
|
|
if(!locked && allow_switch_interact)
|
|
if(active == TRUE)
|
|
active = FALSE
|
|
to_chat(user, "<span class='notice'>You turn off [src].</span>")
|
|
else
|
|
active = TRUE
|
|
to_chat(user, "<span class='notice'>You turn on [src].</span>")
|
|
shot_number = 0
|
|
fire_delay = maximum_fire_delay
|
|
|
|
message_admins("Emitter turned [active ? "ON" : "OFF"] by [ADMIN_LOOKUPFLW(user)] in [ADMIN_VERBOSEJMP(src)]")
|
|
log_game("Emitter turned [active ? "ON" : "OFF"] by [key_name(user)] in [AREACOORD(src)]")
|
|
investigate_log("turned [active ? "<font color='green'>ON</font>" : "<font color='red'>OFF</font>"] by [key_name(user)] at [AREACOORD(src)]", INVESTIGATE_SINGULO)
|
|
|
|
update_icon()
|
|
|
|
else
|
|
to_chat(user, "<span class='warning'>The controls are locked!</span>")
|
|
else
|
|
to_chat(user, "<span class='warning'>[src] needs to be firmly secured to the floor first!</span>")
|
|
return TRUE
|
|
|
|
/obj/machinery/power/emitter/attack_animal(mob/living/simple_animal/M)
|
|
if(ismegafauna(M) && anchored)
|
|
set_anchored(FALSE)
|
|
M.visible_message("<span class='warning'>[M] rips [src] free from its moorings!</span>")
|
|
else
|
|
. = ..()
|
|
if(. && !anchored)
|
|
step(src, get_dir(M, src))
|
|
|
|
/obj/machinery/power/emitter/process(delta_time)
|
|
if(machine_stat & (BROKEN))
|
|
return
|
|
if(!welded || (!powernet && active_power_usage))
|
|
active = FALSE
|
|
update_icon()
|
|
return
|
|
if(active == TRUE)
|
|
if(!active_power_usage || surplus() >= active_power_usage)
|
|
add_load(active_power_usage)
|
|
if(!powered)
|
|
powered = TRUE
|
|
update_icon()
|
|
investigate_log("regained power and turned <font color='green'>ON</font> at [AREACOORD(src)]", INVESTIGATE_SINGULO)
|
|
else
|
|
if(powered)
|
|
powered = FALSE
|
|
update_icon()
|
|
investigate_log("lost power and turned <font color='red'>OFF</font> at [AREACOORD(src)]", INVESTIGATE_SINGULO)
|
|
log_game("Emitter lost power in [AREACOORD(src)]")
|
|
return
|
|
if(charge <= 80)
|
|
charge += 2.5 * delta_time
|
|
if(!check_delay() || manual == TRUE)
|
|
return FALSE
|
|
fire_beam()
|
|
|
|
/obj/machinery/power/emitter/proc/check_delay()
|
|
if((src.last_shot + src.fire_delay) <= world.time)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/machinery/power/emitter/proc/fire_beam_pulse()
|
|
if(!check_delay())
|
|
return FALSE
|
|
if(!welded)
|
|
return FALSE
|
|
if(surplus() >= active_power_usage)
|
|
add_load(active_power_usage)
|
|
fire_beam()
|
|
|
|
/obj/machinery/power/emitter/proc/fire_beam(mob/user)
|
|
var/obj/projectile/P = new projectile_type(get_turf(src))
|
|
playsound(src, projectile_sound, 50, TRUE)
|
|
if(prob(35))
|
|
sparks.start()
|
|
P.firer = user ? user : src
|
|
P.fired_from = src
|
|
if(last_projectile_params)
|
|
P.p_x = last_projectile_params[2]
|
|
P.p_y = last_projectile_params[3]
|
|
P.fire(last_projectile_params[1])
|
|
else
|
|
P.fire(dir2angle(dir))
|
|
if(!manual)
|
|
last_shot = world.time
|
|
if(shot_number < 3)
|
|
fire_delay = 20
|
|
shot_number ++
|
|
else
|
|
fire_delay = rand(minimum_fire_delay,maximum_fire_delay)
|
|
shot_number = 0
|
|
return P
|
|
|
|
/obj/machinery/power/emitter/can_be_unfasten_wrench(mob/user, silent)
|
|
if(active)
|
|
if(!silent)
|
|
to_chat(user, "<span class='warning'>Turn \the [src] off first!</span>")
|
|
return FAILED_UNFASTEN
|
|
|
|
else if(welded)
|
|
if(!silent)
|
|
to_chat(user, "<span class='warning'>[src] is welded to the floor!</span>")
|
|
return FAILED_UNFASTEN
|
|
|
|
return ..()
|
|
|
|
/obj/machinery/power/emitter/wrench_act(mob/living/user, obj/item/I)
|
|
..()
|
|
default_unfasten_wrench(user, I)
|
|
return TRUE
|
|
|
|
/obj/machinery/power/emitter/welder_act(mob/living/user, obj/item/I)
|
|
..()
|
|
if(active)
|
|
to_chat(user, "<span class='warning'>Turn [src] off first!</span>")
|
|
return TRUE
|
|
|
|
if(welded)
|
|
if(!I.tool_start_check(user, amount=0))
|
|
return TRUE
|
|
user.visible_message("<span class='notice'>[user.name] starts to cut the [name] free from the floor.</span>", \
|
|
"<span class='notice'>You start to cut [src] free from the floor...</span>", \
|
|
"<span class='hear'>You hear welding.</span>")
|
|
if(I.use_tool(src, user, 20, volume=50) && welded)
|
|
welded = FALSE
|
|
to_chat(user, "<span class='notice'>You cut [src] free from the floor.</span>")
|
|
disconnect_from_network()
|
|
update_cable_icons_on_turf(get_turf(src))
|
|
|
|
else if(anchored)
|
|
if(!I.tool_start_check(user, amount=0))
|
|
return TRUE
|
|
user.visible_message("<span class='notice'>[user.name] starts to weld the [name] to the floor.</span>", \
|
|
"<span class='notice'>You start to weld [src] to the floor...</span>", \
|
|
"<span class='hear'>You hear welding.</span>")
|
|
if(I.use_tool(src, user, 20, volume=50) && anchored)
|
|
welded = TRUE
|
|
to_chat(user, "<span class='notice'>You weld [src] to the floor.</span>")
|
|
connect_to_network()
|
|
update_cable_icons_on_turf(get_turf(src))
|
|
|
|
else
|
|
to_chat(user, "<span class='warning'>[src] needs to be wrenched to the floor!</span>")
|
|
|
|
return TRUE
|
|
|
|
/obj/machinery/power/emitter/crowbar_act(mob/living/user, obj/item/I)
|
|
if(panel_open && gun)
|
|
return remove_gun(user)
|
|
default_deconstruction_crowbar(I)
|
|
return TRUE
|
|
|
|
/obj/machinery/power/emitter/screwdriver_act(mob/living/user, obj/item/I)
|
|
if(..())
|
|
return TRUE
|
|
default_deconstruction_screwdriver(user, "emitter_open", "emitter", I)
|
|
return TRUE
|
|
|
|
|
|
/obj/machinery/power/emitter/attackby(obj/item/I, mob/user, params)
|
|
if(I.GetID())
|
|
if(obj_flags & EMAGGED)
|
|
to_chat(user, "<span class='warning'>The lock seems to be broken!</span>")
|
|
return
|
|
if(allowed(user))
|
|
if(active)
|
|
locked = !locked
|
|
to_chat(user, "<span class='notice'>You [src.locked ? "lock" : "unlock"] the controls.</span>")
|
|
else
|
|
to_chat(user, "<span class='warning'>The controls can only be locked when \the [src] is online!</span>")
|
|
else
|
|
to_chat(user, "<span class='danger'>Access denied.</span>")
|
|
return
|
|
|
|
else if(is_wire_tool(I) && panel_open)
|
|
wires.interact(user)
|
|
return
|
|
else if(panel_open && !gun && istype(I,/obj/item/gun/energy))
|
|
if(integrate(I,user))
|
|
return
|
|
return ..()
|
|
|
|
/obj/machinery/power/emitter/proc/integrate(obj/item/gun/energy/E,mob/user)
|
|
if(istype(E, /obj/item/gun/energy))
|
|
if(!user.transferItemToLoc(E, src))
|
|
return
|
|
gun = E
|
|
gun_properties = gun.get_turret_properties()
|
|
set_projectile()
|
|
return TRUE
|
|
|
|
/obj/machinery/power/emitter/proc/remove_gun(mob/user)
|
|
if(!gun)
|
|
return
|
|
user.put_in_hands(gun)
|
|
gun = null
|
|
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
gun_properties = list()
|
|
set_projectile()
|
|
return TRUE
|
|
|
|
/obj/machinery/power/emitter/proc/set_projectile()
|
|
if(LAZYLEN(gun_properties))
|
|
if(mode || !gun_properties["lethal_projectile"])
|
|
projectile_type = gun_properties["stun_projectile"]
|
|
projectile_sound = gun_properties["stun_projectile_sound"]
|
|
else
|
|
projectile_type = gun_properties["lethal_projectile"]
|
|
projectile_sound = gun_properties["lethal_projectile_sound"]
|
|
return
|
|
projectile_type = initial(projectile_type)
|
|
projectile_sound = initial(projectile_sound)
|
|
|
|
/obj/machinery/power/emitter/emag_act(mob/user)
|
|
if(obj_flags & EMAGGED)
|
|
return
|
|
locked = FALSE
|
|
obj_flags |= EMAGGED
|
|
if(user)
|
|
user.visible_message("<span class='warning'>[user.name] emags [src].</span>", "<span class='notice'>You short out the lock.</span>")
|
|
|
|
|
|
/obj/machinery/power/emitter/prototype
|
|
name = "Prototype Emitter"
|
|
icon = 'icons/obj/turrets.dmi'
|
|
icon_state = "protoemitter"
|
|
icon_state_on = "protoemitter_+a"
|
|
icon_state_underpowered = "protoemitter_+u"
|
|
can_buckle = TRUE
|
|
buckle_lying = 0
|
|
var/view_range = 4.5
|
|
var/datum/action/innate/protoemitter/firing/auto
|
|
|
|
//BUCKLE HOOKS
|
|
|
|
/obj/machinery/power/emitter/prototype/unbuckle_mob(mob/living/buckled_mob,force = 0)
|
|
playsound(src,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
|
manual = FALSE
|
|
for(var/obj/item/I in buckled_mob.held_items)
|
|
if(istype(I, /obj/item/turret_control))
|
|
qdel(I)
|
|
if(istype(buckled_mob))
|
|
buckled_mob.pixel_x = buckled_mob.base_pixel_x
|
|
buckled_mob.pixel_y = buckled_mob.base_pixel_y
|
|
if(buckled_mob.client)
|
|
buckled_mob.client.view_size.resetToDefault()
|
|
auto.Remove(buckled_mob)
|
|
. = ..()
|
|
|
|
/obj/machinery/power/emitter/prototype/user_buckle_mob(mob/living/M, mob/living/carbon/user)
|
|
if(user.incapacitated() || !istype(user))
|
|
return
|
|
for(var/atom/movable/A in get_turf(src))
|
|
if(A.density && (A != src && A != M))
|
|
return
|
|
M.forceMove(get_turf(src))
|
|
..()
|
|
playsound(src,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
|
M.pixel_y = 14
|
|
layer = 4.1
|
|
if(M.client)
|
|
M.client.view_size.setTo(view_range)
|
|
if(!auto)
|
|
auto = new()
|
|
auto.Grant(M, src)
|
|
|
|
/datum/action/innate/protoemitter
|
|
check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS
|
|
var/obj/machinery/power/emitter/prototype/PE
|
|
var/mob/living/carbon/U
|
|
|
|
|
|
/datum/action/innate/protoemitter/Grant(mob/living/carbon/L, obj/machinery/power/emitter/prototype/proto)
|
|
PE = proto
|
|
U = L
|
|
. = ..()
|
|
|
|
/datum/action/innate/protoemitter/firing
|
|
name = "Switch to Manual Firing"
|
|
desc = "The emitter will only fire on your command and at your designated target"
|
|
button_icon_state = "mech_zoom_on"
|
|
|
|
/datum/action/innate/protoemitter/firing/Activate()
|
|
if(PE.manual)
|
|
playsound(PE,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
|
PE.manual = FALSE
|
|
name = "Switch to Manual Firing"
|
|
desc = "The emitter will only fire on your command and at your designated target"
|
|
button_icon_state = "mech_zoom_on"
|
|
for(var/obj/item/I in U.held_items)
|
|
if(istype(I, /obj/item/turret_control))
|
|
qdel(I)
|
|
UpdateButtonIcon()
|
|
return
|
|
else
|
|
playsound(PE,'sound/mecha/mechmove01.ogg', 50, TRUE)
|
|
name = "Switch to Automatic Firing"
|
|
desc = "Emitters will switch to periodic firing at your last target"
|
|
button_icon_state = "mech_zoom_off"
|
|
PE.manual = TRUE
|
|
for(var/V in U.held_items)
|
|
var/obj/item/I = V
|
|
if(istype(I))
|
|
if(U.dropItemToGround(I))
|
|
var/obj/item/turret_control/TC = new /obj/item/turret_control()
|
|
U.put_in_hands(TC)
|
|
else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand
|
|
var/obj/item/turret_control/TC = new /obj/item/turret_control()
|
|
U.put_in_hands(TC)
|
|
UpdateButtonIcon()
|
|
|
|
|
|
/obj/item/turret_control
|
|
name = "turret controls"
|
|
icon_state = "offhand"
|
|
w_class = WEIGHT_CLASS_HUGE
|
|
item_flags = ABSTRACT | NOBLUDGEON
|
|
resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
|
var/delay = 0
|
|
|
|
/obj/item/turret_control/Initialize()
|
|
. = ..()
|
|
ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT)
|
|
|
|
/obj/item/turret_control/afterattack(atom/targeted_atom, mob/user, proxflag, clickparams)
|
|
. = ..()
|
|
var/obj/machinery/power/emitter/E = user.buckled
|
|
E.setDir(get_dir(E,targeted_atom))
|
|
user.setDir(E.dir)
|
|
switch(E.dir)
|
|
if(NORTH)
|
|
E.layer = 3.9
|
|
user.pixel_x = 0
|
|
user.pixel_y = -14
|
|
if(NORTHEAST)
|
|
E.layer = 3.9
|
|
user.pixel_x = -8
|
|
user.pixel_y = -12
|
|
if(EAST)
|
|
E.layer = 4.1
|
|
user.pixel_x = -14
|
|
user.pixel_y = 0
|
|
if(SOUTHEAST)
|
|
E.layer = 3.9
|
|
user.pixel_x = -8
|
|
user.pixel_y = 12
|
|
if(SOUTH)
|
|
E.layer = 4.1
|
|
user.pixel_x = 0
|
|
user.pixel_y = 14
|
|
if(SOUTHWEST)
|
|
E.layer = 3.9
|
|
user.pixel_x = 8
|
|
user.pixel_y = 12
|
|
if(WEST)
|
|
E.layer = 4.1
|
|
user.pixel_x = 14
|
|
user.pixel_y = 0
|
|
if(NORTHWEST)
|
|
E.layer = 3.9
|
|
user.pixel_x = 8
|
|
user.pixel_y = -12
|
|
|
|
E.last_projectile_params = calculate_projectile_angle_and_pixel_offsets(user, clickparams)
|
|
|
|
if(E.charge >= 10 && world.time > delay)
|
|
E.charge -= 10
|
|
E.fire_beam(user)
|
|
delay = world.time + 10
|
|
else if (E.charge < 10)
|
|
playsound(src,'sound/machines/buzz-sigh.ogg', 50, TRUE)
|
|
|