Merge remote-tracking branch 'polaris/master' into pl-chemistry

This commit is contained in:
GinjaNinja32
2015-12-22 02:55:31 +00:00
160 changed files with 20420 additions and 20049 deletions
+1
View File
@@ -234,6 +234,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
/datum/controller/air_system/proc/remove_zone(zone/z)
zones.Remove(z)
zones_to_update.Remove(z)
/datum/controller/air_system/proc/air_blocked(turf/A, turf/B)
#ifdef ZASDBG
+3 -2
View File
@@ -108,11 +108,12 @@ Class Procs:
c_invalidate()
for(var/turf/simulated/T in contents)
into.add(T)
T.update_graphic(graphic_remove = air.graphic)
#ifdef ZASDBG
T.dbg(merged)
#endif
//rebuild the old zone's edges so that the will be possesed by the new zone
//rebuild the old zone's edges so that they will be possessed by the new zone
for(var/connection_edge/E in edges)
if(E.contains_zone(into))
continue //don't need to rebuild this edge
+1 -1
View File
@@ -91,7 +91,7 @@ var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret
// Will not bother pumping or filtering if the gas source as fewer than this amount of moles, to help with performance.
#define MINIMUM_MOLES_TO_PUMP 0.01
#define MINIMUM_MOLES_TO_FILTER 0.1
#define MINIMUM_MOLES_TO_FILTER 0.04
// The flow rate/effectiveness of various atmos devices is limited by their internal volume,
// so for many atmos devices these will control maximum flow rates in L/s.
+4
View File
@@ -0,0 +1,4 @@
#define TARGET_CAN_MOVE 1
#define TARGET_CAN_RUN 2
#define TARGET_CAN_CLICK 4
#define TARGET_CAN_RADIO 8
+12 -14
View File
@@ -38,8 +38,10 @@
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
*/
/mob/proc/ClickOn(var/atom/A, var/params)
if(world.time <= next_click) // Hard check, before anything else, to avoid crashing
return
next_click = world.time + 1
if(client.buildmode)
@@ -49,19 +51,19 @@
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
return 1
if(modifiers["middle"])
MiddleClickOn(A)
return
return 1
if(modifiers["shift"])
ShiftClickOn(A)
return
return 0
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
return 1
if(modifiers["ctrl"])
CtrlClickOn(A)
return
return 1
if(stat || paralysis || stunned || weakened)
return
@@ -80,17 +82,14 @@
if(restrained())
setClickCooldown(10)
RestrainedClickOn(A)
return
return 1
if(in_throw_mode)
if(isturf(A) || isturf(A.loc))
throw_item(A)
return
return 1
throw_mode_off()
if(!istype(A, /obj/item/weapon/gun) && !isturf(A) && !istype(A, /obj/screen))
last_target_click = world.time
var/obj/item/W = get_active_hand()
if(W == A) // Handle attack_self
@@ -99,7 +98,7 @@
update_inv_l_hand(0)
else
update_inv_r_hand(0)
return
return 1
//Atoms on your person
// A is your location but is not a turf; or is on you (backpack); or is on something on you (box in backpack); sdepth is needed here because contents depth does not equate inventory storage depth.
@@ -117,7 +116,7 @@
if(ismob(A)) // No instant mob attacking
setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
UnarmedAttack(A, 1)
return
return 1
if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that
return
@@ -144,8 +143,7 @@
W.afterattack(A, src, 0, params) // 0: not Adjacent
else
RangedAttack(A, params)
return
return 1
/mob/proc/setClickCooldown(var/timeout)
next_move = max(world.time + timeout, next_move)
+66
View File
@@ -0,0 +1,66 @@
/obj/screen/gun
name = "gun"
icon = 'icons/mob/screen1.dmi'
master = null
dir = 2
/obj/screen/gun/Click(location, control, params)
if(!usr)
return
return 1
/obj/screen/gun/move
name = "Allow Movement"
icon_state = "no_walk0"
screen_loc = ui_gun2
/obj/screen/gun/move/Click(location, control, params)
if(..())
var/mob/living/user = usr
if(istype(user))
if(!user.aiming) user.aiming = new(user)
user.aiming.toggle_permission(TARGET_CAN_MOVE)
return 1
return 0
/obj/screen/gun/item
name = "Allow Item Use"
icon_state = "no_item0"
screen_loc = ui_gun1
/obj/screen/gun/item/Click(location, control, params)
if(..())
var/mob/living/user = usr
if(istype(user))
if(!user.aiming) user.aiming = new(user)
user.aiming.toggle_permission(TARGET_CAN_CLICK)
return 1
return 0
/obj/screen/gun/mode
name = "Toggle Gun Mode"
icon_state = "gun0"
screen_loc = ui_gun_select
/obj/screen/gun/mode/Click(location, control, params)
if(..())
var/mob/living/user = usr
if(istype(user))
if(!user.aiming) user.aiming = new(user)
user.aiming.toggle_active()
return 1
return 0
/obj/screen/gun/radio
name = "Allow Radio Use"
icon_state = "no_radio0"
screen_loc = ui_gun4
/obj/screen/gun/radio/Click(location, control, params)
if(..())
var/mob/living/user = usr
if(istype(user))
if(!user.aiming) user.aiming = new(user)
user.aiming.toggle_permission(TARGET_CAN_RADIO)
return 1
return 0
-2
View File
@@ -257,8 +257,6 @@ datum/hud/New(mob/owner)
human_hud(ui_style, ui_color, ui_alpha, mymob) // Pass the player the UI style chosen in preferences
else if(isrobot(mymob))
robot_hud()
else if(issmall(mymob))
monkey_hud(ui_style, ui_color, ui_alpha)
else if(isbrain(mymob))
brain_hud(ui_style)
else if(isalien(mymob))
+3 -7
View File
@@ -1,5 +1,7 @@
/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255, var/mob/living/carbon/human/target)
/mob/living/carbon/human/instantiate_hud(var/datum/hud/HUD, var/ui_style, var/ui_color, var/ui_alpha)
HUD.human_hud(ui_style, ui_color, ui_alpha, src)
/datum/hud/proc/human_hud(var/ui_style='icons/mob/screen1_White.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255, var/mob/living/carbon/human/target)
var/datum/hud_data/hud_data
if(!istype(target))
hud_data = new()
@@ -354,17 +356,11 @@
mymob.gun_move_icon.color = ui_color
mymob.gun_move_icon.alpha = ui_alpha
mymob.gun_run_icon = new /obj/screen/gun/run(null)
mymob.gun_run_icon.icon = ui_style
mymob.gun_run_icon.color = ui_color
mymob.gun_run_icon.alpha = ui_alpha
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
mymob.radio_use_icon.icon = ui_style
mymob.radio_use_icon.color = ui_color
mymob.radio_use_icon.alpha = ui_alpha
mymob.client.screen = null
mymob.client.screen += hud_elements
-282
View File
@@ -1,282 +0,0 @@
/datum/hud/proc/monkey_hud(var/ui_style='icons/mob/screen1_old.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255)
src.adding = list()
src.other = list()
var/obj/screen/using
var/obj/screen/inventory/inv_box
using = new /obj/screen()
using.name = "act_intent"
using.icon = ui_style
using.color = ui_color
using.alpha = ui_alpha
using.icon_state = mymob.a_intent
using.screen_loc = ui_acti
using.layer = 20
src.adding += using
action_intent = using
//intent small hud objects
var/icon/ico
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),1,ico.Height()/2,ico.Width()/2,ico.Height())
using = new /obj/screen( src )
using.name = I_HELP
using.icon = ico
using.screen_loc = ui_acti
using.layer = 21
src.adding += using
help_intent = using
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,ico.Height()/2,ico.Width(),ico.Height())
using = new /obj/screen( src )
using.name = I_DISARM
using.icon = ico
using.screen_loc = ui_acti
using.layer = 21
src.adding += using
disarm_intent = using
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),ico.Width()/2,1,ico.Width(),ico.Height()/2)
using = new /obj/screen( src )
using.name = I_GRAB
using.icon = ico
using.screen_loc = ui_acti
using.layer = 21
src.adding += using
grab_intent = using
ico = new(ui_style, "black")
ico.MapColors(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, -1,-1,-1,-1)
ico.DrawBox(rgb(255,255,255,1),1,1,ico.Width()/2,ico.Height()/2)
using = new /obj/screen( src )
using.name = I_HURT
using.icon = ico
using.screen_loc = ui_acti
using.layer = 21
src.adding += using
hurt_intent = using
//end intent small hud objects
using = new /obj/screen()
using.name = "mov_intent"
using.icon = ui_style
using.color = ui_color
using.alpha = ui_alpha
using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
using.screen_loc = ui_movi
using.layer = 20
src.adding += using
move_intent = using
using = new /obj/screen()
using.name = "drop"
using.icon = ui_style
using.color = ui_color
using.alpha = ui_alpha
using.icon_state = "act_drop"
using.screen_loc = ui_drop_throw
using.layer = 19
src.adding += using
inv_box = new /obj/screen/inventory()
inv_box.name = "r_hand"
inv_box.icon = ui_style
using.color = ui_color
using.alpha = ui_alpha
inv_box.icon_state = "r_hand_inactive"
if(mymob && !mymob.hand) //This being 0 or null means the right hand is in use
inv_box.icon_state = "hand_active"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
inv_box.layer = 19
src.r_hand_hud_object = inv_box
src.adding += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "l_hand"
inv_box.icon = ui_style
using.color = ui_color
using.alpha = ui_alpha
inv_box.icon_state = "l_hand_inactive"
if(mymob && mymob.hand) //This being 1 means the left hand is in use
inv_box.icon_state = "hand_active"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
inv_box.layer = 19
src.l_hand_hud_object = inv_box
src.adding += inv_box
using = new /obj/screen/inventory()
using.name = "hand"
using.icon = ui_style
using.color = ui_color
using.alpha = ui_alpha
using.icon_state = "hand1"
using.screen_loc = ui_swaphand1
using.layer = 19
src.adding += using
using = new /obj/screen/inventory()
using.name = "hand"
using.icon = ui_style
using.color = ui_color
using.alpha = ui_alpha
using.icon_state = "hand2"
using.screen_loc = ui_swaphand2
using.layer = 19
src.adding += using
inv_box = new /obj/screen/inventory()
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.color = ui_color
inv_box.alpha = ui_alpha
inv_box.icon_state = "equip"
inv_box.screen_loc = ui_monkey_mask
inv_box.slot_id = slot_wear_mask
inv_box.layer = 19
src.adding += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.color = ui_color
inv_box.alpha = ui_alpha
inv_box.icon_state = "equip"
inv_box.screen_loc = ui_back
inv_box.slot_id = slot_back
inv_box.layer = 19
src.adding += inv_box
mymob.throw_icon = new /obj/screen()
mymob.throw_icon.icon = ui_style
mymob.throw_icon.color = ui_color
mymob.throw_icon.alpha = ui_alpha
mymob.throw_icon.icon_state = "act_throw_off"
mymob.throw_icon.name = "throw"
mymob.throw_icon.screen_loc = ui_drop_throw
mymob.oxygen = new /obj/screen()
mymob.oxygen.icon = ui_style
mymob.oxygen.color = ui_color
mymob.oxygen.alpha = ui_alpha
mymob.oxygen.icon_state = "oxy0"
mymob.oxygen.name = "oxygen"
mymob.oxygen.screen_loc = ui_oxygen
mymob.pressure = new /obj/screen()
mymob.pressure.icon = ui_style
mymob.pressure.color = ui_color
mymob.pressure.alpha = ui_alpha
mymob.pressure.icon_state = "pressure0"
mymob.pressure.name = "pressure"
mymob.pressure.screen_loc = ui_pressure
mymob.toxin = new /obj/screen()
mymob.toxin.icon = ui_style
mymob.toxin.color = ui_color
mymob.toxin.alpha = ui_alpha
mymob.toxin.icon_state = "tox0"
mymob.toxin.name = "toxin"
mymob.toxin.screen_loc = ui_toxin
mymob.internals = new /obj/screen()
mymob.internals.icon = ui_style
mymob.internals.color = ui_color
mymob.internals.alpha = ui_alpha
mymob.internals.icon_state = "internal0"
mymob.internals.name = "internal"
mymob.internals.screen_loc = ui_internal
mymob.fire = new /obj/screen()
mymob.fire.icon = ui_style
mymob.fire.color = ui_color
mymob.fire.alpha = ui_alpha
mymob.fire.icon_state = "fire0"
mymob.fire.name = "fire"
mymob.fire.screen_loc = ui_fire
mymob.bodytemp = new /obj/screen()
mymob.bodytemp.icon = ui_style
mymob.bodytemp.color = ui_color
mymob.bodytemp.alpha = ui_alpha
mymob.bodytemp.icon_state = "temp1"
mymob.bodytemp.name = "body temperature"
mymob.bodytemp.screen_loc = ui_temp
mymob.healths = new /obj/screen()
mymob.healths.icon = ui_style
mymob.healths.color = ui_color
mymob.healths.alpha = ui_alpha
mymob.healths.icon_state = "health0"
mymob.healths.name = "health"
mymob.healths.screen_loc = ui_health
mymob.pullin = new /obj/screen()
mymob.pullin.icon = ui_style
mymob.pullin.color = ui_color
mymob.pullin.alpha = ui_alpha
mymob.pullin.icon_state = "pull0"
mymob.pullin.name = "pull"
mymob.pullin.screen_loc = ui_pull_resist
mymob.blind = new /obj/screen()
mymob.blind.icon = 'icons/mob/screen1_full.dmi'
mymob.blind.icon_state = "blackimageoverlay"
mymob.blind.name = " "
mymob.blind.screen_loc = "1,1"
mymob.blind.layer = 0
mymob.flash = new /obj/screen()
mymob.flash.icon = ui_style
mymob.flash.icon_state = "blank"
mymob.flash.name = "flash"
mymob.flash.screen_loc = ui_entire_screen
mymob.flash.layer = 17
mymob.zone_sel = new /obj/screen/zone_sel()
mymob.zone_sel.icon = ui_style
mymob.zone_sel.color = ui_color
mymob.zone_sel.alpha = ui_alpha
mymob.zone_sel.overlays.Cut()
mymob.zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[mymob.zone_sel.selecting]")
//Handle the gun settings buttons
mymob.gun_setting_icon = new /obj/screen/gun/mode(null)
if (mymob.client)
if (mymob.client.gun_mode) // If in aim mode, correct the sprite
mymob.gun_setting_icon.set_dir(2)
for(var/obj/item/weapon/gun/G in mymob) // If targeting someone, display other buttons
if (G.aim_targets)
mymob.item_use_icon = new /obj/screen/gun/item(null)
if (mymob.client.target_can_click)
mymob.item_use_icon.set_dir(1)
src.adding += mymob.item_use_icon
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
if (mymob.client.target_can_radio)
mymob.radio_use_icon.set_dir(1)
src.adding += mymob.radio_use_icon
mymob.gun_move_icon = new /obj/screen/gun/move(null)
if (mymob.client.target_can_move)
mymob.gun_move_icon.set_dir(1)
mymob.gun_run_icon = new /obj/screen/gun/run(null)
if (mymob.client.target_can_run)
mymob.gun_run_icon.set_dir(1)
src.adding += mymob.gun_run_icon
src.adding += mymob.gun_move_icon
mymob.client.screen = null
mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.pressure, mymob.toxin, mymob.bodytemp, mymob.internals, mymob.fire, mymob.healths, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon) //, mymob.hands, mymob.rest, mymob.sleep, mymob.mach )
mymob.client.screen += src.adding + src.other
return
+4 -22
View File
@@ -153,31 +153,13 @@ var/obj/screen/robot_inventory
//Handle the gun settings buttons
mymob.gun_setting_icon = new /obj/screen/gun/mode(null)
if (mymob.client)
if (mymob.client.gun_mode) // If in aim mode, correct the sprite
mymob.gun_setting_icon.set_dir(2)
for(var/obj/item/weapon/gun/G in mymob) // If targeting someone, display other buttons
if (G.aim_targets)
mymob.item_use_icon = new /obj/screen/gun/item(null)
if (mymob.client.target_can_click)
mymob.item_use_icon.set_dir(1)
src.adding += mymob.item_use_icon
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
if (mymob.client.target_can_radio)
mymob.radio_use_icon.set_dir(1)
src.adding += mymob.radio_use_icon
mymob.gun_move_icon = new /obj/screen/gun/move(null)
if (mymob.client.target_can_move)
mymob.gun_move_icon.set_dir(1)
mymob.gun_run_icon = new /obj/screen/gun/run(null)
if (mymob.client.target_can_run)
mymob.gun_run_icon.set_dir(1)
src.adding += mymob.gun_run_icon
src.adding += mymob.gun_move_icon
mymob.item_use_icon = new /obj/screen/gun/item(null)
mymob.gun_move_icon = new /obj/screen/gun/move(null)
mymob.radio_use_icon = new /obj/screen/gun/radio(null)
mymob.client.screen = null
mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, mymob.gun_setting_icon, robot_inventory) //, mymob.rest, mymob.sleep, mymob.mach )
mymob.client.screen += list( mymob.throw_icon, mymob.zone_sel, mymob.oxygen, mymob.fire, mymob.hands, mymob.healths, mymob:cells, mymob.pullin, mymob.blind, mymob.flash, robot_inventory, mymob.gun_setting_icon)
mymob.client.screen += src.adding + src.other
return
-74
View File
@@ -12,7 +12,6 @@
layer = 20.0
unacidable = 1
var/obj/master = null //A reference to the object in the slot. Grabs or items, generally.
var/gun_click_time = -100 //I'm lazy.
/obj/screen/Destroy()
master = null
@@ -95,38 +94,6 @@
usr.ClickOn(master)
return 1
/obj/screen/gun
name = "gun"
icon = 'icons/mob/screen1.dmi'
master = null
dir = 2
move
name = "Allow Walking"
icon_state = "no_walk0"
screen_loc = ui_gun2
run
name = "Allow Running"
icon_state = "no_run0"
screen_loc = ui_gun3
item
name = "Allow Item Use"
icon_state = "no_item0"
screen_loc = ui_gun1
mode
name = "Toggle Gun Mode"
icon_state = "gun0"
screen_loc = ui_gun_select
//dir = 1
radio
name = "Allow Radio Use"
icon_state = "no_radio0"
screen_loc = ui_gun4
/obj/screen/zone_sel
name = "damage zone"
icon_state = "zone_sel"
@@ -201,7 +168,6 @@
/obj/screen/Click(location, control, params)
if(!usr) return 1
switch(name)
if("toggle")
if(usr.hud_used.inventory_shown)
@@ -431,46 +397,6 @@
if("module3")
if(istype(usr, /mob/living/silicon/robot))
usr:toggle_module(3)
if("Allow Walking", "Disallow Walking")
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
return
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
usr << "You need your gun in your active hand to do that!"
return
usr.client.AllowTargetMove()
gun_click_time = world.time
if("Allow Running", "Disallow Running")
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
return
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
usr << "You need your gun in your active hand to do that!"
return
usr.client.AllowTargetRun()
gun_click_time = world.time
if("Allow Item Use", "Disallow Item Use")
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
return
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
usr << "You need your gun in your active hand to do that!"
return
usr.client.AllowTargetClick()
gun_click_time = world.time
if("Toggle Gun Mode")
usr.client.ToggleGunMode()
if("Allow Radio Use", "Disallow Radio Use")
if(gun_click_time > world.time - 30) //give them 3 seconds between mode changes.
return
if(!istype(usr.get_active_hand(),/obj/item/weapon/gun))
usr << "You need your gun in your active hand to do that!"
return
usr.client.AllowTargetRadio()
gun_click_time = world.time
else
return 0
return 1
+127
View File
@@ -0,0 +1,127 @@
/*
Exonet Protocol Version 2
This is designed to be a fairly simple fake-networking system, allowing you to send and receive messages
between the exonet_protocol datums, and for atoms to react to those messages, based on the contents of the message.
Hopefully, this can evolve to be a more robust fake-networking system and allow for some devious network hacking in the future.
Version 1 never existed.
*Setting up*
To set up the exonet link, define a variable on your desired atom it is like this;
var/datum/exonet_protocol/exonet = null
Afterwards, before you want to do networking, call exonet = New(src), then exonet.make_address(string), and give it a string to hash into the new IP.
The reason it needs a string is so you can have the addresses be persistant, assuming no-one already took it first.
When you're no longer wanting to use the address and want to free it up, like when you want to Destroy() it, you need to call remove_address()
*Sending messages*
To send a message to another datum, you need to know it's EPv2 (fake IP) address. Once you know that, call send_message(), place your
intended address in the first argument, then the message in the second. For example, send_message(exonet.address, "ping") will make you
ping yourself.
*Receiving messages*
You don't need to do anything special to receive the messages, other than give your target exonet datum an address as well. Once something hits
your datum with send_message(), receive_message() is called, and the default action is to call receive_exonet_message() on the datum's holder.
You'll want to override receive_exonet_message() on your atom, and define what will occur when the message is received.
The receiving atom will receive the origin atom (the atom that sent the message), the origin address, and finally the message itself.
It's suggested to start with an if or switch statement for the message, to determine what to do.
*/
var/global/list/all_exonet_connections = list()
/datum/exonet_protocol
var/address = "" //Resembles IPv6, but with only five 'groups', e.g. XXXX:XXXX:XXXX:XXXX:XXXX
var/atom/movable/holder = null
/datum/exonet_protocol/New(var/atom/holder)
src.holder = holder
..()
// Proc: make_address()
// Parameters: 1 (string - used to make into a hash that will be part of the new address)
// Description: Allocates a new address based on the string supplied. It results in consistant addresses for each round assuming it is not already taken..
/datum/exonet_protocol/proc/make_address(var/string)
if(string)
var/new_address = null
while(new_address == find_address(new_address)) //Collision test.
var/hash = md5(string)
var/raw_address = copytext(hash,1,25)
var/addr_0 = "fc00" //Used for unique local address in real-life IPv6.
var/addr_1 = hexadecimal_to_EPv2(raw_address)
new_address = "[addr_0]:[addr_1]"
string = "[string]0" //If we did get a collision, this should make the next attempt not have one.
sleep(1)
address = new_address
all_exonet_connections |= src
// Proc: make_arbitrary_address()
// Parameters: 1 (new_address - the desired address)
// Description: Allocates that specific address, if it is available.
/datum/exonet_protocol/proc/make_arbitrary_address(var/new_address)
if(new_address)
if(new_address == find_address(new_address) ) //Collision test.
return 0
address = new_address
all_exonet_connections |= src
return 1
// Proc: hexadecimal_to_EPv2()
// Parameters: 1 (hex - a string of hexadecimals to convert)
// Description: Helper proc to add colons to a string in the right places.
/proc/hexadecimal_to_EPv2(var/hex)
if(!hex)
return null
var/addr_1 = copytext(hex,1,5)
var/addr_2 = copytext(hex,5,9)
var/addr_3 = copytext(hex,9,13)
var/addr_4 = copytext(hex,13,17)
var/new_address = "[addr_1]:[addr_2]:[addr_3]:[addr_4]"
return new_address
// Proc: remove_address()
// Parameters: None
// Description: Deallocates the address, freeing it for use.
/datum/exonet_protocol/proc/remove_address()
address = ""
all_exonet_connections.Remove(src)
// Proc: find_address()
// Parameters: 1 (target_address - the desired address to find)
// Description: Searches the global list all_exonet_connections for a specific address, and returns it if found, otherwise returns null.
/datum/exonet_protocol/proc/find_address(var/target_address)
for(var/datum/exonet_protocol/exonet in all_exonet_connections)
if(exonet.address == target_address)
return exonet.address
return null
// Proc: send_message()
// Parameters: 2 (target_address - the desired address to send the message to, message - the message to send)
// Description: Sends the message to target_address, by calling receive_message() on the desired datum.
/datum/exonet_protocol/proc/send_message(var/target_address, var/message)
if(!address)
return 0
for(var/datum/exonet_protocol/exonet in all_exonet_connections)
if(exonet.address == target_address)
exonet.receive_message(holder, address, message)
break
// Proc: receive_message()
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
// Description: Called when send_message() successfully reaches the intended datum. By default, calls receive_exonet_message() on the holder atom.
/datum/exonet_protocol/proc/receive_message(var/atom/origin_atom, var/origin_address, var/message)
holder.receive_exonet_message(origin_atom, origin_address, message)
return
// Proc: receive_exonet_message()
// Parameters: 3 (origin_atom - the origin datum's holder, origin_address - the address the message originated from, message - the message that was sent)
// Description: Override this to make your atom do something when a message is received.
/atom/proc/receive_exonet_message(var/atom/origin_atom, var/origin_address, var/message)
return
+19 -1
View File
@@ -8,7 +8,7 @@
if(creator)
parent = creator
var/global/datum/locations/milky_way/locations = new()
var/global/datum/locations/milky_way/all_locations = new()
//Galaxy
@@ -26,6 +26,24 @@ var/global/datum/locations/milky_way/locations = new()
new /datum/locations/uueoa_esa(src),
new /datum/locations/vir(src)
)
/proc/choose_location_datum(client/user)
var/datum/locations/choice = all_locations
while(length(choice.contents) > 0) //For some reason it wouldn't let me do contents.len even when I defined it as a list.
var/specific = alert(user, "The location currently selected is [choice.name]. More specific options exist, would you like to pick a more specific location?",
"Choose location", "Yes", "No")
if(specific == "Yes" && length(choice.contents) > 0)
choice = input(user, "Please choose a location.","Locations") as null|anything in choice.contents
else
break
user << choice.name
user << choice.desc
return choice
// var/datum/locations/choice = input(user, "Please choose a location.","Locations") as null|anything in all_locations
// if(choice && choice.contents.len > 0)
/*
/datum/locations/proc/show_contents()
// world << "[src]\n[desc]"
+11
View File
@@ -52,6 +52,17 @@
desc = "The Northern Star is an asteroid colony owned and operated by Nanotrasen, among many other asteroid installations. \
Originally conceived as 'just another pitstop' for weary asteroid miners, it has grown to become a significant installation in the Kara subsystem."
/datum/locations/northern_star/New(var/creator)
contents.Add(
new /datum/locations/northern_star_interior(src)
)
..(creator)
/datum/locations/northern_star_interior
name = "Northern Star Inner Level"
desc = "The Northern Star contains multiple layers, this one being the inner level, also known as the residentual area. It contains most of the \
homes for the Northern Star, as well as acting as the heart of commerece, with many shops and markets near the center."
/datum/locations/rota
name = "Rota"
desc = "A Neptune-like ice giant, with a beautiful ring system circling it. It is 165 kelvin (-157°C)."
+2 -2
View File
@@ -715,8 +715,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/obj/item/weapon/gun/energy/gun,
/obj/item/weapon/gun/energy/taser,
/obj/item/weapon/gun/energy/taser,
/obj/item/weapon/gun/projectile/sec,
/obj/item/weapon/gun/projectile/sec,
/obj/item/weapon/gun/projectile/colt/detective,
/obj/item/weapon/gun/projectile/colt/detective,
/obj/item/weapon/storage/box/flashbangs,
/obj/item/weapon/storage/box/flashbangs)
cost = 40
-1
View File
@@ -174,7 +174,6 @@
w_class = 3.0
origin_tech = list(TECH_MATERIAL = 1)
var/breakouttime = 300 //Deciseconds = 30s = 0.5 minute
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/handcuffs.dmi')
/obj/item/weapon/caution
desc = "Caution! Wet Floor!"
+1 -2
View File
@@ -86,8 +86,7 @@ var/datum/antagonist/raider/raiders
/obj/item/weapon/gun/projectile/shotgun/doublebarrel,
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet,
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/sawn,
/obj/item/weapon/gun/projectile/colt,
/obj/item/weapon/gun/projectile/sec,
/obj/item/weapon/gun/projectile/colt/detective,
/obj/item/weapon/gun/projectile/pistol,
/obj/item/weapon/gun/projectile/revolver,
/obj/item/weapon/gun/projectile/pirate
+4 -2
View File
@@ -561,6 +561,7 @@ area/space/atmosalert()
icon_state = "yellow"
requires_power = 0
flags = RAD_SHIELDED
base_turf = /turf/space
/area/syndicate_station/start
name = "\improper Mercenary Forward Operating Base"
@@ -620,6 +621,7 @@ area/space/atmosalert()
name = "\improper Skipjack"
icon_state = "yellow"
requires_power = 0
base_turf = /turf/space
/area/skipjack_station/start
name = "\improper Skipjack"
@@ -2760,7 +2762,7 @@ var/list/the_station_areas = list (
lighting_use_dynamic = 0
requires_power = 0
var/sound/mysound = null
/*
New()
..()
var/sound/S = new/sound()
@@ -2808,4 +2810,4 @@ var/list/the_station_areas = list (
H << S
spawn(60) .()
*/
+3 -3
View File
@@ -1,8 +1,8 @@
// Returns the lowest turf available on a given Z-level, defaults to asteroid for Polaris.
var/global/list/base_turf_by_z = list(
"1" = /turf/simulated/floor/asteroid,
"4" = /turf/simulated/floor/asteroid,
"5" = /turf/simulated/floor/asteroid
"1" = /turf/simulated/mineral/floor,
"4" = /turf/simulated/mineral/floor,
"5" = /turf/simulated/mineral/floor
)
proc/get_base_turf(var/z)
@@ -72,8 +72,8 @@
icon_state = "lingarmor"
// item_state = "lingarmor"
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
armor = list(melee = 85, bullet = 70, laser = 70, energy = 70, bomb = 70, bio = 0, rad = 0) //It costs 3 points, so it should be very protective.
siemens_coefficient = 0.1
armor = list(melee = 75, bullet = 60, laser = 60, energy = 60, bomb = 60, bio = 0, rad = 0) //It costs 3 points, so it should be very protective.
siemens_coefficient = 0.3
max_heat_protection_temperature = FIRESUIT_MAX_HEAT_PROTECTION_TEMPERATURE
slowdown = 3
@@ -92,8 +92,8 @@
desc = "A tough, hard covering of black chitin with transparent chitin in front."
icon_state = "lingarmorhelmet"
// item_state = "lingarmorhelmet"
armor = list(melee = 85, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0)
siemens_coefficient = 0.1
armor = list(melee = 75, bullet = 60, laser = 60,energy = 60, bomb = 60, bio = 0, rad = 0)
siemens_coefficient = 0.3
max_heat_protection_temperature = FIRE_HELMET_MAX_HEAT_PROTECTION_TEMPERATURE
/obj/item/clothing/head/helmet/space/changeling/armored/dropped()
@@ -103,7 +103,7 @@
name = "chitinous gauntlets"
desc = "Very resilient gauntlets made out of black chitin. It looks very durable, and can probably resist electrical shock in addition to the elements."
icon_state = "lingarmorgloves"
armor = list(melee = 85, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0) //No idea if glove armor gets checked
armor = list(melee = 75, bullet = 60, laser = 60,energy = 60, bomb = 60, bio = 0, rad = 0) //No idea if glove armor gets checked
siemens_coefficient = 0
/obj/item/clothing/shoes/combat/changeling //Noslips
@@ -111,8 +111,8 @@
name = "Footwear made out of a hard, black chitinous material. The bottoms of these appear to have spikes that can protrude or extract itself into and out \
of the floor at will, granting the wearer stability."
icon_state = "lingboots"
armor = list(melee = 85, bullet = 70, laser = 70,energy = 70, bomb = 70, bio = 0, rad = 0)
siemens_coefficient = 0.1
armor = list(melee = 75, bullet = 60, laser = 70,energy = 60, bomb = 60, bio = 0, rad = 0)
siemens_coefficient = 0.3
cold_protection = FEET
min_cold_protection_temperature = SHOE_MIN_COLD_PROTECTION_TEMPERATURE
heat_protection = FEET
@@ -22,6 +22,10 @@
if(T.reagents)
T.reagents.add_reagent("cryotoxin", inject_amount)
feedback_add_details("changeling_powers","CS")
src.verbs -= /mob/proc/changeling_cryo_sting
spawn(3 MINUTES)
src << "<span class='notice'>Our cryogenic string is ready to be used once more.</span>"
src.verbs |= /mob/proc/changeling_cryo_sting
return 1
/datum/reagent/cryotoxin //A much more potent version of frost oil.
@@ -34,7 +38,7 @@
/datum/reagent/cryotoxin/affect_blood(var/mob/living/carbon/M, var/alien, var/removed)
if(alien == IS_DIONA)
return
M.bodytemperature = max(M.bodytemperature - 40 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
M.bodytemperature = max(M.bodytemperature - 30 * TEMPERATURE_DAMAGE_COEFFICIENT, 0)
if(prob(3))
M.emote("shiver")
..()
@@ -19,13 +19,18 @@
i = i * 2
src << "<span class='notice'>Our toxin will be extra potent, when it strikes.</span>"
src.mind.changeling.recursive_enhancement = 0
spawn(120) //Two minutes
spawn(2 MINUTES)
if(T) //We might not exist in two minutes, for whatever reason.
T << "<span class='danger'>You feel a burning sensation flowing through your veins!</span>"
while(i)
T.adjustToxLoss(1)
i--
sleep(20)
src.verbs -= /mob/proc/changeling_delayed_toxic_sting
spawn(3 MINUTES)
src << "<span class='notice'>We are ready to use our delayed toxic string once more.</span>"
src.verbs |= /mob/proc/changeling_delayed_toxic_sting
feedback_add_details("changeling_powers","DTS")
return 1
feedback_add_details("changeling_powers","DTS")
return 1
+2 -37
View File
@@ -39,7 +39,7 @@
if(!isbroken)
if(prob(1+ damage * 5))
user.visible_message(
"<span class='danger'>[user] smashed the pylon!</span>",
"<span class='danger'>[user] smashed the pylon!</span>",
"<span class='warning'>You hit the pylon, and its crystal breaks apart!</span>",
"You hear a tinkle of crystal shards"
)
@@ -137,39 +137,4 @@
var/mob/living/M = A
if(M.stat != DEAD)
if(M.transforming)
return
if(M.has_brain_worms())
return //Borer stuff - RR
if(iscultist(M)) return
if(!ishuman(M) && !isrobot(M)) return
M.transforming = 1
M.canmove = 0
M.icon = null
M.overlays.len = 0
M.invisibility = 101
if(istype(M, /mob/living/silicon/robot))
var/mob/living/silicon/robot/Robot = M
if(Robot.mmi)
qdel(Robot.mmi)
else
for(var/obj/item/W in M)
if(istype(W, /obj/item/weapon/implant))
qdel(W)
continue
W.layer = initial(W.layer)
W.loc = M.loc
W.dropped(M)
var/mob/living/new_mob = new /mob/living/simple_animal/corgi(A.loc)
new_mob.a_intent = I_HURT
if(M.mind)
M.mind.transfer_to(new_mob)
else
new_mob.key = M.key
new_mob << "<B>Your form morphs into that of a corgi.</B>" //Because we don't have cluwnes
M << "<span class='danger'>Walking into \the [src] is probably a bad idea, you think.</span>"
+4 -15
View File
@@ -1,11 +1,8 @@
/*
In short:
* Random area alarms
* All areas jammed
* Random gateways spawning hellmonsters (and turn people into cluwnes if ran into)
* Broken APCs/Fire Alarms
* Scary music
* Random gateways spawning hellmonsters
* Broken Fire Alarms
* Random tiles changing to culty tiles.
*/
@@ -42,7 +39,7 @@ In short:
// Apply changes when entering state
/datum/universal_state/hell/OnEnter()
set background = 1
garbage_collector.garbage_collect = 0
// garbage_collector.garbage_collect = 0
escape_list = get_area_turfs(locate(/area/hallway/secondary/exit))
@@ -50,8 +47,8 @@ In short:
AreaSet()
MiscSet()
APCSet()
KillMobs()
OverlayAndAmbientSet()
lightsout(0,0)
runedec += 9000 //basically removing the rune cap
@@ -83,13 +80,5 @@ In short:
/datum/universal_state/hell/proc/APCSet()
for (var/obj/machinery/power/apc/APC in machines)
if (!(APC.stat & BROKEN) && !APC.is_critical)
APC.chargemode = 0
if(APC.cell)
APC.cell.charge = 0
APC.emagged = 1
APC.queue_icon_update()
/datum/universal_state/hell/proc/KillMobs()
for(var/mob/living/simple_animal/M in mob_list)
if(M && !M.client)
M.stat = DEAD
+17 -3
View File
@@ -196,10 +196,24 @@ var/list/sacrificed = list()
for(var/mob/M in range(1,src))
if(iscultist(M) && !M.stat)
M.say("Tok-lyr rqa'nap g[pick("'","`")]lt-ulotf!")
cultists += 1
if(istype(M, /mob/living/carbon/human/dummy)) //No manifest cheese.
continue
cultists.Add(M)
if(cultists.len >= 9)
log_and_message_admins_many(cultists, "summoned Nar-sie.")
new /obj/singularity/narsie/large(src.loc)
if(!narsie_cometh)//so we don't initiate Hell more than one time.
world << "<font size='15' color='red'><b>THE VEIL HAS BEEN SHATTERED!</b></font>"
world << sound('sound/effects/wind/wind_5_1.ogg')
SetUniversalState(/datum/universal_state/hell)
narsie_cometh = 1
spawn(10 SECONDS)
if(emergency_shuttle)
emergency_shuttle.call_evac()
emergency_shuttle.launch_time = 0 // Cannot recall
log_and_message_admins_many(cultists, "summoned the end of days.")
// new /obj/singularity/narsie/large(src.loc)
return
else
return fizzle()
+6
View File
@@ -18,6 +18,10 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
minimal_access = list() //See get_access()
minimal_player_age = 14
economic_modifier = 20
ideal_character_age = 70 // Old geezer captains ftw
equip(var/mob/living/carbon/human/H)
if(!H) return 0
H.equip_to_slot_or_del(new /obj/item/device/radio/headset/heads/captain(H), slot_l_ear)
@@ -63,6 +67,8 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
req_admin_notify = 1
minimal_player_age = 10
economic_modifier = 10
ideal_character_age = 50
access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
+2
View File
@@ -101,6 +101,8 @@
access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
minimal_access = list(access_maint_tunnels, access_mailsorting, access_cargo, access_cargo_bot, access_qm, access_mining, access_mining_station)
ideal_character_age = 40
equip(var/mob/living/carbon/human/H)
if(!H) return 0
+4
View File
@@ -12,6 +12,10 @@
idtype = /obj/item/weapon/card/id/silver
req_admin_notify = 1
economic_modifier = 10
ideal_character_age = 50
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction, access_sec_doors,
+2
View File
@@ -19,6 +19,8 @@
var/minimal_player_age = 0 // If you have use_age_restriction_for_jobs config option enabled and the database set up, this option will add a requirement for players to be at least minimal_player_age days old. (meaning they first signed in at least that many days before.)
var/department = null // Does this position have a department tag?
var/head_position = 0 // Is this position Command?
var/minimum_character_age = 17
var/ideal_character_age = 30
var/account_allowed = 1 // Does this job type come with a station account?
var/economic_modifier = 2 // With how much does this job modify the initial account amount?
+2
View File
@@ -18,7 +18,9 @@
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
minimal_player_age = 10
ideal_character_age = 50
equip(var/mob/living/carbon/human/H)
if(!H) return 0
+2
View File
@@ -20,7 +20,9 @@
access_tox_storage, access_teleporter, access_sec_doors,
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch)
minimal_player_age = 14
ideal_character_age = 50
equip(var/mob/living/carbon/human/H)
if(!H) return 0
+24 -18
View File
@@ -49,9 +49,15 @@ var/global/datum/controller/occupations/job_master
Debug("Running AR, Player: [player], Rank: [rank], LJ: [latejoin]")
if(player && player.mind && rank)
var/datum/job/job = GetJob(rank)
if(!job) return 0
if(jobban_isbanned(player, rank)) return 0
if(!job.player_old_enough(player.client)) return 0
if(!job)
return 0
if(job.minimum_character_age && (player.client.prefs.age < job.minimum_character_age))
return 0
if(jobban_isbanned(player, rank))
return 0
if(!job.player_old_enough(player.client))
return 0
var/position_limit = job.total_positions
if(!latejoin)
position_limit = job.spawn_positions
@@ -82,6 +88,9 @@ var/global/datum/controller/occupations/job_master
if(!job.player_old_enough(player.client))
Debug("FOC player not old enough, Player: [player]")
continue
if(job.minimum_character_age && (player.client.prefs.age < job.minimum_character_age))
Debug("FOC character not old enough, Player: [player]")
continue
if(flag && (!player.client.prefs.be_special & flag))
Debug("FOC flag failed, Player: [player], Flag: [flag], ")
continue
@@ -96,6 +105,9 @@ var/global/datum/controller/occupations/job_master
if(!job)
continue
if(job.minimum_character_age && (player.client.prefs.age < job.minimum_character_age))
continue
if(istype(job, GetJob("Assistant"))) // We don't want to give him assistant, that's boring!
continue
@@ -137,30 +149,24 @@ var/global/datum/controller/occupations/job_master
// Build a weighted list, weight by age.
var/list/weightedCandidates = list()
// Different head positions have different good ages.
var/good_age_minimal = 25
var/good_age_maximal = 60
if(command_position == "Captain")
good_age_minimal = 30
good_age_maximal = 70 // Old geezer captains ftw
for(var/mob/V in candidates)
// Log-out during round-start? What a bad boy, no head position for you!
if(!V.client) continue
var/age = V.client.prefs.age
if(age < job.minimum_character_age) // Nope.
continue
switch(age)
if(good_age_minimal - 10 to good_age_minimal)
if(job.minimum_character_age to (job.minimum_character_age+10))
weightedCandidates[V] = 3 // Still a bit young.
if(good_age_minimal to good_age_minimal + 10)
if((job.minimum_character_age+10) to (job.ideal_character_age-10))
weightedCandidates[V] = 6 // Better.
if(good_age_minimal + 10 to good_age_maximal - 10)
if((job.ideal_character_age-10) to (job.ideal_character_age+10))
weightedCandidates[V] = 10 // Great.
if(good_age_maximal - 10 to good_age_maximal)
if((job.ideal_character_age+10) to (job.ideal_character_age+20))
weightedCandidates[V] = 6 // Still good.
if(good_age_maximal to good_age_maximal + 10)
weightedCandidates[V] = 6 // Bit old, don't you think?
if(good_age_maximal to good_age_maximal + 50)
if((job.ideal_character_age+20) to INFINITY)
weightedCandidates[V] = 3 // Geezer.
else
// If there's ABSOLUTELY NOBODY ELSE
+173
View File
@@ -0,0 +1,173 @@
/obj/machinery/exonet_node
name = "exonet node"
desc = "This machine is one of many, many nodes inside Vir's section of the Exonet, connecting the Northern Star to the rest of the system, at least \
electronically."
icon = 'icons/obj/stationobjs.dmi'
icon_state = "exonet_node"
idle_power_usage = 2500
density = 1
var/on = 1
var/toggle = 1
var/allow_external_PDAs = 1
var/allow_external_communicators = 1
var/allow_external_newscasters = 1
var/opened = 0
// Proc: New()
// Parameters: None
// Description: Adds components to the machine for deconstruction.
/obj/machinery/exonet_node/New()
..()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/telecomms/exonet_node(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/ansible(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/filter(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/crystal(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
component_parts += new /obj/item/weapon/stock_parts/subspace/treatment(src)
component_parts += new /obj/item/stack/cable_coil(src, 2)
RefreshParts()
// Proc: update_icon()
// Parameters: None
// Description: Self explanatory.
/obj/machinery/exonet_node/update_icon()
if(on)
if(!allow_external_PDAs && !allow_external_communicators && !allow_external_newscasters)
icon_state = "[initial(icon_state)]_idle"
else
icon_state = initial(icon_state)
else
icon_state = "[initial(icon_state)]_off"
// Proc: update_power()
// Parameters: None
// Description: Sets the device on/off and adjusts power draw based on stat and toggle variables.
/obj/machinery/exonet_node/proc/update_power()
if(toggle)
if(stat & (BROKEN|NOPOWER|EMPED))
on = 0
idle_power_usage = 0
else
on = 1
idle_power_usage = 2500
else
on = 0
idle_power_usage = 0
// Proc: emp_act()
// Parameters: 1 (severity - how strong the EMP is, with lower numbers being stronger)
// Description: Shuts off the machine for awhile if an EMP hits it. Ion anomalies also call this to turn it off.
/obj/machinery/exonet_node/emp_act(severity)
if(!(stat & EMPED))
stat |= EMPED
var/duration = (300 * 10)/severity
spawn(rand(duration - 20, duration + 20))
stat &= ~EMPED
update_icon()
..()
// Proc: process()
// Parameters: None
// Description: Calls the procs below every tick.
/obj/machinery/exonet_node/process()
update_power()
// Proc: attackby()
// Parameters: 2 (I - the item being whacked against the machine, user - the person doing the whacking)
// Description: Handles deconstruction.
/obj/machinery/exonet_node/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/screwdriver))
default_deconstruction_screwdriver(user, I)
else if(istype(I, /obj/item/weapon/crowbar))
default_deconstruction_crowbar(user, I)
else
..()
// Proc: attack_ai()
// Parameters: 1 (user - the AI clicking on the machine)
// Description: Redirects to attack_hand()
/obj/machinery/exonet_node/attack_ai(mob/user)
attack_hand(user)
// Proc: attack_hand()
// Parameters: 1 (user - the person clicking on the machine)
// Description: Opens the NanoUI interface with ui_interact()
/obj/machinery/exonet_node/attack_hand(mob/user)
ui_interact(user)
// Proc: ui_interact()
// Parameters: 4 (standard NanoUI arguments)
// Description: Allows the user to turn the machine on or off, or open or close certain 'ports' for things like external PDA messages, newscasters, etc.
/obj/machinery/exonet_node/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
// this is the data which will be sent to the ui
var/data[0]
data["on"] = toggle ? 1 : 0
data["allowPDAs"] = allow_external_PDAs
data["allowCommunicators"] = allow_external_communicators
data["allowNewscasters"] = allow_external_newscasters
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "exonet_node.tmpl", "Exonet Node #157", 400, 400)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every Master Controller tick
ui.set_auto_update(1)
// Proc: Topic()
// Parameters: 2 (standard Topic arguments)
// Description: Responds to button presses on the NanoUI interface.
/obj/machinery/exonet_node/Topic(href, href_list)
if(..())
return 1
if(href_list["toggle_power"])
toggle = !toggle
update_power()
if(!toggle)
var/msg = "[usr.client.key] ([usr]) has turned [src] off, at [x],[y],[z]."
message_admins(msg)
log_game(msg)
if(href_list["toggle_PDA_port"])
allow_external_PDAs = !allow_external_PDAs
if(href_list["toggle_communicator_port"])
allow_external_communicators = !allow_external_communicators
if(!allow_external_communicators)
var/msg = "[usr.client.key] ([usr]) has turned [src]'s communicator port off, at [x],[y],[z]."
message_admins(msg)
log_game(msg)
if(href_list["toggle_newscaster_port"])
allow_external_newscasters = !allow_external_newscasters
if(!allow_external_newscasters)
var/msg = "[usr.client.key] ([usr]) has turned [src]'s newscaster port off, at [x],[y],[z]."
message_admins(msg)
log_game(msg)
update_icon()
nanomanager.update_uis(src)
add_fingerprint(usr)
// Proc: get_exonet_node()
// Parameters: None
// Description: Helper proc to get a reference to an Exonet node.
/proc/get_exonet_node()
for(var/obj/machinery/exonet_node/E in machines)
if(E.on)
return E
+15 -6
View File
@@ -166,6 +166,7 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
var/datum/feed_channel/viewing_channel = null
light_range = 0
anchored = 1
var/obj/machinery/exonet_node/node = null
/obj/machinery/newscaster/security_unit //Security unit
@@ -178,6 +179,8 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
for(var/obj/machinery/newscaster/NEWSCASTER in allCasters) // Let's give it an appropriate unit number
src.unit_no++
src.update_icon() //for any custom ones on the map...
spawn(10) //Should be enough time for the node to spawn at tcomms.
node = get_exonet_node()
..() //I just realised the newscasters weren't in the global machines list. The superconstructor call will tend to that
/obj/machinery/newscaster/Destroy()
@@ -247,6 +250,14 @@ var/list/obj/machinery/newscaster/allCasters = list() //Global list that will co
if(!src.ispowered || src.isbroken)
return
if(!node)
node = get_exonet_node()
if(!node || !node.on || !node.allow_external_newscasters)
user << "<span class='danger'>Error: Cannot connect to external content. Please try again in a few minutes. If this error persists, please \
contact the system administrator.</span>"
return 0
if(!user.IsAdvancedToolUser())
return 0
@@ -984,12 +995,10 @@ obj/item/weapon/newspaper/attackby(obj/item/weapon/W as obj, mob/user as mob)
src.paper_remaining--
return
//Removed for now so these aren't even checked every tick. Left this here in-case Agouri needs it later.
///obj/machinery/newscaster/process() //Was thinking of doing the icon update through process, but multiple iterations per second does not
// return //bode well with a newscaster network of 10+ machines. Let's just return it, as it's added in the machines list.
/obj/machinery/newscaster/proc/newsAlert(var/news_call) //This isn't Agouri's work, for it is ugly and vile.
var/turf/T = get_turf(src) //Who the fuck uses spawn(600) anyway, jesus christ
/obj/machinery/newscaster/proc/newsAlert(var/news_call)
if(!node || !node.on || !node.allow_external_newscasters) //The messages will still be there once the connection returns.
return
var/turf/T = get_turf(src)
if(news_call)
for(var/mob/O in hearers(world.view-1, T))
O.show_message("<span class='newscaster'><EM>[src.name]</EM> beeps, \"[news_call]\"</span>",2)
-13
View File
@@ -107,10 +107,6 @@
for(var/obj/item/weapon/ore/ore in range(chassis,1))
if(get_dir(chassis,ore)&chassis.dir)
ore.Move(ore_box)
else if(istype(target, /turf/simulated/floor/asteroid))
for(var/turf/simulated/floor/asteroid/M in range(chassis,1))
if(get_dir(chassis,M)&chassis.dir)
M.gets_dug()
log_message("Drilled through [target]")
if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
@@ -160,15 +156,6 @@
for(var/obj/item/weapon/ore/ore in range(chassis,1))
if(get_dir(chassis,ore)&chassis.dir)
ore.Move(ore_box)
else if(istype(target,/turf/simulated/floor/asteroid))
for(var/turf/simulated/floor/asteroid/M in range(target,1))
M.gets_dug()
log_message("Drilled through [target]")
if(locate(/obj/item/mecha_parts/mecha_equipment/tool/hydraulic_clamp) in chassis.equipment)
var/obj/structure/ore_box/ore_box = locate(/obj/structure/ore_box) in chassis:cargo
if(ore_box)
for(var/obj/item/weapon/ore/ore in range(target,1))
ore.Move(ore_box)
else if(target.loc == C)
log_message("Drilled through [target]")
target.ex_act(2)
+2 -1
View File
@@ -56,7 +56,8 @@
user << "<span class='warning'>You can't buckle anyone in before the game starts.</span>"
if(!user.Adjacent(M) || user.restrained() || user.lying || user.stat || istype(user, /mob/living/silicon/pai))
return
if(M == buckled_mob)
return
if(istype(M, /mob/living/carbon/slime))
user << "<span class='warning'>The [M] is too squishy to buckle in.</span>"
return
+1 -3
View File
@@ -107,7 +107,7 @@ steam.start() -- spawns the effect
var/turf/T = src.loc
if (istype(T, /turf))
T.hotspot_expose(1000,100)
spawn (100)
spawn (20)
qdel(src)
return
@@ -156,8 +156,6 @@ steam.start() -- spawns the effect
sleep(5)
step(sparks,direction)
spawn(20)
if(sparks)
qdel(sparks)
src.total_sparks--
@@ -11,7 +11,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
item_state = "electronic"
w_class = 2.0
slot_flags = SLOT_ID | SLOT_BELT
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/id.dmi')
//Main variables
var/owner = null
@@ -949,7 +948,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
/obj/item/device/pda/proc/create_message(var/mob/living/U = usr, var/obj/item/device/pda/P, var/tap = 1)
if(tap)
U.visible_message("<span class='notice'>\The [U] taps on \his PDA's screen.</span>")
U.last_target_click = world.time
var/t = input(U, "Please enter message", P.name, null) as text
t = sanitize(t)
//t = readd_quotes(t)
@@ -1,3 +1,7 @@
// Communicators
//
// Allows ghosts to roleplay with crewmembers without having to commit to joining the round, and also allows communications between two communicators.
var/global/list/obj/item/device/communicator/all_communicators = list()
/obj/item/device/communicator
@@ -12,21 +16,33 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
origin_tech = list(TECH_ENGINEERING = 2, TECH_MAGNET = 2, TECH_BLUESPACE = 2, TECH_DATA = 2)
matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 10)
var/mob/living/voice/voice_mob = null
var/list/voice_mobs = list()
var/list/voice_requests = list()
var/owner = null
var/owner_job = null
var/owner_rank = null //Is this different from job?
var/list/voice_invites = list()
var/selected_tab = 1 //1 equals dialing, 2 equals reviewing requests/invites.
var/owner = ""
var/alert_called = 0
var/obj/machinery/message_server/server = null //Reference to the PDA server, to avoid having to look it up so often.
var/obj/machinery/exonet_node/node = null //Reference to the Exonet node, to avoid having to look it up so often.
var/target_address = ""
var/network_visibility = 1
var/list/known_devices = list()
var/datum/exonet_protocol/exonet = null
var/list/communicating = list()
var/update_ticks = 0
// Proc: New()
// Parameters: None
// Description: Adds the new communicator to the global list of all communicators, sorts the list, obtains a reference to the Exonet node, then tries to
// assign the device to the holder's name automatically in a spectacularly shitty way.
/obj/item/device/communicator/New()
..()
all_communicators += src
all_communicators = sortAtom(all_communicators)
server = get_message_server()
node = get_exonet_node()
processing_objects |= src
//This is a pretty terrible way of doing this.
spawn(20) //Wait for our mob to finish spawning.
spawn(50) //Wait for our mob to finish spawning.
if(ismob(loc))
register_device(loc)
else if(istype(loc, /obj/item/weapon/storage))
@@ -34,201 +50,450 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
if(ismob(S.loc))
register_device(S.loc)
// Proc: examine()
// Parameters: 1 (user - the person examining the device)
// Description: Shows all the voice mobs inside the device, and their status.
/obj/item/device/communicator/examine(mob/user)
if(!..(user))
return
var/msg = ""
if(voice_mob)
msg += "<span class='notice'>On the screen, you can see a image feed of [voice_mob].</span>\n"
msg += "<span class='warning'>"
for(var/mob/living/voice/voice in contents)
msg += "<span class='notice'>On the screen, you can see a image feed of [voice].</span>\n"
msg += "<span class='warning'>"
if(src.voice_mob && src.voice_mob.key)
switch(src.voice_mob.stat)
if(CONSCIOUS)
if(!src.voice_mob.client)
msg += "[voice_mob] appears to be asleep.\n" //afk
if(UNCONSCIOUS)
msg += "[voice_mob] doesn't appear to be conscious.\n"
if(DEAD)
msg += "<span class='deadsay'>[voice_mob] appears to have died...</span>\n" //Hopefully this never has to be used.
else
msg += "<span class='notice'>The device doesn't appear to be transmitting any data.</span>\n"
msg += "</span>"
if(voice && voice.key)
switch(voice.stat)
if(CONSCIOUS)
if(!voice.client)
msg += "[voice] appears to be asleep.\n" //afk
if(UNCONSCIOUS)
msg += "[voice] doesn't appear to be conscious.\n"
if(DEAD)
msg += "<span class='deadsay'>[voice] appears to have died...</span>\n" //Hopefully this never has to be used.
else
msg += "<span class='notice'>The device doesn't appear to be transmitting any data.</span>\n"
msg += "</span>"
user << msg
return
//This is pretty lengthy
// Proc: emp_act()
// Parameters: None
// Description: Drops all calls when EMPed, so the holder can then get murdered by the antagonist.
/obj/item/device/communicator/emp_act()
close_connection(reason = "Hardware error de%#_^@%-BZZZZZZZT")
// Proc: add_to_EPv2()
// Parameters: 1 (hex - a single hexadecimal character)
// Description: Called when someone is manually dialing with nanoUI. Adds colons when appropiate.
/obj/item/device/communicator/proc/add_to_EPv2(var/hex)
var/length = length(target_address)
if(length >= 24)
return
if(length == 4 || length == 9 || length == 14 || length == 19 || length == 24 || length == 29)
target_address += ":[hex]"
return
target_address += hex
// Proc: populate_known_devices()
// Parameters: 1 (user - the person using the device)
// Description: Searches all communicators and ghosts in the world, and adds them to the known_devices list if they are 'visible'.
/obj/item/device/communicator/proc/populate_known_devices(mob/user)
if(!exonet)
exonet = new(src)
src.known_devices.Cut()
if(!get_connection_to_tcomms()) //If the network's down, we can't see anything.
return
for(var/obj/item/device/communicator/comm in all_communicators)
if(!comm || !comm.exonet || !comm.exonet.address || comm.exonet.address == src.exonet.address) //Don't add addressless devices, and don't add ourselves.
continue
src.known_devices |= comm
for(var/mob/dead/observer/O in dead_mob_list)
if(!O.client || O.client.prefs.communicator_visibility == 0)
continue
src.known_devices |= O
// Proc: get_connection_to_tcomms()
// Parameters: None
// Description: Simple check to see if the exonet node is active.
/obj/item/device/communicator/proc/get_connection_to_tcomms()
if(node)
if(node.on && node.allow_external_communicators)
return 1
return 0
// Proc: process()
// Parameters: None
// Description: Ticks the update_ticks variable, and checks to see if it needs to disconnect communicators every five ticks..
/obj/item/device/communicator/process()
update_ticks++
if(update_ticks % 5)
if(!node)
node = get_exonet_node()
if(!node || !node.on || !node.allow_external_communicators)
close_connection(reason = "Connection timed out")
// Proc: attack_self()
// Parameters: 1 (user - the mob that clicked the device in their hand)
// Description: Makes an exonet datum if one does not exist, allocates an address for it, maintains the lists of all devies, clears the alert icon, and
// finally makes NanoUI appear.
/obj/item/device/communicator/attack_self(mob/user)
if(!owner)
var/choice = alert(user,"Would you like to register [src]?","Communicator","Yes","No")
if(choice == "Yes")
register_device(user)
return
if(!exonet)
exonet = new(src)
if(!exonet.address)
exonet.make_address("communicator-[user.client]-[user.name]")
if(!node)
node = get_exonet_node()
populate_known_devices()
alert_called = 0
update_icon()
ui_interact(user)
if(voice_mob)
var/choice = alert(user,"Would you like to hang up?","Communicator","No","Yes")
if(choice == "Yes")
close_connection(user, "[user] hung up")
return
// Proc: attack_ghost()
// Parameters: 1 (user - the ghost clicking on the device)
// Description: Recreates the known_devices list, so that the ghost looking at the device can see themselves, then calls ..() so that NanoUI appears.
/obj/item/device/communicator/attack_ghost(mob/user)
populate_known_devices() //Update the devices so ghosts can see the list on NanoUI.
..()
if(!server || !server.active)
user << "<span class='danger'>\icon[src] Error: Cannot establish connection to telecommunications.</span>"
sleep(30)
user << "<span class='danger'>\icon[src] Attempting to connect to telecommunications.</span>"
sleep(30)
if(!server)
server = get_message_server()
if(!server)
user << "<span class='danger'>\icon[src] Query to telecommunications timed out.</span>"
else if(server.active)
user << "<span class='notice'>\icon[src] Connection re-established.</span>"
/mob/dead/observer
var/datum/exonet_protocol/exonet = null
// Proc: New()
// Parameters: None
// Description: Gives ghosts an exonet address based on their key and ghost name.
/mob/dead/observer/New()
. = ..()
spawn(20)
exonet = new(src)
if(client)
exonet.make_address("communicator-[src.client]-[src.client.prefs.real_name]")
else
if(server.active)
user << "<span class='notice'>\icon[src] Connection re-established.</span>"
else
user << "<span class='danger'>\icon[src] Query to telecommunications timed out.</span>"
exonet.make_address("communicator-[key]-[src.real_name]")
return
// Proc: Destroy()
// Parameters: None
// Description: Removes the ghost's address and nulls the exonet datum, to allow qdel()ing.
/mob/dead/observer/Destroy()
. = ..()
if(exonet)
exonet.remove_address()
exonet = null
..()
var/mode = alert(user,"Would you like to check for communications requests or attempt to send a communication request to an external device?",
"Communicator","Check Requests","Send Request", "Cancel")
switch(mode)
if("Check Requests")
if(!voice_requests.len)
user << "\icon[src] No incoming communications requests."
return
// Proc: ui_interact()
// Parameters: 4 (standard NanoUI arguments)
// Description: Uses a bunch of for loops to turn lists into lists of lists, so they can be displayed in nanoUI, then displays various buttons to the user.
/obj/item/device/communicator/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
// this is the data which will be sent to the ui
var/data[0] //General nanoUI information
var/communicators[0] //List of communicators
var/invites[0] //Communicators and ghosts we've invited to our communicator.
var/requests[0] //Communicators and ghosts wanting to go in our communicator.
var/voices[0] //Current /mob/living/voice s inside the device.
var/connected_communicators[0] //Current communicators connected to the device.
else
alert_called = 0
update_icon()
var/choice = input(user,"Would would you like to talk to?","Communicator") as null|anything in voice_requests
if(choice)
open_connection(user, choice)
return
//First we add other 'local' communicators.
for(var/obj/item/device/communicator/comm in known_devices)
if(comm.network_visibility && comm.exonet)
communicators[++communicators.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address)
if("Send Request")
var/list/potential_candidates = list()
for(var/mob/dead/observer/O in dead_mob_list) //To my knowledge, there isn't a list of all ghosts.
if(O.client) //We only want logged in ghosts.
potential_candidates.Add(O.client.prefs.real_name) //This is needed so you don't see ghosted maint drones on the list.
//Now for ghosts who we pretend have communicators.
for(var/mob/dead/observer/O in known_devices)
if(O.client && O.client.prefs.communicator_visibility == 1 && O.exonet)
communicators[++communicators.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address)
if(!potential_candidates.len)
user << "\icon[src] Unfortunately, no other communicators outside your local area could be found. Please try again later."
return
//Lists all the other communicators that we invited.
for(var/obj/item/device/communicator/comm in voice_invites)
if(comm.exonet)
invites[++invites.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address)
var/choice = input(src,"Please select a person to call. Due to the vast distances involved \
as well as time-zones, please note that your request may take a long time to be noticed, and \
that the available people to call may change as time passes.") as null|anything in potential_candidates
if(choice)
var/mob/dead/observer/boo = null
for(var/mob/dead/observer/O in dead_mob_list)
if(O.client && O.client.prefs.real_name == choice)
boo = O
break
boo << "\icon[src] A communications request has been received from [src]. If you would like to answer, please use the <b>Call Communicator</b> verb."
user << "\icon[src] A communications request has been sent to [choice]. Now you need to wait until they answer, if they do."
//Ghosts we invited.
for(var/mob/dead/observer/O in voice_invites)
if(O.exonet && O.client)
invites[++invites.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address)
//Communicators that want to talk to us.
for(var/obj/item/device/communicator/comm in voice_requests)
if(comm.exonet)
requests[++requests.len] = list("name" = sanitize(comm.name), "address" = comm.exonet.address)
//Ghosts that want to talk to us.
for(var/mob/dead/observer/O in voice_requests)
if(O.exonet && O.client)
requests[++requests.len] = list("name" = sanitize("[O.client.prefs.real_name]'s communicator"), "address" = O.exonet.address)
//Now for all the voice mobs inside the communicator.
for(var/mob/living/voice/voice in contents)
voices[++voices.len] = list("name" = sanitize("[voice.name]'s communicator"), "true_name" = sanitize(voice.name))
//Finally, all the communicators linked to this one.
for(var/obj/item/device/communicator/comm in communicating)
connected_communicators[++connected_communicators.len] = list("name" = sanitize(comm.name), "true_name" = sanitize(comm.name))
data["owner"] = owner ? owner : "Unset"
data["connectionStatus"] = get_connection_to_tcomms()
data["visible"] = network_visibility
data["address"] = exonet.address ? exonet.address : "Unallocated"
data["targetAddress"] = target_address
data["currentTab"] = selected_tab
data["knownDevices"] = communicators
data["invitesSent"] = invites
data["requestsReceived"] = requests
data["voice_mobs"] = voices
data["communicating"] = connected_communicators
// update the ui if it exists, returns null if no ui is passed/found
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "communicator.tmpl", "Communicator", 450, 700)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every five Master Controller tick
ui.set_auto_update(5)
// Proc: Topic()
// Parameters: 2 (standard Topic arguments)
// Description: Responds to NanoUI button presses.
/obj/item/device/communicator/Topic(href, href_list)
if(..())
return 1
if(href_list["rename"])
var/new_name = sanitizeSafe(input(usr,"Please enter your name.","Communicator",usr.name) )
if(new_name)
owner = new_name
name = "[owner]'s [initial(name)]"
if(href_list["toggle_visibility"])
network_visibility = !network_visibility
if(href_list["add_hex"])
var/hex = href_list["add_hex"]
add_to_EPv2(hex)
if(href_list["write_target_address"])
var/new_address = sanitizeSafe(input(usr,"Please enter the desired target EPv2 address. Note that you must write the colons \
yourself.","Communicator",src.target_address) )
if(new_address)
target_address = new_address
if(href_list["clear_target_address"])
target_address = ""
if(href_list["dial"])
if(!get_connection_to_tcomms())
usr << "<span class='danger'>Error: Cannot connect to Exonet node.</span>"
return
var/their_address = href_list["dial"]
exonet.send_message(their_address, "voice")
if(href_list["disconnect"])
var/name_to_disconnect = href_list["disconnect"]
for(var/mob/living/voice/V in contents)
if(name_to_disconnect == V.name)
close_connection(usr, V, "[usr] hung up")
for(var/obj/item/device/communicator/comm in communicating)
if(name_to_disconnect == comm.name)
close_connection(usr, comm, "[usr] hung up")
/obj/item/device/communicator/proc/register_device(mob/user, var/job = null)
if(href_list["copy"])
target_address = href_list["copy"]
if(href_list["switch_tab"])
selected_tab = href_list["switch_tab"]
nanomanager.update_uis(src)
add_fingerprint(usr)
// Proc: receive_exonet_message()
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
/obj/item/device/communicator/receive_exonet_message(var/atom/origin_atom, origin_address, message)
if(message == "voice")
if(isobserver(origin_atom) || istype(origin_atom, /obj/item/device/communicator))
if(origin_atom in voice_invites)
var/user = null
if(ismob(origin_atom.loc))
user = origin_atom.loc
open_connection(user, origin_atom)
return
else if(origin_atom in voice_requests)
return //Spam prevention
else
request(origin_atom)
if(message == "ping")
if(network_visibility)
var/random = rand(200,350)
random = random / 10
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
// Proc: receive_exonet_message()
// Parameters: 3 (origin atom - the source of the message's holder, origin_address - where the message came from, message - the message received)
// Description: Handles voice requests and invite messages originating from both real communicators and ghosts. Also includes a ping response.
/mob/dead/observer/receive_exonet_message(origin_atom, origin_address, message)
if(message == "voice")
if(istype(origin_atom, /obj/item/device/communicator))
var/obj/item/device/communicator/comm = origin_atom
if(src in comm.voice_invites)
comm.open_connection(src)
return
src << "<span class='notice'>\icon[origin_atom] Receiving communicator request from [origin_atom]. To answer, use the <b>Call Communicator</b> \
verb, and select that name to answer the call.</span>"
comm.voice_invites |= src
if(message == "ping")
if(client && client.prefs.communicator_visibility)
var/random = rand(450,700)
random = random / 10
exonet.send_message(origin_address, "64 bytes received from [exonet.address] ecmp_seq=1 ttl=51 time=[random] ms")
// Proc: register_device()
// Parameters: 1 (user - the person to use their name for)
// Description: Updates the owner's name and the device's name.
/obj/item/device/communicator/proc/register_device(mob/user)
if(!user)
return
owner = user.name
if(job)
owner_job = job
owner_rank = job
name = "[owner]'s [initial(name)]"
// Proc: open_connection()
// Parameters: 2 (user - the person who initiated the connecting being opened, candidate - the communicator or observer that will connect to the device)
// Description: Typechecks the candidate, then calls the correct proc for further connecting.
/obj/item/device/communicator/proc/open_connection(mob/user, var/atom/candidate)
if(isobserver(candidate))
voice_invites.Remove(candidate)
open_connection_to_ghost(user, candidate)
else
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/obj/item/weapon/card/id/idcard = H.wear_id
if(idcard)
owner_job = idcard.assignment
owner_rank = idcard.rank
else
user << "<span class='warning'>\icon[src] ID not found. Please swipe your ID on the device.</span>"
return
else //They're probably a synth.
owner_job = user.job
owner_rank = user.job
if(istype(candidate, /obj/item/device/communicator))
open_connection_to_communicator(user, candidate)
name = "\improper [initial(name)]-[owner] ([owner_job])"
// Proc: open_connection_to_communicator()
// Parameters: 2 (user - the person who initiated this and will be receiving feedback information, candidate - someone else's communicator)
// Description: Adds the candidate and src to each other's communicating lists, allowing messages seen by the devices to be relayed.
/obj/item/device/communicator/proc/open_connection_to_communicator(mob/user, var/atom/candidate)
if(!istype(candidate, /obj/item/device/communicator))
return
var/obj/item/device/communicator/comm = candidate
voice_invites.Remove(candidate)
comm.voice_requests.Remove(src)
/*
owner = idcard.registered_name
owner_job = idcard.assignment
owner_rank = idcard.rank
name = "\improper communicator-[owner] ([ownjob])"
*/
if(user)
comm.visible_message("<span class='notice'>\icon[src] Connecting to [src].</span>")
user << "<span class='notice'>\icon[src] Attempting to call [comm].</span>"
sleep(10)
user << "<span class='notice'>\icon[src] Dialing internally from [station_name()], Kara Subsystem, [system_name()].</span>"
sleep(20) //If they don't have an exonet something is very wrong and we want a runtime.
user << "<span class='notice'>\icon[src] Connection re-routed to [comm] at [comm.exonet.address].</span>"
sleep(40)
user << "<span class='notice'>\icon[src] Connection to [comm] at [comm.exonet.address] established.</span>"
comm.visible_message("<span class='notice'>\icon[src] Connection to [src] at [exonet.address] established.</span>")
sleep(20)
/obj/item/device/communicator/proc/open_connection(mob/user, var/mob/candidate)
communicating |= comm
comm.communicating |= src
// Proc: open_connection_to_ghost()
// Parameters: 2 (user - the person who initiated this, candidate - the ghost that will be turned into a voice mob)
// Description: Pulls the candidate ghost from deadchat, makes a new voice mob, transfers their identity, then their client.
/obj/item/device/communicator/proc/open_connection_to_ghost(mob/user, var/mob/candidate)
if(!isobserver(candidate))
return
//Handle moving the ghost into the new shell.
announce_ghost_joinleave(candidate, 0, "They are occupying a personal communications device now.")
voice_mob = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
voice_mob.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
voice_requests.Remove(candidate)
voice_invites.Remove(candidate)
var/mob/living/voice/new_voice = new /mob/living/voice(src) //Make the voice mob the ghost is going to be.
new_voice.transfer_identity(candidate) //Now make the voice mob load from the ghost's active character in preferences.
//Do some simple logging since this is a tad risky as a concept.
var/msg = "[candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
[user.client ? "[user.client.key]" : "*no key*"] ([user]) at [x],[y],[z]. They have joined as [voice_mob.name]."
var/msg = "[candidate && candidate.client ? "[candidate.client.key]" : "*no key*"] ([candidate]) has entered [src], triggered by \
[user && user.client ? "[user.client.key]" : "*no key*"] ([user ? "[user]" : "*null*"]) at [x],[y],[z]. They have joined as [new_voice.name]."
message_admins(msg)
log_game(msg)
voice_mob.mind = candidate.mind //Transfer the mind, if any.
voice_mob.ckey = candidate.ckey //Finally, bring the client over.
new_voice.mind = candidate.mind //Transfer the mind, if any.
new_voice.ckey = candidate.ckey //Finally, bring the client over.
voice_mobs.Add(new_voice)
var/obj/screen/blackness = new() //Makes a black screen, so the candidate can't see what's going on before actually 'connecting' to the communicator.
blackness.screen_loc = ui_entire_screen
blackness.icon = 'icons/effects/effects.dmi'
blackness.icon_state = "1"
blackness.mouse_opacity = 2 //Can't see anything!
voice_mob.client.screen.Add(blackness)
new_voice.client.screen.Add(blackness)
update_icon()
//Now for some connection fluff.
user << "<span class='notice'>\icon[src] Connecting to [candidate].</span>"
src.voice_mob << "<span class='notice'>\icon[src] Attempting to call [src].</span>"
if(user)
user << "<span class='notice'>\icon[src] Connecting to [candidate].</span>"
new_voice << "<span class='notice'>\icon[src] Attempting to call [src].</span>"
sleep(10)
src.voice_mob << "<span class='notice'>\icon[src] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>"
new_voice << "<span class='notice'>\icon[src] Dialing to [station_name()], Kara Subsystem, [system_name()].</span>"
sleep(20)
src.voice_mob << "<span class='notice'>\icon[src] Connecting to [station_name()] telecommunications array.</span>"
new_voice << "<span class='notice'>\icon[src] Connecting to [station_name()] telecommunications array.</span>"
sleep(40)
src.voice_mob << "<span class='notice'>\icon[src] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>"
new_voice << "<span class='notice'>\icon[src] Connection to [station_name()] telecommunications array established. Redirecting signal to [src].</span>"
sleep(20)
//We're connected, no need to hide everything.
voice_mob.client.screen.Remove(blackness)
new_voice.client.screen.Remove(blackness)
qdel(blackness)
voice_mob.stable_connection = 1
voice_mob << "<span class='notice'>\icon[src] Connection to [src] established.</span>"
voice_mob << "<b>To talk to the person on the other end of the call, just talk normally.</b>"
voice_mob << "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>"
voice_mob << "<b>Remember, your character does not know anything you've learned from observing!</b>"
if(voice_mob.mind)
voice_mob.mind.assigned_role = "Disembodied Voice"
user << "<span class='notice'>\icon[src] Your communicator is now connected to [candidate]'s communicator.</span>"
new_voice << "<span class='notice'>\icon[src] Connection to [src] established.</span>"
new_voice << "<b>To talk to the person on the other end of the call, just talk normally.</b>"
new_voice << "<b>If you want to end the call, use the 'Hang Up' verb. The other person can also hang up at any time.</b>"
new_voice << "<b>Remember, your character does not know anything you've learned from observing!</b>"
if(new_voice.mind)
new_voice.mind.assigned_role = "Disembodied Voice"
if(user)
user << "<span class='notice'>\icon[src] Your communicator is now connected to [candidate]'s communicator.</span>"
/obj/item/device/communicator/proc/close_connection(mob/user, var/reason)
if(!voice_mob)
// Proc: close_connection()
// Parameters: 3 (user - the user who initiated the disconnect, target - the mob or device being disconnected, reason - string shown when disconnected)
// Description: Deletes specific voice_mobs or disconnects communicators, and shows a message to everyone when doing so. If target is null, all communicators
// and voice mobs are removed.
/obj/item/device/communicator/proc/close_connection(mob/user, var/atom/target, var/reason)
if(voice_mobs.len == 0 && communicating.len == 0)
return
if(user != voice_mob)
user << "<span class='notice'>\icon[src] [reason].</span>"
voice_mob << "<span class='danger'>\icon[src] [reason].</span>"
else
if(ismob(loc))
user << "<span class='notice'>\icon[src] [reason].</span>"
loc << "<span class='danger'>\icon[src] [reason].</span>"
qdel(voice_mob)
for(var/mob/living/voice/voice in voice_mobs) //Handle ghost-callers
if(target && voice != target) //If no target is inputted, it deletes all of them.
continue
voice << "<span class='danger'>\icon[src] [reason].</span>"
visible_message("<span class='danger'>\icon[src] [reason].</span>")
voice_mobs.Remove(voice)
qdel(voice)
for(var/obj/item/device/communicator/comm in communicating) //Now we handle real communicators.
if(target && comm != target)
continue
comm.visible_message("<span class='danger'>\icon[src] [reason].</span>")
visible_message("<span class='danger'>\icon[src] [reason].</span>")
comm.communicating.Remove(src)
communicating.Remove(comm)
update_icon()
/obj/item/device/communicator/proc/request(var/mob/candidate)
if(!isobserver(candidate))
return
// Proc: request()
// Parameters: 1 (candidate - the ghost or communicator wanting to call the device)
// Description: Response to a communicator or observer trying to call the device. Adds them to the list of requesters
/obj/item/device/communicator/proc/request(var/atom/candidate)
if(candidate in voice_requests)
return
voice_requests.Add(candidate)
var/who = null
if(isobserver(candidate))
who = candidate.name
else if(istype(candidate, /obj/item/device/communicator))
var/obj/item/device/communicator/comm = candidate
who = comm.owner
comm.voice_invites |= src
if(!who)
return
voice_requests |= candidate
playsound(loc, 'sound/machines/twobeep.ogg', 50, 1)
for (var/mob/O in hearers(2, loc))
@@ -243,17 +508,32 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
L = loc
if(L)
L << "<span class='notice'>\icon[src] Communications request from [candidate].</span>"
L << "<span class='notice'>\icon[src] Communications request from [who].</span>"
// Proc: Destroy()
// Parameters: None
// Description: Deletes all the voice mobs, disconnects all linked communicators, and cuts lists to allow successful qdel()
/obj/item/device/communicator/Destroy()
if(voice_mob)
voice_mob << "<span class='danger'>\icon[src] Connection timed out with remote host.</span>"
qdel(voice_mob)
for(var/mob/living/voice/voice in contents)
voice_mobs.Remove(voice)
voice << "<span class='danger'>\icon[src] Connection timed out with remote host.</span>"
qdel(voice)
close_connection(reason = "Connection timed out")
communicating.Cut()
voice_requests.Cut()
voice_invites.Cut()
all_communicators -= src
processing_objects -= src
if(exonet)
exonet.remove_address()
exonet = null
..()
// Proc: update_icon()
// Parameters: None
// Description: Self explanatory
/obj/item/device/communicator/update_icon()
if(voice_mob)
if(voice_mobs.len > 0)
icon_state = "communicator-active"
return
@@ -263,37 +543,55 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
icon_state = initial(icon_state)
// Proc: see_emote()
// Parameters: 2 (M - the mob the emote originated from, text - the emote's contents)
// Description: Relays the emote to all linked communicators.
/obj/item/device/communicator/see_emote(mob/living/M, text)
if(voice_mob && voice_mob.client)
if(!voice_mob.stable_connection)
return 0
var/rendered = "<span class='message'>[text]</span>"
voice_mob.show_message(rendered, 2)
var/rendered = "\icon[src] <span class='message'>[text]</span>"
for(var/obj/item/device/communicator/comm in communicating)
for(var/mob/mob in viewers(get_turf(comm))) //We can't use visible_message(), or else we will get an infinite loop if two communicators hear each other.
mob.show_message(rendered)
for(var/mob/living/voice/V in comm.contents)
V.show_message(rendered)
..()
// Proc: hear_talk()
// Parameters: 4 (M - the mob the speech originated from, text - what is being said, verb - the word used to describe how text is being said, speaking - language
// being used)
// Description: Relays the speech to all linked communicators.
/obj/item/device/communicator/hear_talk(mob/living/M, text, verb, datum/language/speaking)
for(var/obj/item/device/communicator/comm in communicating)
var/list/mobs_to_relay = list()
mobs_to_relay |= viewers(get_turf(comm))
mobs_to_relay |= comm.contents //Needed so ghost-callers can see speech.
for(var/mob/mob in mobs_to_relay)
//Can whoever is hearing us understand?
if(!mob.say_understands(M, speaking))
if(speaking)
text = speaking.scramble(text)
else
text = stars(text)
var/name_used = M.GetVoice()
var/rendered = null
if(speaking) //Language being used
rendered = "<span class='game say'>\icon[src] <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span>"
else
rendered = "<span class='game say'>\icon[src] <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span>"
mob.show_message(rendered, 2)
// Proc: show_message()
// Parameters: 4 (msg - the message, type - number to determine if message is visible or audible, alt - unknown, alt_type - unknown)
// Description: Relays the message to all linked communicators.
/obj/item/device/communicator/show_message(msg, type, alt, alt_type)
if(voice_mob && voice_mob.client)
if(!voice_mob.stable_connection)
return 0
var/rendered = "<span class='message'>[msg]</span>"
voice_mob.show_message(rendered, type)
var/rendered = "\icon[src] <span class='message'>[msg]</span>"
for(var/obj/item/device/communicator/comm in communicating)
for(var/mob/mob in hearers(get_turf(comm))) //Ditto for audible messages.
mob.show_message(rendered)
..()
/obj/item/device/communicator/attackby(obj/item/C as obj, mob/user as mob)
if(istype(C, /obj/item/weapon/card/id))
var/obj/item/weapon/card/id/idcard = C
if(!idcard.registered_name)
user << "<span class='notice'>\icon[src] \The [src] rejects the ID.</span>"
return
if(!owner)
owner = idcard.registered_name
owner_job = idcard.assignment
owner_rank = idcard.rank
name = "\improper communicator-[owner] ([owner_job])"
user << "<span class='notice'>\icon[src] Card scanned.</span>"
else
..()
// Verb: join_as_voice()
// Parameters: None
// Description: Allows ghosts to call communicators, if they meet all the requirements.
/mob/dead/verb/join_as_voice()
set category = "Ghost"
set name = "Call Communicator"
@@ -319,25 +617,50 @@ var/global/list/obj/item/device/communicator/all_communicators = list()
src << "<span class='danger'>Your identity is already present in the game world. Please load in a different character first.</span>"
return
if(!all_communicators.len)
var/obj/machinery/exonet_node/E = get_exonet_node()
if(!E || !E.on || !E.allow_external_communicators)
src << "<span class='danger'>The Exonet node at telecommunications is down at the moment, or is actively blocking you, so your call can't go through.</span>"
return
var/list/choices = list()
for(var/obj/item/device/communicator/comm in all_communicators)
if(!comm.network_visibility || !comm.exonet || !comm.exonet.address)
continue
choices.Add(comm)
if(!choices.len)
src << "<span class='danger'>There are no available communicators, sorry.</span>"
return
if(!get_message_server())
src << "<span class='danger'>The messaging server or telecommunications is down at the moment, so your call can't go through.</span>"
return
var/choice = input(src,"Send a voice request to whom?") as null|anything in all_communicators
var/choice = input(src,"Send a voice request to whom?") as null|anything in choices
if(choice)
var/obj/item/device/communicator/chosen_communicator = choice
chosen_communicator.request(src)
var/mob/dead/observer/O = src
if(O.exonet)
O.exonet.send_message(chosen_communicator.exonet.address, "voice")
src << "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers."
src << "A communications request has been sent to [chosen_communicator]. Now you need to wait until someone answers."
/obj/item/device/communicator/integrated //For synths who have no hands.
name = "integrated communicator"
desc = "A circuit used for long-range communications, able to be integrated into a system."
//A stupid hack because synths don't use languages properly or something.
//I don't want to go digging in saycode for a week, so BS it as translation software or something.
// Proc: open_connection_to_ghost()
// Parameters: 2 (refer to base definition for arguments)
// Description: Synths don't use languages properly, so this is a bandaid fix until that can be resolved..
/obj/item/device/communicator/integrated/open_connection_to_ghost(user, candidate)
..(user, candidate)
spawn(1)
for(var/mob/living/voice/V in contents)
V.universal_speak = 1
V.universal_understand = 1
// Verb: activate()
// Parameters: None
// Description: Lets synths use their communicators without hands.
/obj/item/device/communicator/integrated/verb/activate()
set category = "AI IM"
set name = "Use Communicator"
@@ -273,13 +273,13 @@ var/global/list/default_medbay_channels = list(
// Fix for permacell radios, but kinda eh about actually fixing them.
if(!M || !message) return 0
if(istype(M)) M.trigger_aiming(TARGET_CAN_RADIO)
// Uncommenting this. To the above comment:
// The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom
if(wires.IsIndexCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
return 0
M.last_target_radio = world.time // For the projectile targeting system
if(!radio_connection)
set_frequency(frequency)
@@ -98,6 +98,7 @@ A list of items and costs is stored under the datum of every game mode, alongsid
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui) // No auto-refresh
ui = new(user, src, ui_key, "uplink.tmpl", title, 450, 600, state = inventory_state)
data["menu"] = 0
ui.set_initial_data(data)
ui.open()
+3 -3
View File
@@ -104,7 +104,7 @@
build_cost = 1
build_type = "floor"
build_turf = /turf/simulated/floor/airless
else if(!deconstruct && istype(T,/turf/simulated/floor/asteroid))
else if(!deconstruct && istype(T,/turf/simulated/mineral/floor))
build_cost = 1
build_type = "floor"
build_turf = /turf/simulated/floor/plating
@@ -114,8 +114,8 @@
build_cost = 5
build_type = (!canRwall && W.reinf_material) ? null : "wall"
build_turf = /turf/simulated/floor
else if(istype(T,/turf/simulated/floor))
var/turf/simulated/floor/F = T
else if(istype(T,/turf/simulated/floor) || (istype(T,/turf/simulated/mineral) && !T.density))
var/turf/simulated/F = T
build_delay = deconstruct ? 50 : 20
build_cost = deconstruct ? 10 : 3
build_type = deconstruct ? "floor" : "wall"
@@ -94,10 +94,6 @@
icon_state = "id"
item_state = "card-id"
sprite_sheets = list(
"Resomi" = 'icons/mob/species/resomi/id.dmi'
)
var/access = list()
var/registered_name = "Unknown" // The name registered_name on the card
slot_flags = SLOT_ID
@@ -1,5 +1,5 @@
#ifndef T_BOARD
#error T_BOARD macro is not defined but we need it!
#error T_BOARD macro is not defined but we need it!
#endif
/obj/item/weapon/circuitboard/telecomms
@@ -73,3 +73,17 @@
"/obj/item/weapon/stock_parts/subspace/filter" = 1,
"/obj/item/weapon/stock_parts/subspace/crystal" = 1,
"/obj/item/weapon/stock_parts/micro_laser/high" = 2)
//This isn't a real telecomms board but I don't want to make a whole file to hold only one circuitboard.
/obj/item/weapon/circuitboard/telecomms/exonet_node
name = T_BOARD("exonet node")
build_path = "/obj/machinery/exonet_node"
origin_tech = list(TECH_DATA = 5, TECH_ENGINEERING = 5, TECH_BLUESPACE = 4)
req_components = list(
"/obj/item/weapon/stock_parts/subspace/ansible" = 1,
"/obj/item/weapon/stock_parts/subspace/filter" = 1,
"/obj/item/weapon/stock_parts/manipulator" = 2,
"/obj/item/weapon/stock_parts/micro_laser" = 1,
"/obj/item/weapon/stock_parts/subspace/crystal" = 1,
"/obj/item/weapon/stock_parts/subspace/treatment" = 2,
"/obj/item/stack/cable_coil" = 2)
@@ -17,7 +17,6 @@
var/breakouttime = 1200 //Deciseconds = 120s = 2 minutes
var/cuff_sound = 'sound/weapons/handcuffs.ogg'
var/cuff_type = "handcuffs"
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/handcuffs.dmi')
/obj/item/weapon/handcuffs/attack(var/mob/living/carbon/C, var/mob/living/user)
@@ -17,9 +17,6 @@
slot_l_hand_str = "backpack",
slot_r_hand_str = "backpack",
)
sprite_sheets = list(
"Resomi" = 'icons/mob/species/resomi/back.dmi'
)
w_class = 4
slot_flags = SLOT_BACK
max_w_class = 3
@@ -6,7 +6,6 @@
item_state = "utility"
slot_flags = SLOT_BELT
attack_verb = list("whipped", "lashed", "disciplined")
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/belt.dmi')
var/show_above_suit = 0
@@ -23,10 +23,6 @@ var/list/global/tank_gauge_cache = list()
throw_speed = 1
throw_range = 4
sprite_sheets = list(
"Resomi" = 'icons/mob/species/resomi/back.dmi'
)
var/datum/gas_mixture/air_contents = null
var/distribute_pressure = ONE_ATMOSPHERE
var/integrity = 3
+1 -1
View File
@@ -69,7 +69,7 @@
return ..()
/obj/structure/proc/can_climb(var/mob/living/user, post_climb_check=0)
if (!can_touch(user) || !climbable || (!post_climb_check && (user in climbers)))
if (!climbable || !can_touch(user) || (!post_climb_check && (user in climbers)))
return 0
if (!user.Adjacent(src))
+4 -3
View File
@@ -10,10 +10,11 @@
/obj/structure/lattice/New() //turf/simulated/floor/asteroid
..()
///// Z-Level Stuff
if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/floor/asteroid)))
///// Z-Level Stuff
if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/mineral)))
qdel(src)
return
for(var/obj/structure/lattice/LAT in src.loc)
if(LAT != src)
qdel(LAT)
+1 -1
View File
@@ -42,7 +42,7 @@ var/round_progressing = 1
//Set to 1 to enable it.
var/destroy_floor_override = 1
//Below is the path of turf used in place of space tiles.
var/destroy_floor_override_path = /turf/simulated/floor/asteroid
var/destroy_floor_override_path = /turf/simulated/mineral/floor
//A list of z-levels to apply the override to. This is so z-levels like tcomms work as they did before.
var/list/destroy_floor_override_z_levels = list(1,4,5)
//Some areas you may want to not turn into the override path you made above, like space or the solars.
+16
View File
@@ -1342,3 +1342,19 @@ proc/admin_notice(var/message, var/rights)
message_admins(msg)
else
usr << "You do not have access to this command."
/datum/admins/proc/paralyze_mob(mob/living/H as mob)
set category = "Admin"
set name = "Toggle Paralyze"
set desc = "Paralyzes a player. Or unparalyses them."
var/msg
if(check_rights(R_ADMIN|R_MOD))
if (H.paralysis == 0)
H.paralysis = 8000
msg = "[key_name(usr)] has paralyzed [key_name(H)]."
else
H.paralysis = 0
msg = "[key_name(usr)] has unparalyzed [key_name(H)]."
message_admins(msg)
+4 -2
View File
@@ -94,7 +94,8 @@ var/list/admin_verbs_admin = list(
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
/client/proc/change_security_level,
/client/proc/view_chemical_reaction_logs,
/client/proc/makePAI
/client/proc/makePAI,
/datum/admins/proc/paralyze_mob
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
@@ -303,7 +304,8 @@ var/list/admin_verbs_mod = list(
/datum/admins/proc/show_player_panel,
/client/proc/check_antagonists,
/client/proc/jobbans,
/client/proc/cmd_admin_subtle_message /*send an message to somebody as a 'voice in their head'*/
/client/proc/cmd_admin_subtle_message, /*send an message to somebody as a 'voice in their head'*/
/datum/admins/proc/paralyze_mob
)
var/list/admin_verbs_mentor = list(
+1 -1
View File
@@ -54,7 +54,7 @@
update_icon()
/obj/effect/blob/proc/expand(var/turf/T)
if(istype(T, /turf/unsimulated/) || istype(T, /turf/space))
if(istype(T, /turf/unsimulated/) || istype(T, /turf/space) || (istype(T, /turf/simulated/mineral) && T.density))
return
if(istype(T, /turf/simulated/wall))
var/turf/simulated/wall/SW = T
@@ -45,8 +45,8 @@
if(href_list["flavor_text"])
switch(href_list["flavor_text"])
if("open")
else if("general")
var/msg = sanitize(input(usr,"Give a general description of your character. This will be shown regardless of clothing, and may include OOC notes and preferences.","Flavor Text",html_decode(pref.flavor_texts[href_list["task"]])) as message, extra = 0)
if("general")
var/msg = sanitize(input(usr,"Give a general description of your character. This will be shown regardless of clothing, and may include OOC notes and preferences.","Flavor Text",html_decode(pref.flavor_texts[href_list["flavor_text"]])) as message, extra = 0)
if(CanUseTopic(user))
pref.flavor_texts[href_list["flavor_text"]] = msg
else
@@ -59,7 +59,7 @@
else if(href_list["flavour_text_robot"])
switch(href_list["flavour_text_robot"])
if("open")
else if("Default")
if("Default")
var/msg = sanitize(input(usr,"Set the default flavour text for your robot. It will be used for any module without individual setting.","Flavour Text",html_decode(pref.flavour_texts_robot["Default"])) as message, extra = 0)
if(CanUseTopic(user))
pref.flavour_texts_robot[href_list["flavour_text_robot"]] = msg
@@ -0,0 +1,26 @@
/datum/category_item/player_setup_item/player_global/communicators
name = "Communicators"
sort_order = 4
/datum/category_item/player_setup_item/player_global/communicators/load_preferences(var/savefile/S)
S["communicator_visibility"] >> pref.communicator_visibility
/datum/category_item/player_setup_item/player_global/communicators/save_preferences(var/savefile/S)
S["communicator_visibility"] << pref.communicator_visibility
/datum/category_item/player_setup_item/player_global/communicators/sanitize_preferences()
pref.communicator_visibility = sanitize_integer(pref.communicator_visibility, 0, 1, initial(pref.communicator_visibility))
/datum/category_item/player_setup_item/player_global/communicators/content(var/mob/user)
. += "<b>Communicator Identity:</b><br>"
. += "Visibility: <a href='?src=\ref[src];toggle_comm_visibility=1'><b>[(pref.communicator_visibility) ? "Yes" : "No"]</b></a><br>"
/datum/category_item/player_setup_item/player_global/communicators/OnTopic(var/href,var/list/href_list, var/mob/user)
if(href_list["toggle_comm_visibility"])
if(CanUseTopic(user))
pref.communicator_visibility = !pref.communicator_visibility
return TOPIC_REFRESH
return ..()
@@ -89,6 +89,9 @@
var/available_in_days = job.available_in_days(user.client)
. += "<del>[rank]</del></td><td> \[IN [(available_in_days)] DAYS]</td></tr>"
continue
if(job.minimum_character_age && user.client && (user.client.prefs.age < job.minimum_character_age))
. += "<del>[rank]</del></td><td> \[MINIMUM CHARACTER AGE: [job.minimum_character_age]]</td></tr>"
continue
if((pref.job_civilian_low & ASSISTANT) && (rank != "Assistant"))
. += "<font color=orange>[rank]</font></td><td></td></tr>"
continue
+3
View File
@@ -108,6 +108,9 @@ datum/preferences
// OOC Metadata:
var/metadata = ""
// Communicator identity data
var/communicator_visibility = 0
var/client/client = null
var/datum/category_collection/player_setup_collection/player_setup
File diff suppressed because it is too large Load Diff
-1
View File
@@ -38,7 +38,6 @@
icons.Add(usr.gun_setting_icon)
icons.Add(usr.item_use_icon)
icons.Add(usr.gun_move_icon)
icons.Add(usr.gun_run_icon)
icons.Add(usr.radio_use_icon)
var/icon/ic = all_ui_styles[UI_style_new]
+6 -17
View File
@@ -101,7 +101,6 @@
w_class = 1.0
throwforce = 2
slot_flags = SLOT_EARS
sprite_sheets = list("Resomi" = 'icons/mob/species/resomi/ears.dmi')
/obj/item/clothing/ears/attack_hand(mob/user as mob)
if (!user) return
@@ -209,10 +208,6 @@ BLIND // can't see anything
var/vision_flags = 0
var/darkness_view = 0//Base human is 2
var/see_invisible = -1
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
"Resomi" = 'icons/mob/species/resomi/eyes.dmi',
)
/obj/item/clothing/glasses/update_clothing_icon()
if (ismob(src.loc))
@@ -235,8 +230,7 @@ BLIND // can't see anything
attack_verb = list("challenged")
species_restricted = list("exclude","Unathi","Tajara", "Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/gloves.dmi',
"Resomi" = 'icons/mob/species/resomi/gloves.dmi',
"Vox" = 'icons/mob/species/vox/gloves.dmi'
)
/obj/item/clothing/gloves/update_clothing_icon()
@@ -293,8 +287,7 @@ BLIND // can't see anything
var/on = 0
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
"Resomi" = 'icons/mob/species/resomi/head.dmi'
"Vox" = 'icons/mob/species/vox/head.dmi'
)
/obj/item/clothing/head/attack_self(mob/user)
@@ -392,8 +385,7 @@ BLIND // can't see anything
slot_flags = SLOT_MASK
body_parts_covered = FACE|EYES
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/masks.dmi',
"Resomi" = 'icons/mob/species/resomi/masks.dmi',
"Vox" = 'icons/mob/species/vox/masks.dmi'
)
var/voicechange = 0
@@ -428,8 +420,7 @@ BLIND // can't see anything
var/overshoes = 0
species_restricted = list("exclude","Unathi","Tajara","Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/shoes.dmi',
"Resomi" = 'icons/mob/species/resomi/shoes.dmi',
"Vox" = 'icons/mob/species/vox/shoes.dmi'
)
/obj/item/clothing/shoes/proc/draw_knife()
@@ -503,8 +494,7 @@ BLIND // can't see anything
w_class = 3
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/suit.dmi',
"Resomi" = 'icons/mob/species/resomi/suit.dmi'
"Vox" = 'icons/mob/species/vox/suit.dmi'
)
/obj/item/clothing/suit/update_clothing_icon()
@@ -537,8 +527,7 @@ BLIND // can't see anything
var/displays_id = 1
var/rolled_down = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/uniform.dmi',
"Resomi" = 'icons/mob/species/resomi/uniform.dmi'
"Vox" = 'icons/mob/species/vox/uniform.dmi'
)
//convenience var for defining the icon state for the overlay used when the clothing is worn.
+49 -1
View File
@@ -28,8 +28,56 @@
icon_state = "skrell_cloth_female"
item_state = "skrell_cloth_female"
/obj/item/clothing/ears/skrell/cloth_female/black
name = "skrell headtail cloth"
desc = "A cloth shawl worn by female skrell draped around their head tails."
icon_state = "skrell_cloth_black_female"
item_state = "skrell_cloth_black_female"
/obj/item/clothing/ears/skrell/cloth_female/blue
name = "skrell headtail cloth"
desc = "A cloth shawl worn by female skrell draped around their head tails."
icon_state = "skrell_cloth_blue_female"
item_state = "skrell_cloth_blue_female"
/obj/item/clothing/ears/skrell/cloth_female/green
name = "skrell headtail cloth"
desc = "A cloth shawl worn by female skrell draped around their head tails."
icon_state = "skrell_cloth_green_female"
item_state = "skrell_cloth_green_female"
/obj/item/clothing/ears/skrell/cloth_female/pink
name = "skrell headtail cloth"
desc = "A cloth shawl worn by female skrell draped around their head tails."
icon_state = "skrell_cloth_pink_female"
item_state = "skrell_cloth_pink_female"
/obj/item/clothing/ears/skrell/cloth_male
name = "skrell headtail cloth"
desc = "A cloth band worn by male skrell around their head tails."
icon_state = "skrell_cloth_male"
item_state = "skrell_cloth_male"
item_state = "skrell_cloth_male"
/obj/item/clothing/ears/skrell/cloth_male/black
name = "skrell headtail cloth"
desc = "A cloth band worn by male skrell around their head tails."
icon_state = "skrell_cloth_black_male"
item_state = "skrell_cloth_black_male"
/obj/item/clothing/ears/skrell/cloth_male/blue
name = "skrell headtail cloth"
desc = "A cloth band worn by male skrell around their head tails."
icon_state = "skrell_cloth_blue_male"
item_state = "skrell_cloth_blue_male"
/obj/item/clothing/ears/skrell/cloth_male/green
name = "skrell headtail cloth"
desc = "A cloth band worn by male skrell around their head tails."
icon_state = "skrell_cloth_green_male"
item_state = "skrell_cloth_green_male"
/obj/item/clothing/ears/skrell/cloth_male/pink
name = "skrell headtail cloth"
desc = "A cloth band worn by male skrell around their head tails."
icon_state = "skrell_cloth_pink_male"
item_state = "skrell_cloth_pink_male"
-2
View File
@@ -19,7 +19,6 @@
/obj/item/clothing/glasses/hud/health/prescription
name = "Prescription Health Scanner HUD"
desc = "A medical HUD integrated with a set of prescription glasses"
icon_state = "healthhud"
prescription = 1
icon_state = "healthhudpresc"
item_state = "healthhudpresc"
@@ -37,7 +36,6 @@
/obj/item/clothing/glasses/hud/security/prescription
name = "Prescription Security HUD"
desc = "A security HUD integrated with a set of prescription glasses"
icon_state = "securityhud"
prescription = 1
icon_state = "sechudpresc"
item_state = "sechudpresc"
+1 -2
View File
@@ -10,8 +10,7 @@
desc = "an ultra rare hat. It commands a certain respect."
icon_state = "petehat"
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
"Resomi" = 'icons/mob/species/resomi/head.dmi'
"Vox" = 'icons/mob/species/vox/head.dmi'
)
/obj/item/clothing/head/collectable/slime
+7
View File
@@ -204,6 +204,13 @@
//end bs12 hats
/obj/item/clothing/head/cowboy_hat
name = "cowboy hat"
desc = "For those that have spurs that go jingle jangle jingle."
icon_state = "cowboyhat"
item_state = "cowboy_hat"
body_parts_covered = 0
/obj/item/clothing/head/witchwig
name = "witch costume wig"
desc = "Eeeee~heheheheheheh!"
+13 -1
View File
@@ -5,7 +5,7 @@
* Ushanka
* Pumpkin head
* Kitty ears
*
* Holiday hats
*/
/*
@@ -153,3 +153,15 @@
icon_state = "richard"
body_parts_covered = HEAD|FACE
flags_inv = BLOCKHAIR
/obj/item/clothing/head/santa
name = "santa hat"
desc = "It's a festive christmas hat, in red!"
icon_state = "santahatnorm"
body_parts_covered = 0
/obj/item/clothing/head/santa/green
name = "green santa hat"
desc = "It's a festive christmas hat, in green!"
icon_state = "santahatgreen"
body_parts_covered = 0
@@ -851,7 +851,6 @@
return 0
// AIs are a bit slower than regular and ignore move intent.
wearer.last_move_intent = world.time + ai_controlled_move_delay
wearer_move_delay = world.time + ai_controlled_move_delay
var/tickcomp = 0
+31 -8
View File
@@ -355,17 +355,17 @@
icon_state = "puffervest"
item_state = "puffervest"
/obj/item/clothing/suit/jacket/miljacket
/obj/item/clothing/suit/storage/miljacket
name = "military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
icon_state = "militaryjacket"
item_state = "militaryjacket"
icon_state = "militaryjacket_nobadge"
item_state = "militaryjacket_nobadge"
/obj/item/clothing/suit/jacket/miljacket2
/obj/item/clothing/suit/storage/miljacket/alt
name = "military jacket"
desc = "A canvas jacket styled after classical American military garb. Feels sturdy, yet comfortable."
icon_state = "militaryjacket2"
item_state = "militaryjacket2"
icon_state = "militaryjacket_badge"
item_state = "militaryjacket_badge"
/obj/item/clothing/suit/storage/toggle/bomber
name = "bomber jacket"
@@ -478,6 +478,29 @@
icon_open = "yellow_hoodie_open"
icon_closed = "yellow_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/cti
name = "CTI hoodie"
desc = "A warm, black sweatshirt. It bears the letters CTI on the back, a lettering to the prestigious university in Tau Ceti, Ceti Technical Institute. There is a blue supernova embroidered on the front, the emblem of CTI."
icon_state = "cti_hoodie"
item_state = "cti_hoodie"
icon_open = "cti_hoodie_open"
icon_closed = "cti_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/mu
name = "mars university hoodie"
desc = "A warm, gray sweatshirt. It bears the letters MU on the front, a lettering to the well-known public college, Mars University."
icon_state = "mu_hoodie"
item_state = "mu_hoodie"
icon_open = "mu_hoodie_open"
icon_closed = "mu_hoodie"
/obj/item/clothing/suit/storage/toggle/hoodie/nt
name = "NT hoodie"
desc = "A warm, blue sweatshirt. It proudly bears the silver NanoTrasen insignia lettering on the back. The edges are trimmed with silver."
icon_state = "nt_hoodie"
item_state = "nt_hoodie"
icon_open = "nt_hoodie_open"
icon_closed = "nt_hoodie"
// FUN!
@@ -557,12 +580,12 @@
/obj/item/clothing/suit/storage/hooded/wintercoat/captain
name = "captain's winter coat"
icon_state = "coatcaptain"
armor = list(melee = 25, bullet = 30, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
armor = list(melee = 20, bullet = 15, laser = 20, energy = 10, bomb = 15, bio = 0, rad = 0)
/obj/item/clothing/suit/storage/hooded/wintercoat/security
name = "security winter coat"
icon_state = "coatsecurity"
armor = list(melee = 25, bullet = 15, laser = 30, energy = 10, bomb = 25, bio = 0, rad = 0)
armor = list(melee = 25, bullet = 20, laser = 20, energy = 15, bomb = 20, bio = 0, rad = 0)
/obj/item/clothing/suit/storage/hooded/wintercoat/medical
name = "medical winter coat"
+1 -1
View File
@@ -98,7 +98,7 @@
icon_state = icon_badge
usr << "You reveal \the [src]'s badge."
else
usr << "\The [src] does not have a vest badge."
usr << "\The [src] does not have a badge."
return
update_clothing_icon()
@@ -5,8 +5,8 @@
slot = "utility"
var/obj/item/holstered = null
/obj/item/clothing/accessory/holster/proc/holster(obj/item/I, mob/user as mob)
if(holstered)
/obj/item/clothing/accessory/holster/proc/holster(var/obj/item/I, var/mob/living/user)
if(holstered && istype(user))
user << "<span class='warning'>There is already \a [holstered] holstered here!</span>"
return
@@ -14,6 +14,8 @@
user << "<span class='warning'>[I] won't fit in [src]!</span>"
return
if(istype(user))
user.stop_aiming(no_message=1)
holstered = I
user.drop_from_inventory(holstered)
holstered.loc = src
@@ -566,3 +566,38 @@
icon_state = "blue_blazer"
item_state = "blue_blazer"
worn_state = "blue_blazer"
/obj/item/clothing/under/croptop
name = "crop top"
desc = "A shirt that has had the top cropped. This one is NT sponsored."
icon_state = "croptop"
item_state = "gy_suit"
worn_state = "croptop"
/obj/item/clothing/under/croptop/red
name = "red crop top"
desc = "A red shirt that has had the top cropped."
icon_state = "croptop_red"
item_state = "r_suit"
worn_state = "croptop_red"
/obj/item/clothing/under/croptop/grey
name = "grey crop top"
desc = "A grey shirt that has had the top cropped."
icon_state = "croptop_grey"
item_state = "gy_suit"
worn_state = "croptop_grey"
/obj/item/clothing/under/cuttop
name = "grey cut top"
desc = "A grey shirt that has had the top cut low."
icon_state = "cuttop"
item_state = "gy_suit"
worn_state = "cuttop"
/obj/item/clothing/under/cuttop/red
name = "red cut top"
desc = "A red shirt that has had the top cut low."
icon_state = "cuttop_red"
item_state = "r_suit"
worn_state = "cuttop_red"
+56
View File
@@ -28,3 +28,59 @@
name = "grey athletic shorts"
icon_state = "greyshorts"
worn_state = "greyshorts"
/obj/item/clothing/under/shorts/jeans
name = "jeans shorts"
desc = "Some jeans! Just in short form!"
icon_state = "jeans_shorts"
worn_state = "jeans_shorts"
/obj/item/clothing/under/shorts/jeans/female
icon_state = "jeans_shorts_f"
worn_state = "jeans_shorts_f"
/obj/item/clothing/under/shorts/jeans/classic
name = "classic jeans shorts"
icon_state = "jeansclassic_shorts"
worn_state = "jeansclassic_shorts"
/obj/item/clothing/under/shorts/jeans/classic/female
icon_state = "jeansclassic_shorts_f"
worn_state = "jeansclassic_shorts_f"
/obj/item/clothing/under/shorts/jeans/mustang
name = "mustang jeans shorts"
icon_state = "jeansmustang_shorts"
worn_state = "jeansmustang_shorts"
/obj/item/clothing/under/shorts/jeans/mustang/female
icon_state = "jeansmustang_shorts_f"
worn_state = "jeansmustang_shorts_f"
/obj/item/clothing/under/shorts/jeans/youngfolks
name = "young folks jeans shorts"
icon_state = "jeansyoungfolks_shorts"
worn_state = "jeansyoungfolks_shorts"
/obj/item/clothing/under/shorts/jeans/youngfolks/female
icon_state = "jeansyoungfolks_shorts_f"
worn_state = "jeansyoungfolks_shorts_f"
/obj/item/clothing/under/shorts/jeans/black
name = "black jeans shorts"
icon_state = "black_shorts"
worn_state = "black_shorts"
/obj/item/clothing/under/shorts/jeans/black/female
icon_state = "black_shorts_f"
worn_state = "black_shorts_f"
/obj/item/clothing/under/shorts/khaki
name = "khaki shorts"
desc = "For that island getaway. It's five o'clock somewhere, right?"
icon_state = "khaki_shorts"
worn_state = "khaki_shorts"
/obj/item/clothing/under/shorts/khaki/female
icon_state = "khaki_shorts_f"
worn_state = "khaki_shorts_f"
@@ -1,32 +0,0 @@
/obj/item/clothing/under/resomi
name = "small grey smock"
desc = "It looks fitted to nonhuman proportions."
icon = 'icons/obj/clothing/species/resomi/uniform.dmi'
icon_state = "resomi_grey"
worn_state = "resomi_grey"
species_restricted = list("Resomi")
/obj/item/clothing/under/resomi/white
name = "small white smock"
icon_state = "resomi_white"
worn_state = "resomi_white"
/obj/item/clothing/under/resomi/red
name = "small Security smock"
icon_state = "resomi_red"
worn_state = "resomi_red"
/obj/item/clothing/under/resomi/yellow
name = "small Engineering smock"
icon_state = "resomi_yellow"
worn_state = "resomi_yellow"
/obj/item/clothing/under/resomi/medical
name = "small Medical uniform"
icon_state = "resomi_medical"
worn_state = "resomi_medical"
/obj/item/clothing/under/resomi/rainbow
name = "small rainbow smock"
icon_state = "resomi_rainbow"
worn_state = "resomi_rainbow"
@@ -18,3 +18,5 @@
/datum/event/communications_blackout/start()
for(var/obj/machinery/telecomms/T in telecomms_list)
T.emp_act(1)
for(var/obj/machinery/exonet_node/N in machines)
N.emp_act(1)
+6
View File
@@ -2,6 +2,7 @@
endWhen = 36000
var/last_spam_time = 0
var/obj/machinery/message_server/useMS
var/obj/machinery/exonet_node/node
/datum/event/pda_spam/setup()
last_spam_time = world.time
@@ -19,6 +20,11 @@
//if there's no spam managed to get to receiver for five minutes, give up
kill()
return
if(!node)
node = get_exonet_node()
if(!node || !node.on || !node.allow_external_PDAs)
return
if(!useMS || !useMS.active)
useMS = null
@@ -0,0 +1,22 @@
/obj/item/device/communicator
description_info = "This device allows someone to speak to another player sourced from the observer pool, as well as other communicators linked to it. \
To use the device, use it in your hand, and it will open an interface with various buttons. Near the bottom will be a list of devices currently available \
for you to call, both from communications on the station, and communicators very far away (observers). To call someone, send a communications request to \
someone and hope they respond, or receive one yourself and respond to them. Hanging up is also simple, and is handled in the 'Manage Connections' tab."
description_fluff = "As a concept, a device that allows long-distance communication has existed for over five hundred years. A device that can accomplish \
that while in space, across star systems, and that the consumer can afford and use without training, is much more recent, and is thanks to the backbone \
that is the Exonet.<br>\
<br>\
The Exonet is the predominant interstellar telecom system, servicing trillions of devices across a large portion of human-controlled space. \
It is distributed by a massive network of telecommunication satellites, some privately owned and others owned by the systems local governments, \
that utilize FTL technologies to bounce data between satellites at speeds that would not be possible at sub-light technology. This communicator \
uses a protocol called Exonet Protocol Version 2, generally shortened to EPv2.<br>\
<br>\
EPv2 is the most common communications protocol in the Exonet, and was specifically designed for it. It was designed to facilitate communication \
between any device in a star system, and have the ability to forward interstellar requests at the root node of that systems Exonet. \
It is also built to cope with the reality that the numerous nodes in a system will likely have frequent outages. The protocol allows for \
up to 18,446,744,073,709,551,616 unique addresses, one of which is assigned to this device."
description_antag = "Electromagnetic pulses will cause the device to disconnect all linked communicators. Turning off the Exonet node at the Telecomms \
satellite will also accomplish this, but for all communicators on and near the station. This may be needed to allow for a quiet kill or capture."
@@ -0,0 +1,36 @@
//This is not strictly a telecomms machine but conceptually it is.
/obj/machinery/exonet_node
description_info = "This machine is needed for several machines back at the colony to interact with systems beyond this region of space, such as \
communicators, external PDA messages, and even newscaster units, which host their content externally. You can fiddle with the device with \
just your hands, due to the integrated monitor and keyboard. Synthetic units can interface with it as well, just like most other machines."
description_fluff = "This is one of many nodes that make up the Exonet, which services trillions of devices across space. This particular node \
is referred to as a terminal node, servicing the Northern Star.<br>\
<br>\
In the beginning of humanity's ascend into space, the Exonet didn't exist. Instead, the Exonet is the evolution to a network called the Interplanetary \
Internet (sometimes referred to as the InterPlaNet), which was conceived and developed due to the limitations of the terrestrial Internet, mainly because \
the IP protocol was unsuitable for long range communications in space, due to the massive delays associated with lightspeed being unable to overcome \
the massive distances between planets in a timely manner. It was a store-and-forward network of smaller internets, distributed between various nodes, \
and was designed to be error, fault, and delay tolerant. The first nodes were put into space around the time when colonization had begun, to service humanitys \
close holdings, such as Luna and Mars.<br>\
<br>\
By 2104, the Interplanetary Internet had coverage within most of Sol, but the network of networks were limited by the speed of light, and due \
to orbital mechanics, the delay for a request to be processed could vary. As an example, a direct message from Mars to Earth could take anywhere \
between three to twenty two minutes to get to Earth, and then the same amount of time to return to Mars. Coverage was also spotty due to the \
nature of operating at such vast distances.<br>\
<br>\
Fortunately, a method for traveling faster than light was discovered, which could allow data to be transmitted beyond the speed of light, \
and thus overcome the limitations of the Interplanetary Internet. One by one, each of the nodes were upgraded to utilize cutting edge \
(at the time) FTL technologies to rapidly increase response time.<br>\
<br>\
Once humanity had send colonists out beyond Sol, to other star systems such as Sirius and Alpha Centauri, they required their own interplanetary \
internet, so a new protocol had to be created, and another hardware upgrade for the separate interplanetary internets. The end result allowed \
communications between Sol and the various exosolar systems, and was dubbed the Exonet. It remains the most common way for consumers to engage \
in long range communications across planets and star systems. Generally, each system has their own Exonet, which is connected to all the other \
Exonets at the root node(s), and is typically arranged in a tree structure. The root node(s) are generally government-owned and are very secure \
and resilient to failure.<br>\
<br>\
This node is privately owned and maintained by Nanotrasen, and allows the colonists of the Northern Star to have access to the Exonet."
description_antag = "An EMP will disable this device for a short period of time. A longer downage can be achieved by turning it off, or rigging \
the APC it uses to turn off remotely, such as with a signaler in the right wire."
+2 -6
View File
@@ -74,12 +74,8 @@
return
//Drill through the flooring, if any.
if(istype(get_turf(src), /turf/simulated/floor/asteroid))
var/turf/simulated/floor/asteroid/T = get_turf(src)
if(!T.dug)
T.gets_dug()
else if(istype(get_turf(src), /turf/simulated/floor))
var/turf/simulated/floor/T = get_turf(src)
if(istype(get_turf(src), /turf/simulated))
var/turf/simulated/T = get_turf(src)
T.ex_act(2.0)
//Dig out the tasty ores.
+1 -1
View File
@@ -235,7 +235,7 @@
var/obj/item/stack/flag/F = locate() in get_turf(src)
var/turf/T = get_turf(src)
if(!T || !istype(T,/turf/simulated/floor/asteroid))
if(!T || !istype(T,/turf/simulated/mineral))
user << "The flag won't stand up in this terrain."
return
+341 -364
View File
@@ -1,3 +1,5 @@
var/list/mining_overlay_cache = list()
/**********************Mineral deposits**************************/
/turf/unsimulated/mineral
name = "impassable rock"
@@ -5,7 +7,7 @@
icon_state = "rock-dark"
/turf/simulated/mineral //wall piece
name = "Rock"
name = "rock"
icon = 'icons/turf/walls.dmi'
icon_state = "rock"
oxygen = 0
@@ -14,11 +16,13 @@
density = 1
blocks_air = 1
temperature = T0C
var/mined_turf = /turf/simulated/floor/asteroid
var/ore/mineral
var/sand_dug
var/mined_ore = 0
var/last_act = 0
var/emitter_blasts_taken = 0 // EMITTER MINING! Muhehe.
var/overlay_detail
var/datum/geosample/geologic_data
var/excavation_level = 0
@@ -28,26 +32,121 @@
var/excav_overlay = ""
var/obj/item/weapon/last_find
var/datum/artifact_find/artifact_find
var/ignore_mapgen
has_resources = 1
/turf/simulated/mineral/New()
spawn(0)
MineralSpread()
spawn(2)
updateMineralOverlays(1)
/turf/simulated/mineral/ignore_mapgen
ignore_mapgen = 1
/turf/simulated/mineral/proc/updateMineralOverlays(var/update_neighbors)
var/list/step_overlays = list("s" = NORTH, "n" = SOUTH, "w" = EAST, "e" = WEST)
for(var/direction in step_overlays)
var/turf/turf_to_check = get_step(src,step_overlays[direction])
if(update_neighbors && istype(turf_to_check,/turf/simulated/floor/asteroid))
var/turf/simulated/floor/asteroid/T = turf_to_check
T.updateMineralOverlays()
else if(istype(turf_to_check,/turf/space) || istype(turf_to_check,/turf/simulated/floor))
turf_to_check.overlays += image('icons/turf/walls.dmi', "rock_side_[direction]")
/turf/simulated/mineral/floor
name = "sand"
icon = 'icons/turf/flooring/asteroid.dmi'
icon_state = "asteroid"
density = 0
opacity = 0
blocks_air = 0
/turf/simulated/mineral/floor/ignore_mapgen
ignore_mapgen = 1
/turf/simulated/mineral/proc/make_floor()
if(!density && !opacity)
return
density = 0
opacity = 0
blocks_air = 0
update_general()
/turf/simulated/mineral/proc/make_wall()
if(density && opacity)
return
density = 1
opacity = 1
blocks_air = 1
update_general()
/turf/simulated/mineral/proc/update_general()
update_icon(1)
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
reconsider_lights()
if(air_master)
air_master.mark_for_update(src)
/turf/simulated/mineral/Entered(atom/movable/M as mob|obj)
. = ..()
if(istype(M,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = M
if(R.module)
for(var/obj/item/weapon/storage/bag/ore/O in list(R.module_state_1, R.module_state_2, R.module_state_3))
attackby(O, R)
return
/turf/simulated/mineral/initialize()
if(prob(20))
overlay_detail = "asteroid[rand(0,9)]"
if(density)
spawn(0)
MineralSpread()
update_icon(1)
/turf/simulated/mineral/update_icon(var/update_neighbors)
overlays.Cut()
if(density)
if(mineral)
name = "[mineral.display_name] deposit"
else
name = "rock"
icon = 'icons/turf/walls.dmi'
icon_state = "rock"
for(var/direction in cardinal)
var/turf/T = get_step(src,direction)
if(istype(T) && !T.density)
var/place_dir = turn(direction, 180)
if(!mining_overlay_cache["rock_side_[place_dir]"])
mining_overlay_cache["rock_side_[place_dir]"] = image('icons/turf/walls.dmi', "rock_side", dir = place_dir)
T.overlays += mining_overlay_cache["rock_side_[place_dir]"]
else
name = "sand"
icon = 'icons/turf/flooring/asteroid.dmi'
icon_state = "asteroid"
if(sand_dug)
if(!mining_overlay_cache["dug_overlay"])
mining_overlay_cache["dug_overlay"] = image('icons/turf/flooring/asteroid.dmi', "dug_overlay")
overlays += mining_overlay_cache["dug_overlay"]
for(var/direction in cardinal)
if(istype(get_step(src, direction), /turf/space))
if(!mining_overlay_cache["asteroid_edge_[direction]"])
mining_overlay_cache["asteroid_edge_[direction]"] = image('icons/turf/flooring/asteroid.dmi', "asteroid_edges", dir = direction)
overlays += mining_overlay_cache["asteroid_edge_[direction]"]
else
var/turf/simulated/mineral/M = get_step(src, direction)
if(istype(M) && M.density)
if(!mining_overlay_cache["rock_side_[direction]"])
mining_overlay_cache["rock_side_[direction]"] = image('icons/turf/walls.dmi', "rock_side", dir = direction)
overlays += mining_overlay_cache["rock_side_[direction]"]
if(overlay_detail)
if(!mining_overlay_cache["decal_[overlay_detail]"])
mining_overlay_cache["decal_[overlay_detail]"] = image(icon = 'icons/turf/flooring/decals.dmi', icon_state = overlay_detail)
overlays += mining_overlay_cache["decal_[overlay_detail]"]
if(update_neighbors)
for(var/direction in alldirs)
if(istype(get_step(src, direction), /turf/simulated/mineral))
var/turf/simulated/mineral/M = get_step(src, direction)
M.update_icon()
/turf/simulated/mineral/ex_act(severity)
switch(severity)
if(2.0)
if (prob(70))
@@ -62,13 +161,17 @@
// Emitter blasts
if(istype(Proj, /obj/item/projectile/beam/emitter))
emitter_blasts_taken++
if(emitter_blasts_taken > 2) // 3 blasts per tile
mined_ore = 1
GetDrilled()
/turf/simulated/mineral/Bumped(AM)
. = ..()
if(!density)
return .
if(istype(AM,/mob/living/carbon/human))
var/mob/living/carbon/human/H = AM
if((istype(H.l_hand,/obj/item/weapon/pickaxe)) && (!H.hand))
@@ -91,7 +194,7 @@
for(var/trydir in cardinal)
if(prob(mineral.spread_chance))
var/turf/simulated/mineral/target_turf = get_step(src, trydir)
if(istype(target_turf) && !target_turf.mineral)
if(istype(target_turf) && target_turf.density && !target_turf.mineral)
target_turf.mineral = mineral
target_turf.UpdateMineral()
target_turf.MineralSpread()
@@ -99,143 +202,213 @@
/turf/simulated/mineral/proc/UpdateMineral()
clear_ore_effects()
if(!mineral)
name = "\improper Rock"
icon_state = "rock"
return
name = "\improper [mineral.display_name] deposit"
new /obj/effect/mineral(src, mineral)
if(mineral)
new /obj/effect/mineral(src, mineral)
update_icon()
//Not even going to touch this pile of spaghetti
/turf/simulated/mineral/attackby(obj/item/weapon/W as obj, mob/user as mob)
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
usr << "\red You don't have the dexterity to do this!"
usr << "<span class='warning'>You don't have the dexterity to do this!</span>"
return
if (istype(W, /obj/item/device/core_sampler))
geologic_data.UpdateNearbyArtifactInfo(src)
var/obj/item/device/core_sampler/C = W
C.sample_item(src, user)
return
if(!density)
if (istype(W, /obj/item/device/depth_scanner))
var/obj/item/device/depth_scanner/C = W
C.scan_atom(user, src)
return
var/list/usable_tools = list(
/obj/item/weapon/shovel,
/obj/item/weapon/pickaxe/diamonddrill,
/obj/item/weapon/pickaxe/drill,
/obj/item/weapon/pickaxe/borgdrill
)
if (istype(W, /obj/item/device/measuring_tape))
var/obj/item/device/measuring_tape/P = W
user.visible_message("\blue[user] extends [P] towards [src].","\blue You extend [P] towards [src].")
if(do_after(user,25))
user << "\blue \icon[P] [src] has been excavated to a depth of [2*excavation_level]cm."
return
var/valid_tool
for(var/valid_type in usable_tools)
if(istype(W,valid_type))
valid_tool = 1
break
if (istype(W, /obj/item/weapon/pickaxe))
var/turf/T = user.loc
if (!( istype(T, /turf) ))
return
var/obj/item/weapon/pickaxe/P = W
if(last_act + P.digspeed > world.time)//prevents message spam
return
last_act = world.time
playsound(user, P.drill_sound, 20, 1)
//handle any archaeological finds we might uncover
var/fail_message
if(finds && finds.len)
var/datum/find/F = finds[1]
if(excavation_level + P.excavation_amount > F.excavation_required)
//Chance to destroy / extract any finds here
fail_message = ". <b>[pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]</b>"
user << "\red You start [P.drill_verb][fail_message ? fail_message : ""]."
if(fail_message && prob(90))
if(prob(25))
excavate_find(5, finds[1])
else if(prob(50))
finds.Remove(finds[1])
if(prob(50))
artifact_debris()
if(do_after(user,P.digspeed))
user << "\blue You finish [P.drill_verb] the rock."
if(finds && finds.len)
var/datum/find/F = finds[1]
if(round(excavation_level + P.excavation_amount) == F.excavation_required)
//Chance to extract any items here perfectly, otherwise just pull them out along with the rock surrounding them
if(excavation_level + P.excavation_amount > F.excavation_required)
//if you can get slightly over, perfect extraction
excavate_find(100, F)
else
excavate_find(80, F)
else if(excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range)
//just pull the surrounding rock out
excavate_find(0, F)
if( excavation_level + P.excavation_amount >= 100 )
//if players have been excavating this turf, leave some rocky debris behind
var/obj/structure/boulder/B
if(artifact_find)
if( excavation_level > 0 || prob(15) )
//boulder with an artifact inside
B = new(src)
if(artifact_find)
B.artifact_find = artifact_find
else
artifact_debris(1)
else if(prob(15))
//empty boulder
B = new(src)
if(B)
GetDrilled(0)
else
GetDrilled(1)
if(valid_tool)
if (sand_dug)
user << "<span class='warning'>This area has already been dug.</span>"
return
excavation_level += P.excavation_amount
var/turf/T = user.loc
if (!(istype(T)))
return
//archaeo overlays
if(!archaeo_overlay && finds && finds.len)
var/datum/find/F = finds[1]
if(F.excavation_required <= excavation_level + F.view_range)
archaeo_overlay = "overlay_archaeo[rand(1,3)]"
overlays += archaeo_overlay
user << "<span class='notice'>You start digging.</span>"
playsound(user.loc, 'sound/effects/rustle1.ogg', 50, 1)
//there's got to be a better way to do this
var/update_excav_overlay = 0
if(excavation_level >= 75)
if(excavation_level - P.excavation_amount < 75)
update_excav_overlay = 1
else if(excavation_level >= 50)
if(excavation_level - P.excavation_amount < 50)
update_excav_overlay = 1
else if(excavation_level >= 25)
if(excavation_level - P.excavation_amount < 25)
update_excav_overlay = 1
if(!do_after(user,40)) return
//update overlays displaying excavation level
if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
var/excav_quadrant = round(excavation_level / 25) + 1
excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
overlays += excav_overlay
user << "<span class='notice'>You dug a hole.</span>"
GetDrilled()
else if(istype(W,/obj/item/weapon/storage/bag/ore))
var/obj/item/weapon/storage/bag/ore/S = W
if(S.collection_mode)
for(var/obj/item/weapon/ore/O in contents)
O.attackby(W,user)
return
else if(istype(W,/obj/item/weapon/storage/bag/fossils))
var/obj/item/weapon/storage/bag/fossils/S = W
if(S.collection_mode)
for(var/obj/item/weapon/fossil/F in contents)
F.attackby(W,user)
return
else if(istype(W, /obj/item/stack/rods))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
return
var/obj/item/stack/rods/R = W
if (R.use(1))
user << "<span class='notice'>Constructing support lattice ...</span>"
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
new /obj/structure/lattice(get_turf(src))
else if(istype(W, /obj/item/stack/tile/floor))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
var/obj/item/stack/tile/floor/S = W
if (S.get_amount() < 1)
return
qdel(L)
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ChangeTurf(/turf/simulated/floor)
S.use(1)
return
else
user << "<span class='warning'>The plating is going to need some support.</span>"
return
//drop some rocks
next_rock += P.excavation_amount * 10
while(next_rock > 100)
next_rock -= 100
var/obj/item/weapon/ore/O = new(src)
geologic_data.UpdateNearbyArtifactInfo(src)
O.geologic_data = geologic_data
else
return attack_hand(user)
if (istype(W, /obj/item/device/core_sampler))
geologic_data.UpdateNearbyArtifactInfo(src)
var/obj/item/device/core_sampler/C = W
C.sample_item(src, user)
return
if (istype(W, /obj/item/device/depth_scanner))
var/obj/item/device/depth_scanner/C = W
C.scan_atom(user, src)
return
if (istype(W, /obj/item/device/measuring_tape))
var/obj/item/device/measuring_tape/P = W
user.visible_message("<span class='notice'>\The [user] extends \a [P] towards \the [src].</span>","<span class='notice'>You extend \the [P] towards \the [src].</span>")
if(do_after(user,25))
user << "<span class='notice'>\icon[P] [src] has been excavated to a depth of [2*excavation_level]cm.</span>"
return
if (istype(W, /obj/item/weapon/pickaxe))
var/turf/T = user.loc
if (!( istype(T, /turf) ))
return
var/obj/item/weapon/pickaxe/P = W
if(last_act + P.digspeed > world.time)//prevents message spam
return
last_act = world.time
playsound(user, P.drill_sound, 20, 1)
//handle any archaeological finds we might uncover
var/fail_message
if(finds && finds.len)
var/datum/find/F = finds[1]
if(excavation_level + P.excavation_amount > F.excavation_required)
//Chance to destroy / extract any finds here
fail_message = ". <b>[pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]</b>"
user << "<span class='notice'>You start [P.drill_verb][fail_message ? fail_message : ""].</span>"
if(fail_message && prob(90))
if(prob(25))
excavate_find(5, finds[1])
else if(prob(50))
finds.Remove(finds[1])
if(prob(50))
artifact_debris()
if(do_after(user,P.digspeed))
user << "<span class='notice'>You finish [P.drill_verb] \the [src].</span>"
if(finds && finds.len)
var/datum/find/F = finds[1]
if(round(excavation_level + P.excavation_amount) == F.excavation_required)
//Chance to extract any items here perfectly, otherwise just pull them out along with the rock surrounding them
if(excavation_level + P.excavation_amount > F.excavation_required)
//if you can get slightly over, perfect extraction
excavate_find(100, F)
else
excavate_find(80, F)
else if(excavation_level + P.excavation_amount > F.excavation_required - F.clearance_range)
//just pull the surrounding rock out
excavate_find(0, F)
if( excavation_level + P.excavation_amount >= 100 )
//if players have been excavating this turf, leave some rocky debris behind
var/obj/structure/boulder/B
if(artifact_find)
if( excavation_level > 0 || prob(15) )
//boulder with an artifact inside
B = new(src)
if(artifact_find)
B.artifact_find = artifact_find
else
artifact_debris(1)
else if(prob(15))
//empty boulder
B = new(src)
if(B)
GetDrilled(0)
else
GetDrilled(1)
return
excavation_level += P.excavation_amount
//archaeo overlays
if(!archaeo_overlay && finds && finds.len)
var/datum/find/F = finds[1]
if(F.excavation_required <= excavation_level + F.view_range)
archaeo_overlay = "overlay_archaeo[rand(1,3)]"
overlays += archaeo_overlay
//there's got to be a better way to do this
var/update_excav_overlay = 0
if(excavation_level >= 75)
if(excavation_level - P.excavation_amount < 75)
update_excav_overlay = 1
else if(excavation_level >= 50)
if(excavation_level - P.excavation_amount < 50)
update_excav_overlay = 1
else if(excavation_level >= 25)
if(excavation_level - P.excavation_amount < 25)
update_excav_overlay = 1
//update overlays displaying excavation level
if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
var/excav_quadrant = round(excavation_level / 25) + 1
excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
overlays += excav_overlay
//drop some rocks
next_rock += P.excavation_amount * 10
while(next_rock > 100)
next_rock -= 100
var/obj/item/weapon/ore/O = new(src)
geologic_data.UpdateNearbyArtifactInfo(src)
O.geologic_data = geologic_data
return
return attack_hand(user)
/turf/simulated/mineral/proc/clear_ore_effects()
for(var/obj/effect/mineral/M in contents)
@@ -244,7 +417,6 @@
/turf/simulated/mineral/proc/DropMineral()
if(!mineral)
return
clear_ore_effects()
var/obj/item/weapon/ore/O = new mineral.ore (src)
if(istype(O))
@@ -253,7 +425,15 @@
return O
/turf/simulated/mineral/proc/GetDrilled(var/artifact_fail = 0)
//var/destroyed = 0 //used for breaking strange rocks
if(!density)
if(!sand_dug)
sand_dug = 1
for(var/i=0;i<(rand(3)+2);i++)
new/obj/item/weapon/ore/glass(src)
update_icon()
return
if (mineral && mineral.result_amount)
//if the turf has already been excavated, some of it's ore has been removed
@@ -267,7 +447,7 @@
if(prob(50))
pain = 1
for(var/mob/living/M in range(src, 200))
M << "<font color='red'><b>[pick("A high pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!</b></font>"
M << "<span class='danger'>[pick("A high-pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!</span>"
if(pain)
flick("pain",M.pain)
if(prob(50))
@@ -278,25 +458,8 @@
M.Stun(5)
M.apply_effect(25, IRRADIATE)
var/list/step_overlays = list("n" = NORTH, "s" = SOUTH, "e" = EAST, "w" = WEST)
//Add some rubble, you did just clear out a big chunk of rock.
var/turf/simulated/floor/asteroid/N = ChangeTurf(mined_turf)
// Kill and update the space overlays around us.
for(var/direction in step_overlays)
var/turf/space/T = get_step(src, step_overlays[direction])
if(istype(T))
T.overlays.Cut()
for(var/next_direction in step_overlays)
if(istype(get_step(T, step_overlays[next_direction]),/turf/simulated/mineral))
T.overlays += image('icons/turf/walls.dmi', "rock_side_[next_direction]")
if(istype(N))
N.overlay_detail = "asteroid[rand(0,9)]"
N.updateMineralOverlays(1)
make_floor()
update_icon(1)
/turf/simulated/mineral/proc/excavate_find(var/prob_clean = 0, var/datum/find/F)
//with skill and luck, players can cleanly extract finds
@@ -311,7 +474,7 @@
//some find types delete the /obj/item/weapon/archaeological_find and replace it with something else, this handles when that happens
//yuck
var/display_name = "something"
var/display_name = "Something"
if(!X)
X = last_find
if(X)
@@ -322,12 +485,11 @@
var/obj/effect/suspension_field/S = locate() in src
if(!S || S.field_type != get_responsive_reagent(F.find_type))
if(X)
visible_message("\red<b>[pick("[display_name] crumbles away into dust","[display_name] breaks apart")].</b>")
visible_message("<span class='danger'>\The [pick("[display_name] crumbles away into dust","[display_name] breaks apart")].</span>")
qdel(X)
finds.Remove(F)
/turf/simulated/mineral/proc/artifact_debris(var/severity = 0)
//cael's patented random limited drop componentized loot system!
//sky's patented not-fucking-retarded overhaul!
@@ -336,219 +498,34 @@
for(var/j in 1 to rand(1, 3 + max(min(severity, 1), 0) * 2))
switch(rand(1,7))
if(1)
var/obj/item/stack/rods/R = new(src)
R.amount = rand(5,25)
new /obj/item/stack/rods(src, rand(5,25))
if(2)
var/obj/item/stack/material/plasteel/R = new(src)
R.amount = rand(5,25)
new /obj/item/stack/material/plasteel(src, rand(5,25))
if(3)
var/obj/item/stack/material/steel/R = new(src)
R.amount = rand(5,25)
new /obj/item/stack/material/steel(src, rand(5,25))
if(4)
var/obj/item/stack/material/plasteel/R = new(src)
R.amount = rand(5,25)
new /obj/item/stack/material/plasteel(src, rand(5,25))
if(5)
var/quantity = rand(1,3)
for(var/i=0, i<quantity, i++)
for(var/i=1 to rand(1,3))
new /obj/item/weapon/material/shard(src)
if(6)
var/quantity = rand(1,3)
for(var/i=0, i<quantity, i++)
for(var/i=1 to rand(1,3))
new /obj/item/weapon/material/shard/phoron(src)
if(7)
var/obj/item/stack/material/uranium/R = new(src)
R.amount = rand(5,25)
new /obj/item/stack/material/uranium(src, rand(5,25))
/turf/simulated/mineral/random
name = "Mineral deposit"
var/mineralSpawnChanceList = list("Uranium" = 5, "Platinum" = 5, "Iron" = 35, "Coal" = 35, "Diamond" = 1, "Gold" = 5, "Silver" = 5, "Phoron" = 10)
var/mineralChance = 100 //10 //means 10% chance of this plot changing to a mineral deposit
/turf/simulated/mineral/random/New()
if (prob(mineralChance) && !mineral)
var/mineral_name = pickweight(mineralSpawnChanceList) //temp mineral name
mineral_name = lowertext(mineral_name)
if (mineral_name && (mineral_name in ore_data))
mineral = ore_data[mineral_name]
UpdateMineral()
. = ..()
/turf/simulated/mineral/random/high_chance
mineralChance = 100 //25
mineralSpawnChanceList = list("Uranium" = 10, "Platinum" = 10, "Iron" = 20, "Coal" = 20, "Diamond" = 2, "Gold" = 10, "Silver" = 10, "Phoron" = 20)
/**********************Asteroid**************************/
// Setting icon/icon_state initially will use these values when the turf is built on/replaced.
// This means you can put grass on the asteroid etc.
/turf/simulated/floor/asteroid
name = "sand"
icon = 'icons/turf/flooring/asteroid.dmi'
icon_state = "asteroid"
base_name = "sand"
base_desc = "Gritty and unpleasant."
base_icon = 'icons/turf/flooring/asteroid.dmi'
base_icon_state = "asteroid"
initial_flooring = null
oxygen = 0
nitrogen = 0
temperature = TCMB
var/dug = 0 //0 = has not yet been dug, 1 = has already been dug
var/overlay_detail
has_resources = 1
/turf/simulated/floor/asteroid/New()
if(prob(20))
overlay_detail = "asteroid[rand(0,9)]"
/turf/simulated/floor/asteroid/ex_act(severity)
switch(severity)
if(3.0)
return
if(2.0)
if (prob(70))
gets_dug()
if(1.0)
gets_dug()
return
/turf/simulated/floor/asteroid/is_plating()
return 0
/turf/simulated/floor/asteroid/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(!W || !user)
return 0
var/list/usable_tools = list(
/obj/item/weapon/shovel,
/obj/item/weapon/pickaxe/diamonddrill,
/obj/item/weapon/pickaxe/drill,
/obj/item/weapon/pickaxe/borgdrill
)
var/valid_tool
for(var/valid_type in usable_tools)
if(istype(W,valid_type))
valid_tool = 1
break
if(valid_tool)
if (dug)
user << "\red This area has already been dug"
return
var/turf/T = user.loc
if (!(istype(T)))
return
user << "\red You start digging."
playsound(user.loc, 'sound/effects/rustle1.ogg', 50, 1)
if(!do_after(user,40)) return
user << "\blue You dug a hole."
gets_dug()
else if(istype(W,/obj/item/weapon/storage/bag/ore))
var/obj/item/weapon/storage/bag/ore/S = W
if(S.collection_mode)
for(var/obj/item/weapon/ore/O in contents)
O.attackby(W,user)
return
else if(istype(W,/obj/item/weapon/storage/bag/fossils))
var/obj/item/weapon/storage/bag/fossils/S = W
if(S.collection_mode)
for(var/obj/item/weapon/fossil/F in contents)
F.attackby(W,user)
return
else if(istype(W, /obj/item/stack/rods))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
return
var/obj/item/stack/rods/R = W
if (R.use(1))
user << "<span class='notice'>Constructing support lattice ...</span>"
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
new /obj/structure/lattice(get_turf(src))
/turf/simulated/mineral/proc/make_ore(var/rare_ore)
if(mineral)
return
else if(istype(W, /obj/item/stack/tile/floor))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
var/obj/item/stack/tile/floor/S = W
if (S.get_amount() < 1)
return
qdel(L)
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ChangeTurf(/turf/simulated/floor/airless)
S.use(1)
return
else
user << "<span class='warning'>The plating is going to need some support.</span>"
return
var/mineral_name
if(rare_ore)
mineral_name = pickweight(list("uranium" = 10, "platinum" = 10, "iron" = 20, "coal" = 20, "diamond" = 2, "gold" = 10, "silver" = 10, "phoron" = 20))
else
..(W,user)
return
mineral_name = pickweight(list("uranium" = 5, "platinum" = 5, "iron" = 35, "coal" = 35, "diamond" = 1, "gold" = 5, "silver" = 5, "phoron" = 10))
/turf/simulated/floor/asteroid/proc/gets_dug()
if(dug)
return
for(var/i=0;i<(rand(3)+2);i++)
new/obj/item/weapon/ore/glass(src)
dug = 1
icon_state = "asteroid_dug"
return
/turf/simulated/floor/asteroid/proc/updateMineralOverlays(var/update_neighbors)
overlays.Cut()
var/list/step_overlays = list("n" = NORTH, "s" = SOUTH, "e" = EAST, "w" = WEST)
for(var/direction in step_overlays)
if(istype(get_step(src, step_overlays[direction]), /turf/space))
overlays += image('icons/turf/floors.dmi', "asteroid_edge_[direction]")
if(istype(get_step(src, step_overlays[direction]), /turf/simulated/mineral))
overlays += image('icons/turf/walls.dmi', "rock_side_[direction]")
//todo cache
if(overlay_detail) overlays |= image(icon = 'icons/turf/flooring/decals.dmi', icon_state = overlay_detail)
if(update_neighbors)
var/list/all_step_directions = list(NORTH,NORTHEAST,EAST,SOUTHEAST,SOUTH,SOUTHWEST,WEST,NORTHWEST)
for(var/direction in all_step_directions)
var/turf/simulated/floor/asteroid/A
if(istype(get_step(src, direction), /turf/simulated/floor/asteroid))
A = get_step(src, direction)
A.updateMineralOverlays()
/turf/simulated/floor/asteroid/Entered(atom/movable/M as mob|obj)
..()
if(istype(M,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = M
if(R.module)
if(istype(R.module_state_1,/obj/item/weapon/storage/bag/ore))
attackby(R.module_state_1,R)
else if(istype(R.module_state_2,/obj/item/weapon/storage/bag/ore))
attackby(R.module_state_2,R)
else if(istype(R.module_state_3,/obj/item/weapon/storage/bag/ore))
attackby(R.module_state_3,R)
else
return
if(mineral_name && (mineral_name in ore_data))
mineral = ore_data[mineral_name]
UpdateMineral()
update_icon()
+1 -2
View File
@@ -8,8 +8,7 @@ var/list/holder_mob_icon_cache = list()
slot_flags = SLOT_HEAD | SLOT_HOLSTER
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
"Resomi" = 'icons/mob/species/resomi/head.dmi'
"Vox" = 'icons/mob/species/vox/head.dmi'
)
origin_tech = null
+1
View File
@@ -165,6 +165,7 @@ var/list/slot_equipment_priority = list( \
// Removes an item from inventory and places it in the target atom.
// If canremove or other conditions need to be checked then use unEquip instead.
/mob/proc/drop_from_inventory(var/obj/item/W, var/atom/Target = null)
if(W)
if(!Target)
Target = loc
-19
View File
@@ -114,25 +114,6 @@
new_name = pick(ai_names)
return new_name
/datum/language/resomi
name = "Resomi"
desc = "A trilling language spoken by the diminutive Resomi."
speech_verb = "chirps"
ask_verb = "chirrups"
exclaim_verb = "trills"
colour = "alien"
key = "v"
flags = WHITELISTED
space_chance = 50
syllables = list(
"ca", "ra", "ma", "sa", "na", "ta", "la", "sha", "scha", "a", "a",
"ce", "re", "me", "se", "ne", "te", "le", "she", "sche", "e", "e",
"ci", "ri", "mi", "si", "ni", "ti", "li", "shi", "schi", "i", "i"
)
/datum/language/resomi/get_random_name(gender)
return ..(gender, 1, 4, 1.5)
//Syllable Lists
/*
This list really long, mainly because I can't make up my mind about which mandarin syllables should be removed,
@@ -49,6 +49,8 @@
if(shock_stage >= 10) tally += 3
if(aiming && aiming.aiming_at) tally += 5 // Iron sights make you slower, it's a well-known fact.
if(FAT in src.mutations)
tally += 1.5
if (bodytemperature < 283.222)
+1 -1
View File
@@ -375,7 +375,7 @@
safe_pressure_min *= 1.25
var/safe_exhaled_max = 10
var/safe_toxins_max = 0.005
var/safe_toxins_max = 0.2
var/SA_para_min = 1
var/SA_sleep_min = 5
var/inhaled_gas_used = 0
@@ -1,114 +0,0 @@
/datum/species/resomi
name = "Resomi"
name_plural = "Resomii"
blurb = "A race of feathered raptors who developed on a cold world, almost \
outside of the Goldilocks zone. Extremely fragile, they developed hunting skills \
that emphasized taking out their prey without themselves getting hit. They are an \
advanced post-scarcity culture on good terms with Skrellian and Human interests."
num_alternate_languages = 2
secondary_langs = list("Resomi")
name_language = "Resomi"
blood_color = "#D514F7"
flesh_color = "#5F7BB0"
base_color = "#001144"
tail = "resomitail"
tail_hair = "feathers"
icobase = 'icons/mob/human_races/r_resomi.dmi'
deform = 'icons/mob/human_races/r_resomi.dmi'
damage_overlays = 'icons/mob/human_races/masks/dam_resomi.dmi'
damage_mask = 'icons/mob/human_races/masks/dam_mask_resomi.dmi'
blood_mask = 'icons/mob/human_races/masks/blood_resomi.dmi'
eyes = "eyes_resomi"
slowdown = -1
total_health = 50
brute_mod = 1.35
burn_mod = 1.35
mob_size = MOB_SMALL
holder_type = /obj/item/weapon/holder/human
short_sighted = 1
gluttonous = 1
spawn_flags = CAN_JOIN | IS_WHITELISTED
appearance_flags = HAS_HAIR_COLOR | HAS_SKIN_COLOR | HAS_EYE_COLOR
bump_flag = MONKEY
swap_flags = MONKEY|SLIME|SIMPLE_ANIMAL
push_flags = MONKEY|SLIME|SIMPLE_ANIMAL|ALIEN
cold_level_1 = 180
cold_level_2 = 130
cold_level_3 = 70
heat_level_1 = 320
heat_level_2 = 370
heat_level_3 = 600
heat_discomfort_level = 292
heat_discomfort_strings = list(
"Your feathers prickle in the heat.",
"You feel uncomfortably warm.",
)
cold_discomfort_level = 180
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest),
"groin" = list("path" = /obj/item/organ/external/groin),
"head" = list("path" = /obj/item/organ/external/head),
"l_arm" = list("path" = /obj/item/organ/external/arm),
"r_arm" = list("path" = /obj/item/organ/external/arm/right),
"l_leg" = list("path" = /obj/item/organ/external/leg),
"r_leg" = list("path" = /obj/item/organ/external/leg/right),
"l_hand" = list("path" = /obj/item/organ/external/hand/resomi),
"r_hand" = list("path" = /obj/item/organ/external/hand/right/resomi),
"l_foot" = list("path" = /obj/item/organ/external/foot/resomi),
"r_foot" = list("path" = /obj/item/organ/external/foot/right/resomi)
)
has_organ = list(
"heart" = /obj/item/organ/heart,
"lungs" = /obj/item/organ/lungs,
"liver" = /obj/item/organ/liver,
"kidneys" = /obj/item/organ/kidneys,
"brain" = /obj/item/organ/brain,
"eyes" = /obj/item/organ/eyes
)
unarmed_types = list(
/datum/unarmed_attack/bite/sharp,
/datum/unarmed_attack/claws,
/datum/unarmed_attack/stomp/weak
)
var/shock_cap = 30
var/hallucination_cap = 25
// I'm... so... ronrery, so ronery...
/datum/species/resomi/handle_environment_special(var/mob/living/carbon/human/H)
// If they're dead or unconcious they're a bit beyond this kind of thing.
if(H.stat)
return
// No point processing if we're already stressing the hell out.
if(H.hallucination >= hallucination_cap && H.shock_stage >= shock_cap)
return
// Check for company.
for(var/mob/living/M in viewers(H))
if(M == H || M.stat == DEAD || M.invisibility > H.see_invisible)
continue
if(M.faction == "neutral" || M.faction == H.faction)
return
// No company? Suffer :(
if(H.shock_stage < shock_cap)
H.shock_stage += 1
if(H.shock_stage >= shock_cap && H.hallucination < hallucination_cap)
H.hallucination += 2.5
/datum/species/resomi/get_vision_flags(var/mob/living/carbon/human/H)
if(!(H.sdisabilities & DEAF) && !H.ear_deaf)
return SEE_SELF|SEE_MOBS
else
return SEE_SELF
@@ -429,17 +429,6 @@ var/global/list/damage_icon_parts = list()
overlays_standing[MUTATIONS_LAYER] = null
if(update_icons) update_icons()
//Call when target overlay should be added/removed
/mob/living/carbon/human/update_targeted(var/update_icons=1)
if (targeted_by && target_locked)
overlays_standing[TARGETED_LAYER] = target_locked
else if (!targeted_by && target_locked)
qdel(target_locked)
if (!targeted_by)
overlays_standing[TARGETED_LAYER] = null
if(update_icons) update_icons()
/* --------------------------------------- */
//For legacy support.
/mob/living/carbon/human/regenerate_icons()
@@ -502,6 +491,7 @@ var/global/list/damage_icon_parts = list()
//need to append _s to the icon state for legacy compatibility
var/image/standing = image(icon = under_icon, icon_state = "[under_state]_s")
standing.color = w_uniform.color
//apply blood overlay
if(w_uniform.blood_DNA)
@@ -562,6 +552,7 @@ var/global/list/damage_icon_parts = list()
bloodsies.color = gloves.blood_color
standing.overlays += bloodsies
gloves.screen_loc = ui_gloves
standing.color = gloves.color
overlays_standing[GLOVES_LAYER] = standing
else
if(blood_DNA)
@@ -637,6 +628,7 @@ var/global/list/damage_icon_parts = list()
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "shoeblood")
bloodsies.color = shoes.blood_color
standing.overlays += bloodsies
standing.color = shoes.color
overlays_standing[SHOES_LAYER] = standing
else
if(feet_blood_DNA)
@@ -702,6 +694,7 @@ var/global/list/damage_icon_parts = list()
if(hat.on && light_overlay_cache[cache_key])
standing.overlays |= light_overlay_cache[cache_key]
standing.color = head.color
overlays_standing[HEAD_LAYER] = standing
else
@@ -736,6 +729,8 @@ var/global/list/damage_icon_parts = list()
if(!i_state) i_state = i.icon_state
standing.overlays += image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[i_state]")
standing.color = belt.color
overlays_standing[belt_layer] = standing
else
overlays_standing[BELT_LAYER] = null
@@ -759,6 +754,7 @@ var/global/list/damage_icon_parts = list()
t_icon = wear_suit.item_icons[slot_wear_suit_str]
standing = image("icon" = t_icon, "icon_state" = "[wear_suit.icon_state]")
standing.color = wear_suit.color
if( istype(wear_suit, /obj/item/clothing/suit/straight_jacket) )
drop_from_inventory(handcuffed)
@@ -800,6 +796,7 @@ var/global/list/damage_icon_parts = list()
standing = image("icon" = wear_mask.sprite_sheets[species.get_bodytype()], "icon_state" = "[wear_mask.icon_state]")
else
standing = image("icon" = 'icons/mob/mask.dmi', "icon_state" = "[wear_mask.icon_state]")
standing.color = wear_mask.color
if( !istype(wear_mask, /obj/item/clothing/mask/smokable/cigarette) && wear_mask.blood_DNA )
var/image/bloodsies = image("icon" = species.blood_mask, "icon_state" = "maskblood")
@@ -839,8 +836,12 @@ var/global/list/damage_icon_parts = list()
else
overlay_state = back.icon_state
//apply color
var/image/standing = image(icon = overlay_icon, icon_state = overlay_state)
standing.color = back.color
//create the image
overlays_standing[BACK_LAYER] = image(icon = overlay_icon, icon_state = overlay_state)
overlays_standing[BACK_LAYER] = standing
else
overlays_standing[BACK_LAYER] = null
@@ -919,7 +920,11 @@ var/global/list/damage_icon_parts = list()
else
t_icon = INV_R_HAND_DEF_ICON
overlays_standing[R_HAND_LAYER] = image(icon = t_icon, icon_state = t_state)
//apply color
var/image/standing = image(icon = t_icon, icon_state = t_state)
standing.color = r_hand.color
overlays_standing[R_HAND_LAYER] = standing
if (handcuffed) drop_r_hand() //this should be moved out of icon code
else
@@ -951,7 +956,11 @@ var/global/list/damage_icon_parts = list()
else
t_icon = INV_L_HAND_DEF_ICON
overlays_standing[L_HAND_LAYER] = image(icon = t_icon, icon_state = t_state)
//apply color
var/image/standing = image(icon = t_icon, icon_state = t_state)
standing.color = l_hand.color
overlays_standing[L_HAND_LAYER] = standing
if (handcuffed) drop_l_hand() //This probably should not be here
else
@@ -703,14 +703,6 @@
icon_state = module_sprites[icontype]
return
//Call when target overlay should be added/removed
/mob/living/silicon/robot/update_targeted()
if(!targeted_by && target_locked)
qdel(target_locked)
updateicon()
if (targeted_by && target_locked)
overlays += target_locked
/mob/living/silicon/robot/proc/installed_modules()
if(weapon_lock)
src << "\red Weapon lock active, unable to use modules! Count:[weaponlock_time]"
@@ -16,9 +16,9 @@
maxHealth = 20
health = 20
harm_intent_damage = 8
melee_damage_lower = 10
melee_damage_upper = 10
harm_intent_damage = 10
melee_damage_lower = 3
melee_damage_upper = 3
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
@@ -6,14 +6,15 @@
icon_state = "otherthing"
icon_living = "otherthing"
icon_dead = "otherthing-dead"
health = 80
maxHealth = 80
melee_damage_lower = 25
melee_damage_upper = 50
health = 40
maxHealth = 40
melee_damage_lower = 5
melee_damage_upper = 5
attacktext = "chomped"
attack_sound = 'sound/weapons/bite.ogg'
faction = "creature"
speed = 4
speed = 8
harm_intent_damage = 10
/mob/living/simple_animal/hostile/creature/cult
faction = "cult"
@@ -9,13 +9,13 @@
response_help = "passes through"
response_disarm = "shoves"
response_harm = "hits"
speed = -1
maxHealth = 80
health = 80
speed = 8
maxHealth = 50
health = 50
harm_intent_damage = 10
melee_damage_lower = 15
melee_damage_upper = 15
melee_damage_lower = 5
melee_damage_upper = 5
attacktext = "gripped"
attack_sound = 'sound/hallucinations/growl1.ogg'
@@ -50,6 +50,7 @@
/mob/living/simple_animal/hostile/faithless/cult
faction = "cult"
supernatural = 1
/mob/living/simple_animal/hostile/faithless/cult/cultify()
return
@@ -365,14 +365,6 @@
return (0)
return 1
//Call when target overlay should be added/removed
/mob/living/simple_animal/update_targeted()
if(!targeted_by && target_locked)
qdel(target_locked)
overlays = null
if (targeted_by && target_locked)
overlays += target_locked
/mob/living/simple_animal/say(var/message)
var/verb = "says"
if(speak_emote.len)
+56 -25
View File
@@ -1,13 +1,11 @@
//A very, very simple mob that exists inside other objects to talk and has zero influence on the world.
/mob/living/voice
name = "unknown"
name = "unknown person"
desc = "How are you examining me?"
// default_language = "Galactic Common"
see_invisible = SEE_INVISIBLE_LIVING
var/obj/item/device/communicator/comm = null
emote_type = 2 //This lets them emote through containers. The communicator has a image feed of the person calling them so...
var/stable_connection = 0 //If set to zero, makes the mob effectively deaf, mute, and blind, due to interferance.
/mob/living/voice/New(loc)
add_language("Galactic Common")
@@ -20,11 +18,15 @@
comm = loc
..()
// Proc: transfer_identity()
// Parameters: 1 (speaker - the mob (usually an observer) to copy information from)
// Description: Copies the mob's icons, overlays, TOD, gender, currently loaded character slot, and languages, to src.
/mob/living/voice/proc/transfer_identity(mob/speaker)
if(ismob(speaker))
icon = speaker.icon
icon_state = speaker.icon_state
overlays = speaker.overlays
timeofdeath = speaker.timeofdeath
alpha = 127 //Maybe we'll have hologram calls later.
if(speaker.client && speaker.client.prefs)
@@ -36,6 +38,9 @@
for(var/language in p.alternate_languages)
add_language(language)
// Proc: Login()
// Parameters: None
// Description: Adds a static overlay to the client's screen.
/mob/living/voice/Login()
var/obj/screen/static_effect = new() //Since what the player sees is essentially a video feed, from a vast distance away, the view isn't going to be perfect.
static_effect.screen_loc = ui_entire_screen
@@ -44,10 +49,23 @@
static_effect.mouse_opacity = 0 //So the static doesn't get in the way of clicking.
client.screen.Add(static_effect)
// Proc: Destroy()
// Parameters: None
// Description: Removes reference to the communicator, so it can qdel() successfully.
/mob/living/voice/Destroy()
comm = null
..()
// Proc: ghostize()
// Parameters: None
// Description: Sets a timeofdeath variable, to fix the free respawn bug.
/mob/living/voice/ghostize()
timeofdeath = world.time
. = ..()
// Verb: hang_up()
// Parameters: None
// Description: Disconnects the voice mob from the communicator.
/mob/living/voice/verb/hang_up()
set name = "Hang Up"
set category = "Communicator"
@@ -55,40 +73,53 @@
set src = usr
if(comm)
comm.close_connection(src, "[src] hung up")
comm.close_connection(user = src, target = src, reason = "[src] hung up")
else
src << "You appear to not be inside a communicator. This is a bug and you should report it."
// Verb: change_name()
// Parameters: None
// Description: Allows the voice mob to change their name, assuming it is valid.
/mob/living/voice/verb/change_name()
set name = "Change Name"
set category = "Communicator"
set desc = "Changes your name."
set src = usr
var/new_name = sanitizeSafe(input(src, "Who would you like to be now?", "Communicator", src.client.prefs.real_name) as text, MAX_NAME_LEN)
if(new_name)
if(comm)
comm.visible_message("<span class='notice'>\icon[comm] [src.name] has left, and now you see [new_name].</span>")
//Do a bit of logging in-case anyone tries to impersonate other characters for whatever reason.
var/msg = "[src.client.key] ([src]) has changed their communicator identity's name to [new_name]."
message_admins(msg)
log_game(msg)
src.name = new_name
else
src << "<span class='warning'>Invalid name. Rejected.</span>"
// Proc: Life()
// Parameters: None
// Description: Checks the active variable on the Exonet node, and kills the mob if it goes down or stops existing.
/mob/living/voice/Life()
if(comm && comm.server && !comm.server.active)
comm.close_connection(src,"Connection to telecommunications array timed out")
if(comm)
if(!comm.node || !comm.node.on || !comm.node.allow_external_communicators)
comm.close_connection(user = src, target = src, reason = "Connection to telecommunications array timed out")
..()
// Proc: say()
// Parameters: 4 (generic say() arguments)
// Description: Adds a speech bubble to the communicator device, then calls ..() to do the real work.
/mob/living/voice/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="")
// world << "say() was called. Arguments: ([message], [speaking], [verb], [alt_name])."
if(!stable_connection)
return 0
//Speech bubbles.
if(comm)
var/speech_bubble_test = say_test(message)
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
var/image/speech_bubble = image('icons/mob/talk.dmi',comm,"h[speech_bubble_test]")
spawn(30)
qdel(speech_bubble)
for(var/mob/M in hearers(world.view,comm)) //simplifed since it's just a speech bubble
for(var/mob/M in hearers(comm)) //simplifed since it's just a speech bubble
M << speech_bubble
src << speech_bubble
..(message, speaking, verb, alt_name) //mob/living/say() can do the actual talking.
/*
/mob/verb/test_voice_mob()
set name = "Make Voice Mob"
set category = "Debug"
set desc = "For testing only!"
set src = usr
var/turf/T = get_turf(src)
var/obj/item/device/communicator/comm = new(T)
comm.open_connection(src, src)
*/
..(message, speaking, verb, alt_name) //mob/living/say() can do the actual talking.
+2 -3
View File
@@ -39,7 +39,6 @@
pain = null
item_use_icon = null
gun_move_icon = null
gun_run_icon = null
gun_setting_icon = null
spell_masters = null
zone_sel = null
@@ -765,8 +764,8 @@
if(lying)
density = 0
drop_l_hand()
drop_r_hand()
if(l_hand) unEquip(l_hand)
if(r_hand) unEquip(r_hand)
else
density = initial(density)
+1 -1
View File
@@ -265,7 +265,7 @@
return 0
move_delay = world.time//set move delay
mob.last_move_intent = world.time + 10
switch(mob.m_intent)
if("run")
if(mob.drowsyness > 0)
+3 -1
View File
@@ -375,9 +375,11 @@
else // Crew transfer initiated
dat += "<font color='red'>The station is currently undergoing crew transfer procedures.</font><br>"
dat += "Choose from the following open positions:<br>"
dat += "Choose from the following open/valid positions:<br>"
for(var/datum/job/job in job_master.occupations)
if(job && IsJobAvailable(job.title))
if(job.minimum_character_age && (client.prefs.age < job.minimum_character_age))
continue
var/active = 0
// Only players with the job assigned and AFK for less than 10 minutes count as active
for(var/mob/M in player_list) if(M.mind && M.client && M.mind.assigned_role == job.title && M.client.inactivity <= 10 * 60 * 10)
@@ -61,21 +61,6 @@
name = "Short Hair 2"
icon_state = "hair_shorthair3"
resomi
name = "Resomi Plumage"
icon_state = "resomi_default"
species_allowed = list("Resomi")
resomi_ears
name = "Resomi Ears"
icon_state = "resomi_ears"
species_allowed = list("Resomi")
resomi_excited
name = "Resomi Spiky"
icon_state = "resomi_spiky"
species_allowed = list("Resomi")
cut
name = "Cut Hair"
icon_state = "hair_c"
@@ -152,6 +137,10 @@
name = "Side Ponytail"
icon_state = "hair_stail"
sideponytail4 //Not happy about this... but it's for the save files.
name = "Side Ponytail 2"
icon_state = "hair_ponytailf"
sideponytail2
name = "One Shoulder"
icon_state = "hair_oneshoulder"
@@ -160,6 +149,10 @@
name = "Tress Shoulder"
icon_state = "hair_tressshoulder"
wisp
name = "Wisp"
icon_state = "hair_wisp"
parted
name = "Parted"
icon_state = "hair_parted"
+1 -1
View File
@@ -15,7 +15,7 @@ var/global/datum/robolimb/basic_robolimb
var/desc = "A generic unbranded robotic prosthesis." // Seen when examining a limb.
var/icon = 'icons/mob/human_races/robotic.dmi' // Icon base to draw from.
var/unavailable_at_chargen // If set, not available at chargen.
var/list/species_cannot_use = list("Resomi")
var/list/species_cannot_use = list()
/datum/robolimb/bishop
company = "Bishop Cybernetics"
-8
View File
@@ -1,8 +0,0 @@
/obj/item/organ/external/foot/resomi
body_hair = "feathers"
/obj/item/organ/external/foot/right/resomi
body_hair = "feathers"
/obj/item/organ/external/hand/resomi
body_hair = "feathers"
/obj/item/organ/external/hand/right/resomi
body_hair = "feathers"
+11 -11
View File
@@ -107,7 +107,7 @@
if(process_projectile(P, user, user, pick("l_foot", "r_foot")))
handle_post_fire(user, user)
user.visible_message(
"<span class='danger'>[user] shoots \himself in the foot with \the [src]!</span>",
"<span class='danger'>\The [user] shoots \himself in the foot with \the [src]!</span>",
"<span class='danger'>You shoot yourself in the foot with \the [src]!</span>"
)
M.drop_item()
@@ -123,17 +123,17 @@
/obj/item/weapon/gun/afterattack(atom/A, mob/living/user, adjacent, params)
if(adjacent) return //A is adjacent, is the user, or is on the user's person
//decide whether to aim or shoot normally
var/aiming = 0
if(user && user.client && !(A in aim_targets))
if(user.client.gun_mode)
aiming = PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
if(!user.aiming)
user.aiming = new(user)
if (!aiming)
if(user && user.a_intent == I_HELP) //regardless of what happens, refuse to shoot if help intent is on
user << "\red You refrain from firing your [src] as your intent is set to help."
else
Fire(A,user,params) //Otherwise, fire normally.
if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A)
PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
return
if(user && user.a_intent == I_HELP) //regardless of what happens, refuse to shoot if help intent is on
user << "<span class='warning'>You refrain from firing your [src] as your intent is set to help.</span>"
else
Fire(A,user,params) //Otherwise, fire normally.
/obj/item/weapon/gun/attack(atom/A, mob/living/user, def_zone)
if (A == user && user.zone_sel.selecting == "mouth" && !mouthshoot)

Some files were not shown because too many files have changed in this diff Show More