Merge branch 'master' into upstream-merge-37476
# Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty message aborts # the commit.
This commit is contained in:
@@ -95,7 +95,7 @@
|
||||
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Jump To Key") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/Getmob(mob/M in GLOB.mob_list)
|
||||
/client/proc/Getmob(mob/M in GLOB.mob_list - GLOB.dummy_mob_list)
|
||||
set category = "Admin"
|
||||
set name = "Get Mob"
|
||||
set desc = "Mob to teleport"
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
if(isnewplayer(M))
|
||||
continue
|
||||
if (M.stat == DEAD || (M.client && M.client.holder && (M.client.prefs.chat_toggles & CHAT_DEAD))) //admins can toggle deadchat on and off. This is a proc in admin.dm and is only give to Administrators and above
|
||||
M.show_message(rendered, 2)
|
||||
to_chat(M, rendered)
|
||||
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Dsay") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
|
||||
@@ -151,6 +151,7 @@
|
||||
desc = "You get the feeling that you shouldn't be standing here."
|
||||
clockwork_desc = "A sigil that will soon erupt and smite any unenlightened nearby."
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = ""
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
@@ -33,10 +33,8 @@
|
||||
desc = "A sword humming with unholy energy. It glows with a dim red light."
|
||||
icon_state = "cultblade"
|
||||
item_state = "cultblade"
|
||||
lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/64x64_righthand.dmi'
|
||||
inhand_x_dimension = 64
|
||||
inhand_y_dimension = 64
|
||||
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
|
||||
flags_1 = CONDUCT_1
|
||||
sharpness = IS_SHARP
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
@@ -708,6 +708,11 @@ structure_check() searches for nearby cultist structures required for the invoca
|
||||
fail_invoke()
|
||||
log_game("Summon Cultist rune failed - target died")
|
||||
return
|
||||
if(cultist_to_summon.pulledby || cultist_to_summon.buckled)
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_summon] is being held in place!</span>")
|
||||
fail_invoke()
|
||||
log_game("Summon Cultist rune failed - target restrained")
|
||||
return
|
||||
if(!iscultist(cultist_to_summon))
|
||||
to_chat(user, "<span class='cult italic'>[cultist_to_summon] is not a follower of the Geometer!</span>")
|
||||
fail_invoke()
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/morph/AttackingTarget()
|
||||
if(!melee_damage_disguised)
|
||||
if(morphed && !melee_damage_disguised)
|
||||
to_chat(src, "<span class='warning'>You can not attack while disguised!</span>")
|
||||
return
|
||||
if(isliving(target)) //Eat Corpses to regen health
|
||||
|
||||
@@ -501,16 +501,37 @@ This is here to make the tiles around the station mininuke change when it's arme
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/fake = FALSE
|
||||
var/turf/lastlocation
|
||||
var/last_disk_move
|
||||
|
||||
/obj/item/disk/nuclear/Initialize()
|
||||
. = ..()
|
||||
if(!fake)
|
||||
GLOB.poi_list |= src
|
||||
last_disk_move = world.time
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/disk/nuclear/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/stationloving, !fake)
|
||||
|
||||
/obj/item/disk/nuclear/process()
|
||||
if(fake)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
CRASH("A fake nuke disk tried to call process(). Who the fuck and how the fuck")
|
||||
var/turf/newturf = get_turf(src)
|
||||
if(newturf && lastlocation == newturf)
|
||||
if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.00001))
|
||||
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control
|
||||
if(istype(loneop))
|
||||
loneop.weight += 1
|
||||
else
|
||||
lastlocation = newturf
|
||||
last_disk_move = world.time
|
||||
var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control
|
||||
if(istype(loneop) && prob(loneop.weight))
|
||||
loneop.weight = max(loneop.weight - 1, 0)
|
||||
|
||||
/obj/item/disk/nuclear/examine(mob/user)
|
||||
. = ..()
|
||||
if(!fake)
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
name = "pile of viscera"
|
||||
desc = "A repulsive pile of guts and gore."
|
||||
gender = NEUTER
|
||||
random_icon_states = list("innards")
|
||||
icon_state = "innards"
|
||||
|
||||
/mob/living/simple_animal/slaughter/phasein()
|
||||
. = ..()
|
||||
|
||||
@@ -493,10 +493,10 @@
|
||||
D.pixel_z = target.pixel_z
|
||||
if(do_mob(src, target, 100))
|
||||
to_chat(src, "<span class='info'>Dismantling complete.</span>")
|
||||
var/obj/item/stack/sheet/metal/M = new /obj/item/stack/sheet/metal(target.loc)
|
||||
M.amount = 5
|
||||
var/atom/Tsec = target.drop_location()
|
||||
new /obj/item/stack/sheet/metal(Tsec, 5)
|
||||
for(var/obj/item/I in target.component_parts)
|
||||
I.forceMove(M.drop_location())
|
||||
I.forceMove(Tsec)
|
||||
var/obj/effect/temp_visual/swarmer/disintegration/N = new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
|
||||
N.pixel_x = target.pixel_x
|
||||
N.pixel_y = target.pixel_y
|
||||
@@ -505,7 +505,7 @@
|
||||
if(istype(target, /obj/machinery/computer))
|
||||
var/obj/machinery/computer/C = target
|
||||
if(C.circuit)
|
||||
C.circuit.forceMove(M.drop_location())
|
||||
C.circuit.forceMove(Tsec)
|
||||
qdel(target)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#define WIRE_PULSE_SPECIAL (1<<2)
|
||||
#define WIRE_RADIO_RECEIVE (1<<3)
|
||||
#define WIRE_RADIO_PULSE (1<<4)
|
||||
#define ASSEMBLY_BEEP_VOLUME 5
|
||||
|
||||
/obj/item/assembly
|
||||
name = "assembly"
|
||||
@@ -16,6 +17,8 @@
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
|
||||
var/is_position_sensitive = FALSE //set to true if the device has different icons for each position.
|
||||
//This will prevent things such as visible lasers from facing the incorrect direction when transformed by assembly_holder's update_icon()
|
||||
var/secured = TRUE
|
||||
var/list/attached_overlays = null
|
||||
var/obj/item/assembly_holder/holder = null
|
||||
@@ -30,14 +33,18 @@
|
||||
|
||||
/obj/item/assembly/proc/on_attach()
|
||||
|
||||
/obj/item/assembly/proc/on_detach()
|
||||
/obj/item/assembly/proc/on_detach() //call this when detaching it from a device. handles any special functions that need to be updated ex post facto
|
||||
if(!holder)
|
||||
return FALSE
|
||||
forceMove(holder.drop_location())
|
||||
holder = null
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/proc/holder_movement() //Called when the holder is moved
|
||||
return
|
||||
|
||||
/obj/item/assembly/proc/describe() // Called by grenades to describe the state of the trigger (time left, etc)
|
||||
return "The trigger assembly looks broken!"
|
||||
|
||||
if(!holder)
|
||||
return FALSE
|
||||
setDir(holder.dir)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/proc/is_secured(mob/user)
|
||||
if(!secured)
|
||||
@@ -47,7 +54,7 @@
|
||||
|
||||
|
||||
//Called when another assembly acts on this one, var/radio will determine where it came from for wire calcs
|
||||
/obj/item/assembly/proc/pulsed(radio = 0)
|
||||
/obj/item/assembly/proc/pulsed(radio = FALSE)
|
||||
if(wire_type & WIRE_RECEIVE)
|
||||
INVOKE_ASYNC(src, .proc/activate)
|
||||
if(radio && (wire_type & WIRE_RADIO_RECEIVE))
|
||||
@@ -56,7 +63,7 @@
|
||||
|
||||
|
||||
//Called when this device attempts to act on another device, var/radio determines if it was sent via radio or direct
|
||||
/obj/item/assembly/proc/pulse(radio = 0)
|
||||
/obj/item/assembly/proc/pulse(radio = FALSE)
|
||||
if(connected && wire_type)
|
||||
connected.pulse_assembly(src)
|
||||
return TRUE
|
||||
@@ -91,21 +98,19 @@
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Both devices must be in attachable mode to be attached together.</span>")
|
||||
return
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
if(toggle_secure())
|
||||
to_chat(user, "<span class='notice'>\The [src] is ready!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] can now be attached!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/assembly/screwdriver_act(mob/living/user, obj/item/I)
|
||||
if(toggle_secure())
|
||||
to_chat(user, "<span class='notice'>\The [src] is ready!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>\The [src] can now be attached!</span>")
|
||||
add_fingerprint(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/examine(mob/user)
|
||||
..()
|
||||
if(secured)
|
||||
to_chat(user, "\The [src] is secured and ready to be used.")
|
||||
else
|
||||
to_chat(user, "\The [src] can be attached to other things.")
|
||||
to_chat(user, "<span class='notice'>\The [src] [secured? "is secured and ready to be used!" : "can be attached to other things."]</span>")
|
||||
|
||||
|
||||
/obj/item/assembly/attack_self(mob/user)
|
||||
|
||||
@@ -13,11 +13,14 @@
|
||||
var/obj/item/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device
|
||||
var/obj/item/tank/bombtank = null //the second part of the bomb is a plasma tank
|
||||
|
||||
/obj/item/onetankbomb/IsSpecialAssembly()
|
||||
return TRUE
|
||||
|
||||
/obj/item/onetankbomb/examine(mob/user)
|
||||
bombtank.examine(user)
|
||||
|
||||
/obj/item/onetankbomb/update_icon()
|
||||
cut_overlays()
|
||||
if(bombtank)
|
||||
icon = bombtank.icon
|
||||
icon_state = bombtank.icon_state
|
||||
@@ -30,29 +33,37 @@
|
||||
if(istype(W, /obj/item/analyzer))
|
||||
bombtank.attackby(W, user)
|
||||
return
|
||||
if(istype(W, /obj/item/wrench) && !status) //This is basically bomb assembly code inverted. apparently it works.
|
||||
|
||||
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
|
||||
add_fingerprint(user)
|
||||
..()
|
||||
|
||||
/obj/item/onetankbomb/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
|
||||
if(bombassembly)
|
||||
bombassembly.forceMove(drop_location())
|
||||
bombassembly.master = null
|
||||
bombassembly = null
|
||||
|
||||
if(bombtank)
|
||||
bombtank.forceMove(drop_location())
|
||||
bombtank.master = null
|
||||
bombtank = null
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
qdel(src)
|
||||
/obj/item/onetankbomb/welder_act(mob/living/user, obj/item/I)
|
||||
. = FALSE
|
||||
if(status)
|
||||
to_chat(user, "<span class='notice'>[bombtank] already has a pressure hole!</span>")
|
||||
return
|
||||
var/obj/item/weldingtool/WT = W
|
||||
if((istype(WT) && WT.welding))
|
||||
if(!status)
|
||||
status = TRUE
|
||||
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
|
||||
message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
|
||||
add_fingerprint(user)
|
||||
..()
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return
|
||||
if(I.use_tool(src, user, 0, volume=40))
|
||||
status = TRUE
|
||||
GLOB.bombers += "[key_name(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]"
|
||||
message_admins("[key_name_admin(user)] welded a single tank bomb. Temp: [bombtank.air_contents.temperature-T0C]")
|
||||
to_chat(user, "<span class='notice'>A pressure hole has been bored to [bombtank] valve. \The [bombtank] can now be ignited.</span>")
|
||||
add_fingerprint(user)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
|
||||
bombassembly.attack_self(user, TRUE)
|
||||
@@ -60,16 +71,20 @@
|
||||
return
|
||||
|
||||
/obj/item/onetankbomb/receive_signal() //This is mainly called by the sensor through sense() to the holder, and from the holder to here.
|
||||
visible_message("[icon2html(src, viewers(src))] *beep* *beep*", "*beep* *beep*")
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
|
||||
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
sleep(10)
|
||||
if(!src)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(status)
|
||||
bombtank.ignite() //if its not a dud, boom (or not boom if you made shitty mix) the ignite proc is below, in this file
|
||||
else
|
||||
bombtank.release()
|
||||
|
||||
//Assembly / attached device memes
|
||||
|
||||
/obj/item/onetankbomb/Crossed(atom/movable/AM as mob|obj) //for mousetraps
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.Crossed(AM)
|
||||
|
||||
@@ -77,6 +92,26 @@
|
||||
if(bombassembly)
|
||||
bombassembly.on_found(finder)
|
||||
|
||||
/obj/item/onetankbomb/attack_hand() //also for mousetraps
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(bombassembly)
|
||||
bombassembly.attack_hand()
|
||||
|
||||
/obj/item/onetankbomb/Move()
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.setDir(dir)
|
||||
bombassembly.Move()
|
||||
|
||||
/obj/item/onetankbomb/dropped()
|
||||
. = ..()
|
||||
if(bombassembly)
|
||||
bombassembly.dropped()
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ----------
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
name = "blast door controller"
|
||||
desc = "A small electronic device able to control a blast door remotely."
|
||||
icon_state = "control"
|
||||
attachable = 1
|
||||
attachable = TRUE
|
||||
var/id = null
|
||||
var/can_change_id = 0
|
||||
var/cooldown = 0//Door cooldowns
|
||||
var/cooldown = FALSE //Door cooldowns
|
||||
|
||||
/obj/item/assembly/control/examine(mob/user)
|
||||
..()
|
||||
@@ -13,15 +13,14 @@
|
||||
to_chat(user, "<span class='notice'>Its channel ID is '[id]'.</span>")
|
||||
|
||||
/obj/item/assembly/control/activate()
|
||||
cooldown = 1
|
||||
cooldown = TRUE
|
||||
var/openclose
|
||||
for(var/obj/machinery/door/poddoor/M in GLOB.machines)
|
||||
if(M.id == src.id)
|
||||
if(openclose == null)
|
||||
openclose = M.density
|
||||
INVOKE_ASYNC(M, openclose ? /obj/machinery/door/poddoor.proc/open : /obj/machinery/door/poddoor.proc/close)
|
||||
sleep(10)
|
||||
cooldown = 0
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
|
||||
|
||||
|
||||
/obj/item/assembly/control/airlock
|
||||
@@ -38,7 +37,7 @@
|
||||
*/
|
||||
|
||||
/obj/item/assembly/control/airlock/activate()
|
||||
cooldown = 1
|
||||
cooldown = TRUE
|
||||
var/doors_need_closing = FALSE
|
||||
var/list/obj/machinery/door/airlock/open_or_close = list()
|
||||
for(var/obj/machinery/door/airlock/D in GLOB.airlocks)
|
||||
@@ -66,8 +65,7 @@
|
||||
for(var/D in open_or_close)
|
||||
INVOKE_ASYNC(D, doors_need_closing ? /obj/machinery/door/airlock.proc/close : /obj/machinery/door/airlock.proc/open)
|
||||
|
||||
sleep(10)
|
||||
cooldown = 0
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
|
||||
|
||||
|
||||
/obj/item/assembly/control/massdriver
|
||||
@@ -75,7 +73,7 @@
|
||||
desc = "A small electronic device able to control a mass driver."
|
||||
|
||||
/obj/item/assembly/control/massdriver/activate()
|
||||
cooldown = 1
|
||||
cooldown = TRUE
|
||||
for(var/obj/machinery/door/poddoor/M in GLOB.machines)
|
||||
if (M.id == src.id)
|
||||
INVOKE_ASYNC(M, /obj/machinery/door/poddoor.proc/open)
|
||||
@@ -92,8 +90,7 @@
|
||||
if (M.id == src.id)
|
||||
INVOKE_ASYNC(M, /obj/machinery/door/poddoor.proc/close)
|
||||
|
||||
sleep(10)
|
||||
cooldown = 0
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 10)
|
||||
|
||||
|
||||
/obj/item/assembly/control/igniter
|
||||
@@ -101,7 +98,7 @@
|
||||
desc = "A remote controller for a mounted igniter."
|
||||
|
||||
/obj/item/assembly/control/igniter/activate()
|
||||
cooldown = 1
|
||||
cooldown = TRUE
|
||||
for(var/obj/machinery/sparker/M in GLOB.machines)
|
||||
if (M.id == src.id)
|
||||
INVOKE_ASYNC(M, /obj/machinery/sparker.proc/ignite)
|
||||
@@ -112,22 +109,19 @@
|
||||
M.on = !M.on
|
||||
M.icon_state = "igniter[M.on]"
|
||||
|
||||
sleep(30)
|
||||
cooldown = 0
|
||||
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 30)
|
||||
|
||||
/obj/item/assembly/control/flasher
|
||||
name = "flasher controller"
|
||||
desc = "A remote controller for a mounted flasher."
|
||||
|
||||
/obj/item/assembly/control/flasher/activate()
|
||||
cooldown = 1
|
||||
cooldown = TRUE
|
||||
for(var/obj/machinery/flasher/M in GLOB.machines)
|
||||
if(M.id == src.id)
|
||||
INVOKE_ASYNC(M, /obj/machinery/flasher.proc/flash)
|
||||
|
||||
sleep(50)
|
||||
cooldown = 0
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
|
||||
|
||||
|
||||
/obj/item/assembly/control/crematorium
|
||||
@@ -135,10 +129,9 @@
|
||||
desc = "An evil-looking remote controller for a crematorium."
|
||||
|
||||
/obj/item/assembly/control/crematorium/activate()
|
||||
cooldown = 1
|
||||
cooldown = TRUE
|
||||
for (var/obj/structure/bodycontainer/crematorium/C in GLOB.crematoriums)
|
||||
if (C.id == id)
|
||||
C.cremate(usr)
|
||||
|
||||
sleep(50)
|
||||
cooldown = 0
|
||||
addtimer(VARSET_CALLBACK(src, cooldown, FALSE), 50)
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
if(crit_fail || (world.time < last_trigger + cooldown))
|
||||
return FALSE
|
||||
last_trigger = world.time
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, TRUE)
|
||||
times_used++
|
||||
flash_recharge()
|
||||
update_icon(TRUE)
|
||||
@@ -195,6 +195,8 @@
|
||||
|
||||
/obj/item/assembly/flash/cyborg/attackby(obj/item/W, mob/user, params)
|
||||
return
|
||||
/obj/item/assembly/flash/cyborg/screwdriver_act(mob/living/user, obj/item/I)
|
||||
return
|
||||
|
||||
/obj/item/assembly/flash/memorizer
|
||||
name = "memorizer"
|
||||
@@ -226,7 +228,7 @@
|
||||
return FALSE
|
||||
overheat = TRUE
|
||||
addtimer(CALLBACK(src, .proc/cooldown), flashcd)
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, 1)
|
||||
playsound(src, 'sound/weapons/flash.ogg', 100, TRUE)
|
||||
update_icon(1)
|
||||
return TRUE
|
||||
|
||||
@@ -272,7 +274,7 @@
|
||||
return
|
||||
crit_fail = FALSE
|
||||
times_used = 0
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
update_icon()
|
||||
flash.crit_fail = TRUE
|
||||
flash.update_icon()
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
desc = "Used for scanning and monitoring health."
|
||||
icon_state = "health"
|
||||
materials = list(MAT_METAL=800, MAT_GLASS=200)
|
||||
attachable = 1
|
||||
secured = 0
|
||||
attachable = TRUE
|
||||
secured = FALSE
|
||||
|
||||
var/scanning = 0
|
||||
var/scanning = FALSE
|
||||
var/health_scan
|
||||
var/alarm_health = 0
|
||||
|
||||
@@ -16,31 +16,28 @@
|
||||
|
||||
/obj/item/assembly/health/activate()
|
||||
if(!..())
|
||||
return 0//Cooldown check
|
||||
return FALSE//Cooldown check
|
||||
toggle_scan()
|
||||
return 0
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/health/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured && scanning)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
scanning = 0
|
||||
scanning = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
|
||||
/obj/item/assembly/health/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/multitool))
|
||||
if(alarm_health == 0)
|
||||
alarm_health = -90
|
||||
user.show_message("You toggle [src] to \"detect death\" mode.")
|
||||
else
|
||||
alarm_health = 0
|
||||
user.show_message("You toggle [src] to \"detect critical state\" mode.")
|
||||
return
|
||||
/obj/item/assembly/health/multitool_act(mob/living/user, obj/item/I)
|
||||
if(alarm_health == 0)
|
||||
alarm_health = -90
|
||||
to_chat(user, "<span class='notice'>You toggle [src] to \"detect death\" mode.</span>")
|
||||
else
|
||||
return ..()
|
||||
alarm_health = 0
|
||||
to_chat(user, "<span class='notice'>You toggle [src] to \"detect critical state\" mode.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/health/process()
|
||||
if(!scanning || !secured)
|
||||
@@ -58,7 +55,8 @@
|
||||
health_scan = M.health
|
||||
if(health_scan <= alarm_health)
|
||||
pulse()
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", "*beep* *beep*")
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
|
||||
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
toggle_scan()
|
||||
return
|
||||
return
|
||||
@@ -77,8 +75,9 @@
|
||||
. = ..()
|
||||
if(!secured)
|
||||
user.show_message("<span class='warning'>The [name] is unsecured!</span>")
|
||||
return 0
|
||||
var/dat = "<TT><B>Health Sensor</B> <A href='?src=[REF(src)];scanning=1'>[scanning?"On":"Off"]</A>"
|
||||
return FALSE
|
||||
var/dat = "<TT><B>Health Sensor</B></TT>"
|
||||
dat += "<BR><A href='?src=[REF(src)];scanning=1'>[scanning?"On":"Off"]</A>"
|
||||
if(scanning && health_scan)
|
||||
dat += "<BR>Health: [health_scan]"
|
||||
user << browse(dat, "window=hscan")
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
// See _DEFINES/is_helpers.dm for type helpers
|
||||
|
||||
/*
|
||||
Name: IsSpecialAssembly
|
||||
Desc: If true is an object that can be attached to an assembly holder but is a special thing like a plasma can or door
|
||||
*/
|
||||
|
||||
/obj/proc/IsSpecialAssembly()
|
||||
return 0
|
||||
|
||||
/*
|
||||
Name: IsAssemblyHolder
|
||||
Desc: If true is an object that can hold an assemblyholder object
|
||||
*/
|
||||
/obj/proc/IsAssemblyHolder()
|
||||
return 0
|
||||
// See _DEFINES/is_helpers.dm for type helpers
|
||||
|
||||
/*
|
||||
Name: IsSpecialAssembly
|
||||
Desc: If true is an object that can be attached to an assembly holder but is a special thing like a plasma can or door
|
||||
*/
|
||||
|
||||
/obj/proc/IsSpecialAssembly()
|
||||
return FALSE
|
||||
|
||||
/*
|
||||
Name: IsAssemblyHolder
|
||||
Desc: If true is an object that can hold an assemblyholder object
|
||||
*/
|
||||
/obj/proc/IsAssemblyHolder()
|
||||
return FALSE
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var/obj/item/assembly/a_right = null
|
||||
|
||||
/obj/item/assembly_holder/IsAssemblyHolder()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly_holder/proc/assemble(obj/item/assembly/A, obj/item/assembly/A2, mob/user)
|
||||
@@ -37,6 +37,7 @@
|
||||
a_left = A
|
||||
else
|
||||
a_right = A
|
||||
A.holder_movement()
|
||||
|
||||
/obj/item/assembly_holder/update_icon()
|
||||
cut_overlays()
|
||||
@@ -46,11 +47,16 @@
|
||||
add_overlay("[O]_l")
|
||||
|
||||
if(a_right)
|
||||
var/mutable_appearance/right = mutable_appearance(icon, "[a_right.icon_state]_left")
|
||||
right.transform = matrix(-1, 0, 0, 0, 1, 0)
|
||||
for(var/O in a_right.attached_overlays)
|
||||
right.add_overlay("[O]_l")
|
||||
add_overlay(right)
|
||||
if(a_right.is_position_sensitive)
|
||||
add_overlay("[a_right.icon_state]_right")
|
||||
for(var/O in a_right.attached_overlays)
|
||||
add_overlay("[O]_r")
|
||||
else
|
||||
var/mutable_appearance/right = mutable_appearance(icon, "[a_right.icon_state]_left")
|
||||
right.transform = matrix(-1, 0, 0, 0, 1, 0)
|
||||
for(var/O in a_right.attached_overlays)
|
||||
right.add_overlay("[O]_l")
|
||||
add_overlay(right)
|
||||
|
||||
if(master)
|
||||
master.update_icon()
|
||||
@@ -69,32 +75,37 @@
|
||||
|
||||
/obj/item/assembly_holder/Move()
|
||||
. = ..()
|
||||
if(a_left && a_right)
|
||||
if(a_left)
|
||||
a_left.holder_movement()
|
||||
if(a_right)
|
||||
a_right.holder_movement()
|
||||
|
||||
/obj/item/assembly_holder/dropped(mob/user)
|
||||
. = ..()
|
||||
if(a_left)
|
||||
a_left.dropped()
|
||||
if(a_right)
|
||||
a_right.dropped()
|
||||
|
||||
/obj/item/assembly_holder/attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(a_left && a_right)
|
||||
a_left.holder_movement()
|
||||
a_right.holder_movement()
|
||||
if(a_left)
|
||||
a_left.attack_hand()
|
||||
if(a_right)
|
||||
a_right.attack_hand()
|
||||
|
||||
/obj/item/assembly_holder/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/screwdriver))
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return 0
|
||||
if(a_left)
|
||||
a_left.holder = null
|
||||
a_left.forceMove(T)
|
||||
if(a_right)
|
||||
a_right.holder = null
|
||||
a_right.forceMove(T)
|
||||
qdel(src)
|
||||
else
|
||||
..()
|
||||
/obj/item/assembly_holder/screwdriver_act(mob/user, obj/item/tool)
|
||||
to_chat(user, "<span class='notice'>You disassemble [src]!</span>")
|
||||
if(a_left)
|
||||
a_left.on_detach()
|
||||
a_left = null
|
||||
if(a_right)
|
||||
a_right.on_detach()
|
||||
a_right = null
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly_holder/attack_self(mob/user)
|
||||
src.add_fingerprint(user)
|
||||
@@ -115,12 +126,12 @@
|
||||
|
||||
/obj/item/assembly_holder/proc/process_activation(obj/D, normal = 1, special = 1)
|
||||
if(!D)
|
||||
return 0
|
||||
return FALSE
|
||||
if((normal) && (a_right) && (a_left))
|
||||
if(a_right != D)
|
||||
a_right.pulsed(0)
|
||||
a_right.pulsed(FALSE)
|
||||
if(a_left != D)
|
||||
a_left.pulsed(0)
|
||||
a_left.pulsed(FALSE)
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
@@ -23,12 +23,12 @@
|
||||
|
||||
/obj/item/assembly/igniter/activate()
|
||||
if(!..())
|
||||
return 0//Cooldown check
|
||||
return FALSE//Cooldown check
|
||||
var/turf/location = get_turf(loc)
|
||||
if(location)
|
||||
location.hotspot_expose(1000,1000)
|
||||
sparks.start()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/igniter/attack_self(mob/user)
|
||||
activate()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "Emits a visible or invisible beam and is triggered when the beam is interrupted."
|
||||
icon_state = "infrared"
|
||||
materials = list(MAT_METAL=1000, MAT_GLASS=500)
|
||||
is_position_sensitive = TRUE
|
||||
|
||||
var/on = FALSE
|
||||
var/visible = FALSE
|
||||
@@ -10,6 +11,7 @@
|
||||
var/list/obj/effect/beam/i_beam/beams
|
||||
var/olddir = 0
|
||||
var/datum/component/redirect/listener
|
||||
var/hearing_range = 3
|
||||
|
||||
/obj/item/assembly/infra/Initialize()
|
||||
. = ..()
|
||||
@@ -30,23 +32,27 @@
|
||||
refreshBeam()
|
||||
|
||||
/obj/item/assembly/infra/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
QDEL_LIST(beams)
|
||||
return ..()
|
||||
. = ..()
|
||||
|
||||
/obj/item/assembly/infra/describe()
|
||||
return "The infrared trigger is [on?"on":"off"]."
|
||||
/obj/item/assembly/infra/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>The infrared trigger is [on?"on":"off"].</span>")
|
||||
|
||||
/obj/item/assembly/infra/activate()
|
||||
if(!..())
|
||||
return 0//Cooldown check
|
||||
return FALSE//Cooldown check
|
||||
on = !on
|
||||
refreshBeam()
|
||||
update_icon()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/infra/toggle_secure()
|
||||
secured = !secured
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
refreshBeam()
|
||||
else
|
||||
QDEL_LIST(beams)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
@@ -59,13 +65,20 @@
|
||||
if(on)
|
||||
add_overlay("infrared_on")
|
||||
attached_overlays += "infrared_on"
|
||||
if(visible && secured)
|
||||
add_overlay("infrared_visible")
|
||||
attached_overlays += "infrared_visible"
|
||||
|
||||
if(holder)
|
||||
holder.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/assembly/infra/dropped()
|
||||
refreshBeam()
|
||||
. = ..()
|
||||
if(holder)
|
||||
holder_movement() //sync the dir of the device as well if it's contained in a TTV or an assembly holder
|
||||
else
|
||||
refreshBeam()
|
||||
|
||||
/obj/item/assembly/infra/process()
|
||||
if(!on || !secured)
|
||||
@@ -74,7 +87,15 @@
|
||||
|
||||
/obj/item/assembly/infra/proc/refreshBeam()
|
||||
QDEL_LIST(beams)
|
||||
if(throwing || !on || !secured || !(isturf(loc) || holder && isturf(holder.loc)))
|
||||
if(throwing || !on || !secured)
|
||||
return
|
||||
if(holder)
|
||||
if(holder.master) //incase the sensor is part of an assembly that's contained in another item, such as a single tank bomb
|
||||
if(!holder.master.IsSpecialAssembly() || !isturf(holder.master.loc))
|
||||
return
|
||||
else if(!isturf(holder.loc)) //else just check where the holder is
|
||||
return
|
||||
else if(!isturf(loc)) //or just where the fuck we are in general
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/_dir = dir
|
||||
@@ -82,6 +103,11 @@
|
||||
if(_T)
|
||||
for(var/i in 1 to maxlength)
|
||||
var/obj/effect/beam/i_beam/I = new(T)
|
||||
if(istype(holder, /obj/item/assembly_holder))
|
||||
var/obj/item/assembly_holder/assembly_holder = holder
|
||||
I.icon_state = "[initial(I.icon_state)]_[(assembly_holder.a_left == src) ? "l":"r"]" //Sync the offset of the beam with the position of the sensor.
|
||||
else if(istype(holder, /obj/item/transfer_valve))
|
||||
I.icon_state = "[initial(I.icon_state)]_ttv"
|
||||
I.density = TRUE
|
||||
if(!I.Move(_T))
|
||||
qdel(I)
|
||||
@@ -96,6 +122,12 @@
|
||||
_T = get_step(_T, _dir)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/item/assembly/infra/on_detach()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
refreshBeam()
|
||||
|
||||
/obj/item/assembly/infra/attack_hand()
|
||||
. = ..()
|
||||
refreshBeam()
|
||||
@@ -116,19 +148,17 @@
|
||||
setDir(olddir)
|
||||
olddir = null
|
||||
|
||||
/obj/item/assembly/infra/holder_movement()
|
||||
if(!holder)
|
||||
return 0
|
||||
refreshBeam()
|
||||
return 1
|
||||
|
||||
/obj/item/assembly/infra/proc/trigger_beam(atom/movable/AM, turf/location)
|
||||
refreshBeam()
|
||||
switchListener(location)
|
||||
if(!secured || !on || next_activate > world.time)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
|
||||
pulse(FALSE)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
|
||||
for(var/CHM in get_hearers_in_view(hearing_range, src))
|
||||
if(ismob(CHM))
|
||||
var/mob/LM = CHM
|
||||
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
next_activate = world.time + 30
|
||||
|
||||
/obj/item/assembly/infra/proc/switchListener(turf/newloc)
|
||||
@@ -144,7 +174,9 @@
|
||||
. = ..()
|
||||
if(is_secured(user))
|
||||
user.set_machine(src)
|
||||
var/dat = "<TT><B>Infrared Laser</B>\n<B>Status</B>: [on ? "<A href='?src=[REF(src)];state=0'>On</A>" : "<A href='?src=[REF(src)];state=1'>Off</A>"]<BR>\n<B>Visibility</B>: [visible ? "<A href='?src=[REF(src)];visible=0'>Visible</A>" : "<A href='?src=[REF(src)];visible=1'>Invisible</A>"]<BR>\n</TT>"
|
||||
var/dat = "<TT><B>Infrared Laser</B></TT>"
|
||||
dat += "<BR><B>Status</B>: [on ? "<A href='?src=[REF(src)];state=0'>On</A>" : "<A href='?src=[REF(src)];state=1'>Off</A>"]"
|
||||
dat += "<BR><B>Visibility</B>: [visible ? "<A href='?src=[REF(src)];visible=0'>Visible</A>" : "<A href='?src=[REF(src)];visible=1'>Invisible</A>"]"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
|
||||
user << browse(dat, "window=infra")
|
||||
@@ -163,6 +195,7 @@
|
||||
refreshBeam()
|
||||
if(href_list["visible"])
|
||||
visible = !(visible)
|
||||
update_icon()
|
||||
refreshBeam()
|
||||
if(href_list["close"])
|
||||
usr << browse(null, "window=infra")
|
||||
|
||||
@@ -2,17 +2,15 @@
|
||||
name = "mousetrap"
|
||||
desc = "A handy little spring-loaded trap for catching pesty rodents."
|
||||
icon_state = "mousetrap"
|
||||
item_state = "mousetrap"
|
||||
materials = list(MAT_METAL=100)
|
||||
attachable = 1
|
||||
var/armed = 0
|
||||
attachable = TRUE
|
||||
var/armed = FALSE
|
||||
|
||||
|
||||
/obj/item/assembly/mousetrap/examine(mob/user)
|
||||
..()
|
||||
if(armed)
|
||||
to_chat(user, "The mousetrap is armed!")
|
||||
else
|
||||
to_chat(user, "The mousetrap is not armed.")
|
||||
to_chat(user, "<span class='notice'>The pressure plate is [armed?"primed":"safe"].</span>")
|
||||
|
||||
/obj/item/assembly/mousetrap/activate()
|
||||
if(..())
|
||||
@@ -22,13 +20,9 @@
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if((user.has_trait(TRAIT_DUMB) || user.has_trait(TRAIT_CLUMSY)) && prob(50))
|
||||
to_chat(user, "<span class='warning'>Your hand slips, setting off the trigger!</span>")
|
||||
pulse(0)
|
||||
pulse(FALSE)
|
||||
update_icon()
|
||||
if(usr)
|
||||
playsound(usr.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
|
||||
|
||||
/obj/item/assembly/mousetrap/describe()
|
||||
return "The pressure switch is [armed?"primed":"safe"]."
|
||||
playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3)
|
||||
|
||||
/obj/item/assembly/mousetrap/update_icon()
|
||||
if(armed)
|
||||
@@ -45,10 +39,10 @@
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(H.has_trait(TRAIT_PIERCEIMMUNE))
|
||||
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
|
||||
armed = FALSE
|
||||
update_icon()
|
||||
pulse(0)
|
||||
pulse(FALSE)
|
||||
return FALSE
|
||||
switch(type)
|
||||
if("feet")
|
||||
@@ -66,10 +60,10 @@
|
||||
var/mob/living/simple_animal/mouse/M = target
|
||||
visible_message("<span class='boldannounce'>SPLAT!</span>")
|
||||
M.splat()
|
||||
playsound(src.loc, 'sound/effects/snap.ogg', 50, 1)
|
||||
playsound(src, 'sound/effects/snap.ogg', 50, TRUE)
|
||||
armed = FALSE
|
||||
update_icon()
|
||||
pulse(0)
|
||||
pulse(FALSE)
|
||||
|
||||
|
||||
/obj/item/assembly/mousetrap/attack_self(mob/living/carbon/human/user)
|
||||
@@ -87,7 +81,7 @@
|
||||
to_chat(user, "<span class='notice'>You disarm [src].</span>")
|
||||
armed = !armed
|
||||
update_icon()
|
||||
playsound(user.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3)
|
||||
playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3)
|
||||
|
||||
|
||||
//ATTACK HAND IGNORING PARENT RETURN VALUE
|
||||
@@ -145,4 +139,4 @@
|
||||
|
||||
/obj/item/assembly/mousetrap/armed
|
||||
icon_state = "mousetraparmed"
|
||||
armed = 1
|
||||
armed = TRUE
|
||||
|
||||
@@ -3,34 +3,36 @@
|
||||
desc = "Used for scanning and alerting when someone enters a certain proximity."
|
||||
icon_state = "prox"
|
||||
materials = list(MAT_METAL=800, MAT_GLASS=200)
|
||||
attachable = 1
|
||||
attachable = TRUE
|
||||
|
||||
var/scanning = 0
|
||||
var/timing = 0
|
||||
var/scanning = FALSE
|
||||
var/timing = FALSE
|
||||
var/time = 10
|
||||
var/sensitivity = 1
|
||||
|
||||
/obj/item/assembly/prox_sensor/proc/toggle_scan()
|
||||
|
||||
|
||||
/obj/item/assembly/prox_sensor/proc/sense()
|
||||
|
||||
var/hearing_range = 3
|
||||
|
||||
/obj/item/assembly/prox_sensor/Initialize()
|
||||
. = ..()
|
||||
proximity_monitor = new(src, 0)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/assembly/prox_sensor/describe()
|
||||
if(timing)
|
||||
return "<span class='notice'>The proximity sensor is arming.</span>"
|
||||
return "The proximity sensor is [scanning?"armed":"disarmed"]."
|
||||
/obj/item/assembly/prox_sensor/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/assembly/prox_sensor/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>The proximity sensor is [timing ? "arming" : (scanning ? "armed" : "disarmed")].</span>")
|
||||
|
||||
/obj/item/assembly/prox_sensor/activate()
|
||||
if(!..())
|
||||
return 0//Cooldown check
|
||||
timing = !timing
|
||||
return FALSE//Cooldown check
|
||||
if(!scanning)
|
||||
timing = !timing
|
||||
else
|
||||
scanning = FALSE
|
||||
update_icon()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/prox_sensor/toggle_secure()
|
||||
secured = !secured
|
||||
@@ -38,8 +40,10 @@
|
||||
if(scanning)
|
||||
toggle_scan()
|
||||
proximity_monitor.host = src
|
||||
timing = 0
|
||||
timing = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
else
|
||||
START_PROCESSING(SSobj, src)
|
||||
proximity_monitor.host = loc
|
||||
update_icon()
|
||||
return secured
|
||||
@@ -51,25 +55,31 @@
|
||||
sense()
|
||||
|
||||
|
||||
/obj/item/assembly/prox_sensor/sense()
|
||||
/obj/item/assembly/prox_sensor/proc/sense()
|
||||
if(!scanning || !secured || next_activate > world.time)
|
||||
return 0
|
||||
pulse(0)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
|
||||
return FALSE
|
||||
pulse(FALSE)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
|
||||
for(var/CHM in get_hearers_in_view(hearing_range, src))
|
||||
if(ismob(CHM))
|
||||
var/mob/LM = CHM
|
||||
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
next_activate = world.time + 30
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly/prox_sensor/process()
|
||||
if(timing)
|
||||
time--
|
||||
if(time <= 0)
|
||||
timing = 0
|
||||
toggle_scan(1)
|
||||
time = initial(time)
|
||||
if(!timing)
|
||||
return
|
||||
time--
|
||||
if(time <= 0)
|
||||
timing = FALSE
|
||||
toggle_scan(TRUE)
|
||||
time = initial(time)
|
||||
|
||||
/obj/item/assembly/prox_sensor/toggle_scan(scan)
|
||||
/obj/item/assembly/prox_sensor/proc/toggle_scan(scan)
|
||||
if(!secured)
|
||||
return 0
|
||||
return FALSE
|
||||
scanning = scan
|
||||
proximity_monitor.SetRange(scanning ? sensitivity : 0)
|
||||
update_icon()
|
||||
@@ -98,8 +108,11 @@
|
||||
if(is_secured(user))
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/dat = "<TT><B>Proximity Sensor</B>\n[(timing ? "<A href='?src=[REF(src)];time=0'>Arming</A>" : "<A href='?src=[REF(src)];time=1'>Not Arming</A>")] [minute]:[second]\n<A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>\n</TT>"
|
||||
dat += "<BR><A href='?src=[REF(src)];scanning=[scanning?"0'>Armed":"1'>Unarmed"]</A> (Movement sensor active when armed!)"
|
||||
var/dat = "<TT><B>Proximity Sensor</B></TT>"
|
||||
if(!scanning)
|
||||
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Arming</A>" : "<A href='?src=[REF(src)];time=1'>Not Arming</A>")] [minute]:[second]"
|
||||
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
|
||||
dat += "<BR><A href='?src=[REF(src)];scanning=[scanning?"0'>Armed":"1'>Unarmed (Movement sensor active when armed!)"]</A>"
|
||||
dat += "<BR>Detection range: <A href='?src=[REF(src)];sense=down'>-</A> [sensitivity] <A href='?src=[REF(src)];sense=up'>+</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
|
||||
|
||||
@@ -13,18 +13,18 @@
|
||||
qdel(part2)
|
||||
return ..()
|
||||
|
||||
/obj/item/assembly/shock_kit/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/wrench))
|
||||
/obj/item/assembly/shock_kit/wrench_act(mob/living/user, obj/item/I)
|
||||
to_chat(user, "<span class='notice'>You disassemble [src].</span>")
|
||||
if(part1)
|
||||
part1.forceMove(drop_location())
|
||||
part2.forceMove(drop_location())
|
||||
part1.master = null
|
||||
part2.master = null
|
||||
part1 = null
|
||||
if(part2)
|
||||
part2.forceMove(drop_location())
|
||||
part2.master = null
|
||||
part2 = null
|
||||
qdel(src)
|
||||
return
|
||||
add_fingerprint(user)
|
||||
return
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/shock_kit/attack_self(mob/user)
|
||||
part1.attack_self(user)
|
||||
|
||||
@@ -7,17 +7,18 @@
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=120)
|
||||
wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE
|
||||
attachable = 1
|
||||
attachable = TRUE
|
||||
|
||||
var/code = DEFAULT_SIGNALER_CODE
|
||||
var/frequency = FREQ_SIGNALER
|
||||
var/delay = 0
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/suicider = null
|
||||
var/hearing_range = 1
|
||||
|
||||
/obj/item/assembly/signaler/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message("<span class='suicide'>[user] eats \the [src]! If it is signaled, [user.p_they()] will die!</span>")
|
||||
playsound(src, 'sound/items/eatfood.ogg', 50, 1)
|
||||
playsound(src, 'sound/items/eatfood.ogg', 50, TRUE)
|
||||
user.transferItemToLoc(src, user, TRUE)
|
||||
suicider = user
|
||||
return MANUAL_SUICIDE
|
||||
@@ -27,15 +28,14 @@
|
||||
user.adjustOxyLoss(200)//it sends an electrical pulse to their heart, killing them. or something.
|
||||
user.death(0)
|
||||
|
||||
/obj/item/assembly/signaler/New()
|
||||
..()
|
||||
spawn(40)
|
||||
set_frequency(frequency)
|
||||
/obj/item/assembly/signaler/Initialize()
|
||||
. = ..()
|
||||
set_frequency(frequency)
|
||||
|
||||
|
||||
/obj/item/assembly/signaler/Destroy()
|
||||
SSradio.remove_object(src,frequency)
|
||||
return ..()
|
||||
. = ..()
|
||||
|
||||
/obj/item/assembly/signaler/activate()
|
||||
if(!..())//cooldown processing
|
||||
@@ -80,7 +80,7 @@ Code:
|
||||
/obj/item/assembly/signaler/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
usr << browse(null, "window=radio")
|
||||
onclose(usr, "radio")
|
||||
return
|
||||
@@ -111,7 +111,7 @@ Code:
|
||||
var/obj/item/assembly/signaler/signaler2 = W
|
||||
if(secured && signaler2.secured)
|
||||
code = signaler2.code
|
||||
frequency = signaler2.frequency
|
||||
set_frequency(signaler2.frequency)
|
||||
to_chat(user, "You transfer the frequency and code of \the [signaler2.name] to \the [name]")
|
||||
..()
|
||||
|
||||
@@ -131,17 +131,22 @@ Code:
|
||||
return
|
||||
|
||||
/obj/item/assembly/signaler/receive_signal(datum/signal/signal)
|
||||
. = FALSE
|
||||
if(!signal)
|
||||
return 0
|
||||
return
|
||||
if(signal.data["code"] != code)
|
||||
return 0
|
||||
return
|
||||
if(!(src.wires & WIRE_RADIO_RECEIVE))
|
||||
return 0
|
||||
return
|
||||
if(suicider)
|
||||
manual_suicide(suicider)
|
||||
pulse(1)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 1)
|
||||
return
|
||||
pulse(TRUE)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
|
||||
for(var/CHM in get_hearers_in_view(hearing_range, src))
|
||||
if(ismob(CHM))
|
||||
var/mob/LM = CHM
|
||||
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly/signaler/proc/set_frequency(new_frequency)
|
||||
@@ -161,10 +166,11 @@ Code:
|
||||
|
||||
/obj/item/assembly/signaler/reciever/activate()
|
||||
toggle_safety()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/reciever/describe()
|
||||
return "The radio receiver is [on?"on":"off"]."
|
||||
/obj/item/assembly/signaler/reciever/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>The radio receiver is [on?"on":"off"].</span>")
|
||||
|
||||
/obj/item/assembly/signaler/reciever/receive_signal(datum/signal/signal)
|
||||
if(!on)
|
||||
@@ -180,14 +186,16 @@ Code:
|
||||
item_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
|
||||
var/anomaly_type = /obj/effect/anomaly
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/receive_signal(datum/signal/signal)
|
||||
if(!signal)
|
||||
return 0
|
||||
return FALSE
|
||||
if(signal.data["code"] != code)
|
||||
return 0
|
||||
return FALSE
|
||||
for(var/obj/effect/anomaly/A in get_turf(src))
|
||||
A.anomalyNeutralize()
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/signaler/anomaly/attack_self()
|
||||
return
|
||||
@@ -196,3 +204,5 @@ Code:
|
||||
|
||||
/obj/item/assembly/signaler/cyborg/attackby(obj/item/W, mob/user, params)
|
||||
return
|
||||
/obj/item/assembly/signaler/cyborg/screwdriver_act(mob/living/user, obj/item/I)
|
||||
return
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
desc = "Used to time things. Works well with contraptions which has to count down. Tick tock."
|
||||
icon_state = "timer"
|
||||
materials = list(MAT_METAL=500, MAT_GLASS=50)
|
||||
attachable = 1
|
||||
attachable = TRUE
|
||||
|
||||
var/timing = 0
|
||||
var/timing = FALSE
|
||||
var/time = 5
|
||||
var/saved_time = 5
|
||||
var/loop = 0
|
||||
var/loop = FALSE
|
||||
var/hearing_range = 3
|
||||
|
||||
/obj/item/assembly/timer/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] looks at the timer and decides [user.p_their()] fate! It looks like [user.p_theyre()] going to commit suicide!</span>")
|
||||
@@ -21,22 +22,24 @@
|
||||
user.adjustOxyLoss(200)
|
||||
user.death(0)
|
||||
|
||||
/obj/item/assembly/timer/New()
|
||||
..()
|
||||
/obj/item/assembly/timer/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/assembly/timer/describe()
|
||||
if(timing)
|
||||
return "The timer is counting down from [time]!"
|
||||
return "The timer is set for [time] seconds."
|
||||
/obj/item/assembly/timer/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
. = ..()
|
||||
|
||||
/obj/item/assembly/timer/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>The timer is [timing ? "counting down from [time]":"set for [time] seconds"].</span>")
|
||||
|
||||
/obj/item/assembly/timer/activate()
|
||||
if(!..())
|
||||
return 0//Cooldown check
|
||||
return FALSE//Cooldown check
|
||||
timing = !timing
|
||||
update_icon()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/assembly/timer/toggle_secure()
|
||||
@@ -44,7 +47,7 @@
|
||||
if(secured)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
timing = 0
|
||||
timing = FALSE
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return secured
|
||||
@@ -53,20 +56,25 @@
|
||||
/obj/item/assembly/timer/proc/timer_end()
|
||||
if(!secured || next_activate > world.time)
|
||||
return FALSE
|
||||
pulse(0)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 3)
|
||||
pulse(FALSE)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
|
||||
for(var/CHM in get_hearers_in_view(hearing_range, src))
|
||||
if(ismob(CHM))
|
||||
var/mob/LM = CHM
|
||||
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
if(loop)
|
||||
timing = 1
|
||||
timing = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/assembly/timer/process()
|
||||
if(timing)
|
||||
time--
|
||||
if(time <= 0)
|
||||
timing = 0
|
||||
timer_end()
|
||||
time = saved_time
|
||||
if(!timing)
|
||||
return
|
||||
time--
|
||||
if(time <= 0)
|
||||
timing = FALSE
|
||||
timer_end()
|
||||
time = saved_time
|
||||
|
||||
|
||||
/obj/item/assembly/timer/update_icon()
|
||||
@@ -84,7 +92,9 @@
|
||||
if(is_secured(user))
|
||||
var/second = time % 60
|
||||
var/minute = (time - second) / 60
|
||||
var/dat = "<TT><B>Timing Unit</B>\n[(timing ? "<A href='?src=[REF(src)];time=0'>Timing</A>" : "<A href='?src=[REF(src)];time=1'>Not Timing</A>")] [minute]:[second]\n<A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>\n</TT>"
|
||||
var/dat = "<TT><B>Timing Unit</B></TT>"
|
||||
dat += "<BR>[(timing ? "<A href='?src=[REF(src)];time=0'>Timing</A>" : "<A href='?src=[REF(src)];time=1'>Not Timing</A>")] [minute]:[second]"
|
||||
dat += "<BR><A href='?src=[REF(src)];tp=-30'>-</A> <A href='?src=[REF(src)];tp=-1'>-</A> <A href='?src=[REF(src)];tp=1'>+</A> <A href='?src=[REF(src)];tp=30'>+</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];repeat=[(loop ? "0'>Stop repeating" : "1'>Set to repeat")]</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];refresh=1'>Refresh</A>"
|
||||
dat += "<BR><BR><A href='?src=[REF(src)];close=1'>Close</A>"
|
||||
@@ -95,7 +105,7 @@
|
||||
|
||||
/obj/item/assembly/timer/Topic(href, href_list)
|
||||
..()
|
||||
if(usr.incapacitated() || !in_range(loc, usr))
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
usr << browse(null, "window=timer")
|
||||
onclose(usr, "timer")
|
||||
return
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#define INCLUSIVE_MODE 1
|
||||
#define EXCLUSIVE_MODE 2
|
||||
#define RECOGNIZER_MODE 3
|
||||
#define VOICE_SENSOR_MODE 4
|
||||
|
||||
/obj/item/assembly/voice
|
||||
name = "voice analyzer"
|
||||
desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated."
|
||||
icon_state = "voice"
|
||||
materials = list(MAT_METAL=500, MAT_GLASS=50)
|
||||
flags_1 = HEAR_1
|
||||
attachable = 1
|
||||
attachable = TRUE
|
||||
verb_say = "beeps"
|
||||
verb_ask = "beeps"
|
||||
verb_exclaim = "beeps"
|
||||
var/listening = 0
|
||||
var/listening = FALSE
|
||||
var/recorded = "" //the activation message
|
||||
var/mode = 1
|
||||
var/static/list/modes = list("inclusive",
|
||||
@@ -32,60 +37,64 @@
|
||||
|
||||
/obj/item/assembly/voice/proc/record_speech(atom/movable/speaker, raw_message, datum/language/message_language)
|
||||
switch(mode)
|
||||
if(1)
|
||||
if(INCLUSIVE_MODE)
|
||||
recorded = raw_message
|
||||
listening = 0
|
||||
listening = FALSE
|
||||
say("Activation message is '[recorded]'.", message_language)
|
||||
if(2)
|
||||
if(EXCLUSIVE_MODE)
|
||||
recorded = raw_message
|
||||
listening = 0
|
||||
listening = FALSE
|
||||
say("Activation message is '[recorded]'.", message_language)
|
||||
if(3)
|
||||
if(RECOGNIZER_MODE)
|
||||
recorded = speaker.GetVoice()
|
||||
listening = 0
|
||||
listening = FALSE
|
||||
say("Your voice pattern is saved.", message_language)
|
||||
if(4)
|
||||
if(VOICE_SENSOR_MODE)
|
||||
if(length(raw_message))
|
||||
addtimer(CALLBACK(src, .proc/pulse, 0), 10)
|
||||
|
||||
/obj/item/assembly/voice/proc/check_activation(atom/movable/speaker, raw_message)
|
||||
. = 0
|
||||
. = FALSE
|
||||
switch(mode)
|
||||
if(1)
|
||||
if(INCLUSIVE_MODE)
|
||||
if(findtext(raw_message, recorded))
|
||||
. = 1
|
||||
if(2)
|
||||
. = TRUE
|
||||
if(EXCLUSIVE_MODE)
|
||||
if(raw_message == recorded)
|
||||
. = 1
|
||||
if(3)
|
||||
. = TRUE
|
||||
if(RECOGNIZER_MODE)
|
||||
if(speaker.GetVoice() == recorded)
|
||||
. = 1
|
||||
if(4)
|
||||
. = TRUE
|
||||
if(VOICE_SENSOR_MODE)
|
||||
if(length(raw_message))
|
||||
. = 1
|
||||
. = TRUE
|
||||
|
||||
/obj/item/assembly/voice/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/multitool))
|
||||
mode %= modes.len
|
||||
mode++
|
||||
to_chat(user, "You set [src] into a [modes[mode]] mode.")
|
||||
listening = 0
|
||||
recorded = ""
|
||||
else
|
||||
return ..()
|
||||
/obj/item/assembly/voice/multitool_act(mob/living/user, obj/item/I)
|
||||
mode %= modes.len
|
||||
mode++
|
||||
to_chat(user, "<span class='notice'>You set [src] into [modes[mode]] mode.</span>")
|
||||
listening = FALSE
|
||||
recorded = ""
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/voice/activate()
|
||||
if(secured)
|
||||
if(!holder)
|
||||
listening = !listening
|
||||
say("[listening ? "Now" : "No longer"] recording input.")
|
||||
if(!secured || holder)
|
||||
return FALSE
|
||||
listening = !listening
|
||||
say("[listening ? "Now" : "No longer"] recording input.")
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/voice/attack_self(mob/user)
|
||||
if(!user)
|
||||
return 0
|
||||
return FALSE
|
||||
activate()
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
/obj/item/assembly/voice/toggle_secure()
|
||||
. = ..()
|
||||
listening = 0
|
||||
listening = FALSE
|
||||
|
||||
#undef INCLUSIVE_MODE
|
||||
#undef EXCLUSIVE_MODE
|
||||
#undef RECOGNIZER_MODE
|
||||
#undef VOICE_SENSOR_MODE
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
//fusion: a terrible idea that was fun but broken. Now reworked to be less broken and more interesting. Again.
|
||||
/datum/gas_reaction/fusion
|
||||
exclude = FALSE
|
||||
exclude = TRUE
|
||||
priority = 2
|
||||
name = "Plasmic Fusion"
|
||||
id = "fusion"
|
||||
|
||||
@@ -34,8 +34,10 @@ Iconnery
|
||||
var/turf/T = loc
|
||||
if(level == 2 || !T.intact)
|
||||
showpipe = TRUE
|
||||
plane = GAME_PLANE
|
||||
else
|
||||
showpipe = FALSE
|
||||
plane = FLOOR_PLANE
|
||||
|
||||
if(!showpipe)
|
||||
return //no need to update the pipes if they aren't showing
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
export_types = list(/obj/machinery/iv_drip)
|
||||
|
||||
/datum/export/large/barrier
|
||||
cost = 325
|
||||
cost = 100
|
||||
unit_name = "security barrier"
|
||||
export_types = list(/obj/item/grenade/barrier, /obj/structure/barricade/security)
|
||||
|
||||
|
||||
@@ -1649,8 +1649,9 @@
|
||||
. = ..()
|
||||
if(prob(50))
|
||||
var/mob/living/simple_animal/pet/dog/corgi/D = locate() in .
|
||||
qdel(D)
|
||||
new /mob/living/simple_animal/pet/dog/corgi/Lisa(.)
|
||||
if(D.gender == FEMALE)
|
||||
qdel(D)
|
||||
new /mob/living/simple_animal/pet/dog/corgi/Lisa(.)
|
||||
|
||||
/datum/supply_pack/critter/cow
|
||||
name = "Cow Crate"
|
||||
|
||||
@@ -157,12 +157,14 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
|
||||
//get an assetdatum or make a new one
|
||||
/proc/get_asset_datum(var/type)
|
||||
if (!(type in GLOB.asset_datums))
|
||||
return new type()
|
||||
return GLOB.asset_datums[type]
|
||||
return GLOB.asset_datums[type] || new type()
|
||||
|
||||
/datum/asset
|
||||
var/_abstract = /datum/asset
|
||||
|
||||
/datum/asset/New()
|
||||
GLOB.asset_datums[type] = src
|
||||
register()
|
||||
|
||||
/datum/asset/proc/register()
|
||||
return
|
||||
@@ -170,20 +172,173 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
/datum/asset/proc/send(client)
|
||||
return
|
||||
|
||||
|
||||
//If you don't need anything complicated.
|
||||
/datum/asset/simple
|
||||
_abstract = /datum/asset/simple
|
||||
var/assets = list()
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/simple/register()
|
||||
for(var/asset_name in assets)
|
||||
register_asset(asset_name, assets[asset_name])
|
||||
|
||||
/datum/asset/simple/send(client)
|
||||
send_asset_list(client,assets,verify)
|
||||
|
||||
|
||||
// For registering or sending multiple others at once
|
||||
/datum/asset/group
|
||||
_abstract = /datum/asset/group
|
||||
var/list/children
|
||||
|
||||
/datum/asset/group/register()
|
||||
for(var/type in children)
|
||||
get_asset_datum(type)
|
||||
|
||||
/datum/asset/group/send(client/C)
|
||||
for(var/type in children)
|
||||
var/datum/asset/A = get_asset_datum(type)
|
||||
A.send(C)
|
||||
|
||||
|
||||
// spritesheet implementation - coalesces various icons into a single .png file
|
||||
// and uses CSS to select icons out of that file - saves on transferring some
|
||||
// 1400-odd individual PNG files
|
||||
#define SPR_SIZE 1
|
||||
#define SPR_IDX 2
|
||||
#define SPRSZ_COUNT 1
|
||||
#define SPRSZ_ICON 2
|
||||
#define SPRSZ_STRIPPED 3
|
||||
|
||||
/datum/asset/spritesheet
|
||||
_abstract = /datum/asset/spritesheet
|
||||
var/name
|
||||
var/list/sizes = list() // "32x32" -> list(10, icon/normal, icon/stripped)
|
||||
var/list/sprites = list() // "foo_bar" -> list("32x32", 5)
|
||||
var/verify = FALSE
|
||||
|
||||
/datum/asset/spritesheet/register()
|
||||
if (!name)
|
||||
CRASH("spritesheet [type] cannot register without a name")
|
||||
ensure_stripped()
|
||||
|
||||
var/res_name = "spritesheet_[name].css"
|
||||
var/fname = "data/spritesheets/[res_name]"
|
||||
call("rust_g", "file_write")(generate_css(), fname)
|
||||
register_asset(res_name, file(fname))
|
||||
|
||||
for(var/size_id in sizes)
|
||||
var/size = sizes[size_id]
|
||||
register_asset("[name]_[size_id].png", size[SPRSZ_STRIPPED])
|
||||
|
||||
/datum/asset/spritesheet/send(client/C)
|
||||
if (!name)
|
||||
return
|
||||
var/all = list("spritesheet_[name].css")
|
||||
for(var/size_id in sizes)
|
||||
all += "[name]_[size_id].png"
|
||||
send_asset_list(C, all, verify)
|
||||
|
||||
/datum/asset/spritesheet/proc/ensure_stripped(sizes_to_strip = sizes)
|
||||
for(var/size_id in sizes_to_strip)
|
||||
var/size = sizes[size_id]
|
||||
if (size[SPRSZ_STRIPPED])
|
||||
continue
|
||||
|
||||
// save flattened version
|
||||
var/fname = "data/spritesheets/[name]_[size_id].png"
|
||||
fcopy(size[SPRSZ_ICON], fname)
|
||||
var/error = call("rust_g", "dmi_strip_metadata")(fname)
|
||||
if(length(error))
|
||||
stack_trace("Failed to strip [name]_[size_id].png: [error]")
|
||||
size[SPRSZ_STRIPPED] = icon(fname)
|
||||
|
||||
/datum/asset/spritesheet/proc/generate_css()
|
||||
var/list/out = list()
|
||||
|
||||
for (var/size_id in sizes)
|
||||
var/size = sizes[size_id]
|
||||
var/icon/tiny = size[SPRSZ_ICON]
|
||||
out += ".[name][size_id]{display:inline-block;width:[tiny.Width()]px;height:[tiny.Height()]px;background:url('[name]_[size_id].png') no-repeat;}"
|
||||
|
||||
for (var/sprite_id in sprites)
|
||||
var/sprite = sprites[sprite_id]
|
||||
var/size_id = sprite[SPR_SIZE]
|
||||
var/idx = sprite[SPR_IDX]
|
||||
var/size = sizes[size_id]
|
||||
|
||||
var/icon/tiny = size[SPRSZ_ICON]
|
||||
var/icon/big = size[SPRSZ_STRIPPED]
|
||||
var/per_line = big.Width() / tiny.Width()
|
||||
var/x = (idx % per_line) * tiny.Width()
|
||||
var/y = round(idx / per_line) * tiny.Height()
|
||||
|
||||
out += ".[name][size_id].[sprite_id]{background-position:-[x]px -[y]px;}"
|
||||
|
||||
return out.Join("\n")
|
||||
|
||||
/datum/asset/spritesheet/proc/Insert(sprite_name, icon/I, icon_state="", dir=SOUTH, frame=1, moving=FALSE)
|
||||
I = icon(I, icon_state=icon_state, dir=dir, frame=frame, moving=moving)
|
||||
if (!I || !length(icon_states(I))) // that direction or state doesn't exist
|
||||
return
|
||||
var/size_id = "[I.Width()]x[I.Height()]"
|
||||
var/size = sizes[size_id]
|
||||
|
||||
if (sprites[sprite_name])
|
||||
CRASH("duplicate sprite \"[sprite_name]\" in sheet [name] ([type])")
|
||||
|
||||
if (size)
|
||||
var/position = size[SPRSZ_COUNT]++
|
||||
var/icon/sheet = size[SPRSZ_ICON]
|
||||
size[SPRSZ_STRIPPED] = null
|
||||
sheet.Insert(I, icon_state=sprite_name)
|
||||
sprites[sprite_name] = list(size_id, position)
|
||||
else
|
||||
sizes[size_id] = size = list(1, I, null)
|
||||
sprites[sprite_name] = list(size_id, 0)
|
||||
|
||||
/datum/asset/spritesheet/proc/InsertAll(prefix, icon/I, list/directions)
|
||||
if (length(prefix))
|
||||
prefix = "[prefix]-"
|
||||
|
||||
if (!directions)
|
||||
directions = list(SOUTH)
|
||||
|
||||
for (var/icon_state_name in icon_states(I))
|
||||
for (var/direction in directions)
|
||||
var/prefix2 = (directions.len > 1) ? "[dir2text(direction)]-" : ""
|
||||
Insert("[prefix][prefix2][icon_state_name]", I, icon_state=icon_state_name, dir=direction)
|
||||
|
||||
/datum/asset/spritesheet/proc/css_tag()
|
||||
return {"<link rel="stylesheet" href="spritesheet_[name].css" />"}
|
||||
|
||||
/datum/asset/spritesheet/proc/icon_tag(sprite_name)
|
||||
var/sprite = sprites[sprite_name]
|
||||
if (!sprite)
|
||||
return null
|
||||
var/size_id = sprite[SPR_SIZE]
|
||||
return {"<span class="[name][size_id] [sprite_name]"></span>"}
|
||||
|
||||
#undef SPR_SIZE
|
||||
#undef SPR_IDX
|
||||
#undef SPRSZ_COUNT
|
||||
#undef SPRSZ_ICON
|
||||
#undef SPRSZ_STRIPPED
|
||||
|
||||
|
||||
/datum/asset/spritesheet/simple
|
||||
_abstract = /datum/asset/spritesheet/simple
|
||||
var/list/assets
|
||||
|
||||
/datum/asset/spritesheet/simple/register()
|
||||
for (var/key in assets)
|
||||
Insert(key, assets[key])
|
||||
..()
|
||||
|
||||
//Generates assets based on iconstates of a single icon
|
||||
/datum/asset/simple/icon_states
|
||||
_abstract = /datum/asset/simple/icon_states
|
||||
var/icon
|
||||
var/list/directions = list(SOUTH)
|
||||
var/frame = 1
|
||||
@@ -209,6 +364,7 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
register_asset(asset_name, asset)
|
||||
|
||||
/datum/asset/simple/icon_states/multiple_icons
|
||||
_abstract = /datum/asset/simple/icon_states/multiple_icons
|
||||
var/list/icons
|
||||
|
||||
/datum/asset/simple/icon_states/multiple_icons/register()
|
||||
@@ -260,50 +416,52 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
"smmon_6.gif" = 'icons/program_icons/smmon_6.gif'
|
||||
)
|
||||
|
||||
/datum/asset/simple/pda
|
||||
/datum/asset/spritesheet/simple/pda
|
||||
name = "pda"
|
||||
assets = list(
|
||||
"pda_atmos.png" = 'icons/pda_icons/pda_atmos.png',
|
||||
"pda_back.png" = 'icons/pda_icons/pda_back.png',
|
||||
"pda_bell.png" = 'icons/pda_icons/pda_bell.png',
|
||||
"pda_blank.png" = 'icons/pda_icons/pda_blank.png',
|
||||
"pda_boom.png" = 'icons/pda_icons/pda_boom.png',
|
||||
"pda_bucket.png" = 'icons/pda_icons/pda_bucket.png',
|
||||
"pda_medbot.png" = 'icons/pda_icons/pda_medbot.png',
|
||||
"pda_floorbot.png" = 'icons/pda_icons/pda_floorbot.png',
|
||||
"pda_cleanbot.png" = 'icons/pda_icons/pda_cleanbot.png',
|
||||
"pda_crate.png" = 'icons/pda_icons/pda_crate.png',
|
||||
"pda_cuffs.png" = 'icons/pda_icons/pda_cuffs.png',
|
||||
"pda_eject.png" = 'icons/pda_icons/pda_eject.png',
|
||||
"pda_flashlight.png" = 'icons/pda_icons/pda_flashlight.png',
|
||||
"pda_honk.png" = 'icons/pda_icons/pda_honk.png',
|
||||
"pda_mail.png" = 'icons/pda_icons/pda_mail.png',
|
||||
"pda_medical.png" = 'icons/pda_icons/pda_medical.png',
|
||||
"pda_menu.png" = 'icons/pda_icons/pda_menu.png',
|
||||
"pda_mule.png" = 'icons/pda_icons/pda_mule.png',
|
||||
"pda_notes.png" = 'icons/pda_icons/pda_notes.png',
|
||||
"pda_power.png" = 'icons/pda_icons/pda_power.png',
|
||||
"pda_rdoor.png" = 'icons/pda_icons/pda_rdoor.png',
|
||||
"pda_reagent.png" = 'icons/pda_icons/pda_reagent.png',
|
||||
"pda_refresh.png" = 'icons/pda_icons/pda_refresh.png',
|
||||
"pda_scanner.png" = 'icons/pda_icons/pda_scanner.png',
|
||||
"pda_signaler.png" = 'icons/pda_icons/pda_signaler.png',
|
||||
"pda_status.png" = 'icons/pda_icons/pda_status.png',
|
||||
"pda_dronephone.png" = 'icons/pda_icons/pda_dronephone.png'
|
||||
"atmos" = 'icons/pda_icons/pda_atmos.png',
|
||||
"back" = 'icons/pda_icons/pda_back.png',
|
||||
"bell" = 'icons/pda_icons/pda_bell.png',
|
||||
"blank" = 'icons/pda_icons/pda_blank.png',
|
||||
"boom" = 'icons/pda_icons/pda_boom.png',
|
||||
"bucket" = 'icons/pda_icons/pda_bucket.png',
|
||||
"medbot" = 'icons/pda_icons/pda_medbot.png',
|
||||
"floorbot" = 'icons/pda_icons/pda_floorbot.png',
|
||||
"cleanbot" = 'icons/pda_icons/pda_cleanbot.png',
|
||||
"crate" = 'icons/pda_icons/pda_crate.png',
|
||||
"cuffs" = 'icons/pda_icons/pda_cuffs.png',
|
||||
"eject" = 'icons/pda_icons/pda_eject.png',
|
||||
"flashlight" = 'icons/pda_icons/pda_flashlight.png',
|
||||
"honk" = 'icons/pda_icons/pda_honk.png',
|
||||
"mail" = 'icons/pda_icons/pda_mail.png',
|
||||
"medical" = 'icons/pda_icons/pda_medical.png',
|
||||
"menu" = 'icons/pda_icons/pda_menu.png',
|
||||
"mule" = 'icons/pda_icons/pda_mule.png',
|
||||
"notes" = 'icons/pda_icons/pda_notes.png',
|
||||
"power" = 'icons/pda_icons/pda_power.png',
|
||||
"rdoor" = 'icons/pda_icons/pda_rdoor.png',
|
||||
"reagent" = 'icons/pda_icons/pda_reagent.png',
|
||||
"refresh" = 'icons/pda_icons/pda_refresh.png',
|
||||
"scanner" = 'icons/pda_icons/pda_scanner.png',
|
||||
"signaler" = 'icons/pda_icons/pda_signaler.png',
|
||||
"status" = 'icons/pda_icons/pda_status.png',
|
||||
"dronephone" = 'icons/pda_icons/pda_dronephone.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/paper
|
||||
/datum/asset/spritesheet/simple/paper
|
||||
name = "paper"
|
||||
assets = list(
|
||||
"large_stamp-clown.png" = 'icons/stamp_icons/large_stamp-clown.png',
|
||||
"large_stamp-deny.png" = 'icons/stamp_icons/large_stamp-deny.png',
|
||||
"large_stamp-ok.png" = 'icons/stamp_icons/large_stamp-ok.png',
|
||||
"large_stamp-hop.png" = 'icons/stamp_icons/large_stamp-hop.png',
|
||||
"large_stamp-cmo.png" = 'icons/stamp_icons/large_stamp-cmo.png',
|
||||
"large_stamp-ce.png" = 'icons/stamp_icons/large_stamp-ce.png',
|
||||
"large_stamp-hos.png" = 'icons/stamp_icons/large_stamp-hos.png',
|
||||
"large_stamp-rd.png" = 'icons/stamp_icons/large_stamp-rd.png',
|
||||
"large_stamp-cap.png" = 'icons/stamp_icons/large_stamp-cap.png',
|
||||
"large_stamp-qm.png" = 'icons/stamp_icons/large_stamp-qm.png',
|
||||
"large_stamp-law.png" = 'icons/stamp_icons/large_stamp-law.png'
|
||||
"stamp-clown" = 'icons/stamp_icons/large_stamp-clown.png',
|
||||
"stamp-deny" = 'icons/stamp_icons/large_stamp-deny.png',
|
||||
"stamp-ok" = 'icons/stamp_icons/large_stamp-ok.png',
|
||||
"stamp-hop" = 'icons/stamp_icons/large_stamp-hop.png',
|
||||
"stamp-cmo" = 'icons/stamp_icons/large_stamp-cmo.png',
|
||||
"stamp-ce" = 'icons/stamp_icons/large_stamp-ce.png',
|
||||
"stamp-hos" = 'icons/stamp_icons/large_stamp-hos.png',
|
||||
"stamp-rd" = 'icons/stamp_icons/large_stamp-rd.png',
|
||||
"stamp-cap" = 'icons/stamp_icons/large_stamp-cap.png',
|
||||
"stamp-qm" = 'icons/stamp_icons/large_stamp-qm.png',
|
||||
"stamp-law" = 'icons/stamp_icons/large_stamp-law.png'
|
||||
)
|
||||
|
||||
/datum/asset/simple/IRV
|
||||
@@ -335,10 +493,22 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
"changelog.css" = 'html/changelog.css'
|
||||
)
|
||||
|
||||
/datum/asset/simple/goonchat
|
||||
/datum/asset/group/goonchat
|
||||
children = list(
|
||||
/datum/asset/simple/jquery,
|
||||
/datum/asset/simple/goonchat,
|
||||
/datum/asset/spritesheet/goonchat
|
||||
)
|
||||
|
||||
/datum/asset/simple/jquery
|
||||
verify = FALSE
|
||||
assets = list(
|
||||
"jquery.min.js" = 'code/modules/goonchat/browserassets/js/jquery.min.js',
|
||||
)
|
||||
|
||||
/datum/asset/simple/goonchat
|
||||
verify = FALSE
|
||||
assets = list(
|
||||
"json2.min.js" = 'code/modules/goonchat/browserassets/js/json2.min.js',
|
||||
"errorHandler.js" = 'code/modules/goonchat/browserassets/js/errorHandler.js',
|
||||
"browserOutput.js" = 'code/modules/goonchat/browserassets/js/browserOutput.js',
|
||||
@@ -350,6 +520,24 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
"browserOutput.css" = 'code/modules/goonchat/browserassets/css/browserOutput.css',
|
||||
)
|
||||
|
||||
/datum/asset/spritesheet/goonchat
|
||||
name = "chat"
|
||||
|
||||
/datum/asset/spritesheet/goonchat/register()
|
||||
InsertAll("emoji", 'icons/emoji.dmi')
|
||||
|
||||
// pre-loading all lanugage icons also helps to avoid meta
|
||||
InsertAll("language", 'icons/misc/language.dmi')
|
||||
// catch languages which are pulling icons from another file
|
||||
for(var/path in typesof(/datum/language))
|
||||
var/datum/language/L = path
|
||||
var/icon = initial(L.icon)
|
||||
if (icon != 'icons/misc/language.dmi')
|
||||
var/icon_state = initial(L.icon_state)
|
||||
Insert("language-[icon_state]", icon, icon_state=icon_state)
|
||||
|
||||
..()
|
||||
|
||||
/datum/asset/simple/permissions
|
||||
assets = list(
|
||||
"padlock.png" = 'html/padlock.png'
|
||||
@@ -362,26 +550,19 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
var/datum/language/L = new path ()
|
||||
L.get_icon()
|
||||
|
||||
/datum/asset/simple/icon_states/emojis
|
||||
icon = 'icons/emoji.dmi'
|
||||
generic_icon_names = TRUE
|
||||
/datum/asset/spritesheet/pipes
|
||||
name = "pipes"
|
||||
|
||||
/datum/asset/simple/icon_states/multiple_icons/pipes
|
||||
icons = list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi')
|
||||
prefix = "pipe"
|
||||
|
||||
/datum/asset/simple/icon_states/multiple_icons/pipes/New()
|
||||
directions = GLOB.alldirs
|
||||
/datum/asset/spritesheet/pipes/register()
|
||||
for (var/each in list('icons/obj/atmospherics/pipes/pipe_item.dmi', 'icons/obj/atmospherics/pipes/disposal.dmi', 'icons/obj/atmospherics/pipes/transit_tube.dmi'))
|
||||
InsertAll("", each, GLOB.alldirs)
|
||||
..()
|
||||
|
||||
/datum/asset/simple/icon_states/multiple_icons/pipes/register()
|
||||
..()
|
||||
var/meter = icon('icons/obj/atmospherics/pipes/simple.dmi', "meterX", SOUTH, frame, movement_states)
|
||||
if(meter)
|
||||
register_asset(sanitize_filename("[prefix].south.meterX.png"), fcopy_rsc(meter))
|
||||
|
||||
// Representative icons for each research design
|
||||
/datum/asset/simple/research_designs/register()
|
||||
/datum/asset/spritesheet/research_designs
|
||||
name = "design"
|
||||
|
||||
/datum/asset/spritesheet/research_designs/register()
|
||||
for (var/path in subtypesof(/datum/design))
|
||||
var/datum/design/D = path
|
||||
|
||||
@@ -401,7 +582,6 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
if (machine)
|
||||
item = machine
|
||||
var/icon_file = initial(item.icon)
|
||||
var/all_states = icon_states(icon_file)
|
||||
var/icon/I = icon(icon_file, initial(item.icon_state), SOUTH)
|
||||
|
||||
// computers (and snowflakes) get their screen and keyboard sprites
|
||||
@@ -409,10 +589,11 @@ GLOBAL_LIST_EMPTY(asset_datums)
|
||||
var/obj/machinery/computer/C = item
|
||||
var/screen = initial(C.icon_screen)
|
||||
var/keyboard = initial(C.icon_keyboard)
|
||||
var/all_states = icon_states(icon_file)
|
||||
if (screen && (screen in all_states))
|
||||
I.Blend(icon(icon_file, screen, SOUTH), ICON_OVERLAY)
|
||||
if (keyboard && (keyboard in all_states))
|
||||
I.Blend(icon(icon_file, keyboard, SOUTH), ICON_OVERLAY)
|
||||
|
||||
assets["design_[initial(D.id)].png"] = I
|
||||
Insert(initial(D.id), I)
|
||||
return ..()
|
||||
|
||||
@@ -165,6 +165,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
return var_name != NAMEOF(src, holder) && ..()
|
||||
|
||||
/client/New(TopicData)
|
||||
world.SetConfig("APP/admin", ckey, "role=admin") //CITADEL EDIT - Allows admins to reboot in OOM situations
|
||||
var/tdata = TopicData //save this for later use
|
||||
chatOutput = new /datum/chatOutput(src)
|
||||
TopicData = null //Prevent calls to client.Topic from connect
|
||||
@@ -179,10 +180,15 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
var/connecting_admin = FALSE //because de-admined admins connecting should be treated like admins.
|
||||
//Admin Authorisation
|
||||
holder = GLOB.admin_datums[ckey]
|
||||
var/debug_tools_allowed = FALSE //CITADEL EDIT
|
||||
if(holder)
|
||||
GLOB.admins |= src
|
||||
holder.owner = src
|
||||
connecting_admin = TRUE
|
||||
//CITADEL EDIT
|
||||
if(check_rights_for(src, R_DEBUG))
|
||||
debug_tools_allowed = TRUE
|
||||
//END CITADEL EDIT
|
||||
else if(GLOB.deadmins[ckey])
|
||||
verbs += /client/proc/readmin
|
||||
connecting_admin = TRUE
|
||||
@@ -197,6 +203,12 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
to_chat(world, "Autoadmin rank not found")
|
||||
else
|
||||
new /datum/admins(autorank, ckey)
|
||||
//CITADEL EDIT
|
||||
if(check_rights_for(src, R_DEBUG)) //check if autoadmin gave us it
|
||||
debug_tools_allowed = TRUE
|
||||
if(!debug_tools_allowed)
|
||||
world.SetConfig("APP/admin", ckey, null)
|
||||
//END CITADEL EDIT
|
||||
if(CONFIG_GET(flag/enable_localhost_rank) && !connecting_admin)
|
||||
var/localhost_addresses = list("127.0.0.1", "::1")
|
||||
if(isnull(address) || (address in localhost_addresses))
|
||||
@@ -381,7 +393,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
winset(src, "[topmenu.type]", "parent=menu;name=[url_encode(topmenuname)]")
|
||||
var/list/entries = topmenu.Generate_list(src)
|
||||
for (var/child in entries)
|
||||
winset(src, "[url_encode(child)]", "[entries[child]]")
|
||||
winset(src, "[child]", "[entries[child]]")
|
||||
if (!ispath(child, /datum/verbs/menu))
|
||||
var/atom/verb/verbpath = child
|
||||
if (copytext(verbpath.name,1,2) != "@")
|
||||
|
||||
@@ -83,12 +83,12 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
//Mob preview
|
||||
var/icon/preview_icon = null
|
||||
|
||||
//Trait list
|
||||
var/list/positive_traits = list()
|
||||
var/list/negative_traits = list()
|
||||
var/list/neutral_traits = list()
|
||||
var/list/all_traits = list()
|
||||
var/list/character_traits = list()
|
||||
//Quirk list
|
||||
var/list/positive_quirks = list()
|
||||
var/list/negative_quirks = list()
|
||||
var/list/neutral_quirks = list()
|
||||
var/list/all_quirks = list()
|
||||
var/list/character_quirks = list()
|
||||
|
||||
//Jobs, uses bitflags
|
||||
var/job_civilian_high = 0
|
||||
@@ -120,6 +120,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
|
||||
var/parallax
|
||||
|
||||
var/ambientocclusion = TRUE
|
||||
|
||||
var/uplink_spawn_loc = UPLINK_PDA
|
||||
|
||||
var/list/exp = list()
|
||||
@@ -193,9 +195,9 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<center><h2>Occupation Choices</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=job;task=menu'>Set Occupation Preferences</a><br></center>"
|
||||
if(CONFIG_GET(flag/roundstart_traits))
|
||||
dat += "<center><h2>Trait Setup</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=trait;task=menu'>Configure Traits</a><br></center>"
|
||||
dat += "<center><b>Current traits:</b> [all_traits.len ? all_traits.Join(", ") : "None"]</center>"
|
||||
dat += "<center><h2>Quirk Setup</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=trait;task=menu'>Configure Quirks</a><br></center>"
|
||||
dat += "<center><b>Current quirks:</b> [all_quirks.len ? all_quirks.Join(", ") : "None"]</center>"
|
||||
dat += "<h2>Identity</h2>"
|
||||
dat += "<table width='100%'><tr><td width='75%' valign='top'>"
|
||||
if(jobban_isbanned(user, "appearance"))
|
||||
@@ -490,6 +492,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "High"
|
||||
dat += "</a><br>"
|
||||
|
||||
dat += "<b>Ambient Occlusion:</b> <a href='?_src_=prefs;preference=ambientocclusion'>[ambientocclusion ? "Enabled" : "Disabled"]</a><br>"
|
||||
|
||||
dat += "</td><td width='300px' height='300px' valign='top'>"
|
||||
|
||||
dat += "<h2>Special Role Settings</h2>"
|
||||
@@ -855,72 +859,72 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
return job_engsec_low
|
||||
return 0
|
||||
|
||||
/datum/preferences/proc/SetTraits(mob/user)
|
||||
if(!SStraits)
|
||||
to_chat(user, "<span class='danger'>The trait subsystem is still initializing! Try again in a minute.</span>")
|
||||
/datum/preferences/proc/SetQuirks(mob/user)
|
||||
if(!SSquirks)
|
||||
to_chat(user, "<span class='danger'>The quirk subsystem is still initializing! Try again in a minute.</span>")
|
||||
return
|
||||
|
||||
var/list/dat = list()
|
||||
if(!SStraits.traits.len)
|
||||
dat += "The trait subsystem hasn't finished initializing, please hold..."
|
||||
if(!SSquirks.quirks.len)
|
||||
dat += "The quirk subsystem hasn't finished initializing, please hold..."
|
||||
dat += "<center><a href='?_src_=prefs;preference=trait;task=close'>Done</a></center><br>"
|
||||
|
||||
else
|
||||
dat += "<center><b>Choose trait setup</b></center><br>"
|
||||
dat += "<div align='center'>Left-click to add or remove traits. You need one negative trait for every positive trait.<br>\
|
||||
Traits are applied at roundstart and cannot normally be removed.</div>"
|
||||
dat += "<center><b>Choose quirk setup</b></center><br>"
|
||||
dat += "<div align='center'>Left-click to add or remove quirks. You need negative quirks to have positive ones.<br>\
|
||||
Quirks are applied at roundstart and cannot normally be removed.</div>"
|
||||
dat += "<center><a href='?_src_=prefs;preference=trait;task=close'>Done</a></center>"
|
||||
dat += "<hr>"
|
||||
dat += "<center><b>Current traits:</b> [all_traits.len ? all_traits.Join(", ") : "None"]</center>"
|
||||
dat += "<center>[all_traits.len] / [MAX_TRAITS] max traits<br>\
|
||||
<b>Trait balance remaining:</b> [GetTraitBalance()]</center><br>"
|
||||
for(var/V in SStraits.traits)
|
||||
var/datum/trait/T = SStraits.traits[V]
|
||||
var/trait_name = initial(T.name)
|
||||
var/has_trait
|
||||
var/trait_cost = initial(T.value) * -1
|
||||
dat += "<center><b>Current quirks:</b> [all_quirks.len ? all_quirks.Join(", ") : "None"]</center>"
|
||||
dat += "<center>[positive_quirks.len] / [MAX_QUIRKS] max positive quirks<br>\
|
||||
<b>Quirk balance remaining:</b> [GetQuirkBalance()]</center><br>"
|
||||
for(var/V in SSquirks.quirks)
|
||||
var/datum/quirk/T = SSquirks.quirks[V]
|
||||
var/quirk_name = initial(T.name)
|
||||
var/has_quirk
|
||||
var/quirk_cost = initial(T.value) * -1
|
||||
var/lock_reason = "This trait is unavailable."
|
||||
var/trait_conflict = FALSE
|
||||
for(var/_V in all_traits)
|
||||
if(_V == trait_name)
|
||||
has_trait = TRUE
|
||||
if(initial(T.mood_trait) && CONFIG_GET(flag/disable_human_mood))
|
||||
var/quirk_conflict = FALSE
|
||||
for(var/_V in all_quirks)
|
||||
if(_V == quirk_name)
|
||||
has_quirk = TRUE
|
||||
if(initial(T.mood_quirk) && CONFIG_GET(flag/disable_human_mood))
|
||||
lock_reason = "Mood is disabled."
|
||||
trait_conflict = TRUE
|
||||
if(has_trait)
|
||||
if(trait_conflict)
|
||||
all_traits -= trait_name
|
||||
has_trait = FALSE
|
||||
quirk_conflict = TRUE
|
||||
if(has_quirk)
|
||||
if(quirk_conflict)
|
||||
all_quirks -= quirk_name
|
||||
has_quirk = FALSE
|
||||
else
|
||||
trait_cost *= -1 //invert it back, since we'd be regaining this amount
|
||||
if(trait_cost > 0)
|
||||
trait_cost = "+[trait_cost]"
|
||||
quirk_cost *= -1 //invert it back, since we'd be regaining this amount
|
||||
if(quirk_cost > 0)
|
||||
quirk_cost = "+[quirk_cost]"
|
||||
var/font_color = "#AAAAFF"
|
||||
if(initial(T.value) != 0)
|
||||
font_color = initial(T.value) > 0 ? "#AAFFAA" : "#FFAAAA"
|
||||
if(trait_conflict)
|
||||
dat += "<font color='[font_color]'>[trait_name]</font> - [initial(T.desc)] \
|
||||
if(quirk_conflict)
|
||||
dat += "<font color='[font_color]'>[quirk_name]</font> - [initial(T.desc)] \
|
||||
<font color='red'><b>LOCKED: [lock_reason]</b></font><br>"
|
||||
else
|
||||
if(has_trait)
|
||||
dat += "<b><font color='[font_color]'>[trait_name]</font></b> - [initial(T.desc)] \
|
||||
<a href='?_src_=prefs;preference=trait;task=update;trait=[trait_name]'>[has_trait ? "Lose" : "Take"] ([trait_cost] pts.)</a><br>"
|
||||
if(has_quirk)
|
||||
dat += "<b><font color='[font_color]'>[quirk_name]</font></b> - [initial(T.desc)] \
|
||||
<a href='?_src_=prefs;preference=trait;task=update;trait=[quirk_name]'>[has_quirk ? "Lose" : "Take"] ([quirk_cost] pts.)</a><br>"
|
||||
else
|
||||
dat += "<font color='[font_color]'>[trait_name]</font> - [initial(T.desc)] \
|
||||
<a href='?_src_=prefs;preference=trait;task=update;trait=[trait_name]'>[has_trait ? "Lose" : "Take"] ([trait_cost] pts.)</a><br>"
|
||||
dat += "<font color='[font_color]'>[quirk_name]</font> - [initial(T.desc)] \
|
||||
<a href='?_src_=prefs;preference=trait;task=update;trait=[quirk_name]'>[has_quirk ? "Lose" : "Take"] ([quirk_cost] pts.)</a><br>"
|
||||
dat += "<br><center><a href='?_src_=prefs;preference=trait;task=reset'>Reset Traits</a></center>"
|
||||
|
||||
user << browse(null, "window=preferences")
|
||||
var/datum/browser/popup = new(user, "mob_occupation", "<div align='center'>Trait Preferences</div>", 900, 600) //no reason not to reuse the occupation window, as it's cleaner that way
|
||||
var/datum/browser/popup = new(user, "mob_occupation", "<div align='center'>Quirk Preferences</div>", 900, 600) //no reason not to reuse the occupation window, as it's cleaner that way
|
||||
popup.set_window_options("can_close=0")
|
||||
popup.set_content(dat.Join())
|
||||
popup.open(0)
|
||||
return
|
||||
|
||||
/datum/preferences/proc/GetTraitBalance()
|
||||
/datum/preferences/proc/GetQuirkBalance()
|
||||
var/bal = 0
|
||||
for(var/V in all_traits)
|
||||
var/datum/trait/T = SStraits.traits[V]
|
||||
for(var/V in all_quirks)
|
||||
var/datum/quirk/T = SSquirks.quirks[V]
|
||||
bal -= initial(T.value)
|
||||
return bal
|
||||
|
||||
@@ -977,55 +981,49 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
user << browse(null, "window=mob_occupation")
|
||||
ShowChoices(user)
|
||||
if("update")
|
||||
var/trait = href_list["trait"]
|
||||
if(!SStraits.traits[trait])
|
||||
var/quirk = href_list["trait"]
|
||||
if(!SSquirks.quirks[quirk])
|
||||
return
|
||||
var/value = SStraits.trait_points[trait]
|
||||
var/value = SSquirks.quirk_points[quirk]
|
||||
if(value == 0)
|
||||
if(trait in neutral_traits)
|
||||
neutral_traits -= trait
|
||||
all_traits -= trait
|
||||
if(quirk in neutral_quirks)
|
||||
neutral_quirks -= quirk
|
||||
all_quirks -= quirk
|
||||
else
|
||||
if(all_traits.len >= MAX_TRAITS)
|
||||
to_chat(user, "<span class='warning'>You can't have more than [MAX_TRAITS] traits!</span>")
|
||||
return
|
||||
neutral_traits += trait
|
||||
all_traits += trait
|
||||
neutral_quirks += quirk
|
||||
all_quirks += quirk
|
||||
else
|
||||
var/balance = GetTraitBalance()
|
||||
if(trait in positive_traits)
|
||||
positive_traits -= trait
|
||||
all_traits -= trait
|
||||
else if(trait in negative_traits)
|
||||
var/balance = GetQuirkBalance()
|
||||
if(quirk in positive_quirks)
|
||||
positive_quirks -= quirk
|
||||
all_quirks -= quirk
|
||||
else if(quirk in negative_quirks)
|
||||
if(balance + value < 0)
|
||||
to_chat(user, "<span class='warning'>Refunding this would cause you to go below your balance!</span>")
|
||||
return
|
||||
negative_traits -= trait
|
||||
all_traits -= trait
|
||||
negative_quirks -= quirk
|
||||
all_quirks -= quirk
|
||||
else if(value > 0)
|
||||
if(all_traits.len >= MAX_TRAITS)
|
||||
to_chat(user, "<span class='warning'>You can't have more than [MAX_TRAITS] traits!</span>")
|
||||
if(positive_quirks.len >= MAX_QUIRKS)
|
||||
to_chat(user, "<span class='warning'>You can't have more than [MAX_QUIRKS] positive quirks!</span>")
|
||||
return
|
||||
if(balance - value < 0)
|
||||
to_chat(user, "<span class='warning'>You don't have enough balance to gain this trait!</span>")
|
||||
to_chat(user, "<span class='warning'>You don't have enough balance to gain this quirk!</span>")
|
||||
return
|
||||
positive_traits += trait
|
||||
all_traits += trait
|
||||
positive_quirks += quirk
|
||||
all_quirks += quirk
|
||||
else
|
||||
if(all_traits.len >= MAX_TRAITS)
|
||||
to_chat(user, "<span class='warning'>You can't have more than [MAX_TRAITS] traits!</span>")
|
||||
return
|
||||
negative_traits += trait
|
||||
all_traits += trait
|
||||
SetTraits(user)
|
||||
negative_quirks += quirk
|
||||
all_quirks += quirk
|
||||
SetQuirks(user)
|
||||
if("reset")
|
||||
all_traits = list()
|
||||
positive_traits = list()
|
||||
negative_traits = list()
|
||||
neutral_traits = list()
|
||||
SetTraits(user)
|
||||
all_quirks = list()
|
||||
positive_quirks = list()
|
||||
negative_quirks = list()
|
||||
neutral_quirks = list()
|
||||
SetQuirks(user)
|
||||
else
|
||||
SetTraits(user)
|
||||
SetQuirks(user)
|
||||
return TRUE
|
||||
|
||||
switch(href_list["task"])
|
||||
@@ -1535,6 +1533,14 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
cit_toggles ^= DIGESTION_NOISES
|
||||
//END CITADEL EDIT
|
||||
|
||||
if("ambientocclusion")
|
||||
ambientocclusion = !ambientocclusion
|
||||
if(parent && parent.screen && parent.screen.len)
|
||||
var/obj/screen/plane_master/game_world/PM = locate(/obj/screen/plane_master/game_world) in parent.screen
|
||||
PM.filters -= AMBIENT_OCCLUSION
|
||||
if(ambientocclusion)
|
||||
PM.filters += AMBIENT_OCCLUSION
|
||||
|
||||
if("save")
|
||||
save_preferences()
|
||||
save_character()
|
||||
@@ -1642,4 +1648,4 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(icon_updates)
|
||||
character.update_body()
|
||||
character.update_hair()
|
||||
character.update_body_parts()
|
||||
character.update_body_parts()
|
||||
|
||||
@@ -130,6 +130,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["uses_glasses_colour"]>> uses_glasses_colour
|
||||
S["clientfps"] >> clientfps
|
||||
S["parallax"] >> parallax
|
||||
S["ambientocclusion"] >> ambientocclusion
|
||||
S["menuoptions"] >> menuoptions
|
||||
S["enable_tips"] >> enable_tips
|
||||
S["tip_delay"] >> tip_delay
|
||||
@@ -160,6 +161,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
toggles = sanitize_integer(toggles, 0, 65535, initial(toggles))
|
||||
clientfps = sanitize_integer(clientfps, 0, 1000, 0)
|
||||
parallax = sanitize_integer(parallax, PARALLAX_INSANE, PARALLAX_DISABLE, null)
|
||||
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
|
||||
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
|
||||
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
|
||||
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
|
||||
@@ -210,6 +212,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["uses_glasses_colour"], uses_glasses_colour)
|
||||
WRITE_FILE(S["clientfps"], clientfps)
|
||||
WRITE_FILE(S["parallax"], parallax)
|
||||
WRITE_FILE(S["ambientocclusion"], ambientocclusion)
|
||||
WRITE_FILE(S["menuoptions"], menuoptions)
|
||||
WRITE_FILE(S["enable_tips"], enable_tips)
|
||||
WRITE_FILE(S["tip_delay"], tip_delay)
|
||||
@@ -310,11 +313,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
S["job_engsec_med"] >> job_engsec_med
|
||||
S["job_engsec_low"] >> job_engsec_low
|
||||
|
||||
//Traits
|
||||
S["all_traits"] >> all_traits
|
||||
S["positive_traits"] >> positive_traits
|
||||
S["negative_traits"] >> negative_traits
|
||||
S["neutral_traits"] >> neutral_traits
|
||||
//Quirks
|
||||
S["all_quirks"] >> all_quirks
|
||||
S["positive_quirks"] >> positive_quirks
|
||||
S["negative_quirks"] >> negative_quirks
|
||||
S["neutral_quirks"] >> neutral_quirks
|
||||
|
||||
//Citadel code
|
||||
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
|
||||
@@ -421,10 +424,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
job_engsec_med = sanitize_integer(job_engsec_med, 0, 65535, initial(job_engsec_med))
|
||||
job_engsec_low = sanitize_integer(job_engsec_low, 0, 65535, initial(job_engsec_low))
|
||||
|
||||
all_traits = SANITIZE_LIST(all_traits)
|
||||
positive_traits = SANITIZE_LIST(positive_traits)
|
||||
negative_traits = SANITIZE_LIST(negative_traits)
|
||||
neutral_traits = SANITIZE_LIST(neutral_traits)
|
||||
all_quirks = SANITIZE_LIST(all_quirks)
|
||||
positive_quirks = SANITIZE_LIST(positive_quirks)
|
||||
negative_quirks = SANITIZE_LIST(negative_quirks)
|
||||
neutral_quirks = SANITIZE_LIST(neutral_quirks)
|
||||
|
||||
cit_character_pref_load(S)
|
||||
|
||||
@@ -491,11 +494,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["job_engsec_med"] , job_engsec_med)
|
||||
WRITE_FILE(S["job_engsec_low"] , job_engsec_low)
|
||||
|
||||
//Traits
|
||||
WRITE_FILE(S["all_traits"] , all_traits)
|
||||
WRITE_FILE(S["positive_traits"] , positive_traits)
|
||||
WRITE_FILE(S["negative_traits"] , negative_traits)
|
||||
WRITE_FILE(S["neutral_traits"] , neutral_traits)
|
||||
//Quirks
|
||||
WRITE_FILE(S["all_quirks"] , all_quirks)
|
||||
WRITE_FILE(S["positive_quirks"] , positive_quirks)
|
||||
WRITE_FILE(S["negative_quirks"] , negative_quirks)
|
||||
WRITE_FILE(S["neutral_quirks"] , neutral_quirks)
|
||||
|
||||
cit_character_pref_save(S)
|
||||
|
||||
|
||||
@@ -81,12 +81,14 @@
|
||||
|
||||
/obj/item/clothing/equipped(mob/user, slot)
|
||||
..()
|
||||
|
||||
if (!istype(user))
|
||||
return
|
||||
if(slot_flags & slotdefine2slotbit(slot)) //Was equipped to a valid slot for this item?
|
||||
for(var/variable in user_vars_to_edit)
|
||||
if(variable in user.vars)
|
||||
user_vars_remembered[variable] = user.vars[variable]
|
||||
user.vars[variable] = user_vars_to_edit[variable]
|
||||
if (LAZYLEN(user_vars_to_edit))
|
||||
for(var/variable in user_vars_to_edit)
|
||||
if(variable in user.vars)
|
||||
LAZYSET(user_vars_remembered, variable, user.vars[variable])
|
||||
user.vv_edit_var(variable, user_vars_to_edit[variable])
|
||||
|
||||
/obj/item/clothing/examine(mob/user)
|
||||
..()
|
||||
@@ -285,4 +287,4 @@ BLIND // can't see anything
|
||||
Shreds.desc = "The sad remains of what used to be [name]."
|
||||
deconstruct(FALSE)
|
||||
else
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -365,6 +365,7 @@
|
||||
scan_reagents = 1
|
||||
flags_1 = NODROP_1
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF
|
||||
|
||||
/obj/item/clothing/glasses/godeye/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
if(istype(W, src) && W != src && W.loc == user)
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
MA.alpha = 180
|
||||
MA.maptext = "[strength]k"
|
||||
MA.color = "#64C864"
|
||||
MA.layer = AREA_LAYER
|
||||
MA.layer = FLY_LAYER
|
||||
pic.appearance = MA
|
||||
flick_overlay(pic, list(user.client), 8)
|
||||
|
||||
|
||||
@@ -158,12 +158,20 @@
|
||||
strip_delay = 100
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/clothing/head/helmet/roman/fake
|
||||
desc = "An ancient helmet made of plastic and leather."
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
|
||||
/obj/item/clothing/head/helmet/roman/legionaire
|
||||
name = "roman legionaire helmet"
|
||||
desc = "An ancient helmet made of bronze and leather. Has a red crest on top of it."
|
||||
icon_state = "roman_c"
|
||||
item_state = "roman_c"
|
||||
|
||||
/obj/item/clothing/head/helmet/roman/legionaire/fake
|
||||
desc = "An ancient helmet made of plastic and leather. Has a red crest on top of it."
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
|
||||
/obj/item/clothing/head/helmet/gladiator
|
||||
name = "gladiator helmet"
|
||||
desc = "Ave, Imperator, morituri te salutant."
|
||||
|
||||
@@ -321,4 +321,27 @@
|
||||
name = "headress of Nemes"
|
||||
desc = "Lavish space tomb not included."
|
||||
icon_state = "nemes_headdress"
|
||||
icon_state = "nemes_headdress"
|
||||
icon_state = "nemes_headdress"
|
||||
|
||||
/obj/item/clothing/head/frenchberet
|
||||
name = "french beret"
|
||||
desc = "A quality beret, infused with the aroma of chain-smoking, wine-swilling Parisians. You feel less inclined to engage military conflict, for some reason."
|
||||
icon_state = "beretblack"
|
||||
|
||||
/obj/item/clothing/head/frenchberet/speechModification(M)
|
||||
if(copytext(M, 1, 2) != "*")
|
||||
M = " [M]"
|
||||
var/list/french_words = strings("french_replacement.json", "french")
|
||||
|
||||
for(var/key in french_words)
|
||||
var/value = french_words[key]
|
||||
if(islist(value))
|
||||
value = pick(value)
|
||||
|
||||
M = replacetextEx(M, " [uppertext(key)]", " [uppertext(value)]")
|
||||
M = replacetextEx(M, " [capitalize(key)]", " [capitalize(value)]")
|
||||
M = replacetextEx(M, " [key]", " [value]")
|
||||
|
||||
if(prob(3))
|
||||
M += pick(" Honh honh honh!"," Honh!"," Zut Alors!")
|
||||
return trim(M)
|
||||
@@ -47,7 +47,7 @@
|
||||
/obj/item/clothing/mask/fakemoustache/italian/speechModification(M)
|
||||
if(copytext(M, 1, 2) != "*")
|
||||
M = " [M]"
|
||||
var/list/italian_words = strings("word_replacement.json", "italian")
|
||||
var/list/italian_words = strings("italian_replacement.json", "italian")
|
||||
|
||||
for(var/key in italian_words)
|
||||
var/value = italian_words[key]
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
if(user.transferItemToLoc(I, src))
|
||||
jetpack = I
|
||||
to_chat(user, "<span class='notice'>You successfully install the jetpack into [src].</span>")
|
||||
|
||||
return
|
||||
else if(istype(I, /obj/item/screwdriver))
|
||||
if(!jetpack)
|
||||
to_chat(user, "<span class='warning'>[src] has no jetpack installed.</span>")
|
||||
@@ -139,6 +139,8 @@
|
||||
jetpack.forceMove(drop_location())
|
||||
jetpack = null
|
||||
to_chat(user, "<span class='notice'>You successfully remove the jetpack from [src].</span>")
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/equipped(mob/user, slot)
|
||||
@@ -237,6 +239,9 @@
|
||||
brightness_on = 7
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
|
||||
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/mining/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/armor_plate)
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/mining
|
||||
icon_state = "hardsuit-mining"
|
||||
@@ -250,6 +255,10 @@
|
||||
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/mining
|
||||
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
|
||||
|
||||
/obj/item/clothing/suit/space/hardsuit/mining/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/armor_plate)
|
||||
|
||||
//Syndicate hardsuit
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/syndi
|
||||
name = "blood-red hardsuit helmet"
|
||||
|
||||
@@ -165,186 +165,6 @@
|
||||
. = ..()
|
||||
allowed = GLOB.detective_vest_allowed
|
||||
|
||||
//Reactive armor
|
||||
/obj/item/clothing/suit/armor/reactive
|
||||
name = "reactive armor"
|
||||
desc = "Doesn't seem to do much for some reason."
|
||||
var/active = 0
|
||||
var/reactivearmor_cooldown_duration = 0 //cooldown specific to reactive armor
|
||||
var/reactivearmor_cooldown = 0
|
||||
icon_state = "reactiveoff"
|
||||
item_state = "reactiveoff"
|
||||
blood_overlay_type = "armor"
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
actions_types = list(/datum/action/item_action/toggle)
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
hit_reaction_chance = 50
|
||||
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/attack_self(mob/user)
|
||||
src.active = !( src.active )
|
||||
if (src.active)
|
||||
to_chat(user, "<span class='notice'>[src] is now active.</span>")
|
||||
src.icon_state = "reactive"
|
||||
src.item_state = "reactive"
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] is now inactive.</span>")
|
||||
src.icon_state = "reactiveoff"
|
||||
src.item_state = "reactiveoff"
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/emp_act(severity)
|
||||
active = 0
|
||||
src.icon_state = "reactiveoff"
|
||||
src.item_state = "reactiveoff"
|
||||
reactivearmor_cooldown = world.time + 200
|
||||
..()
|
||||
|
||||
//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
|
||||
/obj/item/clothing/suit/armor/reactive/teleport
|
||||
name = "reactive teleport armor"
|
||||
desc = "Someone separated our Research Director from his own head!"
|
||||
var/tele_range = 6
|
||||
var/rad_amount= 15
|
||||
reactivearmor_cooldown_duration = 100
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/teleport/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive teleport system is still recharging! It fails to teleport [H]!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>The reactive teleport system flings [H] clear of [attack_text], shutting itself off in the process!</span>")
|
||||
var/list/turfs = new/list()
|
||||
for(var/turf/T in orange(tele_range, H))
|
||||
if(T.density)
|
||||
continue
|
||||
if(T.x>world.maxx-tele_range || T.x<tele_range)
|
||||
continue
|
||||
if(T.y>world.maxy-tele_range || T.y<tele_range)
|
||||
continue
|
||||
turfs += T
|
||||
if(!turfs.len)
|
||||
turfs += pick(/turf in orange(tele_range, H))
|
||||
var/turf/picked = pick(turfs)
|
||||
if(!isturf(picked))
|
||||
return
|
||||
H.forceMove(picked)
|
||||
H.rad_act(rad_amount)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/fire
|
||||
name = "reactive incendiary armor"
|
||||
desc = "An experimental suit of armor with a reactive sensor array rigged to a flame emitter. For the stylish pyromaniac."
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/fire/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive incendiary armor on [owner] activates, but fails to send out flames as it is still recharging its flame jets!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[src] blocks [attack_text], sending out jets of flame!</span>")
|
||||
for(var/mob/living/carbon/C in range(6, owner))
|
||||
if(C != owner)
|
||||
C.fire_stacks += 8
|
||||
C.IgniteMob()
|
||||
owner.fire_stacks = -20
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth
|
||||
name = "reactive stealth armor"
|
||||
desc = "An experimental suit of armor that renders the wearer invisible on detection of imminent harm, and creates a decoy that runs away from the owner. You can't fight what you can't see."
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive stealth system on [owner] activates, but is still recharging its holographic emitters!</span>")
|
||||
return
|
||||
var/mob/living/simple_animal/hostile/illusion/escape/E = new(owner.loc)
|
||||
E.Copy_Parent(owner, 50)
|
||||
E.GiveTarget(owner) //so it starts running right away
|
||||
E.Goto(owner, E.move_to_delay, E.minimum_distance)
|
||||
owner.alpha = 0
|
||||
owner.visible_message("<span class='danger'>[owner] is hit by [attack_text] in the chest!</span>") //We pretend to be hit, since blocking it would stop the message otherwise
|
||||
spawn(40)
|
||||
owner.alpha = initial(owner.alpha)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla
|
||||
name = "reactive tesla armor"
|
||||
desc = "An experimental suit of armor with sensitive detectors hooked up to a huge capacitor grid, with emitters strutting out of it. Zap."
|
||||
siemens_coefficient = -1
|
||||
var/tesla_power = 25000
|
||||
var/tesla_range = 20
|
||||
var/tesla_boom = FALSE
|
||||
var/tesla_stun = FALSE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
|
||||
sparks.set_up(1, 1, src)
|
||||
sparks.start()
|
||||
owner.visible_message("<span class='danger'>The tesla capacitors on [owner]'s reactive tesla armor are still recharging! The armor merely emits some sparks.</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[src] blocks [attack_text], sending out arcs of lightning!</span>")
|
||||
tesla_zap(owner,tesla_range,tesla_power,tesla_boom, tesla_stun)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/table
|
||||
name = "reactive table armor"
|
||||
desc = "If you can't beat the memes, embrace them."
|
||||
var/tele_range = 10
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/table/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive table armor's fabricators are still on cooldown!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>The reactive teleport system flings [H] clear of [attack_text] and slams them into a fabricated table!</span>")
|
||||
owner.visible_message("<font color='red' size='3'>[H] GOES ON THE TABLE!!!</font>")
|
||||
owner.Knockdown(40)
|
||||
var/list/turfs = new/list()
|
||||
for(var/turf/T in orange(tele_range, H))
|
||||
if(T.density)
|
||||
continue
|
||||
if(T.x>world.maxx-tele_range || T.x<tele_range)
|
||||
continue
|
||||
if(T.y>world.maxy-tele_range || T.y<tele_range)
|
||||
continue
|
||||
turfs += T
|
||||
if(!turfs.len)
|
||||
turfs += pick(/turf in orange(tele_range, H))
|
||||
var/turf/picked = pick(turfs)
|
||||
if(!isturf(picked))
|
||||
return
|
||||
H.forceMove(picked)
|
||||
new /obj/structure/table(get_turf(owner))
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/table/emp_act()
|
||||
return
|
||||
|
||||
//All of the armor below is mostly unused
|
||||
|
||||
/obj/item/clothing/suit/armor/centcom
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/obj/item/reactive_armour_shell
|
||||
name = "reactive armour shell"
|
||||
desc = "An experimental suit of armour, awaiting installation of an anomaly core."
|
||||
icon_state = "reactiveoff"
|
||||
icon = 'icons/obj/clothing/suits.dmi'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/reactive_armour_shell/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
var/static/list/anomaly_armour_types = list(
|
||||
/obj/effect/anomaly/grav = /obj/item/clothing/suit/armor/reactive/repulse,
|
||||
/obj/effect/anomaly/flux = /obj/item/clothing/suit/armor/reactive/tesla,
|
||||
/obj/effect/anomaly/bluespace = /obj/item/clothing/suit/armor/reactive/teleport,
|
||||
/obj/effect/anomaly/pyro = /obj/item/clothing/suit/armor/reactive/fire)
|
||||
|
||||
if(istype(I, /obj/item/assembly/signaler/anomaly))
|
||||
var/obj/item/assembly/signaler/anomaly/A = I
|
||||
var/armour_path = anomaly_armour_types[A.anomaly_type]
|
||||
if(!armour_path)
|
||||
armour_path = /obj/item/clothing/suit/armor/reactive/stealth //Lets not cheat the player if an anomaly type doesnt have its own armour coded
|
||||
to_chat(user, "You insert [A] into the chest plate, and the armour gently hums to life.")
|
||||
new armour_path(get_turf(src))
|
||||
qdel(src)
|
||||
qdel(A)
|
||||
|
||||
//Reactive armor
|
||||
/obj/item/clothing/suit/armor/reactive
|
||||
name = "reactive armor"
|
||||
desc = "Doesn't seem to do much for some reason."
|
||||
var/active = 0
|
||||
var/reactivearmor_cooldown_duration = 0 //cooldown specific to reactive armor
|
||||
var/reactivearmor_cooldown = 0
|
||||
icon_state = "reactiveoff"
|
||||
item_state = "reactiveoff"
|
||||
blood_overlay_type = "armor"
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
actions_types = list(/datum/action/item_action/toggle)
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
hit_reaction_chance = 50
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/attack_self(mob/user)
|
||||
active = !(active)
|
||||
if(active)
|
||||
to_chat(user, "<span class='notice'>[src] is now active.</span>")
|
||||
icon_state = "reactive"
|
||||
item_state = "reactive"
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] is now inactive.</span>")
|
||||
icon_state = "reactiveoff"
|
||||
item_state = "reactiveoff"
|
||||
add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/emp_act(severity)
|
||||
active = 0
|
||||
icon_state = "reactiveoff"
|
||||
item_state = "reactiveoff"
|
||||
reactivearmor_cooldown = world.time + 200
|
||||
..()
|
||||
|
||||
//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
|
||||
/obj/item/clothing/suit/armor/reactive/teleport
|
||||
name = "reactive teleport armor"
|
||||
desc = "Someone separated our Research Director from his own head!"
|
||||
var/tele_range = 6
|
||||
var/rad_amount= 15
|
||||
reactivearmor_cooldown_duration = 100
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/teleport/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive teleport system is still recharging! It fails to teleport [H]!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>The reactive teleport system flings [H] clear of [attack_text], shutting itself off in the process!</span>")
|
||||
var/list/turfs = new/list()
|
||||
for(var/turf/T in orange(tele_range, H))
|
||||
if(T.density)
|
||||
continue
|
||||
if(T.x>world.maxx-tele_range || T.x<tele_range)
|
||||
continue
|
||||
if(T.y>world.maxy-tele_range || T.y<tele_range)
|
||||
continue
|
||||
turfs += T
|
||||
if(!turfs.len)
|
||||
turfs += pick(/turf in orange(tele_range, H))
|
||||
var/turf/picked = pick(turfs)
|
||||
if(!isturf(picked))
|
||||
return
|
||||
H.forceMove(picked)
|
||||
H.rad_act(rad_amount)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Fire
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/fire
|
||||
name = "reactive incendiary armor"
|
||||
desc = "An experimental suit of armor with a reactive sensor array rigged to a flame emitter. For the stylish pyromaniac."
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/fire/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive incendiary armor on [owner] activates, but fails to send out flames as it is still recharging its flame jets!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[src] blocks [attack_text], sending out jets of flame!</span>")
|
||||
for(var/mob/living/carbon/C in range(6, owner))
|
||||
if(C != owner)
|
||||
C.fire_stacks += 8
|
||||
C.IgniteMob()
|
||||
owner.fire_stacks = -20
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Stealth
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth
|
||||
name = "reactive stealth armor"
|
||||
desc = "An experimental suit of armor that renders the wearer invisible on detection of imminent harm, and creates a decoy that runs away from the owner. You can't fight what you can't see."
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/stealth/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive stealth system on [owner] activates, but is still recharging its holographic emitters!</span>")
|
||||
return
|
||||
var/mob/living/simple_animal/hostile/illusion/escape/E = new(owner.loc)
|
||||
E.Copy_Parent(owner, 50)
|
||||
E.GiveTarget(owner) //so it starts running right away
|
||||
E.Goto(owner, E.move_to_delay, E.minimum_distance)
|
||||
owner.alpha = 0
|
||||
owner.visible_message("<span class='danger'>[owner] is hit by [attack_text] in the chest!</span>") //We pretend to be hit, since blocking it would stop the message otherwise
|
||||
spawn(40)
|
||||
owner.alpha = initial(owner.alpha)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
|
||||
//Tesla
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla
|
||||
name = "reactive tesla armor"
|
||||
desc = "An experimental suit of armor with sensitive detectors hooked up to a huge capacitor grid, with emitters strutting out of it. Zap."
|
||||
siemens_coefficient = -1
|
||||
var/tesla_power = 25000
|
||||
var/tesla_range = 20
|
||||
var/tesla_boom = FALSE
|
||||
var/tesla_stun = FALSE
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/tesla/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
var/datum/effect_system/spark_spread/sparks = new /datum/effect_system/spark_spread
|
||||
sparks.set_up(1, 1, src)
|
||||
sparks.start()
|
||||
owner.visible_message("<span class='danger'>The tesla capacitors on [owner]'s reactive tesla armor are still recharging! The armor merely emits some sparks.</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>[src] blocks [attack_text], sending out arcs of lightning!</span>")
|
||||
tesla_zap(owner,tesla_range,tesla_power,tesla_boom, tesla_stun)
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
|
||||
|
||||
//Repulse
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/repulse
|
||||
name = "reactive repulse armor"
|
||||
desc = "An experimental suit of armor that violently throws back attackers."
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/repulse/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The repulse generator is still recharging!</span>")
|
||||
return 0
|
||||
owner.visible_message("<span class='danger'>[src] blocks [attack_text], converting the attack into a wave of force!</span>")
|
||||
var/turf/T = get_turf(owner)
|
||||
var/list/thrown_items = list()
|
||||
for(var/atom/movable/A in range(T, 7))
|
||||
if(A == owner || A.anchored || thrown_items[A])
|
||||
continue
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(A, src)))
|
||||
A.throw_at(throwtarget,10,1)
|
||||
thrown_items[A] = A
|
||||
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/table
|
||||
name = "reactive table armor"
|
||||
desc = "If you can't beat the memes, embrace them."
|
||||
var/tele_range = 10
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/table/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(!active)
|
||||
return 0
|
||||
if(prob(hit_reaction_chance))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(world.time < reactivearmor_cooldown)
|
||||
owner.visible_message("<span class='danger'>The reactive table armor's fabricators are still on cooldown!</span>")
|
||||
return
|
||||
owner.visible_message("<span class='danger'>The reactive teleport system flings [H] clear of [attack_text] and slams them into a fabricated table!</span>")
|
||||
owner.visible_message("<font color='red' size='3'>[H] GOES ON THE TABLE!!!</font>")
|
||||
owner.Knockdown(40)
|
||||
var/list/turfs = new/list()
|
||||
for(var/turf/T in orange(tele_range, H))
|
||||
if(T.density)
|
||||
continue
|
||||
if(T.x>world.maxx-tele_range || T.x<tele_range)
|
||||
continue
|
||||
if(T.y>world.maxy-tele_range || T.y<tele_range)
|
||||
continue
|
||||
turfs += T
|
||||
if(!turfs.len)
|
||||
turfs += pick(/turf in orange(tele_range, H))
|
||||
var/turf/picked = pick(turfs)
|
||||
if(!isturf(picked))
|
||||
return
|
||||
H.forceMove(picked)
|
||||
new /obj/structure/table(get_turf(owner))
|
||||
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/clothing/suit/armor/reactive/table/emp_act()
|
||||
return
|
||||
@@ -28,6 +28,14 @@
|
||||
item_state = "gy_suit"
|
||||
item_color = "security"
|
||||
|
||||
/obj/item/clothing/under/rank/security/skirt
|
||||
name = "security jumpskirt"
|
||||
desc = "A \"tactical\" security jumpsuit with the legs replaced by a skirt."
|
||||
icon_state = "secskirt"
|
||||
item_state = "r_suit"
|
||||
item_color = "secskirt"
|
||||
can_adjust = FALSE //you know now that i think of it if you adjust the skirt and the sprite disappears isn't that just like flashing everyone
|
||||
|
||||
|
||||
/obj/item/clothing/under/rank/warden
|
||||
name = "security suit"
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
search = findtext(text, ":", pos+1)
|
||||
if(search)
|
||||
emoji = lowertext(copytext(text, pos+1, search))
|
||||
if(emoji in emojis)
|
||||
parsed += icon2html('icons/emoji.dmi', world, emoji)
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat)
|
||||
var/tag = sheet.icon_tag("emoji-[emoji]")
|
||||
if(tag)
|
||||
parsed += tag
|
||||
pos = search + 1
|
||||
else
|
||||
parsed += copytext(text, pos, search)
|
||||
|
||||
@@ -344,6 +344,15 @@
|
||||
list_reagents = list("limejuice" = 100)
|
||||
foodtype = FRUIT
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/bottle/menthol
|
||||
name = "menthol"
|
||||
desc = "Tastes naturally minty, and imparts a very mild numbing sensation."
|
||||
icon_state = "mentholbox"
|
||||
item_state = "carton"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/kitchen_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/kitchen_righthand.dmi'
|
||||
isGlass = FALSE
|
||||
list_reagents = list("menthol" = 100)
|
||||
|
||||
////////////////////////// MOLOTOV ///////////////////////
|
||||
/obj/item/reagent_containers/food/drinks/bottle/molotov
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
desc = "A timeless classic."
|
||||
ingredients_placement = INGREDIENTS_STACKPLUSTOP
|
||||
icon = 'icons/obj/food/burgerbread.dmi'
|
||||
icon_state = "bun"
|
||||
icon_state = "custburg"
|
||||
foodtype = GRAIN
|
||||
|
||||
|
||||
|
||||
@@ -299,8 +299,7 @@
|
||||
qdel(S)
|
||||
return TRUE
|
||||
for(var/obj/item/stack/sheet/wetleather/WL in src)
|
||||
var/obj/item/stack/sheet/leather/L = new(drop_location())
|
||||
L.amount = WL.amount
|
||||
new /obj/item/stack/sheet/leather(drop_location(), WL.amount)
|
||||
qdel(WL)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -623,4 +623,42 @@
|
||||
id = "crevice_spike"
|
||||
results = list("crevice_spike" = 6)
|
||||
required_reagents = list("limejuice" = 2, "capsaicin" = 4) //2 powdered delta (sour), 4 flanergide (spicy)
|
||||
mix_message = "The mixture stings your eyes as it settles."
|
||||
mix_message = "The mixture stings your eyes as it settles."
|
||||
|
||||
/datum/chemical_reaction/sake
|
||||
name = "sake"
|
||||
id = "sake"
|
||||
results = list("sake" = 10)
|
||||
required_reagents = list("rice" = 10)
|
||||
required_catalysts = list("enzyme" = 5)
|
||||
mix_message = "The rice grains ferment into a clear, sweet-smelling liquid."
|
||||
|
||||
/datum/chemical_reaction/alexander
|
||||
name = "Alexander"
|
||||
id = "alexander"
|
||||
results = list("alexander" = 3)
|
||||
required_reagents = list("cognac" = 1, "creme_de_cacao" = 1, "cream" = 1)
|
||||
|
||||
/datum/chemical_reaction/sidecar
|
||||
name = "Sidecar"
|
||||
id = "sidecar"
|
||||
results = list("sidecar" = 4)
|
||||
required_reagents = list("cognac" = 2, "triple_sec" = 1, "lemonjuice" = 1)
|
||||
|
||||
/datum/chemical_reaction/between_the_sheets
|
||||
name = "Between the Sheets"
|
||||
id = "between_the_sheets"
|
||||
results = list("between_the_sheets" = 5)
|
||||
required_reagents = list("rum" = 1, "sidecar" = 4)
|
||||
|
||||
/datum/chemical_reaction/kamikaze
|
||||
name = "Kamikaze"
|
||||
id = "kamikaze"
|
||||
results = list("kamikaze" = 3)
|
||||
required_reagents = list("vodka" = 1, "triple_sec" = 1, "limejuice" = 1)
|
||||
|
||||
/datum/chemical_reaction/mojito
|
||||
name = "Mojito"
|
||||
id = "mojito"
|
||||
results = list("mojito" = 5)
|
||||
required_reagents = list("rum" = 1, "sugar" = 1, "limejuice" = 1, "sodawater" = 1, "menthol" = 1)
|
||||
|
||||
@@ -46,8 +46,7 @@ GLOBAL_DATUM_INIT(iconCache, /savefile, new("data/iconCache.sav")) //Cache of ic
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
var/datum/asset/stuff = get_asset_datum(/datum/asset/simple/goonchat)
|
||||
stuff.register()
|
||||
var/datum/asset/stuff = get_asset_datum(/datum/asset/group/goonchat)
|
||||
stuff.send(owner)
|
||||
|
||||
owner << browse(file('code/modules/goonchat/browserassets/html/browserOutput.html'), "window=browseroutput")
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<link rel="stylesheet" type="text/css" href="font-awesome.css" />
|
||||
<link rel="stylesheet" type="text/css" href="browserOutput.css" />
|
||||
<link rel="stylesheet" type="text/css" href="spritesheet_chat.css" />
|
||||
<script type="text/javascript" src="errorHandler.js"></script>
|
||||
<script type="text/javascript" src="jquery.min.js"></script>
|
||||
<script type="text/javascript" src="json2.min.js"></script>
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
begin_month = DECEMBER
|
||||
end_day = 2
|
||||
end_month = JANUARY
|
||||
drone_hat = /obj/item/clothing/head/festive
|
||||
|
||||
/datum/holiday/new_year/getStationPrefix()
|
||||
return pick("Party","New","Hangover","Resolution")
|
||||
@@ -78,6 +79,7 @@
|
||||
name = "Groundhog Day"
|
||||
begin_day = 2
|
||||
begin_month = FEBRUARY
|
||||
drone_hat = /obj/item/clothing/head/helmet/space/chronos
|
||||
|
||||
/datum/holiday/valentines
|
||||
name = VALENTINES
|
||||
@@ -92,6 +94,7 @@
|
||||
name = "Birthday of Space Station 13"
|
||||
begin_day = 16
|
||||
begin_month = FEBRUARY
|
||||
drone_hat = /obj/item/clothing/head/festive
|
||||
|
||||
/datum/holiday/birthday/greet()
|
||||
var/game_age = text2num(time2text(world.timeofday, "YY")) - 3
|
||||
@@ -202,6 +205,7 @@
|
||||
name = "UFO Day"
|
||||
begin_day = 2
|
||||
begin_month = JULY
|
||||
drone_hat = /obj/item/clothing/mask/facehugger/dead
|
||||
|
||||
/datum/holiday/UFO/getStationPrefix() //Is such a thing even possible?
|
||||
return pick("Ayy","Truth","Tsoukalos","Mulder") //Yes it is!
|
||||
@@ -272,11 +276,13 @@
|
||||
name = "Smiling Day"
|
||||
begin_day = 7
|
||||
begin_month = OCTOBER
|
||||
drone_hat = /obj/item/clothing/head/papersack/smiley
|
||||
|
||||
/datum/holiday/boss
|
||||
name = "Boss' Day"
|
||||
begin_day = 16
|
||||
begin_month = OCTOBER
|
||||
drone_hat = /obj/item/clothing/head/that
|
||||
|
||||
/datum/holiday/halloween
|
||||
name = HALLOWEEN
|
||||
@@ -305,6 +311,7 @@
|
||||
name = "Flowers Day"
|
||||
begin_day = 19
|
||||
begin_month = NOVEMBER
|
||||
drone_hat = /obj/item/reagent_containers/food/snacks/grown/moonflower
|
||||
|
||||
/datum/holiday/hello
|
||||
name = "Saying-'Hello' Day"
|
||||
@@ -312,7 +319,7 @@
|
||||
begin_month = NOVEMBER
|
||||
|
||||
/datum/holiday/hello/greet()
|
||||
return "[pick(list("Aloha", "Bonjour", "Hello", "Hi", "Greetings", "Salutations", "Bienvenidos", "Hola", "Howdy"))]! " + ..()
|
||||
return "[pick(list("Aloha", "Bonjour", "Hello", "Hi", "Greetings", "Salutations", "Bienvenidos", "Hola", "Howdy", "Ni hao", "Guten Tag", "Konnichiwa", "G'day cunt"))]! " + ..()
|
||||
|
||||
/datum/holiday/human_rights
|
||||
name = "Human-Rights Day"
|
||||
@@ -323,6 +330,7 @@
|
||||
name = "Monkey Day"
|
||||
begin_day = 14
|
||||
begin_month = DECEMBER
|
||||
drone_hat = /obj/item/clothing/mask/gas/monkeymask
|
||||
|
||||
/datum/holiday/thanksgiving
|
||||
name = "Thanksgiving in the United States"
|
||||
|
||||
@@ -262,8 +262,7 @@
|
||||
if(!check_cost(D.materials, amount))
|
||||
return FALSE
|
||||
|
||||
var/obj/item/stack/product = new D.build_path(loc)
|
||||
product.amount = amount
|
||||
new D.build_path(drop_location(), amount)
|
||||
for(var/R in D.make_reagents)
|
||||
beaker.reagents.add_reagent(R, D.make_reagents[R]*amount)
|
||||
else
|
||||
|
||||
@@ -85,14 +85,15 @@
|
||||
interact(user)
|
||||
return
|
||||
else if(istype(I, /obj/item/disk/plantgene))
|
||||
if(disk)
|
||||
to_chat(user, "<span class='warning'>A data disk is already loaded into the machine!</span>")
|
||||
else
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
disk = I
|
||||
to_chat(user, "<span class='notice'>You add [I] to the machine.</span>")
|
||||
interact(user)
|
||||
if (operation)
|
||||
to_chat(user, "<span class='notice'>Please complete current operation.</span>")
|
||||
return
|
||||
eject_disk()
|
||||
if(!user.transferItemToLoc(I, src))
|
||||
return
|
||||
disk = I
|
||||
to_chat(user, "<span class='notice'>You add [I] to the machine.</span>")
|
||||
interact(user)
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -266,18 +267,13 @@
|
||||
to_chat(usr, "<span class='notice'>You add [I] to the machine.</span>")
|
||||
update_icon()
|
||||
else if(href_list["eject_disk"] && !operation)
|
||||
if (disk)
|
||||
disk.forceMove(drop_location())
|
||||
disk.verb_pickup()
|
||||
disk = null
|
||||
update_genes()
|
||||
else
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
if(istype(I, /obj/item/disk/plantgene))
|
||||
if(!usr.transferItemToLoc(I, src))
|
||||
return
|
||||
disk = I
|
||||
to_chat(usr, "<span class='notice'>You add [I] to the machine.</span>")
|
||||
var/obj/item/I = usr.get_active_held_item()
|
||||
eject_disk()
|
||||
if(istype(I, /obj/item/disk/plantgene))
|
||||
if(!usr.transferItemToLoc(I, src))
|
||||
return
|
||||
disk = I
|
||||
to_chat(usr, "<span class='notice'>You add [I] to the machine.</span>")
|
||||
else if(href_list["op"] == "insert" && disk && disk.gene && seed)
|
||||
if(!operation) // Wait for confirmation
|
||||
operation = "insert"
|
||||
@@ -365,6 +361,16 @@
|
||||
update_genes()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/plantgenes/proc/eject_disk()
|
||||
if (disk && !operation)
|
||||
if(Adjacent(usr) && !issilicon(usr))
|
||||
if (!usr.put_in_hands(disk))
|
||||
disk.forceMove(drop_location())
|
||||
else
|
||||
disk.forceMove(drop_location())
|
||||
disk = null
|
||||
update_genes()
|
||||
|
||||
/obj/machinery/plantgenes/proc/update_genes()
|
||||
core_genes = list()
|
||||
reagent_genes = list()
|
||||
|
||||
@@ -36,19 +36,8 @@
|
||||
continue
|
||||
grassAmt += 1 + round(G.seed.potency * tile_coefficient)
|
||||
qdel(G)
|
||||
var/obj/item/stack/tile/GT = new stacktype(user.loc)
|
||||
while(grassAmt > GT.max_amount)
|
||||
GT.amount = GT.max_amount
|
||||
grassAmt -= GT.max_amount
|
||||
GT = new stacktype(user.loc)
|
||||
GT.amount = grassAmt
|
||||
for(var/obj/item/stack/tile/T in user.loc)
|
||||
if((T.type == stacktype) && (T.amount < T.max_amount))
|
||||
GT.merge(T)
|
||||
if(GT.amount <= 0)
|
||||
break
|
||||
new stacktype(user.drop_location(), grassAmt)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// Carpet
|
||||
/obj/item/seeds/grass/carpet
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
var/blood_type = null
|
||||
var/list/features = null
|
||||
var/factions = null
|
||||
var/list/traits = null
|
||||
var/list/quirks = null
|
||||
var/contains_sample = 0
|
||||
|
||||
/obj/item/seeds/replicapod/Initialize()
|
||||
@@ -42,7 +42,7 @@
|
||||
blood_type = B.data["blood_type"]
|
||||
features = B.data["features"]
|
||||
factions = B.data["factions"]
|
||||
factions = B.data["traits"]
|
||||
factions = B.data["quirks"]
|
||||
contains_sample = TRUE
|
||||
visible_message("<span class='notice'>The [src] is injected with a fresh blood sample.</span>")
|
||||
else
|
||||
@@ -114,7 +114,7 @@
|
||||
podman.faction |= factions
|
||||
if(!features["mcolor"])
|
||||
features["mcolor"] = "#59CE00"
|
||||
for(var/V in traits)
|
||||
for(var/V in quirks)
|
||||
new V(podman)
|
||||
podman.hardset_dna(null,null,podman.real_name,blood_type, new /datum/species/pod,features)//Discard SE's and UI's, podman cloning is inaccurate, and always make them a podman
|
||||
podman.set_cloned_appearance()
|
||||
|
||||
@@ -142,21 +142,18 @@
|
||||
|
||||
/obj/item/integrated_circuit/converter/concatenator
|
||||
name = "concatenator"
|
||||
desc = "This joins many strings together to get one big string."
|
||||
desc = "This can join up to 8 strings together to get one big string."
|
||||
complexity = 4
|
||||
inputs = list(
|
||||
"A" = IC_PINTYPE_STRING,
|
||||
"B" = IC_PINTYPE_STRING,
|
||||
"C" = IC_PINTYPE_STRING,
|
||||
"D" = IC_PINTYPE_STRING,
|
||||
"E" = IC_PINTYPE_STRING,
|
||||
"F" = IC_PINTYPE_STRING,
|
||||
"G" = IC_PINTYPE_STRING,
|
||||
"H" = IC_PINTYPE_STRING
|
||||
)
|
||||
inputs = list()
|
||||
outputs = list("result" = IC_PINTYPE_STRING)
|
||||
activators = list("concatenate" = IC_PINTYPE_PULSE_IN, "on concatenated" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
var/number_of_pins = 8
|
||||
|
||||
/obj/item/integrated_circuit/converter/concatenator/Initialize()
|
||||
for(var/i = 1 to number_of_pins)
|
||||
inputs["input [i]"] = IC_PINTYPE_STRING
|
||||
. = ..()
|
||||
|
||||
/obj/item/integrated_circuit/converter/concatenator/do_work()
|
||||
var/result = null
|
||||
@@ -169,6 +166,18 @@
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/concatenator/small
|
||||
name = "small concatenator"
|
||||
desc = "This can join up to 4 strings together to get one big string."
|
||||
complexity = 2
|
||||
number_of_pins = 4
|
||||
|
||||
/obj/item/integrated_circuit/converter/concatenator/large
|
||||
name = "large concatenator"
|
||||
desc = "This can join up to 16 strings together to get one very big string."
|
||||
complexity = 6
|
||||
number_of_pins = 16
|
||||
|
||||
/obj/item/integrated_circuit/converter/separator
|
||||
name = "separator"
|
||||
desc = "This splits as single string into two at the relative split point."
|
||||
@@ -203,6 +212,32 @@
|
||||
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/indexer
|
||||
name = "indexer"
|
||||
desc = "This circuit takes a string and an index value, then returns the character found at in the string at the given index."
|
||||
extended_desc = "Make sure the index is not longer or shorter than the string length. If you don't, the circuit will return empty."
|
||||
icon_state = "split"
|
||||
complexity = 4
|
||||
inputs = list(
|
||||
"string to index" = IC_PINTYPE_STRING,
|
||||
"index" = IC_PINTYPE_NUMBER,
|
||||
)
|
||||
outputs = list(
|
||||
"found character" = IC_PINTYPE_STRING
|
||||
)
|
||||
activators = list("index" = IC_PINTYPE_PULSE_IN, "on indexed" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/indexer/do_work()
|
||||
var/strin = get_pin_data(IC_INPUT, 1)
|
||||
var/ind = get_pin_data(IC_INPUT, 2)
|
||||
if(ind > 0 && ind <= length(strin))
|
||||
set_pin_data(IC_OUTPUT, 1, strin[ind])
|
||||
else
|
||||
set_pin_data(IC_OUTPUT, 1, "")
|
||||
push_data()
|
||||
activate_pin(2)
|
||||
|
||||
/obj/item/integrated_circuit/converter/findstring
|
||||
name = "find text"
|
||||
desc = "This gives position of sample in the string. Or returns 0."
|
||||
@@ -216,14 +251,38 @@
|
||||
outputs = list(
|
||||
"position" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("search" = IC_PINTYPE_PULSE_IN, "after search" = IC_PINTYPE_PULSE_OUT)
|
||||
activators = list("search" = IC_PINTYPE_PULSE_IN, "after search" = IC_PINTYPE_PULSE_OUT, "found" = IC_PINTYPE_PULSE_OUT, "not found" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
|
||||
|
||||
/obj/item/integrated_circuit/converter/findstring/do_work()
|
||||
var/position = findtext(get_pin_data(IC_INPUT, 1),get_pin_data(IC_INPUT, 2))
|
||||
|
||||
set_pin_data(IC_OUTPUT, 1, findtext(get_pin_data(IC_INPUT, 1),get_pin_data(IC_INPUT, 2)) )
|
||||
set_pin_data(IC_OUTPUT, 1, position)
|
||||
push_data()
|
||||
|
||||
activate_pin(2)
|
||||
if(position)
|
||||
activate_pin(3)
|
||||
else
|
||||
activate_pin(4)
|
||||
|
||||
/obj/item/integrated_circuit/converter/stringlength
|
||||
name = "get length"
|
||||
desc = "This circuit will return the number of characters in a string."
|
||||
complexity = 1
|
||||
inputs = list(
|
||||
"string" = IC_PINTYPE_STRING
|
||||
)
|
||||
outputs = list(
|
||||
"length" = IC_PINTYPE_NUMBER
|
||||
)
|
||||
activators = list("get length" = IC_PINTYPE_PULSE_IN, "on acquisition" = IC_PINTYPE_PULSE_OUT)
|
||||
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
|
||||
|
||||
/obj/item/integrated_circuit/converter/stringlength/do_work()
|
||||
set_pin_data(IC_OUTPUT, 1, length(get_pin_data(IC_INPUT, 1)))
|
||||
push_data()
|
||||
|
||||
activate_pin(2)
|
||||
@@ -232,7 +291,8 @@
|
||||
name = "string exploder"
|
||||
desc = "This splits a single string into a list of strings."
|
||||
extended_desc = "This circuit splits a given string into a list of strings based on the string and given delimiter. \
|
||||
For example, 'eat this burger' will be converted to list('eat','this','burger')."
|
||||
For example, 'eat this burger' will be converted to list('eat','this','burger'). Leave the delimiter null to get a list \
|
||||
of every individual character."
|
||||
icon_state = "split"
|
||||
complexity = 4
|
||||
inputs = list(
|
||||
@@ -248,7 +308,10 @@
|
||||
/obj/item/integrated_circuit/converter/exploders/do_work()
|
||||
var/strin = get_pin_data(IC_INPUT, 1)
|
||||
var/delimiter = get_pin_data(IC_INPUT, 2)
|
||||
set_pin_data(IC_OUTPUT, 1, splittext(strin, delimiter))
|
||||
if(delimiter == null)
|
||||
set_pin_data(IC_OUTPUT, 1, string2charlist(strin))
|
||||
else
|
||||
set_pin_data(IC_OUTPUT, 1, splittext(strin, delimiter))
|
||||
push_data()
|
||||
|
||||
activate_pin(2)
|
||||
|
||||
@@ -637,6 +637,7 @@
|
||||
var/frequency = FREQ_SIGNALER
|
||||
var/code = DEFAULT_SIGNALER_CODE
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/hearing_range = 1
|
||||
|
||||
/obj/item/integrated_circuit/input/signaler/Initialize()
|
||||
. = ..()
|
||||
@@ -690,7 +691,11 @@
|
||||
return 0
|
||||
|
||||
activate_pin(3)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep*", null, 1)
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range)
|
||||
for(var/CHM in get_hearers_in_view(hearing_range, src))
|
||||
if(ismob(CHM))
|
||||
var/mob/LM = CHM
|
||||
LM.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
|
||||
/obj/item/integrated_circuit/input/ntnet_packet
|
||||
name = "NTNet networking circuit"
|
||||
|
||||
@@ -226,9 +226,14 @@ GLOBAL_PROTECT(exp_to_update)
|
||||
if(!rolefound)
|
||||
play_records["Unknown"] += minutes
|
||||
else
|
||||
play_records[EXP_TYPE_GHOST] += minutes
|
||||
if(announce_changes)
|
||||
to_chat(src,"<span class='notice'>You got: [minutes] Ghost EXP!</span>")
|
||||
if(holder && !holder.deadmined)
|
||||
play_records[EXP_TYPE_ADMIN] += minutes
|
||||
if(announce_changes)
|
||||
to_chat(src,"<span class='notice'>You got: [minutes] Admin EXP!</span>")
|
||||
else
|
||||
play_records[EXP_TYPE_GHOST] += minutes
|
||||
if(announce_changes)
|
||||
to_chat(src,"<span class='notice'>You got: [minutes] Ghost EXP!</span>")
|
||||
else if(isobserver(mob))
|
||||
play_records[EXP_TYPE_GHOST] += minutes
|
||||
if(announce_changes)
|
||||
|
||||
@@ -91,7 +91,7 @@ Mime
|
||||
uniform = /obj/item/clothing/under/rank/mime
|
||||
mask = /obj/item/clothing/mask/gas/mime
|
||||
gloves = /obj/item/clothing/gloves/color/white
|
||||
head = /obj/item/clothing/head/beret
|
||||
head = /obj/item/clothing/head/frenchberet
|
||||
suit = /obj/item/clothing/suit/suspenders
|
||||
backpack_contents = list(/obj/item/reagent_containers/food/drinks/bottle/bottleofnothing=1)
|
||||
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
return TRUE
|
||||
|
||||
/datum/language/proc/get_icon()
|
||||
return "[icon2html(icon, world, icon_state)]"
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/goonchat)
|
||||
return sheet.icon_tag("language-[icon_state]")
|
||||
|
||||
/datum/language/proc/get_random_name(gender, name_count=2, syllable_count=4, syllable_divisor=2)
|
||||
if(!syllables || !syllables.len)
|
||||
|
||||
@@ -25,6 +25,14 @@
|
||||
armor = list("melee" = 30, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 50, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
/obj/item/clothing/suit/hooded/explorer/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/armor_plate)
|
||||
|
||||
/obj/item/clothing/head/hooded/explorer/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/armor_plate)
|
||||
|
||||
/obj/item/clothing/mask/gas/explorer
|
||||
name = "explorer gas mask"
|
||||
desc = "A military-grade gas mask that can be connected to an air supply."
|
||||
|
||||
@@ -9,38 +9,4 @@
|
||||
novariants = FALSE
|
||||
flags_1 = NOBLUDGEON_1
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
layer = MOB_LAYER
|
||||
var/static/list/goliath_platable_armor_typecache = typecacheof(list(
|
||||
/obj/item/clothing/head/helmet/space/hardsuit/mining,
|
||||
/obj/item/clothing/suit/space/hardsuit/mining,
|
||||
/obj/item/clothing/head/hooded/explorer,
|
||||
/obj/item/clothing/suit/hooded/explorer))
|
||||
|
||||
/obj/item/stack/sheet/animalhide/goliath_hide/afterattack(atom/target, mob/user, proximity_flag)
|
||||
if(!proximity_flag)
|
||||
return
|
||||
if(is_type_in_typecache(target, goliath_platable_armor_typecache))
|
||||
var/obj/item/clothing/C = target
|
||||
if(C.armor.melee < 60)
|
||||
C.armor = C.armor.setRating(melee = min(C.armor.melee + 10, 60))
|
||||
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against melee attacks.</span>")
|
||||
use(1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't improve [C] any further!</span>")
|
||||
else if(istype(target, /obj/mecha/working/ripley))
|
||||
var/obj/mecha/working/ripley/D = target
|
||||
if(D.hides < 3)
|
||||
D.hides++
|
||||
D.armor = D.armor.setRating(\
|
||||
melee = min(D.armor.melee + 10, 70),\
|
||||
bullet = min(D.armor.bullet + 5, 50),\
|
||||
laser = min(D.armor.laser + 5, 50))
|
||||
to_chat(user, "<span class='info'>You strengthen [target], improving its resistance against melee attacks.</span>")
|
||||
D.update_icon()
|
||||
if(D.hides == 3)
|
||||
D.desc = "Autonomous Power Loader Unit. It's wearing a fearsome carapace entirely composed of goliath hide plates - its pilot must be an experienced monster hunter."
|
||||
else
|
||||
D.desc = "Autonomous Power Loader Unit. Its armour is enhanced with some goliath hide plates."
|
||||
use(1)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You can't improve [D] any further!</span>")
|
||||
layer = MOB_LAYER
|
||||
@@ -303,13 +303,12 @@
|
||||
desired = input("How many sheets?", "How many sheets would you like to smelt?", 1) as null|num
|
||||
var/amount = round(min(desired,50,smelt_amount))
|
||||
materials.use_amount(alloy.materials, amount)
|
||||
var/output = new alloy.build_path(src)
|
||||
if(istype(output, /obj/item/stack/sheet))
|
||||
var/obj/item/stack/sheet/produced_alloy = output
|
||||
produced_alloy.amount = amount
|
||||
unload_mineral(produced_alloy)
|
||||
var/output
|
||||
if(ispath(alloy.build_path, /obj/item/stack/sheet))
|
||||
output = new alloy.build_path(src, amount)
|
||||
else
|
||||
unload_mineral(output)
|
||||
output = new alloy.build_path(src)
|
||||
unload_mineral(output)
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Required access not found.</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -44,8 +44,7 @@
|
||||
if(!(text2path(href_list["release"]) in machine.stack_list))
|
||||
return //someone tried to spawn materials by spoofing hrefs
|
||||
var/obj/item/stack/sheet/inp = machine.stack_list[text2path(href_list["release"])]
|
||||
var/obj/item/stack/sheet/out = new inp.type()
|
||||
out.amount = inp.amount
|
||||
var/obj/item/stack/sheet/out = new inp.type(null, inp.amount)
|
||||
inp.amount = 0
|
||||
machine.unload_mineral(out)
|
||||
|
||||
@@ -81,14 +80,12 @@
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/proc/process_sheet(obj/item/stack/sheet/inp)
|
||||
if(!(inp.type in stack_list)) //It's the first of this sheet added
|
||||
var/obj/item/stack/sheet/s = new inp.type(src,0)
|
||||
s.amount = 0
|
||||
var/obj/item/stack/sheet/s = new inp.type(src, 0)
|
||||
stack_list[inp.type] = s
|
||||
var/obj/item/stack/sheet/storage = stack_list[inp.type]
|
||||
storage.amount += inp.amount //Stack the sheets
|
||||
qdel(inp) //Let the old sheet garbage collect
|
||||
while(storage.amount > stack_amt) //Get rid of excessive stackage
|
||||
var/obj/item/stack/sheet/out = new inp.type()
|
||||
out.amount = stack_amt
|
||||
var/obj/item/stack/sheet/out = new inp.type(null, stack_amt)
|
||||
unload_mineral(out)
|
||||
storage.amount -= stack_amt
|
||||
|
||||
@@ -400,7 +400,7 @@
|
||||
SSticker.mode.make_antag_chance(humanc)
|
||||
|
||||
if(humanc && CONFIG_GET(flag/roundstart_traits))
|
||||
SStraits.AssignTraits(humanc, humanc.client, TRUE)
|
||||
SSquirks.AssignQuirks(humanc, humanc.client, TRUE)
|
||||
|
||||
log_manifest(character.mind.key,character.mind,character,latejoin = TRUE)
|
||||
|
||||
|
||||
@@ -592,6 +592,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
|
||||
var/list/possessible = list()
|
||||
for(var/mob/living/L in GLOB.alive_mob_list)
|
||||
if(istype(L,/mob/living/carbon/human/dummy) || !get_turf(L)) //Haha no.
|
||||
continue
|
||||
if(!(L in GLOB.player_list) && !L.mind)
|
||||
possessible += L
|
||||
|
||||
|
||||
@@ -326,7 +326,10 @@
|
||||
I.plane = initial(I.plane)
|
||||
I.appearance_flags &= ~NO_CLIENT_COLOR
|
||||
if(!no_move && !(I.flags_1 & DROPDEL_1)) //item may be moved/qdel'd immedietely, don't bother moving it
|
||||
I.forceMove(newloc)
|
||||
if (isnull(newloc))
|
||||
I.moveToNullspace()
|
||||
else
|
||||
I.forceMove(newloc)
|
||||
I.dropped(src)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -193,10 +193,10 @@
|
||||
blood_data["real_name"] = real_name
|
||||
blood_data["features"] = dna.features
|
||||
blood_data["factions"] = faction
|
||||
blood_data["traits"] = list()
|
||||
for(var/V in roundstart_traits)
|
||||
var/datum/trait/T = V
|
||||
blood_data["traits"] += T.type
|
||||
blood_data["quirks"] = list()
|
||||
for(var/V in roundstart_quirks)
|
||||
var/datum/quirk/T = V
|
||||
blood_data["quirks"] += T.type
|
||||
return blood_data
|
||||
|
||||
//get the id of the substance this mob use as blood.
|
||||
|
||||
@@ -19,6 +19,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
|
||||
|
||||
//Inefficient pooling/caching way.
|
||||
GLOBAL_LIST_EMPTY(human_dummy_list)
|
||||
GLOBAL_LIST_EMPTY(dummy_mob_list)
|
||||
|
||||
/proc/generate_or_wait_for_human_dummy(slotkey)
|
||||
if(!slotkey)
|
||||
@@ -31,6 +32,7 @@ GLOBAL_LIST_EMPTY(human_dummy_list)
|
||||
if(QDELETED(D))
|
||||
D = new
|
||||
GLOB.human_dummy_list[slotkey] = D
|
||||
GLOB.dummy_mob_list += D
|
||||
D.in_use = TRUE
|
||||
return D
|
||||
|
||||
|
||||
@@ -733,8 +733,8 @@
|
||||
if(0 to NUTRITION_LEVEL_STARVING)
|
||||
to_chat(src, "<span class='danger'>You're starving!</span>")
|
||||
|
||||
if(roundstart_traits.len)
|
||||
to_chat(src, "<span class='notice'>You have these traits: [get_trait_string()].</span>")
|
||||
if(roundstart_quirks.len)
|
||||
to_chat(src, "<span class='notice'>You have these quirks: [get_trait_string()].</span>")
|
||||
else
|
||||
if(wear_suit)
|
||||
wear_suit.add_fingerprint(M)
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
message = T.TongueSpeech(message)
|
||||
if(wear_mask)
|
||||
message = wear_mask.speechModification(message)
|
||||
|
||||
if(head)
|
||||
message = head.speechModification(message)
|
||||
return message
|
||||
|
||||
/mob/living/carbon/can_speak_vocal(message)
|
||||
|
||||
@@ -407,16 +407,14 @@
|
||||
*/
|
||||
//Recursive function to find everything a mob is holding. Really shitty proc tbh.
|
||||
/mob/living/get_contents()
|
||||
. = list()
|
||||
. |= list(src)
|
||||
for(var/obj/o in .)
|
||||
var/list/newlist = list()
|
||||
o.SendSignal(COMSIG_TRY_STORAGE_RETURN_INVENTORY, newlist)
|
||||
. |= newlist
|
||||
for(var/obj/item/clothing/under/U in .)
|
||||
. |= U.contents
|
||||
for(var/obj/item/folder/F in .)
|
||||
. |= F.contents
|
||||
var/list/ret = list()
|
||||
ret |= contents //add our contents
|
||||
for(var/i in ret.Copy()) //iterate storage objects
|
||||
var/atom/A = i
|
||||
A.SendSignal(COMSIG_TRY_STORAGE_RETURN_INVENTORY, ret)
|
||||
for(var/obj/item/folder/F in ret.Copy()) //very snowflakey-ly iterate folders
|
||||
ret |= F.contents
|
||||
return ret
|
||||
|
||||
// Living mobs use can_inject() to make sure that the mob is not syringe-proof in general.
|
||||
/mob/living/proc/can_inject()
|
||||
@@ -494,6 +492,11 @@
|
||||
ExtinguishMob()
|
||||
fire_stacks = 0
|
||||
update_canmove()
|
||||
GET_COMPONENT(mood, /datum/component/mood)
|
||||
if (mood)
|
||||
QDEL_LIST(mood.mood_events)
|
||||
mood.sanity = SANITY_GREAT
|
||||
mood.update_mood()
|
||||
|
||||
|
||||
//proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again)
|
||||
|
||||
@@ -317,8 +317,7 @@
|
||||
return shock_damage
|
||||
|
||||
/mob/living/emp_act(severity)
|
||||
var/list/L = src.get_contents()
|
||||
for(var/obj/O in L)
|
||||
for(var/obj/O in contents)
|
||||
O.emp_act(severity)
|
||||
..()
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
var/list/status_traits = list()
|
||||
|
||||
var/list/roundstart_traits = list()
|
||||
var/list/roundstart_quirks = list()
|
||||
|
||||
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
|
||||
|
||||
|
||||
@@ -170,7 +170,8 @@
|
||||
|
||||
if(href_list["send"])
|
||||
signaler.send_activation()
|
||||
audible_message("[icon2html(src, world)] *beep* *beep*")
|
||||
audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*")
|
||||
playsound(src, 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE)
|
||||
|
||||
if(href_list["freq"])
|
||||
var/new_frequency = (signaler.frequency + text2num(href_list["freq"]))
|
||||
|
||||
@@ -831,7 +831,7 @@
|
||||
set_module = /obj/item/robot_module/janitor
|
||||
|
||||
/mob/living/silicon/robot/modules/syndicate
|
||||
icon_state = "syndie_bloodhound"
|
||||
icon_state = "synd_sec"
|
||||
faction = list(ROLE_SYNDICATE)
|
||||
bubble_icon = "syndibot"
|
||||
req_access = list(ACCESS_SYNDICATE)
|
||||
@@ -859,7 +859,7 @@
|
||||
return
|
||||
|
||||
/mob/living/silicon/robot/modules/syndicate/medical
|
||||
icon_state = "syndi-medi"
|
||||
icon_state = "synd_medical"
|
||||
playstyle_string = "<span class='big bold'>You are a Syndicate medical cyborg!</span><br>\
|
||||
<b>You are armed with powerful medical tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
|
||||
Your hypospray will produce Restorative Nanites, a wonder-drug that will heal most types of bodily damages, including clone and brain damage. It also produces morphine for offense. \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/obj/item/robot_module
|
||||
name = "Default"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "std_module"
|
||||
icon_state = "std_mod"
|
||||
w_class = WEIGHT_CLASS_GIGANTIC
|
||||
item_state = "electronic"
|
||||
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
|
||||
|
||||
@@ -164,12 +164,7 @@
|
||||
update_controls()
|
||||
|
||||
/mob/living/simple_animal/bot/floorbot/proc/empty_tiles()
|
||||
var/atom/Tsec = drop_location()
|
||||
|
||||
while(specialtiles > initial(tiletype.max_amount))
|
||||
new tiletype(Tsec,initial(tiletype.max_amount))
|
||||
specialtiles -= initial(tiletype.max_amount)
|
||||
new tiletype(Tsec,specialtiles)
|
||||
new tiletype(drop_location(), specialtiles)
|
||||
specialtiles = 0
|
||||
tiletype = null
|
||||
|
||||
@@ -378,8 +373,7 @@
|
||||
if(prob(50))
|
||||
drop_part(robot_arm, Tsec)
|
||||
|
||||
var/obj/item/stack/tile/plasteel/T = new (Tsec)
|
||||
T.amount = 1
|
||||
new /obj/item/stack/tile/plasteel(Tsec, 1)
|
||||
|
||||
do_sparks(3, TRUE, src)
|
||||
..()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name = "\improper honkbot"
|
||||
desc = "A little robot. It looks happy with its bike horn."
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
icon_state = "honkbot"
|
||||
icon_state = "honkbot1"
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
health = 25
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
attacktext = "pummels"
|
||||
attack_sound = 'sound/weapons/punch1.ogg'
|
||||
dextrous = TRUE
|
||||
held_items = list(null, null)
|
||||
possible_a_intents = list(INTENT_HELP, INTENT_GRAB, INTENT_DISARM, INTENT_HARM)
|
||||
faction = list("jungle")
|
||||
robust_searching = TRUE
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
icon_dead = "Fugu_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
move_to_delay = 5
|
||||
friendly = "floats near"
|
||||
speak_emote = list("puffs")
|
||||
|
||||
@@ -146,12 +146,12 @@
|
||||
else
|
||||
status_traits[trait] |= list(source)
|
||||
|
||||
/mob/living/proc/add_trait_datum(trait, spawn_effects) //separate proc due to the way these ones are handled
|
||||
if(has_trait(trait))
|
||||
/mob/living/proc/add_quirk(quirk, spawn_effects) //separate proc due to the way these ones are handled
|
||||
if(has_trait(quirk))
|
||||
return
|
||||
if(!SStraits || !SStraits.traits[trait])
|
||||
if(!SSquirks || !SSquirks.quirks[quirk])
|
||||
return
|
||||
var/datum/trait/T = SStraits.traits[trait]
|
||||
var/datum/quirk/T = SSquirks.quirks[quirk]
|
||||
new T (src, spawn_effects)
|
||||
return TRUE
|
||||
|
||||
@@ -180,8 +180,8 @@
|
||||
if(!LAZYLEN(status_traits[trait]))
|
||||
status_traits -= trait
|
||||
|
||||
/mob/living/proc/remove_trait_datum(trait)
|
||||
var/datum/trait/T = roundstart_traits[trait]
|
||||
/mob/living/proc/remove_quirk(quirk)
|
||||
var/datum/quirk/T = roundstart_quirks[quirk]
|
||||
if(T)
|
||||
qdel(T)
|
||||
return TRUE
|
||||
@@ -201,8 +201,8 @@
|
||||
else if(LAZYLEN(status_traits[trait]))
|
||||
return TRUE
|
||||
|
||||
/mob/living/proc/has_trait_datum(trait)
|
||||
return roundstart_traits[trait]
|
||||
/mob/living/proc/has_quirk(quirk)
|
||||
return roundstart_quirks[quirk]
|
||||
|
||||
/mob/living/proc/remove_all_traits()
|
||||
status_traits = list()
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
message = src.say_quote(message, get_spans())
|
||||
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name] <span class='message'>[message]</span></span>"
|
||||
|
||||
log_message("DEAD: [message]", INDIVIDUAL_SAY_LOG)
|
||||
deadchat_broadcast(rendered, follow_target = src, speaker_key = K)
|
||||
|
||||
/mob/proc/check_emote(message)
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to fold it.</span>")
|
||||
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/paper)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/paper)
|
||||
assets.send(user)
|
||||
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
@@ -300,7 +300,10 @@
|
||||
if(!in_range(src, user))
|
||||
return
|
||||
|
||||
stamps += "<img src=large_[P.icon_state].png>"
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/simple/paper)
|
||||
if (isnull(stamps))
|
||||
stamps = sheet.css_tag()
|
||||
stamps += sheet.icon_tag(P.icon_state)
|
||||
var/mutable_appearance/stampoverlay = mutable_appearance('icons/obj/bureaucracy.dmi', "paper_[P.icon_state]")
|
||||
stampoverlay.pixel_x = rand(-2, 2)
|
||||
stampoverlay.pixel_y = rand(-3, 2)
|
||||
|
||||
+31
-26
@@ -34,6 +34,10 @@
|
||||
#define APC_COVER_OPENED 1
|
||||
#define APC_COVER_REMOVED 2
|
||||
|
||||
#define APC_NOT_CHARGING 0
|
||||
#define APC_CHARGING 1
|
||||
#define APC_FULLY_CHARGED 2
|
||||
|
||||
// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
|
||||
// one per area, needs wire connection to power network through a terminal
|
||||
|
||||
@@ -66,7 +70,7 @@
|
||||
var/equipment = 3
|
||||
var/environ = 3
|
||||
var/operating = TRUE
|
||||
var/charging = 0
|
||||
var/charging = APC_NOT_CHARGING
|
||||
var/chargemode = 1
|
||||
var/chargecount = 0
|
||||
var/locked = TRUE
|
||||
@@ -291,11 +295,11 @@
|
||||
// And now, separately for cleanness, the lighting changing
|
||||
if(update_state & UPSTATE_ALLGOOD)
|
||||
switch(charging)
|
||||
if(0)
|
||||
if(APC_NOT_CHARGING)
|
||||
light_color = LIGHT_COLOR_RED
|
||||
if(1)
|
||||
if(APC_CHARGING)
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
if(2)
|
||||
if(APC_FULLY_CHARGED)
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
set_light(lon_range)
|
||||
else if(update_state & UPSTATE_BLUESCREEN)
|
||||
@@ -339,9 +343,9 @@
|
||||
|
||||
if(!charging)
|
||||
update_overlay |= APC_UPOVERLAY_CHARGEING0
|
||||
else if(charging == 1)
|
||||
else if(charging == APC_CHARGING)
|
||||
update_overlay |= APC_UPOVERLAY_CHARGEING1
|
||||
else if(charging == 2)
|
||||
else if(charging == APC_FULLY_CHARGED)
|
||||
update_overlay |= APC_UPOVERLAY_CHARGEING2
|
||||
|
||||
if (!equipment)
|
||||
@@ -384,15 +388,6 @@
|
||||
/obj/machinery/power/apc/crowbar_act(mob/user, obj/item/W)
|
||||
. = TRUE
|
||||
if (opened)
|
||||
if(cell)
|
||||
user.visible_message("[user] removes \the [cell] from [src]!","<span class='notice'>You remove \the [cell].</span>")
|
||||
var/turf/T = get_turf(user)
|
||||
cell.forceMove(T)
|
||||
cell.update_icon()
|
||||
cell = null
|
||||
charging = 0
|
||||
update_icon()
|
||||
return
|
||||
if (has_electronics == APC_ELECTRONICS_INSTALLED)
|
||||
if (terminal)
|
||||
to_chat(user, "<span class='warning'>Disconnect the wires first!</span>")
|
||||
@@ -457,8 +452,14 @@
|
||||
/obj/machinery/power/apc/screwdriver_act(mob/living/user, obj/item/W)
|
||||
. = TRUE
|
||||
if(opened)
|
||||
if (cell)
|
||||
to_chat(user, "<span class='warning'>Close the APC first!</span>")
|
||||
if(cell)
|
||||
user.visible_message("[user] removes \the [cell] from [src]!","<span class='notice'>You remove \the [cell].</span>")
|
||||
var/turf/T = get_turf(user)
|
||||
cell.forceMove(T)
|
||||
cell.update_icon()
|
||||
cell = null
|
||||
charging = APC_NOT_CHARGING
|
||||
update_icon()
|
||||
return
|
||||
else
|
||||
switch (has_electronics)
|
||||
@@ -745,7 +746,7 @@
|
||||
user.put_in_hands(cell)
|
||||
cell.update_icon()
|
||||
src.cell = null
|
||||
charging = 0
|
||||
charging = APC_NOT_CHARGING
|
||||
src.update_icon()
|
||||
return
|
||||
if((stat & MAINT) && !opened) //no board; no interface
|
||||
@@ -888,7 +889,7 @@
|
||||
if("charge")
|
||||
chargemode = !chargemode
|
||||
if(!chargemode)
|
||||
charging = 0
|
||||
charging = APC_NOT_CHARGING
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("channel")
|
||||
@@ -1125,10 +1126,10 @@
|
||||
if((cell.charge/GLOB.CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
|
||||
cell.charge = min(cell.maxcharge, cell.charge + GLOB.CELLRATE * excess) //recharge with what we can
|
||||
add_load(excess) // so draw what we can from the grid
|
||||
charging = 0
|
||||
charging = APC_NOT_CHARGING
|
||||
|
||||
else // not enough power available to run the last tick!
|
||||
charging = 0
|
||||
charging = APC_NOT_CHARGING
|
||||
chargecount = 0
|
||||
// This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
|
||||
equipment = autoset(equipment, 0)
|
||||
@@ -1168,7 +1169,7 @@
|
||||
area.poweralert(1, src)
|
||||
|
||||
// now trickle-charge the cell
|
||||
if(chargemode && charging == 1 && operating)
|
||||
if(chargemode && charging == APC_CHARGING && operating)
|
||||
if(excess > 0) // check to make sure we have enough to charge
|
||||
// Max charge is capped to % per second constant
|
||||
var/ch = min(excess*GLOB.CELLRATE, cell.maxcharge*GLOB.CHARGELEVEL)
|
||||
@@ -1176,13 +1177,13 @@
|
||||
cell.give(ch) // actually recharge the cell
|
||||
|
||||
else
|
||||
charging = 0 // stop charging
|
||||
charging = APC_NOT_CHARGING // stop charging
|
||||
chargecount = 0
|
||||
|
||||
// show cell as fully charged if so
|
||||
if(cell.charge >= cell.maxcharge)
|
||||
cell.charge = cell.maxcharge
|
||||
charging = 2
|
||||
charging = APC_FULLY_CHARGED
|
||||
|
||||
if(chargemode)
|
||||
if(!charging)
|
||||
@@ -1194,7 +1195,7 @@
|
||||
if(chargecount == 10)
|
||||
|
||||
chargecount = 0
|
||||
charging = 1
|
||||
charging = APC_CHARGING
|
||||
|
||||
else // chargemode off
|
||||
charging = 0
|
||||
@@ -1202,7 +1203,7 @@
|
||||
|
||||
else // no cell, switch everything off
|
||||
|
||||
charging = 0
|
||||
charging = APC_NOT_CHARGING
|
||||
chargecount = 0
|
||||
equipment = autoset(equipment, 0)
|
||||
lighting = autoset(lighting, 0)
|
||||
@@ -1358,6 +1359,10 @@
|
||||
#undef APC_COVER_OPENED
|
||||
#undef APC_COVER_REMOVED
|
||||
|
||||
#undef APC_NOT_CHARGING
|
||||
#undef APC_CHARGING
|
||||
#undef APC_FULLY_CHARGED
|
||||
|
||||
//update_overlay
|
||||
#undef APC_UPOVERLAY_CHARGEING0
|
||||
#undef APC_UPOVERLAY_CHARGEING1
|
||||
|
||||
@@ -111,13 +111,8 @@
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/DropFuel()
|
||||
if(sheets)
|
||||
var/fail_safe = FALSE
|
||||
while(sheets > 0 && fail_safe < 100)
|
||||
fail_safe += 1
|
||||
var/obj/item/stack/sheet/S = new sheet_path(loc)
|
||||
var/amount = min(sheets, S.max_amount)
|
||||
S.amount = amount
|
||||
sheets -= amount
|
||||
new sheet_path(drop_location(), sheets)
|
||||
sheets = 0
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/UseFuel()
|
||||
var/needed_sheets = 1 / (time_per_sheet * consumption / power_output)
|
||||
|
||||
@@ -191,12 +191,12 @@
|
||||
|
||||
// Give back the glass type we were supplied with
|
||||
/obj/item/solar_assembly/proc/give_glass(device_broken)
|
||||
var/atom/Tsec = drop_location()
|
||||
if(device_broken)
|
||||
new /obj/item/shard(loc)
|
||||
new /obj/item/shard(loc)
|
||||
new /obj/item/shard(Tsec)
|
||||
new /obj/item/shard(Tsec)
|
||||
else if(glass_type)
|
||||
var/obj/item/stack/sheet/S = new glass_type(loc)
|
||||
S.amount = 2
|
||||
new glass_type(Tsec, 2)
|
||||
glass_type = null
|
||||
|
||||
|
||||
|
||||
@@ -62,9 +62,9 @@
|
||||
if(default_deconstruction_crowbar(W))
|
||||
return
|
||||
|
||||
if(is_wire_tool(W) && panel_open)
|
||||
/*if(is_wire_tool(W) && panel_open) CITADEL EDIT - They removed the wires because they don't like my cheating
|
||||
wires.interact(user)
|
||||
return
|
||||
return*/
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -185,4 +185,4 @@
|
||||
flick("grounding_rodhit", src)
|
||||
tesla_buckle_check(power)
|
||||
else
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/obj/item/ammo_box/magazine/m12g
|
||||
name = "shotgun magazine (12g taser slugs)"
|
||||
name = "shotgun magazine (12g buckshot slugs)"
|
||||
desc = "A drum magazine."
|
||||
icon_state = "m12gs"
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/stunslug
|
||||
icon_state = "m12gb"
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/buckshot
|
||||
caliber = "shotgun"
|
||||
max_ammo = 8
|
||||
|
||||
@@ -10,14 +10,14 @@
|
||||
..()
|
||||
icon_state = "[initial(icon_state)]-[CEILING(ammo_count(0)/8, 1)*8]"
|
||||
|
||||
/obj/item/ammo_box/magazine/m12g/buckshot
|
||||
name = "shotgun magazine (12g buckshot slugs)"
|
||||
icon_state = "m12gb"
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/buckshot
|
||||
/obj/item/ammo_box/magazine/m12g/stun
|
||||
name = "shotgun magazine (12g taser slugs)"
|
||||
icon_state = "m12gs"
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/stunslug
|
||||
|
||||
/obj/item/ammo_box/magazine/m12g/slug
|
||||
name = "shotgun magazine (12g slugs)"
|
||||
icon_state = "m12gb"
|
||||
icon_state = "m12gb" //this may need an unique sprite
|
||||
ammo_type = /obj/item/ammo_casing/shotgun
|
||||
|
||||
/obj/item/ammo_box/magazine/m12g/dragon
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
to_chat(user, "<span class='warning'>You need a free hand to hold the gun!</span>")
|
||||
return
|
||||
update_icon()
|
||||
gun.forceMove(user)
|
||||
user.update_inv_back()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You are already holding the gun!</span>")
|
||||
|
||||
@@ -436,7 +436,7 @@
|
||||
|
||||
/obj/item/projectile/beam/beam_rifle
|
||||
name = "particle beam"
|
||||
icon = ""
|
||||
icon = null
|
||||
hitsound = 'sound/effects/explosion3.ogg'
|
||||
damage = 0 //Handled manually.
|
||||
damage_type = BURN
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
/obj/item/projectile/curse_hand
|
||||
name = "curse hand"
|
||||
icon_state = "cursehand"
|
||||
icon_state = "cursehand0"
|
||||
hitsound = 'sound/effects/curse4.ogg'
|
||||
layer = LARGE_MOB_LAYER
|
||||
damage_type = BURN
|
||||
@@ -19,10 +19,7 @@
|
||||
/obj/item/projectile/curse_hand/Initialize(mapload)
|
||||
. = ..()
|
||||
handedness = prob(50)
|
||||
update_icon()
|
||||
|
||||
/obj/item/projectile/curse_hand/update_icon()
|
||||
icon_state = "[icon_state][handedness]"
|
||||
icon_state = "cursehand[handedness]"
|
||||
|
||||
/obj/item/projectile/curse_hand/fire(setAngle)
|
||||
if(starting)
|
||||
|
||||
@@ -433,7 +433,8 @@ obj/machinery/chem_dispenser/proc/work_animation()
|
||||
"orangejuice",
|
||||
"limejuice",
|
||||
"tomatojuice",
|
||||
"lemonjuice"
|
||||
"lemonjuice",
|
||||
"menthol"
|
||||
)
|
||||
emagged_reagents = list(
|
||||
"thirteenloko",
|
||||
@@ -465,7 +466,8 @@ obj/machinery/chem_dispenser/proc/work_animation()
|
||||
"hcider",
|
||||
"creme_de_menthe",
|
||||
"creme_de_cacao",
|
||||
"triple_sec"
|
||||
"triple_sec",
|
||||
"sake"
|
||||
)
|
||||
emagged_reagents = list(
|
||||
"ethanol",
|
||||
@@ -499,3 +501,17 @@ obj/machinery/chem_dispenser/proc/work_animation()
|
||||
"ammonia",
|
||||
"ash",
|
||||
"diethylamine")
|
||||
|
||||
/obj/machinery/chem_dispenser/fullupgrade //fully upgraded stock parts
|
||||
|
||||
/obj/machinery/chem_dispenser/fullupgrade/Initialize()
|
||||
. = ..()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
|
||||
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
|
||||
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
|
||||
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
|
||||
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
|
||||
component_parts += new /obj/item/stack/sheet/glass(null)
|
||||
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
|
||||
RefreshParts()
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer //formerly SCP-294 made by mrty, but now only for testing purposes
|
||||
name = "\improper debug chemical synthesizer"
|
||||
desc = "If you see this, yell at adminbus."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "dispenser"
|
||||
amount = 10
|
||||
resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | ACID_PROOF | LAVA_PROOF
|
||||
working_state = null
|
||||
nopower_state = null
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
var/static/list/shortcuts = list(
|
||||
"meth" = "methamphetamine",
|
||||
"tricord" = "tricordrazine"
|
||||
)
|
||||
var/mutable_appearance/top_overlay
|
||||
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer/Initialize()
|
||||
. = ..()
|
||||
GLOB.poi_list += src
|
||||
top_overlay = mutable_appearance(icon, "disp_beaker", layer = ABOVE_ALL_MOB_LAYER)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer/update_icon()
|
||||
cut_overlays()
|
||||
add_overlay(top_overlay)
|
||||
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer/Destroy()
|
||||
. = ..()
|
||||
GLOB.poi_list -= src
|
||||
QDEL_NULL(top_overlay)
|
||||
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer/display_beaker()
|
||||
return
|
||||
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "chem_synthesizer", name, 390, 315, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
update_icon()
|
||||
switch(action)
|
||||
if("ejectBeaker")
|
||||
if(beaker)
|
||||
beaker.forceMove(drop_location())
|
||||
if(Adjacent(usr) && !issilicon(usr))
|
||||
usr.put_in_hands(beaker)
|
||||
beaker = null
|
||||
. = TRUE
|
||||
if("input")
|
||||
var/input_reagent = replacetext(lowertext(input("Enter the name of any liquid", "Input") as text), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name
|
||||
if(shortcuts[input_reagent])
|
||||
input_reagent = shortcuts[input_reagent]
|
||||
else
|
||||
input_reagent = find_reagent(input_reagent)
|
||||
if(!input_reagent || !GLOB.chemical_reagents_list[input_reagent])
|
||||
say("OUT OF RANGE")
|
||||
return
|
||||
else
|
||||
if(!beaker)
|
||||
return
|
||||
else if(!beaker.reagents && !QDELETED(beaker))
|
||||
beaker.create_reagents(beaker.volume)
|
||||
beaker.reagents.add_reagent(input_reagent, amount)
|
||||
if("makecup")
|
||||
if(beaker)
|
||||
return
|
||||
beaker = new /obj/item/reagent_containers/glass/beaker/bluespace(src)
|
||||
visible_message("<span class='notice'>[src] dispenses a bluespace beaker.</span>")
|
||||
|
||||
/obj/machinery/chem_dispenser/chem_synthesizer/proc/find_reagent(input)
|
||||
. = FALSE
|
||||
if(GLOB.chemical_reagents_list[input]) //prefer IDs!
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[input]
|
||||
if(R.can_synth_debug)
|
||||
return input
|
||||
else
|
||||
for(var/X in GLOB.chemical_reagents_list)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[X]
|
||||
if(R.can_synth_debug && input == replacetext(lowertext(R.name), " ", ""))
|
||||
return X
|
||||
@@ -20,7 +20,8 @@
|
||||
var/current_cycle = 0
|
||||
var/volume = 0
|
||||
var/color = "#000000" // rgb: 0, 0, 0
|
||||
var/can_synth = TRUE
|
||||
var/can_synth = TRUE // can this reagent be synthesized? (for example: odysseus syringe gun)
|
||||
var/can_synth_debug = TRUE // can this reagent be synthesized by the debug chem synthesizer?
|
||||
var/metabolization_rate = REAGENTS_METABOLISM //how fast the reagent is metabolized by the mob
|
||||
var/overrides_metab = 0
|
||||
var/overdose_threshold = 0
|
||||
|
||||
@@ -1546,4 +1546,70 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
glass_desc = "It'll either knock the drunkenness out of you or knock you out cold. Both, probably."
|
||||
|
||||
/datum/reagent/consumable/ethanol/crevice_spike/on_mob_add(mob/living/L) //damage only applies when drink first enters system and won't again until drink metabolizes out
|
||||
L.adjustBruteLoss(3 * min(5,volume)) //minimum 3 brute damage on ingestion to limit non-drink means of injury - a full 5 unit gulp of the drink trucks you for the full 15
|
||||
L.adjustBruteLoss(3 * min(5,volume)) //minimum 3 brute damage on ingestion to limit non-drink means of injury - a full 5 unit gulp of the drink trucks you for the full 15
|
||||
|
||||
/datum/reagent/consumable/ethanol/sake
|
||||
name = "Sake"
|
||||
id = "sake"
|
||||
description = "A sweet rice wine of questionable legality and extreme potency."
|
||||
color = "#DDDDDD"
|
||||
boozepwr = 70
|
||||
taste_description = "sweet rice wine"
|
||||
glass_icon_state = "sakecup"
|
||||
glass_name = "cup of sake"
|
||||
glass_desc = "A traditional cup of sake."
|
||||
|
||||
/datum/reagent/consumable/ethanol/alexander
|
||||
name = "Alexander"
|
||||
id = "alexander"
|
||||
description = "A creamy, indulgent delight that is stronger than it seems."
|
||||
color = "#F5E9D3"
|
||||
boozepwr = 80
|
||||
taste_description = "bitter, creamy cacao"
|
||||
glass_icon_state = "alexander"
|
||||
glass_name = "Alexander"
|
||||
glass_desc = "A creamy, indulgent delight that is stronger than it seems."
|
||||
|
||||
/datum/reagent/consumable/ethanol/sidecar
|
||||
name = "Sidecar"
|
||||
id = "sidecar"
|
||||
description = "The one ride you’ll gladly give up the wheel for."
|
||||
color = "#FFC55B"
|
||||
boozepwr = 80
|
||||
taste_description = "delicious freedom"
|
||||
glass_icon_state = "sidecar"
|
||||
glass_name = "Sidecar"
|
||||
glass_desc = "The one ride you’ll gladly give up the wheel for."
|
||||
|
||||
/datum/reagent/consumable/ethanol/between_the_sheets
|
||||
name = "Between the Sheets"
|
||||
id = "between_the_sheets"
|
||||
description = "A provocatively named classic."
|
||||
color = "#F4C35A"
|
||||
boozepwr = 80
|
||||
taste_description = "seduction"
|
||||
glass_icon_state = "between_the_sheets"
|
||||
glass_name = "Between the Sheets"
|
||||
glass_desc = "A provocatively named classic."
|
||||
|
||||
/datum/reagent/consumable/ethanol/kamikaze
|
||||
name = "Kamikaze"
|
||||
id = "kamikaze"
|
||||
description = "Divinely windy."
|
||||
color = "#EEF191"
|
||||
boozepwr = 60
|
||||
taste_description = "divine windiness"
|
||||
glass_icon_state = "kamikaze"
|
||||
glass_name = "Kamikaze"
|
||||
glass_desc = "Divinely windy."
|
||||
|
||||
/datum/reagent/consumable/ethanol/mojito
|
||||
name = "Mojito"
|
||||
id = "mojito"
|
||||
description = "A drink that looks as refreshing as it tastes."
|
||||
color = "#DFFAD9"
|
||||
boozepwr = 30
|
||||
taste_description = "refreshing mint"
|
||||
glass_icon_state = "mojito"
|
||||
glass_name = "Mojito"
|
||||
glass_desc = "A drink that looks as refreshing as it tastes."
|
||||
|
||||
@@ -721,3 +721,13 @@
|
||||
description = "Milk for cool kids."
|
||||
color = "#7D4E29"
|
||||
taste_description = "chocolate milk"
|
||||
|
||||
/datum/reagent/consumable/menthol
|
||||
name = "Menthol"
|
||||
id = "menthol"
|
||||
description = "Tastes naturally minty, and imparts a very mild numbing sensation."
|
||||
color = "#80AF9C"
|
||||
taste_description = "mint"
|
||||
glass_icon_state = "glass_green"
|
||||
glass_name = "glass of menthol"
|
||||
glass_desc = "Tastes naturally minty, and imparts a very mild numbing sensation."
|
||||
|
||||
@@ -57,15 +57,6 @@
|
||||
..()
|
||||
. = 1
|
||||
|
||||
/datum/reagent/drug/menthol
|
||||
name = "Menthol"
|
||||
id = "menthol"
|
||||
description = "Tastes naturally minty, and imparts a very mild numbing sensation."
|
||||
taste_description = "mint"
|
||||
reagent_state = LIQUID
|
||||
color = "#80AF9C"
|
||||
trippy = FALSE
|
||||
|
||||
/datum/reagent/drug/crank
|
||||
name = "Crank"
|
||||
id = "crank"
|
||||
|
||||
@@ -171,8 +171,7 @@
|
||||
|
||||
else if(istype(O, /obj/item/stack/sheet/hairlesshide))
|
||||
var/obj/item/stack/sheet/hairlesshide/HH = O
|
||||
var/obj/item/stack/sheet/wetleather/WL = new(get_turf(HH))
|
||||
WL.amount = HH.amount
|
||||
new /obj/item/stack/sheet/wetleather(get_turf(HH), HH.amount)
|
||||
qdel(HH)
|
||||
|
||||
/*
|
||||
|
||||
@@ -728,7 +728,7 @@
|
||||
/datum/reagent/toxin/rotatium/on_mob_life(mob/living/M)
|
||||
if(M.hud_used)
|
||||
if(current_cycle >= 20 && current_cycle%20 == 0)
|
||||
var/list/screens = list(M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
var/rotation = min(round(current_cycle/20), 89) // By this point the player is probably puking and quitting anyway
|
||||
for(var/whole_screen in screens)
|
||||
animate(whole_screen, transform = matrix(rotation, MATRIX_ROTATE), time = 5, easing = QUAD_EASING, loop = -1)
|
||||
@@ -737,7 +737,7 @@
|
||||
|
||||
/datum/reagent/toxin/rotatium/on_mob_delete(mob/living/M)
|
||||
if(M && M.hud_used)
|
||||
var/list/screens = list(M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
for(var/whole_screen in screens)
|
||||
animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
|
||||
..()
|
||||
@@ -755,7 +755,7 @@
|
||||
/datum/reagent/toxin/skewium/on_mob_life(mob/living/M)
|
||||
if(M.hud_used)
|
||||
if(current_cycle >= 5 && current_cycle % 3 == 0)
|
||||
var/list/screens = list(M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
var/matrix/skew = matrix()
|
||||
var/intensity = 8
|
||||
skew.set_skew(rand(-intensity,intensity), rand(-intensity,intensity))
|
||||
@@ -772,7 +772,7 @@
|
||||
|
||||
/datum/reagent/toxin/skewium/on_mob_delete(mob/living/M)
|
||||
if(M && M.hud_used)
|
||||
var/list/screens = list(M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
var/list/screens = list(M.hud_used.plane_masters["[FLOOR_PLANE]"], M.hud_used.plane_masters["[GAME_PLANE]"], M.hud_used.plane_masters["[LIGHTING_PLANE]"])
|
||||
for(var/whole_screen in screens)
|
||||
animate(whole_screen, transform = matrix(), time = 5, easing = QUAD_EASING)
|
||||
..()
|
||||
|
||||
@@ -51,8 +51,9 @@ other types of metals and chemistry for reagents).
|
||||
return ..()
|
||||
|
||||
/datum/design/proc/icon_html(client/user)
|
||||
send_asset(user, "design_[id].png", FALSE)
|
||||
return "<img class='icon' src=\"design_[id].png\">"
|
||||
var/datum/asset/spritesheet/sheet = get_asset_datum(/datum/asset/spritesheet/research_designs)
|
||||
sheet.send(user)
|
||||
return sheet.icon_tag(id)
|
||||
|
||||
////////////////////////////////////////
|
||||
//Disks for transporting design datums//
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user