initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
//////////////////////
//Heap object
//////////////////////
/Heap
var/list/L
var/cmp
/Heap/New(compare)
L = new()
cmp = compare
/Heap/proc/IsEmpty()
return !L.len
//Insert and place at its position a new node in the heap
/Heap/proc/Insert(atom/A)
L.Add(A)
Swim(L.len)
//removes and returns the first element of the heap
//(i.e the max or the min dependant on the comparison function)
/Heap/proc/Pop()
if(!L.len)
return 0
. = L[1]
L[1] = L[L.len]
L.Cut(L.len)
Sink(1)
//Get a node up to its right position in the heap
/Heap/proc/Swim(var/index)
var/parent = round(index * 0.5)
while(parent > 0 && (call(cmp)(L[index],L[parent]) > 0))
L.Swap(index,parent)
index = parent
parent = round(index * 0.5)
//Get a node down to its right position in the heap
/Heap/proc/Sink(var/index)
var/g_child = GetGreaterChild(index)
while(g_child > 0 && (call(cmp)(L[index],L[g_child]) < 0))
L.Swap(index,g_child)
index = g_child
g_child = GetGreaterChild(index)
//Returns the greater (relative to the comparison proc) of a node children
//or 0 if there's no child
/Heap/proc/GetGreaterChild(var/index)
if(index * 2 > L.len)
return 0
if(index * 2 + 1 > L.len)
return index * 2
if(call(cmp)(L[index * 2],L[index * 2 + 1]) < 0)
return index * 2 + 1
else
return index * 2
//Replaces a given node so it verify the heap condition
/Heap/proc/ReSort(atom/A)
var/index = L.Find(A)
Swim(index)
Sink(index)
/Heap/proc/List()
. = L.Copy()
+191
View File
@@ -0,0 +1,191 @@
//Ok so it's technically a double linked list, bite me.
/datum/linked_list
var/datum/linked_node/head
var/datum/linked_node/tail
var/node_amt = 0
/datum/linked_node
var/value = null
var/datum/linked_list/linked_list = null
var/datum/linked_node/next_node = null
var/datum/linked_node/previous_node = null
/datum/linked_list/proc/IsEmpty()
. = (node_amt <= 0)
//Add a linked_node (or value, creating a linked_node) at position
//the added node BECOMES the position-th element,
//eg: add("Test",5), the 5th node is now "Test", the previous 5th moves up to become the 6th
/datum/linked_list/proc/Add(node, position)
var/datum/linked_node/adding
if(istype(node, /datum/linked_node))
adding = node
else
adding = new()
adding.value = node
if(!adding.linked_list || (adding.linked_list && (adding.linked_list != src)))
node_amt++
adding.linked_list = src
if(position && position < node_amt)
//Replacing head
if(position == 1)
if(head)
head.previous_node = adding
adding.next_node = head
head = adding
//Replacing any middle node
else
var/location = 0
var/datum/linked_node/at
while((location != position) && (location <= node_amt))
if(at)
if(at.next_node)
at = at.next_node
else
break
else
at = head
location++
//Push at up and assume it's place as the position-th element
if(at && at.previous_node)
at.previous_node.next_node = adding
adding.previous_node = at.previous_node
at.previous_node = adding
adding.next_node = at
return
//Replacing tail
if(tail)
tail.next_node = adding
adding.previous_node = tail
if(!tail.previous_node)
head = tail
tail = adding
//Remove a linked_node or the linked_node of a value
//If you specify a value the FIRST ONE is removed
/datum/linked_list/proc/Remove(node)
var/datum/linked_node/removing
if(istype(node,/datum/linked_node))
removing = node
else
//optimise removing head and tail, no point looping for them, especially the tail
if(removing == head)
removing = head
else if(removing == tail)
removing = tail
else
var/location = 1
var/current_value = null
var/datum/linked_node/at = null
while((current_value != node) && (location <= node_amt))
if(at)
if(at.next_node)
at = at.next_node
else
at = head
location++
if(at)
current_value = at.value
if(current_value == node)
removing = at
break
//Adjust pointers of where removing -was- in the chain.
if(removing)
if(removing.previous_node)
if(removing == tail)
tail = removing.previous_node
if(removing.next_node)
if(removing == head)
head = removing.next_node
removing.next_node.previous_node = removing.previous_node
removing.previous_node.next_node = removing.next_node
else
removing.previous_node.next_node = null
else
if(removing.next_node)
if(removing == head)
head = removing.next_node
removing.next_node.previous_node = null
//if this is still true at this point, there's no more nodes to replace them with
if(removing == head)
head = null
if(removing == tail)
tail = null
removing.next_node = null
removing.previous_node = null
if(removing.linked_list == src)
node_amt--
removing.linked_list = null
return removing
return 0
//Removes and deletes a node or value
/datum/linked_list/proc/RemoveDelete(node)
var/datum/linked_node/dead = Remove(node)
if(dead)
qdel(dead)
return 1
return 0
//Empty the linked_list, deleting all nodes
/datum/linked_list/proc/Empty()
var/datum/linked_node/n = head
while(n)
var/next = n.next_node
Remove(n)
qdel(n)
n = next
node_amt = 0
//Some debugging tools
/datum/linked_list/proc/CheckNodeLinks()
var/datum/linked_node/n = head
while(n)
. = "|[n.value]|"
if(n.previous_node)
. = "[n.previous_node.value]<-" + .
if(n.next_node)
. += "->[n.next_node.value]"
n = n.next_node
. += "<BR>"
/datum/linked_list/proc/DrawNodeLinks()
. = "|<-"
var/datum/linked_node/n = head
while(n)
if(n.previous_node)
. += "<-"
. += "[n.value]"
if(n.next_node)
. += "->"
n = n.next_node
. += "->|"
/datum/linked_list/proc/ToList()
. = list()
var/datum/linked_node/n = head
while(n)
. += n
n = n.next_node
+83
View File
@@ -0,0 +1,83 @@
//////////////////////
//PriorityQueue object
//////////////////////
//an ordered list, using the cmp proc to weight the list elements
/PriorityQueue
var/list/L //the actual queue
var/cmp //the weight function used to order the queue
/PriorityQueue/New(compare)
L = new()
cmp = compare
/PriorityQueue/proc/IsEmpty()
return !L.len
//return the index the element should be in the priority queue using dichotomic search
/PriorityQueue/proc/FindElementIndex(atom/A)
var/i = 1
var/j = L.len
var/mid
while(i < j)
mid = round((i+j)/2)
if(call(cmp)(L[mid],A) < 0)
i = mid + 1
else
j = mid
if(i == 1 || i == L.len) //edge cases
return (call(cmp)(L[i],A) > 0) ? i : i+1
else
return i
//add an element in the list,
//immediatly ordering it to its position using dichotomic search
/PriorityQueue/proc/Enqueue(atom/A)
if(!L.len)
L.Add(A)
return
L.Insert(FindElementIndex(A),A)
//removes and returns the first element in the queue
/PriorityQueue/proc/Dequeue()
if(!L.len)
return 0
. = L[1]
Remove(.)
//removes an element
/PriorityQueue/proc/Remove(atom/A)
return L.Remove(A)
//returns a copy of the elements list
/PriorityQueue/proc/List()
. = L.Copy()
//return the position of an element or 0 if not found
/PriorityQueue/proc/Seek(atom/A)
. = L.Find(A)
//return the element at the i_th position
/PriorityQueue/proc/Get(i)
if(i > L.len || i < 1)
return 0
return L[i]
//replace the passed element at it's right position using the cmp proc
/PriorityQueue/proc/ReSort(atom/A)
var/i = Seek(A)
if(i == 0)
return
while(i < L.len && call(cmp)(L[i],L[i+1]) > 0)
L.Swap(i,i+1)
i++
while(i > 1 && call(cmp)(L[i],L[i-1]) <= 0) //last inserted element being first in case of ties (optimization)
L.Swap(i,i-1)
i--
+56
View File
@@ -0,0 +1,56 @@
/datum/stack
var/list/stack = list()
var/max_elements = 0
/datum/stack/New(list/elements,max)
..()
if(elements)
stack = elements.Copy()
if(max)
max_elements = max
/datum/stack/proc/Pop()
if(is_empty())
return null
. = stack[stack.len]
stack.Cut(stack.len,0)
/datum/stack/proc/Push(element)
if(max_elements && (stack.len+1 > max_elements))
return null
stack += element
/datum/stack/proc/Top()
if(is_empty())
return null
. = stack[stack.len]
/datum/stack/proc/is_empty()
. = stack.len ? 0 : 1
//Rotate entire stack left with the leftmost looping around to the right
/datum/stack/proc/RotateLeft()
if(is_empty())
return 0
. = stack[1]
stack.Cut(1,2)
Push(.)
//Rotate entire stack to the right with the rightmost looping around to the left
/datum/stack/proc/RotateRight()
if(is_empty())
return 0
. = stack[stack.len]
stack.Cut(stack.len,0)
stack.Insert(1,.)
/datum/stack/proc/Copy()
var/datum/stack/S=new()
S.stack = stack.Copy()
S.max_elements = max_elements
return S
/datum/stack/proc/Clear()
stack.Cut()
+49
View File
@@ -0,0 +1,49 @@
#define MC_TICK_CHECK ( world.tick_usage > CURRENT_TICKLIMIT ? pause() : 0 )
// Used to smooth out costs to try and avoid oscillation.
#define MC_AVERAGE_FAST(average, current) (0.7 * (average) + 0.3 * (current))
#define MC_AVERAGE(average, current) (0.8 * (average) + 0.2 * (current))
#define MC_AVERAGE_SLOW(average, current) (0.9 * (average) + 0.1 * (current))
#define NEW_SS_GLOBAL(varname) if(varname != src){if(istype(varname)){Recover();qdel(varname);}varname = src;}
#define START_PROCESSING(Processor, Datum) if (!Datum.isprocessing) Datum.isprocessing = 1;Processor.processing += Datum
#define STOP_PROCESSING(Processor, Datum) if (Datum.isprocessing) Datum.isprocessing = 0;Processor.processing -= Datum
//SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier)
//subsystem should fire during pre-game lobby.
#define SS_FIRE_IN_LOBBY 1
//subsystem does not initialize.
#define SS_NO_INIT 2
//subsystem does not fire.
// (like can_fire = 0, but keeps it from getting added to the processing subsystems list)
// (Requires a MC restart to change)
#define SS_NO_FIRE 4
//subsystem only runs on spare cpu (after all non-background subsystems have ran that tick)
// SS_BACKGROUND has its own priority bracket
#define SS_BACKGROUND 8
//subsystem does not tick check, and should not run unless there is enough time (or its running behind (unless background))
#define SS_NO_TICK_CHECK 16
//Treat wait as a tick count, not DS, run every wait ticks.
// (also forces it to run first in the tick, above even SS_NO_TICK_CHECK subsystems)
// (implies SS_FIRE_IN_LOBBY because of how it works)
// (overrides SS_BACKGROUND)
// This is designed for basically anything that works as a mini-mc (like SStimer)
#define SS_TICKER 32
//keep the subsystem's timing on point by firing early if it fired late last fire because of lag
// ie: if a 20ds subsystem fires say 5 ds late due to lag or what not, its next fire would be in 15ds, not 20ds.
#define SS_KEEP_TIMING 64
//Calculate its next fire after its fired.
// (IE: if a 5ds wait SS takes 2ds to run, its next fire should be 5ds away, not 3ds like it normally would be)
// This flag overrides SS_KEEP_TIMING
#define SS_POST_FIRE_TIMING 128
//Timing subsystem
#define GLOBAL_PROC "some_magic_bullshit"
+14
View File
@@ -0,0 +1,14 @@
/*
This folder is full of #define statements. They are similar to constants,
but must come before any code that references them, and they do not take up
memory the way constants do.
The values in this folder are NOT options. They are not for hosts to play with.
Some of the values are arbitrary and only need to be different from similar constants;
for example, the genetic mutation numbers in genetics.dm mean nothing, but MUST be distinct.
It is wise not to touch them unless you understand what they do, where they're used,
and most importantly,
how to undo your changes if you screw it up.
- Sayu
*/
+38
View File
@@ -0,0 +1,38 @@
//A set of constants used to determine which type of mute an admin wishes to apply:
//Please read and understand the muting/automuting stuff before changing these. MUTE_IC_AUTO etc = (MUTE_IC << 1)
//Therefore there needs to be a gap between the flags for the automute flags
#define MUTE_IC 1
#define MUTE_OOC 2
#define MUTE_PRAY 4
#define MUTE_ADMINHELP 8
#define MUTE_DEADCHAT 16
#define MUTE_ALL 31
//Some constants for DB_Ban
#define BANTYPE_PERMA 1
#define BANTYPE_TEMP 2
#define BANTYPE_JOB_PERMA 3
#define BANTYPE_JOB_TEMP 4
#define BANTYPE_ANY_FULLBAN 5 //used to locate stuff to unban.
#define BANTYPE_APPEARANCE 6
#define BANTYPE_ADMIN_PERMA 7
#define BANTYPE_ADMIN_TEMP 8
#define BANTYPE_ANY_JOB 9 //used to remove jobbans
//Please don't edit these values without speaking to Errorage first ~Carn
//Admin Permissions
#define R_BUILDMODE 1
#define R_ADMIN 2
#define R_BAN 4
#define R_FUN 8
#define R_SERVER 16
#define R_DEBUG 32
#define R_POSSESS 64
#define R_PERMISSIONS 128
#define R_STEALTH 256
#define R_REJUVINATE 512
#define R_VAREDIT 1024
#define R_SOUNDS 2048
#define R_SPAWN 4096
#define R_MAXPERMISSION 4096 //This holds the maximum value for a permission. It is used in iteration, so keep it updated.
+165
View File
@@ -0,0 +1,165 @@
#define FIRE_DAMAGE_MODIFIER 0.0215 //Higher values result in more external fire damage to the skin (default 0.0215)
#define AIR_DAMAGE_MODIFIER 2.025 //More means less damage from hot air scalding lungs, less = more damage. (default 2.025)
#define MOLES_CELLSTANDARD (ONE_ATMOSPHERE*CELL_VOLUME/(T20C*R_IDEAL_GAS_EQUATION)) //moles in a 2.5 m^3 cell at 101.325 Pa and 20 degC
#define M_CELL_WITH_RATIO (MOLES_CELLSTANDARD * 0.005)
#define O2STANDARD 0.21
#define N2STANDARD 0.79
#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%)
#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%)
//indices of values in gas lists. used by listmos.
#define MOLES 1
#define ARCHIVE 2
#define GAS_META 3
#define META_GAS_SPECIFIC_HEAT 1
#define META_GAS_NAME 2
#define META_GAS_OVERLAY 4
#define META_GAS_MOLES_VISIBLE 3
//stuff you should probably leave well alone!
//ATMOS
#define CELL_VOLUME 2500 //liters in a cell
#define BREATH_VOLUME 0.5 //liters in a normal breath
#define BREATH_PERCENTAGE (BREATH_VOLUME/CELL_VOLUME) //Amount of air to take a from a tile
#define HUMAN_NEEDED_OXYGEN (MOLES_CELLSTANDARD*BREATH_PERCENTAGE*0.16) //Amount of air needed before pass out/suffocation commences
#define NORMPIPERATE 30 //pipe-insulation rate divisor
#define HEATPIPERATE 8 //heat-exch pipe insulation
#define FLOWFRAC 0.99 //fraction of gas transfered per process
#define TANK_LEAK_PRESSURE (30.*ONE_ATMOSPHERE) //Tank starts leaking
#define TANK_RUPTURE_PRESSURE (35.*ONE_ATMOSPHERE) //Tank spills all contents into atmosphere
#define TANK_FRAGMENT_PRESSURE (40.*ONE_ATMOSPHERE) //Boom 3x3 base explosion
#define TANK_FRAGMENT_SCALE (6.*ONE_ATMOSPHERE) //+1 for each SCALE kPa aboe threshold
#define MINIMUM_AIR_RATIO_TO_SUSPEND 0.1 //Ratio of air that must move to/from a tile to reset group processing
#define MINIMUM_AIR_RATIO_TO_MOVE 0.001 //Minimum ratio of air that must move to/from a tile
#define MINIMUM_AIR_TO_SUSPEND (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_SUSPEND) //Minimum amount of air that has to move before a group processing can be suspended
#define MINIMUM_MOLES_DELTA_TO_MOVE (MOLES_CELLSTANDARD*MINIMUM_AIR_RATIO_TO_MOVE) //Either this must be active
#define EXCITED_GROUP_BREAKDOWN_CYCLES 4
#define EXCITED_GROUP_DISMANTLE_CYCLES 16
#define MINIMUM_TEMPERATURE_TO_MOVE (T20C+100) //or this (or both, obviously)
#define MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND 0.012
#define MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND 4 //Minimum temperature difference before group processing is suspended
#define MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER 0.5 //Minimum temperature difference before the gas temperatures are just set to be equal
#define MINIMUM_TEMPERATURE_FOR_SUPERCONDUCTION T20C+10
#define MINIMUM_TEMPERATURE_START_SUPERCONDUCTION T20C+200
#define FLOOR_HEAT_TRANSFER_COEFFICIENT 0.4
#define WALL_HEAT_TRANSFER_COEFFICIENT 0.0
#define DOOR_HEAT_TRANSFER_COEFFICIENT 0.0
#define SPACE_HEAT_TRANSFER_COEFFICIENT 0.2 //a hack to partly simulate radiative heat
#define OPEN_HEAT_TRANSFER_COEFFICIENT 0.4
#define WINDOW_HEAT_TRANSFER_COEFFICIENT 0.1 //a hack for now
//Must be between 0 and 1. Values closer to 1 equalize temperature faster
//Should not exceed 0.4 else strange heat flow occur
#define FIRE_MINIMUM_TEMPERATURE_TO_SPREAD 150+T0C
#define FIRE_MINIMUM_TEMPERATURE_TO_EXIST 100+T0C
#define FIRE_SPREAD_RADIOSITY_SCALE 0.85
#define FIRE_CARBON_ENERGY_RELEASED 500000 //Amount of heat released per mole of burnt carbon into the tile
#define FIRE_PLASMA_ENERGY_RELEASED 3000000 //Amount of heat released per mole of burnt plasma into the tile
#define FIRE_GROWTH_RATE 40000 //For small fires
#define CARBON_LIFEFORM_FIRE_RESISTANCE 200+T0C //Resistance to fire damage
#define CARBON_LIFEFORM_FIRE_DAMAGE 4 //Fire damage
//Plasma fire properties
#define OXYGEN_BURN_RATE_BASE 1.4
#define PLASMA_BURN_RATE_DELTA 9
#define PLASMA_MINIMUM_BURN_TEMPERATURE 100+T0C
#define PLASMA_UPPER_TEMPERATURE 1370+T0C
#define PLASMA_MINIMUM_OXYGEN_NEEDED 2
#define PLASMA_MINIMUM_OXYGEN_PLASMA_RATIO 30
#define PLASMA_OXYGEN_FULLBURN 10
#define MIN_PLASMA_DAMAGE 1
#define MAX_PLASMA_DAMAGE 10
#define MOLES_PLASMA_VISIBLE 0.5 //Moles in a standard cell after which plasma is visible
//Plasma fusion properties
#define PLASMA_BINDING_ENERGY 3000000
#define MAX_CARBON_EFFICENCY 9
#define PLASMA_FUSED_COEFFICENT 0.08
#define CARBON_CATALYST_COEFFICENT 0.01
#define FUSION_PURITY_THRESHOLD 0.9
// Pressure limits.
#define HAZARD_HIGH_PRESSURE 550 //This determins at what pressure the ultra-high pressure red icon is displayed. (This one is set as a constant)
#define WARNING_HIGH_PRESSURE 325 //This determins when the orange pressure icon is displayed (it is 0.7 * HAZARD_HIGH_PRESSURE)
#define WARNING_LOW_PRESSURE 50 //This is when the gray low pressure icon is displayed. (it is 2.5 * HAZARD_LOW_PRESSURE)
#define HAZARD_LOW_PRESSURE 20 //This is when the black ultra-low pressure icon is displayed. (This one is set as a constant)
#define TEMPERATURE_DAMAGE_COEFFICIENT 1.5 //This is used in handle_temperature_damage() for humans, and in reagents that affect body temperature. Temperature damage is multiplied by this amount.
#define BODYTEMP_AUTORECOVERY_DIVISOR 12 //This is the divisor which handles how much of the temperature difference between the current body temperature and 310.15K (optimal temperature) humans auto-regenerate each tick. The higher the number, the slower the recovery. This is applied each tick, so long as the mob is alive.
#define BODYTEMP_AUTORECOVERY_MINIMUM 10 //Minimum amount of kelvin moved toward 310.15K per tick. So long as abs(310.15 - bodytemp) is more than 50.
#define BODYTEMP_COLD_DIVISOR 6 //Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is lower than their body temperature. Make it lower to lose bodytemp faster.
#define BODYTEMP_HEAT_DIVISOR 6 //Similar to the BODYTEMP_AUTORECOVERY_DIVISOR, but this is the divisor which is applied at the stage that follows autorecovery. This is the divisor which comes into play when the human's loc temperature is higher than their body temperature. Make it lower to gain bodytemp faster.
#define BODYTEMP_COOLING_MAX 30 //The maximum number of degrees that your body can cool in 1 tick, when in a cold area.
#define BODYTEMP_HEATING_MAX 30 //The maximum number of degrees that your body can heat up in 1 tick, when in a hot area.
#define BODYTEMP_HEAT_DAMAGE_LIMIT 360.15 // The limit the human body can take before it starts taking damage from heat.
#define BODYTEMP_COLD_DAMAGE_LIMIT 260.15 // The limit the human body can take before it starts taking damage from coldness.
#define SPACE_HELM_MIN_TEMP_PROTECT 2.0 //what min_cold_protection_temperature is set to for space-helmet quality headwear. MUST NOT BE 0.
#define SPACE_HELM_MAX_TEMP_PROTECT 1500 //Thermal insulation works both ways /Malkevin
#define SPACE_SUIT_MIN_TEMP_PROTECT 2.0 //what min_cold_protection_temperature is set to for space-suit quality jumpsuits or suits. MUST NOT BE 0.
#define SPACE_SUIT_MAX_TEMP_PROTECT 1500
#define FIRE_SUIT_MIN_TEMP_PROTECT 60 //Cold protection for firesuits
#define FIRE_SUIT_MAX_TEMP_PROTECT 30000 //what max_heat_protection_temperature is set to for firesuit quality suits. MUST NOT BE 0.
#define FIRE_HELM_MIN_TEMP_PROTECT 60 //Cold protection for fire helmets
#define FIRE_HELM_MAX_TEMP_PROTECT 30000 //for fire helmet quality items (red and white hardhats)
#define FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT 35000 //what max_heat_protection_temperature is set to for firesuit quality suits. MUST NOT BE 0.
#define FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT 35000 //for fire helmet quality items (red and white hardhats)
#define HELMET_MIN_TEMP_PROTECT 160 //For normal helmets
#define HELMET_MAX_TEMP_PROTECT 600 //For normal helmets
#define ARMOR_MIN_TEMP_PROTECT 160 //For armor
#define ARMOR_MAX_TEMP_PROTECT 600 //For armor
#define GLOVES_MIN_TEMP_PROTECT 2.0 //For some gloves (black and)
#define GLOVES_MAX_TEMP_PROTECT 1500 //For some gloves
#define SHOES_MIN_TEMP_PROTECT 2.0 //For gloves
#define SHOES_MAX_TEMP_PROTECT 1500 //For gloves
#define PRESSURE_DAMAGE_COEFFICIENT 4 //The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE
#define MAX_HIGH_PRESSURE_DAMAGE 4 //This used to be 20... I got this much random rage for some retarded decision by polymorph?! Polymorph now lies in a pool of blood with a katana jammed in his spleen. ~Errorage --PS: The katana did less than 20 damage to him :(
#define LOW_PRESSURE_DAMAGE 2 //The amounb of damage someone takes when in a low pressure area (The pressure threshold is so low that it doesn't make sense to do any calculations, so it just applies this flat value).
#define COLD_SLOWDOWN_FACTOR 20 //Humans are slowed by the difference between bodytemp and BODYTEMP_COLD_DAMAGE_LIMIT divided by this
// Atmos pipe limits
#define MAX_OUTPUT_PRESSURE 4500 // (kPa) What pressure pumps and powered equipment max out at.
#define MAX_TRANSFER_RATE 200 // (L/s) Maximum speed powered equipment can work at.
//Atmos machinery pipenet stuff
// used for device_type vars; used by DEVICE_TYPE_LOOP
#define UNARY 1
#define BINARY 2
#define TRINARY 3
#define QUATERNARY 4
// this is the standard for loop used by all sorts of atmos machinery procs
#define DEVICE_TYPE_LOOP var/I in 1 to device_type
// defines for the various machinery lists
// NODE_I, AIR_I, PARENT_I are used within DEVICE_TYPE_LOOP
// nodes list - all atmos machinery
#define NODE1 nodes[1]
#define NODE2 nodes[2]
#define NODE3 nodes[3]
#define NODE4 nodes[4]
#define NODE_I nodes[I]
// airs list - components only
#define AIR1 airs[1]
#define AIR2 airs[2]
#define AIR3 airs[3]
#define AIR_I airs[I]
// parents list - components only
#define PARENT1 parents[1]
#define PARENT2 parents[2]
#define PARENT3 parents[3]
#define PARENT_I parents[I]
//Tanks
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
#define TANK_MIN_RELEASE_PRESSURE 0
#define TANK_DEFAULT_RELEASE_PRESSURE 16
+26
View File
@@ -0,0 +1,26 @@
//Bot defines, placed here so they can be read by other things!
#define BOT_STEP_DELAY 4 //Delay between movemements
#define BOT_STEP_MAX_RETRIES 5 //Maximum times a bot will retry to step from its position
#define DEFAULT_SCAN_RANGE 7 //default view range for finding targets.
//Mode defines
#define BOT_IDLE 0 // idle
#define BOT_HUNT 1 // found target, hunting
#define BOT_PREP_ARREST 2 // at target, preparing to arrest
#define BOT_ARREST 3 // arresting target
#define BOT_START_PATROL 4 // start patrol
#define BOT_PATROL 5 // patrolling
#define BOT_SUMMON 6 // summoned by PDA
#define BOT_CLEANING 7 // cleaning (cleanbots)
#define BOT_REPAIRING 8 // repairing hull breaches (floorbots)
#define BOT_MOVING 9 // for clean/floor/med bots, when moving.
#define BOT_HEALING 10 // healing people (medbots)
#define BOT_RESPONDING 11 // responding to a call from the AI
#define BOT_DELIVER 12 // moving to deliver
#define BOT_GO_HOME 13 // returning to home
#define BOT_BLOCKED 14 // blocked
#define BOT_NAV 15 // computing navigation
#define BOT_WAIT_FOR_NAV 16 // waiting for nav computation
#define BOT_NO_ROUTE 17 // no destination beacon found (or no route)
+134
View File
@@ -0,0 +1,134 @@
//ITEM INVENTORY SLOT BITMASKS
#define SLOT_OCLOTHING 1
#define SLOT_ICLOTHING 2
#define SLOT_GLOVES 4
#define SLOT_EYES 8
#define SLOT_EARS 16
#define SLOT_MASK 32
#define SLOT_HEAD 64
#define SLOT_FEET 128
#define SLOT_ID 256
#define SLOT_BELT 512
#define SLOT_BACK 1024
#define SLOT_POCKET 2048 //this is to allow items with a w_class of 3 or 4 to fit in pockets.
#define SLOT_DENYPOCKET 4096 //this is to deny items with a w_class of 2 or 1 to fit in pockets.
//SLOTS
#define slot_back 1
#define slot_wear_mask 2
#define slot_handcuffed 3
#define slot_l_hand 4
#define slot_r_hand 5
#define slot_belt 6
#define slot_wear_id 7
#define slot_ears 8
#define slot_glasses 9
#define slot_gloves 10
#define slot_head 11
#define slot_shoes 12
#define slot_wear_suit 13
#define slot_w_uniform 14
#define slot_l_store 15
#define slot_r_store 16
#define slot_s_store 17
#define slot_in_backpack 18
#define slot_legcuffed 19
#define slot_drone_storage 20
#define slots_amt 20 // Keep this up to date!
//I hate that this has to exist
/proc/slotdefine2slotbit(slotdefine) //Keep this up to date with the value of SLOT BITMASKS and SLOTS (the two define sections above)
. = 0
switch(slotdefine)
if(slot_back)
. = SLOT_BACK
if(slot_wear_mask)
. = SLOT_MASK
if(slot_belt)
. = SLOT_BELT
if(slot_wear_id)
. = SLOT_ID
if(slot_ears)
. = SLOT_EARS
if(slot_glasses)
. = SLOT_EYES
if(slot_gloves)
. = SLOT_GLOVES
if(slot_head)
. = SLOT_HEAD
if(slot_shoes)
. = SLOT_FEET
if(slot_wear_suit)
. = SLOT_OCLOTHING
if(slot_w_uniform)
. = SLOT_ICLOTHING
if(slot_l_store, slot_r_store)
. = SLOT_POCKET
//Bit flags for the flags_inv variable, which determine when a piece of clothing hides another. IE a helmet hiding glasses.
#define HIDEGLOVES 1
#define HIDESUITSTORAGE 2
#define HIDEJUMPSUIT 4 //these first four are only used in exterior suits
#define HIDESHOES 8
#define HIDEMASK 16 //these last six are only used in masks and headgear.
#define HIDEEARS 32 // (ears means headsets and such)
#define HIDEEYES 64 // Whether eyes and glasses are hidden
#define HIDEFACE 128 // Whether we appear as unknown.
#define HIDEHAIR 256
#define HIDEFACIALHAIR 512
//Cant seem to find a mob bitflags area other than the powers one
// bitflags for clothing parts - also used for limbs
#define HEAD 1
#define CHEST 2
#define GROIN 4
#define LEG_LEFT 8
#define LEG_RIGHT 16
#define LEGS 24
#define FOOT_LEFT 32
#define FOOT_RIGHT 64
#define FEET 96
#define ARM_LEFT 128
#define ARM_RIGHT 256
#define ARMS 384
#define HAND_LEFT 512
#define HAND_RIGHT 1024
#define HANDS 1536
#define FULL_BODY 2047
// bitflags for the percentual amount of protection a piece of clothing which covers the body part offers.
// Used with human/proc/get_heat_protection() and human/proc/get_cold_protection()
// The values here should add up to 1.
// Hands and feet have 2.5%, arms and legs 7.5%, each of the torso parts has 15% and the head has 30%
#define THERMAL_PROTECTION_HEAD 0.3
#define THERMAL_PROTECTION_CHEST 0.15
#define THERMAL_PROTECTION_GROIN 0.15
#define THERMAL_PROTECTION_LEG_LEFT 0.075
#define THERMAL_PROTECTION_LEG_RIGHT 0.075
#define THERMAL_PROTECTION_FOOT_LEFT 0.025
#define THERMAL_PROTECTION_FOOT_RIGHT 0.025
#define THERMAL_PROTECTION_ARM_LEFT 0.075
#define THERMAL_PROTECTION_ARM_RIGHT 0.075
#define THERMAL_PROTECTION_HAND_LEFT 0.025
#define THERMAL_PROTECTION_HAND_RIGHT 0.025
//flags for female outfits: How much the game can safely "take off" the uniform without it looking weird
#define NO_FEMALE_UNIFORM 0
#define FEMALE_UNIFORM_FULL 1
#define FEMALE_UNIFORM_TOP 2
//flags for covering body parts
#define GLASSESCOVERSEYES 1
#define MASKCOVERSEYES 2 // get rid of some of the other retardation in these flags
#define HEADCOVERSEYES 4 // feel free to realloc these numbers for other purposes
#define MASKCOVERSMOUTH 8 // on other items, these are just for mask/head
#define HEADCOVERSMOUTH 16
#define TINT_DARKENED 2 //Threshold of tint level to apply weld mask overlay
#define TINT_BLIND 3 //Threshold of tint level to obscure vision fully
+80
View File
@@ -0,0 +1,80 @@
//Damage things //TODO: merge these down to reduce on defines
//Way to waste perfectly good damagetype names (BRUTE) on this... If you were really worried about case sensitivity, you could have just used lowertext(damagetype) in the proc...
#define BRUTE "brute"
#define BURN "fire"
#define TOX "tox"
#define OXY "oxy"
#define CLONE "clone"
#define STAMINA "stamina"
#define STUN "stun"
#define WEAKEN "weaken"
#define PARALYZE "paralize"
#define IRRADIATE "irradiate"
#define STUTTER "stutter"
#define SLUR "slur"
#define EYE_BLUR "eye_blur"
#define DROWSY "drowsy"
#define JITTER "jitter"
//I hate adding defines like this but I'd much rather deal with bitflags than lists and string searches
#define BRUTELOSS 1
#define FIRELOSS 2
#define TOXLOSS 4
#define OXYLOSS 8
#define SHAME 16
//Bitflags defining which status effects could be or are inflicted on a mob
#define CANSTUN 1
#define CANWEAKEN 2
#define CANPARALYSE 4
#define CANPUSH 8
#define IGNORESLOWDOWN 16
#define GOTTAGOFAST 32
#define GOTTAGOREALLYFAST 64
#define GODMODE 4096
#define FAKEDEATH 8192 //Replaces stuff like changeling.changeling_fakedeath
#define DISFIGURED 16384 //I'll probably move this elsewhere if I ever get wround to writing a bitflag mob-damage system
#define XENO_HOST 32768 //Tracks whether we're gonna be a baby alien's mummy.
//Grab levels
#define GRAB_PASSIVE 0
#define GRAB_AGGRESSIVE 1
#define GRAB_NECK 2
#define GRAB_KILL 3
//Hostile Mob AI Status
#define AI_ON 1
#define AI_IDLE 2
#define AI_OFF 3
//Embedded objects
#define EMBEDDED_PAIN_CHANCE 15 //Chance for embedded objects to cause pain (damage user)
#define EMBEDDED_ITEM_FALLOUT 5 //Chance for embedded object to fall out (causing pain but removing the object)
#define EMBED_CHANCE 45 //Chance for an object to embed into somebody when thrown (if it's sharp)
#define EMBEDDED_PAIN_MULTIPLIER 2 //Coefficient of multiplication for the damage the item does while embedded (this*item.w_class)
#define EMBEDDED_FALL_PAIN_MULTIPLIER 5 //Coefficient of multiplication for the damage the item does when it falls out (this*item.w_class)
#define EMBEDDED_IMPACT_PAIN_MULTIPLIER 4 //Coefficient of multiplication for the damage the item does when it first embeds (this*item.w_class)
#define EMBED_THROWSPEED_THRESHOLD 4 //The minimum value of an item's throw_speed for it to embed (Unless it has embedded_ignore_throwspeed_threshold set to 1)
#define EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER 8 //Coefficient of multiplication for the damage the item does when removed without a surgery (this*item.w_class)
#define EMBEDDED_UNSAFE_REMOVAL_TIME 30 //A Time in ticks, total removal time = (this*item.w_class)
//Attack types for checking shields/hit reactions
#define MELEE_ATTACK 1
#define UNARMED_ATTACK 2
#define PROJECTILE_ATTACK 3
#define THROWN_PROJECTILE_ATTACK 4
//Gun Stuff
#define SAWN_INTACT 0
#define SAWN_OFF 1
#define WEAPON_LIGHT 0
#define WEAPON_MEDIUM 1
#define WEAPON_HEAVY 2
+42
View File
@@ -0,0 +1,42 @@
#define CONTRACT_POWER "power"
#define CONTRACT_WEALTH "wealth"
#define CONTRACT_PRESTIGE "prestige"
#define CONTRACT_MAGIC "magic"
#define CONTRACT_REVIVE "revive"
#define CONTRACT_KNOWLEDGE "knowledge"
#define CONTRACT_UNWILLING "unwilling"
#define BANE_SALT "salt"
#define BANE_LIGHT "light"
#define BANE_IRON "iron"
#define BANE_WHITECLOTHES "whiteclothes"
#define BANE_SILVER "silver"
#define BANE_HARVEST "harvest"
#define BANE_TOOLBOX "toolbox"
#define OBLIGATION_FOOD "food"
#define OBLIGATION_DRINK "drink"
#define OBLIGATION_GREET "greet"
#define OBLIGATION_PRESENCEKNOWN "presenceknown"
#define OBLIGATION_SAYNAME "sayname"
#define OBLIGATION_ANNOUNCEKILL "announcekill"
#define OBLIGATION_ANSWERTONAME "answername"
#define BAN_HURTWOMAN "hurtwoman"
#define BAN_CHAPEL "chapel"
#define BAN_HURTPRIEST "hurtpriest"
#define BAN_AVOIDWATER "avoidwater"
#define BAN_STRIKEUNCONCIOUS "strikeunconcious"
#define BAN_HURTLIZARD "hurtlizard"
#define BAN_HURTANIMAL "hurtanimal"
#define BANISH_WATER "water"
#define BANISH_COFFIN "coffin"
#define BANISH_FORMALDYHIDE "embalm"
#define BANISH_RUNES "runes"
#define BANISH_CANDLES "candles"
#define BANISH_DESTRUCTION "destruction"
#define BANISH_FUNERAL_GARB "funeral"
#define LORE 1
#define LAW 2
+4
View File
@@ -0,0 +1,4 @@
#define SUCCESSFUL_SPAWN 2
#define NOT_ENOUGH_PLAYERS 3
#define MAP_ERROR 4
#define WAITING_FOR_SOMETHING 5
+91
View File
@@ -0,0 +1,91 @@
/*
These defines are specific to the atom/flags bitmask
*/
#define ALL ~0 //For convenience.
#define NONE 0
//FLAGS BITMASK
#define STOPSPRESSUREDMAGE 1 //This flag is used on the flags variable for SUIT and HEAD items which stop pressure damage. Note that the flag 1 was previous used as ONBACK, so it is possible for some code to use (flags & 1) when checking if something can be put on your back. Replace this code with (inv_flags & SLOT_BACK) if you see it anywhere
//To successfully stop you taking all pressure damage you must have both a suit and head item with this flag.
#define NODROP 2 // This flag makes it so that an item literally cannot be removed at all, or at least that's how it should be. Only deleted.
#define NOBLUDGEON 4 // when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
#define MASKINTERNALS 8 // mask allows internals
#define HEAR 16 // This flag is what recursive_hear_check() uses to determine wether to add an item to the hearer list or not.
#define HANDSLOW 32 // If an item has this flag, it will slow you to carry it
#define CONDUCT 64 // conducts electricity (metal etc.)
#define ABSTRACT 128 // for all things that are technically items but used for various different stuff, made it 128 because it could conflict with other flags other way
#define NODECONSTRUCT 128 // For machines and structures that should not break into parts, eg, holodeck stuff
#define FPRINT 256 // takes a fingerprint
#define ON_BORDER 512 // item has priority to check when entering or leaving
#define EARBANGPROTECT 1024
#define NOSLIP 1024 //prevents from slipping on wet floors, in space etc (NOTE: flag shared with THICKMATERIAL for external suits and helmet)
#define OPENCONTAINER 4096 // is an open container for chemistry purposes
#define HEADBANGPROTECT 4096
// BLOCK_GAS_SMOKE_EFFECT only used in masks at the moment.
#define BLOCK_GAS_SMOKE_EFFECT 8192 // blocks the effect that chemical clouds would have on a mob --glasses, mask and helmets ONLY! (NOTE: flag shared with THICKMATERIAL)
#define THICKMATERIAL 8192 //prevents syringes, parapens and hypos if the external suit or helmet (if targeting head) has this flag. Example: space suits, biosuit, bombsuits, thick suits that cover your body. (NOTE: flag shared with BLOCK_GAS_SMOKE_EFFECT)
#define DROPDEL 16384 // When dropped, it calls qdel on itself
#define HOLOGRAM 32768 // HOlodeck shit should not be used in any fucking things
//turf-only flags
#define NOJAUNT 1
/*
These defines are used specifically with the atom/pass_flags bitmask
the atom/checkpass() proc uses them (tables will call movable atom checkpass(PASSTABLE) for example)
*/
//flags for pass_flags
#define PASSTABLE 1
#define PASSGLASS 2
#define PASSGRILLE 4
#define PASSBLOB 8
#define PASSMOB 16
#define LETPASSTHROW 32
//flags for species
#define MUTCOLORS 1
#define HAIR 2
#define FACEHAIR 3
#define EYECOLOR 4
#define LIPS 5
#define RESISTTEMP 6
#define RADIMMUNE 7
#define NOBREATH 8
#define NOGUNS 9
#define NOBLOOD 10
#define NOFIRE 11
#define VIRUSIMMUNE 12
#define PIERCEIMMUNE 13
#define NOTRANSSTING 14
#define MUTCOLORS_PARTSONLY 15 //Used if we want the mutant colour to be only used by mutant bodyparts. Don't combine this with MUTCOLORS, or it will be useless.
#define NODISMEMBER 16
#define NOHUNGER 17
#define NOCRITDAMAGE 18
#define NOZOMBIE 19
#define EASYDISMEMBER 20
#define EASYLIMBATTACHMENT 21
#define TOXINLOVER 22
#define FLYING 65536
/*
These defines are used specifically with the atom/movable/languages bitmask.
They are used in atom/movable/Hear() and atom/movable/say() to determine whether hearers can understand a message.
*/
#define HUMAN 1
#define MONKEY 2
#define ALIEN 4
#define ROBOT 8
#define SLIME 16
#define DRONE 32
#define SWARMER 64
#define RATVAR 128
// Flags for reagents
#define REAGENT_NOREACT 1
+105
View File
@@ -0,0 +1,105 @@
//Defines copying names of mutations in all cases, make sure to change this if you change mutation's name
#define HULK "Hulk"
#define XRAY "X Ray Vision"
#define COLDRES "Cold Resistance"
#define TK "Telekinesis"
#define NERVOUS "Nervousness"
#define EPILEPSY "Epilepsy"
#define MUTATE "Unstable DNA"
#define COUGH "Cough"
#define DWARFISM "Dwarfism"
#define CLOWNMUT "Clumsiness"
#define TOURETTES "Tourettes Syndrome"
#define DEAFMUT "Deafness"
#define BLINDMUT "Blindness"
#define RACEMUT "Monkified"
#define BADSIGHT "Near Sightness"
#define LASEREYES "Laser Eyes"
#define CHAMELEON "Chameleon"
#define WACKY "Wacky"
#define MUT_MUTE "Mute"
#define SMILE "Smile"
#define UNINTELLIGABLE "Unintelligable"
#define SWEDISH "Swedish"
#define CHAV "Chav"
#define ELVIS "Elvis"
#define UI_CHANGED "ui changed"
#define UE_CHANGED "ue changed"
#define CHAMELEON_MUTATION_DEFAULT_TRANSPARENCY 204
// String identifiers for associative list lookup
//Types of usual mutations
#define POSITIVE 1
#define NEGATIVE 2
#define MINOR_NEGATIVE 3
//Mutations that cant be taken from genetics and are not in SE
#define NON_SCANNABLE -1
// Extra powers:
#define LASER 9 // harm intent - click anywhere to shoot lasers from eyes
#define HEAL 10 // healing people with hands
#define SHADOW 11 // shadow teleportation (create in/out portals anywhere) (25%)
#define SCREAM 12 // supersonic screaming (25%)
#define EXPLOSIVE 13 // exploding on-demand (15%)
#define REGENERATION 14 // superhuman regeneration (30%)
#define REPROCESSOR 15 // eat anything (50%)
#define SHAPESHIFTING 16 // take on the appearance of anything (40%)
#define PHASING 17 // ability to phase through walls (40%)
#define SHIELD 18 // shielding from all projectile attacks (30%)
#define SHOCKWAVE 19 // attack a nearby tile and cause a massive shockwave, knocking most people on their asses (25%)
#define ELECTRICITY 20 // ability to shoot electric attacks (15%)
//DNA - Because fuck you and your magic numbers being all over the codebase.
#define DNA_BLOCK_SIZE 3
#define DNA_UNI_IDENTITY_BLOCKS 7
#define DNA_HAIR_COLOR_BLOCK 1
#define DNA_FACIAL_HAIR_COLOR_BLOCK 2
#define DNA_SKIN_TONE_BLOCK 3
#define DNA_EYE_COLOR_BLOCK 4
#define DNA_GENDER_BLOCK 5
#define DNA_FACIAL_HAIR_STYLE_BLOCK 6
#define DNA_HAIR_STYLE_BLOCK 7
#define DNA_STRUC_ENZYMES_BLOCKS 19
#define DNA_UNIQUE_ENZYMES_LEN 32
//Transformation proc stuff
#define TR_KEEPITEMS 1
#define TR_KEEPVIRUS 2
#define TR_KEEPDAMAGE 4
#define TR_HASHNAME 8 // hashing names (e.g. monkey(e34f)) (only in monkeyize)
#define TR_KEEPIMPLANTS 16
#define TR_KEEPSE 32 // changelings shouldn't edit the DNA's SE when turning into a monkey
#define TR_DEFAULTMSG 64
#define TR_KEEPSRC 128
#define TR_KEEPORGANS 256
//Organ stuff, It's here because "Genetics" is the most relevant file for organs and bodyparts
#define ORGAN_ORGANIC 1
#define ORGAN_ROBOTIC 2
//Nutrition levels for humans. No idea where else to put it
#define NUTRITION_LEVEL_FAT 600
#define NUTRITION_LEVEL_FULL 550
#define NUTRITION_LEVEL_WELL_FED 450
#define NUTRITION_LEVEL_FED 350
#define NUTRITION_LEVEL_HUNGRY 250
#define NUTRITION_LEVEL_STARVING 150
#define CLONER_FRESH_CLONE "fresh"
#define CLONER_MATURE_CLONE "mature"
//Blood levels
#define BLOOD_VOLUME_MAXIMUM 2000
#define BLOOD_VOLUME_SLIME_SPLIT 1120
#define BLOOD_VOLUME_NORMAL 560
#define BLOOD_VOLUME_SAFE 501
#define BLOOD_VOLUME_OKAY 336
#define BLOOD_VOLUME_BAD 224
#define BLOOD_VOLUME_SURVIVE 122
+47
View File
@@ -0,0 +1,47 @@
// for secHUDs and medHUDs and variants. The number is the location of the image on the list hud_list
// note: if you add more HUDs, even for non-human atoms, make sure to use unique numbers for the defines!
// /datum/atom_hud expects these to be unique
// these need to be strings in order to make them associative lists
#define HEALTH_HUD "1" // dead, alive, sick, health status
#define STATUS_HUD "2" // a simple line rounding the mob's number health
#define ID_HUD "3" // the job asigned to your ID
#define WANTED_HUD "4" // wanted, released, parroled, security status
#define IMPLOYAL_HUD "5" // loyality implant
#define IMPCHEM_HUD "6" // chemical implant
#define IMPTRACK_HUD "7" // tracking implant
#define DIAG_STAT_HUD "8" // Silicon/Mech Status
#define DIAG_HUD "9" // Silicon health bar
#define DIAG_BATT_HUD "10"// Borg/Mech power meter
#define DIAG_MECH_HUD "11"// Mech health bar
#define DIAG_BOT_HUD "12"// Bot HUDs
//for antag huds. these are used at the /mob level
#define ANTAG_HUD "13"
//data HUD (medhud, sechud) defines
//Don't forget to update human/New() if you change these!
#define DATA_HUD_SECURITY_BASIC 1
#define DATA_HUD_SECURITY_ADVANCED 2
#define DATA_HUD_MEDICAL_BASIC 3
#define DATA_HUD_MEDICAL_ADVANCED 4
#define DATA_HUD_DIAGNOSTIC 5
//antag HUD defines
#define ANTAG_HUD_CULT 6
#define ANTAG_HUD_REV 7
#define ANTAG_HUD_OPS 8
#define ANTAG_HUD_WIZ 9
#define ANTAG_HUD_SHADOW 10
#define ANTAG_HUD_HOG_BLUE 11
#define ANTAG_HUD_HOG_RED 12
#define ANTAG_HUD_TRAITOR 13
#define ANTAG_HUD_NINJA 14
#define ANTAG_HUD_CHANGELING 15
#define ANTAG_HUD_ABDUCTOR 16
#define ANTAG_HUD_DEVIL 17
#define ANTAG_HUD_SINTOUCHED 18
#define ANTAG_HUD_SOULLESS 19
#define ANTAG_HUD_CLOCKWORK 20
// Notification action types
#define NOTIFY_JUMP "jump"
#define NOTIFY_ATTACK "attack"
#define NOTIFY_ORBIT "orbit"
+100
View File
@@ -0,0 +1,100 @@
// simple is_type and similar inline helpers
#define islist(L) (istype(L,/list))
#define in_range(source, user) (get_dist(source, user) <= 1)
// MOB HELPERS
#define ishuman(A) (istype(A, /mob/living/carbon/human))
// Human sub-species
#define isabductor(A) (is_species(A, /datum/species/abductor))
#define isgolem(A) (is_species(A, /datum/species/golem))
#define islizard(A) (is_species(A, /datum/species/lizard))
#define isplasmaman(A) (is_species(A, /datum/species/plasmaman))
#define ispodperson(A) (is_species(A, /datum/species/podperson))
#define isflyperson(A) (is_species(A, /datum/species/fly))
#define isslimeperson(A) (is_species(A, /datum/species/jelly/slime))
#define iszombie(A) (is_species(A, /datum/species/zombie))
#define ishumanbasic(A) (is_species(A, /datum/species/human))
#define ismonkey(A) (istype(A, /mob/living/carbon/monkey))
#define isbrain(A) (istype(A, /mob/living/carbon/brain))
#define isalien(A) (istype(A, /mob/living/carbon/alien))
#define isalienadult(A) (istype(A, /mob/living/carbon/alien/humanoid))
#define islarva(A) (istype(A, /mob/living/carbon/alien/larva))
#define isslime(A) (istype(A, /mob/living/simple_animal/slime))
#define isrobot(A) (istype(A, /mob/living/silicon/robot))
#define isanimal(A) (istype(A, /mob/living/simple_animal))
#define iscorgi(A) (istype(A, /mob/living/simple_animal/pet/dog/corgi))
#define iscrab(A) (istype(A, /mob/living/simple_animal/crab))
#define iscat(A) (istype(A, /mob/living/simple_animal/pet/cat))
#define ismouse(A) (istype(A, /mob/living/simple_animal/mouse))
#define isconstruct(A) (istype(A, /mob/living/simple_animal/hostile/construct))
#define isclockmob(A) (istype(A, /mob/living/simple_animal/hostile/clockwork))
#define isshade(A) (istype(A, /mob/living/simple_animal/shade))
#define isbear(A) (istype(A, /mob/living/simple_animal/hostile/bear))
#define iscarp(A) (istype(A, /mob/living/simple_animal/hostile/carp))
#define isclown(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/clown))
#define isAI(A) (istype(A, /mob/living/silicon/ai))
#define ispAI(A) (istype(A, /mob/living/silicon/pai))
#define iscarbon(A) (istype(A, /mob/living/carbon))
#define issilicon(A) (istype(A, /mob/living/silicon))
#define isliving(A) (istype(A, /mob/living))
#define isobserver(A) (istype(A, /mob/dead/observer))
#define isnewplayer(A) (istype(A, /mob/new_player))
#define isovermind(A) (istype(A, /mob/camera/blob))
#define isdrone(A) (istype(A, /mob/living/simple_animal/drone))
#define isswarmer(A) (istype(A, /mob/living/simple_animal/hostile/swarmer))
#define isguardian(A) (istype(A, /mob/living/simple_animal/hostile/guardian))
#define islimb(A) (istype(A, /obj/item/bodypart))
#define isbot(A) (istype(A, /mob/living/simple_animal/bot))
#define ismovableatom(A) (istype(A, /atom/movable))
#define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs
// ASSEMBLY HELPERS
#define isassembly(O) (istype(O, /obj/item/device/assembly))
#define isigniter(O) (istype(O, /obj/item/device/assembly/igniter))
#define isinfared(O) (istype(O, /obj/item/device/assembly/infra))
#define isprox(O) (istype(O, /obj/item/device/assembly/prox_sensor))
#define issignaler(O) (istype(O, /obj/item/device/assembly/signaler))
#define istimer(O) (istype(O, /obj/item/device/assembly/timer))
+57
View File
@@ -0,0 +1,57 @@
//Defines for atom layers
//KEEP THESE IN A NICE ACSCENDING ORDER, PLEASE
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
#define ABOVE_OPEN_TURF_LAYER 2.01
#define CLOSED_TURF_LAYER 2.05
#define ABOVE_NORMAL_TURF_LAYER 2.08
#define LATTICE_LAYER 2.2
#define DISPOSAL_PIPE_LAYER 2.3
#define GAS_PIPE_LAYER 2.35
#define WIRE_LAYER 2.4
#define WIRE_TERMINAL_LAYER 2.45
#define LOW_OBJ_LAYER 2.5
#define BELOW_OPEN_DOOR_LAYER 2.6
#define OPEN_DOOR_LAYER 2.7
#define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible
#define TABLE_LAYER 2.8
#define BELOW_OBJ_LAYER 2.9
#define LOW_ITEM_LAYER 2.95
//#define OBJ_LAYER 3 //For easy recordkeeping; this is a byond define
#define CLOSED_DOOR_LAYER 3.1
#define CLOSED_FIREDOOR_LAYER 3.11
#define ABOVE_OBJ_LAYER 3.2
#define ABOVE_WINDOW_LAYER 3.3
#define SIGN_LAYER 3.4
#define HIGH_OBJ_LAYER 3.5
#define BELOW_MOB_LAYER 3.7
#define LYING_MOB_LAYER 3.8
//#define MOB_LAYER 4 //For easy recordkeeping; this is a byond define
#define ABOVE_MOB_LAYER 4.1
#define WALL_OBJ_LAYER 4.25
#define EDGED_TURF_LAYER 4.3
#define ON_EDGED_TURF_LAYER 4.35
#define LARGE_MOB_LAYER 4.4
#define ABOVE_ALL_MOB_LAYER 4.5
#define SPACEVINE_LAYER 4.8
#define SPACEVINE_MOB_LAYER 4.9
//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
#define RIPPLE_LAYER 5.1
#define GHOST_LAYER 6
#define AREA_LAYER 10
#define MASSIVE_OBJ_LAYER 11
#define POINT_LAYER 12
#define LIGHTING_LAYER 15
//HUD layer defines
#define FLASH_LAYER 17.9
#define FULLSCREEN_LAYER 18
#define UI_DAMAGE_LAYER 18.1
#define BLIND_LAYER 18.2
#define CRIT_LAYER 18.3
#define HUD_LAYER 19
#define ABOVE_HUD_LAYER 19.1
+24
View File
@@ -0,0 +1,24 @@
// channel numbers for power
#define EQUIP 1
#define LIGHT 2
#define ENVIRON 3
#define TOTAL 4 //for total power used only
#define STATIC_EQUIP 5
#define STATIC_LIGHT 6
#define STATIC_ENVIRON 7
//bitflags for door switches.
#define OPEN 1
#define IDSCAN 2
#define BOLTS 4
#define SHOCK 8
#define SAFE 16
//used in design to specify which machine can build it
#define IMPRINTER 1 //For circuits. Uses glass/chemicals.
#define PROTOLATHE 2 //New stuff. Uses glass/metal/chemicals
#define AUTOLATHE 4 //Uses glass/metal only.
#define CRAFTLATHE 8 //Uses fuck if I know. For use eventually.
#define MECHFAB 16 //Remember, objects utilising this flag should have construction_time and construction_cost vars.
//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable.
+17
View File
@@ -0,0 +1,17 @@
#define PI 3.1415
#define SPEED_OF_LIGHT 3e8 //not exact but hey!
#define SPEED_OF_LIGHT_SQ 9e+16
#define INFINITY 1e31 //closer then enough
//atmos
#define R_IDEAL_GAS_EQUATION 8.31 //kPa*L/(K*mol)
#define ONE_ATMOSPHERE 101.325 //kPa
#define T0C 273.15 // 0degC
#define T20C 293.15 // 20degC
#define TCMB 2.7 // -270.3degC
//"fancy" math for calculating time in ms from tick_usage percentage and the length of ticks
//percent_of_tick_used * (ticklag * 100(to convert to ms)) / 100(percent ratio)
//collapsed to percent_of_tick_used * tick_lag
#define TICK_DELTA_TO_MS(percent_of_tick_used) ((percent_of_tick_used) * world.tick_lag)
#define TICK_USAGE_TO_MS(starting_tickusage) (TICK_DELTA_TO_MS(world.tick_usage-starting_tickusage))
+460
View File
@@ -0,0 +1,460 @@
#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day
#define JANUARY 1
#define FEBRUARY 2
#define MARCH 3
#define APRIL 4
#define MAY 5
#define JUNE 6
#define JULY 7
#define AUGUST 8
#define SEPTEMBER 9
#define OCTOBER 10
#define NOVEMBER 11
#define DECEMBER 12
//Select holiday names -- If you test for a holiday in the code, make the holiday's name a define and test for that instead
#define NEW_YEAR "New Year"
#define VALENTINES "Valentine's Day"
#define APRIL_FOOLS "April Fool's Day"
#define EASTER "Easter"
#define HALLOWEEN "Halloween"
#define CHRISTMAS "Christmas"
#define FRIDAY_13TH "Friday the 13th"
//Human Overlays Indexes/////////
#define MUTATIONS_LAYER 26 //mutations. Tk headglows, cold resistance glow, etc
#define BODY_BEHIND_LAYER 25 //certain mutantrace features (tail when looking south) that must appear behind the body parts
#define BODYPARTS_LAYER 24 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag
#define BODY_ADJ_LAYER 23 //certain mutantrace features (snout, body markings) that must appear above the body parts
#define BODY_LAYER 22 //underwear, undershirts, socks, eyes, lips(makeup)
#define FRONT_MUTATIONS_LAYER 21 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes)
#define DAMAGE_LAYER 20 //damage indicators (cuts and burns)
#define UNIFORM_LAYER 19
#define ID_LAYER 18
#define SHOES_LAYER 17
#define GLOVES_LAYER 16
#define EARS_LAYER 15
#define SUIT_LAYER 14
#define GLASSES_LAYER 13
#define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 11
#define BACK_LAYER 10
#define HAIR_LAYER 9 //TODO: make part of head layer?
#define FACEMASK_LAYER 8
#define HEAD_LAYER 7
#define HANDCUFF_LAYER 6
#define LEGCUFF_LAYER 5
#define L_HAND_LAYER 4
#define R_HAND_LAYER 3 //Having the two hands seperate seems rather silly, merge them together? It'll allow for code to be reused on mobs with arbitarily many hands
#define BODY_FRONT_LAYER 2
#define FIRE_LAYER 1 //If you're on fire
#define TOTAL_LAYERS 26 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_;
//Human Overlay Index Shortcuts for alternate_worn_layer, layers
//Because I *KNOW* somebody will think layer+1 means "above"
//IT DOESN'T OK, IT MEANS "UNDER"
#define UNDER_BODY_BEHIND_LAYER BODY_BEHIND_LAYER+1
#define UNDER_BODY_LAYER BODY_LAYER+1
#define UNDER_BODY_ADJ_LAYER BODY_ADJ_LAYER+1
#define UNDER_MUTATIONS_LAYER MUTATIONS_LAYER+1
#define UNDER_BODYPARTS_LAYER BODYPARTS_LAYER+1
#define UNDER_DAMAGE_LAYER DAMAGE_LAYER+1
#define UNDER_UNIFORM_LAYER UNIFORM_LAYER+1
#define UNDER_ID_LAYER ID_LAYER+1
#define UNDER_SHOES_LAYER SHOES_LAYER+1
#define UNDER_GLOVES_LAYER GLOVES_LAYER+1
#define UNDER_EARS_LAYER EARS_LAYER+1
#define UNDER_SUIT_LAYER SUIT_LAYER+1
#define UNDER_GLASSES_LAYER GLASSES_LAYER+1
#define UNDER_BELT_LAYER BELT_LAYER+1
#define UNDER_SUIT_STORE_LAYER SUIT_STORE_LAYER+1
#define UNDER_BACK_LAYER BACK_LAYER+1
#define UNDER_HAIR_LAYER HAIR_LAYER+1
#define UNDER_FACEMASK_LAYER FACEMASK_LAYER+1
#define UNDER_HEAD_LAYER HEAD_LAYER+1
#define UNDER_HANDCUFF_LAYER HANDCUFF_LAYER+1
#define UNDER_LEGCUFF_LAYER LEGCUFF_LAYER+1
#define UNDER_L_HAND_LAYER L_HAND_LAYER+1
#define UNDER_R_HAND_LAYER R_HAND_LAYER+1
#define UNDER_BODY_FRONT_LAYER BODY_FRONT_LAYER+1
#define UNDER_FIRE_LAYER FIRE_LAYER+1
//AND -1 MEANS "ABOVE", OK?, OK!?!
#define ABOVE_BODY_BEHIND_LAYER BODY_BEHIND_LAYER-1
#define ABOVE_BODY_LAYER BODY_LAYER-1
#define ABOVE_BODY_ADJ_LAYER BODY_ADJ_LAYER-1
#define ABOVE_MUTATIONS_LAYER MUTATIONS_LAYER-1
#define ABOVE_BODYPARTS_LAYER BODYPARTS_LAYER-1
#define ABOVE_DAMAGE_LAYER DAMAGE_LAYER-1
#define ABOVE_UNIFORM_LAYER UNIFORM_LAYER-1
#define ABOVE_ID_LAYER ID_LAYER-1
#define ABOVE_SHOES_LAYER SHOES_LAYER-1
#define ABOVE_GLOVES_LAYER GLOVES_LAYER-1
#define ABOVE_EARS_LAYER EARS_LAYER-1
#define ABOVE_SUIT_LAYER SUIT_LAYER-1
#define ABOVE_GLASSES_LAYER GLASSES_LAYER-1
#define ABOVE_BELT_LAYER BELT_LAYER-1
#define ABOVE_SUIT_STORE_LAYER SUIT_STORE_LAYER-1
#define ABOVE_BACK_LAYER BACK_LAYER-1
#define ABOVE_HAIR_LAYER HAIR_LAYER-1
#define ABOVE_FACEMASK_LAYER FACEMASK_LAYER-1
#define ABOVE_HEAD_LAYER HEAD_LAYER-1
#define ABOVE_HANDCUFF_LAYER HANDCUFF_LAYER-1
#define ABOVE_LEGCUFF_LAYER LEGCUFF_LAYER-1
#define ABOVE_L_HAND_LAYER L_HAND_LAYER-1
#define ABOVE_R_HAND_LAYER R_HAND_LAYER-1
#define ABOVE_BODY_FRONT_LAYER BODY_FRONT_LAYER-1
#define ABOVE_FIRE_LAYER FIRE_LAYER-1
//Security levels
#define SEC_LEVEL_GREEN 0
#define SEC_LEVEL_BLUE 1
#define SEC_LEVEL_RED 2
#define SEC_LEVEL_DELTA 3
//some arbitrary defines to be used by self-pruning global lists. (see master_controller)
#define PROCESS_KILL 26 //Used to trigger removal from a processing list
// Cargo-related stuff.
#define MANIFEST_ERROR_CHANCE 5
#define MANIFEST_ERROR_NAME 1
#define MANIFEST_ERROR_CONTENTS 2
#define MANIFEST_ERROR_ITEM 4
#define TRANSITIONEDGE 7 //Distance from edge to move to another z-level
//HUD styles. Please ensure HUD_VERSIONS is the same as the maximum index. Index order defines how they are cycled in F12.
#define HUD_STYLE_STANDARD 1
#define HUD_STYLE_REDUCED 2
#define HUD_STYLE_NOHUD 3
#define HUD_VERSIONS 3 //used in show_hud()
//1 = standard hud
//2 = reduced hud (just hands and intent switcher)
//3 = no hud (for screenshots)
#define MINERAL_MATERIAL_AMOUNT 2000
//The amount of materials you get from a sheet of mineral like iron/diamond/glass etc
#define MAX_STACK_SIZE 50
//The maximum size of a stack object.
#define CLICK_CD_MELEE 8
#define CLICK_CD_RANGE 4
#define CLICK_CD_BREAKOUT 100
#define CLICK_CD_HANDCUFFED 10
#define CLICK_CD_RESIST 20
#define CLICK_CD_GRABBING 10
//click cooldowns, in tenths of a second
#define BE_CLOSE 1 //in the case of a silicon, to select if they need to be next to the atom
#define NO_DEXTERY 1 //if other mobs (monkeys, aliens, etc) can use this
//used by canUseTopic()
//Sizes of mobs, used by mob/living/var/mob_size
#define MOB_SIZE_TINY 0
#define MOB_SIZE_SMALL 1
#define MOB_SIZE_HUMAN 2
#define MOB_SIZE_LARGE 3
//Cuff resist speeds
#define FAST_CUFFBREAK 1
#define INSTANT_CUFFBREAK 2
//Slime evolution threshold. Controls how fast slimes can split/grow
#define SLIME_EVOLUTION_THRESHOLD 10
//singularity defines
#define STAGE_ONE 1
#define STAGE_TWO 3
#define STAGE_THREE 5
#define STAGE_FOUR 7
#define STAGE_FIVE 9
#define STAGE_SIX 11 //From supermatter shard
//zlevel defines, can be overridden for different maps in the appropriate _maps file.
#define ZLEVEL_STATION 1
#define ZLEVEL_CENTCOM 2
#define ZLEVEL_MINING 5
#define ZLEVEL_LAVALAND 5
#define ZLEVEL_EMPTY_SPACE 11
#define ZLEVEL_SPACEMIN 3
#define ZLEVEL_SPACEMAX 11
//ticker.current_state values
#define GAME_STATE_STARTUP 0
#define GAME_STATE_PREGAME 1
#define GAME_STATE_SETTING_UP 2
#define GAME_STATE_PLAYING 3
#define GAME_STATE_FINISHED 4
//SOUND:
#define SOUND_MINIMUM_PRESSURE 10
#define FALLOFF_SOUNDS 1
#define SURROUND_CAP 7
//FONTS:
// Used by Paper and PhotoCopier (and PaperBin once a year).
// Used by PDA's Notekeeper.
// Used by NewsCaster and NewsPaper.
#define PEN_FONT "Verdana"
#define CRAYON_FONT "Comic Sans MS"
#define SIGNFONT "Times New Roman"
//NPC DEFINES
#define INTERACTING 2
#define TRAVEL 4
#define FIGHTING 8
//TRAITS
#define TRAIT_ROBUST 2
#define TRAIT_UNROBUST 4
#define TRAIT_SMART 8
#define TRAIT_DUMB 16
#define TRAIT_MEAN 32
#define TRAIT_FRIENDLY 64
#define TRAIT_THIEVING 128
//SNPC defines
#define MAX_RANGE_FIND 32
#define MIN_RANGE_FIND 16
#define FUZZY_CHANCE_HIGH 85
#define FUZZY_CHANCE_LOW 50
#define CHANCE_TALK 1
#define SNPC_BRUTE 1
#define SNPC_STEALTH 2
#define SNPC_MARTYR 3
#define SNPC_PSYCHO 4
#define MAXCOIL 30
#define RESIZE_DEFAULT_SIZE 1
//transfer_ai() defines. Main proc in ai_core.dm
#define AI_TRANS_TO_CARD 1 //Downloading AI to InteliCard.
#define AI_TRANS_FROM_CARD 2 //Uploading AI from InteliCard
#define AI_MECH_HACK 3 //Malfunctioning AI hijacking mecha
//Material defines
#define MAT_METAL "$metal"
#define MAT_GLASS "$glass"
#define MAT_SILVER "$silver"
#define MAT_GOLD "$gold"
#define MAT_DIAMOND "$diamond"
#define MAT_URANIUM "$uranium"
#define MAT_PLASMA "$plasma"
#define MAT_BANANIUM "$bananium"
//check_target_facings() return defines
#define FACING_FAILED 0
#define FACING_SAME_DIR 1
#define FACING_EACHOTHER 2
#define FACING_INIT_FACING_TARGET_TARGET_FACING_PERPENDICULAR 3 //Do I win the most informative but also most stupid define award?
//Cache of bloody footprint images
//Key:
//"entered-[blood_state]-[dir_of_image]"
//or: "exited-[blood_state]-[dir_of_image]"
var/list/bloody_footprints_cache = list()
//Bloody shoes/footprints
#define MAX_SHOE_BLOODINESS 100
#define BLOODY_FOOTPRINT_BASE_ALPHA 150
#define BLOOD_GAIN_PER_STEP 100
#define BLOOD_LOSS_PER_STEP 5
#define BLOOD_FADEOUT_TIME 2
//Bloody shoe blood states
#define BLOOD_STATE_HUMAN "blood"
#define BLOOD_STATE_XENO "xeno"
#define BLOOD_STATE_OIL "oil"
#define BLOOD_STATE_NOT_BLOODY "no blood whatsoever"
//Turf wet states
#define TURF_DRY 0
#define TURF_WET_WATER 1
#define TURF_WET_LUBE 2
#define TURF_WET_ICE 3
#define TURF_WET_PERMAFROST 4
#define TURF_WET_SLIDE 5
//Maximum amount of time, (in approx. seconds.) a tile can be wet for.
#define MAXIMUM_WET_TIME 300
//Object/Item sharpness
#define IS_BLUNT 0
#define IS_SHARP 1
#define IS_SHARP_ACCURATE 2
//unmagic-strings for types of polls
#define POLLTYPE_OPTION "OPTION"
#define POLLTYPE_TEXT "TEXT"
#define POLLTYPE_RATING "NUMVAL"
#define POLLTYPE_MULTI "MULTICHOICE"
//lighting area defines
#define DYNAMIC_LIGHTING_DISABLED 0 //dynamic lighting disabled (area stays at full brightness)
#define DYNAMIC_LIGHTING_ENABLED 1 //dynamic lighting enabled
#define DYNAMIC_LIGHTING_IFSTARLIGHT 2 //dynamic lighting enabled only if starlight is.
#define IS_DYNAMIC_LIGHTING(A) ( A.lighting_use_dynamic == DYNAMIC_LIGHTING_IFSTARLIGHT ? config.starlight : A.lighting_use_dynamic )
//subtypesof(), typesof() without the parent path
#define subtypesof(typepath) ( typesof(typepath) - typepath )
//Bot types
#define SEC_BOT 1 // Secutritrons (Beepsky) and ED-209s
#define MULE_BOT 2 // MULEbots
#define FLOOR_BOT 4 // Floorbots
#define CLEAN_BOT 8 // Cleanbots
#define MED_BOT 16 // Medibots
//Sentience types
#define SENTIENCE_ORGANIC 1
#define SENTIENCE_ARTIFICIAL 2
#define SENTIENCE_OTHER 3
#define SENTIENCE_MINEBOT 4
#define SENTIENCE_BOSS 5
//Fire stuff, for burn_state
#define LAVA_PROOF -2
#define FIRE_PROOF -1
#define FLAMMABLE 0
#define ON_FIRE 1
//Ghost orbit types:
#define GHOST_ORBIT_CIRCLE "circle"
#define GHOST_ORBIT_TRIANGLE "triangle"
#define GHOST_ORBIT_HEXAGON "hexagon"
#define GHOST_ORBIT_SQUARE "square"
#define GHOST_ORBIT_PENTAGON "pentagon"
//Ghost showing preferences:
#define GHOST_ACCS_NONE 1
#define GHOST_ACCS_DIR 50
#define GHOST_ACCS_FULL 100
#define GHOST_ACCS_NONE_NAME "default sprites"
#define GHOST_ACCS_DIR_NAME "only directional sprites"
#define GHOST_ACCS_FULL_NAME "full accessories"
#define GHOST_ACCS_DEFAULT_OPTION GHOST_ACCS_FULL
var/global/list/ghost_accs_options = list(GHOST_ACCS_NONE, GHOST_ACCS_DIR, GHOST_ACCS_FULL) //So save files can be sanitized properly.
#define GHOST_OTHERS_SIMPLE 1
#define GHOST_OTHERS_DEFAULT_SPRITE 50
#define GHOST_OTHERS_THEIR_SETTING 100
#define GHOST_OTHERS_SIMPLE_NAME "white ghost"
#define GHOST_OTHERS_DEFAULT_SPRITE_NAME "default sprites"
#define GHOST_OTHERS_THEIR_SETTING_NAME "their setting"
#define GHOST_OTHERS_DEFAULT_OPTION GHOST_OTHERS_THEIR_SETTING
var/global/list/ghost_others_options = list(GHOST_OTHERS_SIMPLE, GHOST_OTHERS_DEFAULT_SPRITE, GHOST_OTHERS_THEIR_SETTING) //Same as ghost_accs_options.
//Bloodcrawling
#define BLOODCRAWL 1
#define BLOODCRAWL_EAT 2
//Color Defines
#define OOC_COLOR "#002eb8"
/////////////////////////////////////
// atom.appearence_flags shortcuts //
/////////////////////////////////////
//this was added midway thru 510, so it might not exist in some versions, but we can't check by minor verison
#ifndef TILE_BOUND
#error this version of 510 is too old, You must use byond 510.1332 or later. (TILE_BOUND is not defined)
#endif
// Disabling certain features
#define APPEARANCE_IGNORE_TRANSFORM RESET_TRANSFORM
#define APPEARANCE_IGNORE_COLOUR RESET_COLOR
#define APPEARANCE_IGNORE_CLIENT_COLOUR NO_CLIENT_COLOR
#define APPEARANCE_IGNORE_COLOURING RESET_COLOR|NO_CLIENT_COLOR
#define APPEARANCE_IGNORE_ALPHA RESET_ALPHA
#define APPEARANCE_NORMAL_GLIDE ~LONG_GLIDE
// Enabling certain features
#define APPEARANCE_CONSIDER_TRANSFORM ~RESET_TRANSFORM
#define APPEARANCE_CONSIDER_COLOUR ~RESET_COLOUR
#define APPEARANCE_CONSIDER_CLIENT_COLOUR ~NO_CLIENT_COLOR
#define APPEARANCE_CONSIDER_COLOURING ~RESET_COLOR|~NO_CLIENT_COLOR
#define APPEARANCE_CONSIDER_ALPHA ~RESET_ALPHA
#define APPEARANCE_LONG_GLIDE LONG_GLIDE
// Consider these images/atoms as part of the UI/HUD
#define APPEARANCE_UI_IGNORE_ALPHA RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR|RESET_ALPHA
#define APPEARANCE_UI RESET_COLOR|RESET_TRANSFORM|NO_CLIENT_COLOR
//Just space
#define SPACE_ICON_STATE "[((x + y) ^ ~(x * y) + z) % 25]"
//Gun trigger guards
#define TRIGGER_GUARD_ALLOW_ALL -1
#define TRIGGER_GUARD_NONE 0
#define TRIGGER_GUARD_NORMAL 1
// Plant types
#define PLANT_NORMAL 0
#define PLANT_WEED 1
#define PLANT_MUSHROOM 2
#define PLANT_ALIEN 3
// Maploader bounds indices
#define MAP_MINX 1
#define MAP_MINY 2
#define MAP_MINZ 3
#define MAP_MAXX 4
#define MAP_MAXY 5
#define MAP_MAXZ 6
#define CHECK_DNA_AND_SPECIES(C) if((!(C.dna)) || (!(C.dna.species))) return
// Evil narsie colour
#define NARSIE_WINDOW_COLOUR "#7D1919"
// Defib stats
#define DEFIB_TIME_LIMIT 120
#define DEFIB_TIME_LOSS 60
// Diagonal movement
#define FIRST_DIAG_STEP 1
#define SECOND_DIAG_STEP 2
//Slime commands defines
#define SLIME_FRIENDSHIP_FOLLOW 3 //Min friendship to order it to follow
#define SLIME_FRIENDSHIP_STOPEAT 5 //Min friendship to order it to stop eating someone
#define SLIME_FRIENDSHIP_STOPEAT_NOANGRY 7 //Min friendship to order it to stop eating someone without it losing friendship
#define SLIME_FRIENDSHIP_STOPCHASE 4 //Min friendship to order it to stop chasing someone (their target)
#define SLIME_FRIENDSHIP_STOPCHASE_NOANGRY 6 //Min friendship to order it to stop chasing someone (their target) without it losing friendship
#define SLIME_FRIENDSHIP_STAY 3 //Min friendship to order it to stay
#define SLIME_FRIENDSHIP_ATTACK 8 //Min friendship to order it to attack
#define DEADCHAT_ARRIVALRATTLE "arrivalrattle"
#define DEADCHAT_DEATHRATTLE "deathrattle"
#define DEADCHAT_REGULAR "regular-deadchat"
// Bluespace shelter deploy checks
#define SHELTER_DEPLOY_ALLOWED "allowed"
#define SHELTER_DEPLOY_BAD_TURFS "bad turfs"
#define SHELTER_DEPLOY_BAD_AREA "bad area"
#define SHELTER_DEPLOY_ANCHORED_OBJECTS "anchored objects"
//debug printing macros
#define debug_world(msg) if (Debug2) world << "DEBUG: [msg]"
#define debug_admins(msg) if (Debug2) admins << "DEBUG: [msg]"
#define debug_world_log(msg) if (Debug2) world.log << "DEBUG: [msg]"
+41
View File
@@ -0,0 +1,41 @@
/*
PIPE CONSTRUCTION DEFINES
Update these any time a path is changed
Construction breaks otherwise
*/
//Pipes
#define PIPE_SIMPLE /obj/machinery/atmospherics/pipe/simple
#define PIPE_MANIFOLD /obj/machinery/atmospherics/pipe/manifold
#define PIPE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/manifold4w
#define PIPE_HE /obj/machinery/atmospherics/pipe/heat_exchanging/simple
#define PIPE_HE_MANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold
#define PIPE_HE_4WAYMANIFOLD /obj/machinery/atmospherics/pipe/heat_exchanging/manifold4w
#define PIPE_JUNCTION /obj/machinery/atmospherics/pipe/heat_exchanging/junction
//Unary
#define PIPE_CONNECTOR /obj/machinery/atmospherics/components/unary/portables_connector
#define PIPE_UVENT /obj/machinery/atmospherics/components/unary/vent_pump
#define PIPE_SCRUBBER /obj/machinery/atmospherics/components/unary/vent_scrubber
#define PIPE_HEAT_EXCHANGE /obj/machinery/atmospherics/components/unary/heat_exchanger
//Binary
#define PIPE_PUMP /obj/machinery/atmospherics/components/binary/pump
#define PIPE_PASSIVE_GATE /obj/machinery/atmospherics/components/binary/passive_gate
#define PIPE_VOLUME_PUMP /obj/machinery/atmospherics/components/binary/volume_pump
#define PIPE_MVALVE /obj/machinery/atmospherics/components/binary/valve
#define PIPE_DVALVE /obj/machinery/atmospherics/components/binary/valve/digital
//Trinary
#define PIPE_GAS_FILTER /obj/machinery/atmospherics/components/trinary/filter
#define PIPE_GAS_MIXER /obj/machinery/atmospherics/components/trinary/mixer
//Disposal piping numbers - do NOT hardcode these, use the defines
#define DISP_PIPE_STRAIGHT 0
#define DISP_PIPE_BENT 1
#define DISP_JUNCTION 2
#define DISP_JUNCTION_FLIP 3
#define DISP_YJUNCTION 4
#define DISP_END_TRUNK 5
#define DISP_END_BIN 6
#define DISP_END_OUTLET 7
#define DISP_END_CHUTE 8
#define DISP_SORTJUNCTION 9
#define DISP_SORTJUNCTION_FLIP 10
+33
View File
@@ -0,0 +1,33 @@
//Preference toggles
#define SOUND_ADMINHELP 1
#define SOUND_MIDI 2
#define SOUND_AMBIENCE 4
#define SOUND_LOBBY 8
#define MEMBER_PUBLIC 16
#define INTENT_STYLE 32
#define MIDROUND_ANTAG 64
#define SOUND_INSTRUMENTS 128
#define SOUND_SHIP_AMBIENCE 256
#define SOUND_PRAYERS 512
#define ANNOUNCE_LOGIN 1024
#define SOUND_ANNOUNCEMENTS 2048
#define DISABLE_DEATHRATTLE 4096
#define DISABLE_ARRIVALRATTLE 8192
#define TOGGLES_DEFAULT (SOUND_ADMINHELP|SOUND_MIDI|SOUND_AMBIENCE|SOUND_LOBBY|MEMBER_PUBLIC|INTENT_STYLE|MIDROUND_ANTAG|SOUND_INSTRUMENTS|SOUND_SHIP_AMBIENCE|SOUND_PRAYERS|SOUND_ANNOUNCEMENTS)
//Chat toggles
#define CHAT_OOC 1
#define CHAT_DEAD 2
#define CHAT_GHOSTEARS 4
#define CHAT_GHOSTSIGHT 8
#define CHAT_PRAYER 16
#define CHAT_RADIO 32
#define CHAT_PULLR 64
#define CHAT_GHOSTWHISPER 128
#define CHAT_GHOSTPDA 256
#define CHAT_GHOSTRADIO 512
#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO)
+15
View File
@@ -0,0 +1,15 @@
//defines that give qdel hints. these can be given as a return in destory() or by calling
#define QDEL_HINT_QUEUE 0 //qdel should queue the object for deletion.
#define QDEL_HINT_LETMELIVE 1 //qdel should let the object live after calling destory.
#define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
#define QDEL_HINT_PUTINPOOL 5 //qdel will put this object in the atom pool.
#define QDEL_HINT_FINDREFERENCE 6 //functionally identical to QDEL_HINT_QUEUE if TESTING is not enabled in _compiler_options.dm.
//if TESTING is enabled, qdel will call this object's find_references() verb.
//defines for the gc_destroyed var
#define GC_QUEUED_FOR_QUEUING -1
#define GC_QUEUED_FOR_HARD_DEL -2
+5
View File
@@ -0,0 +1,5 @@
#define MIN_FREE_FREQ 1201
#define MAX_FREE_FREQ 1599
#define MIN_FREQ 1441
#define MAX_FREQ 1489
+3
View File
@@ -0,0 +1,3 @@
#define SOLID 1
#define LIQUID 2
#define GAS 3
+52
View File
@@ -0,0 +1,52 @@
//Values for antag preferences, event roles, etc. unified here
//These are synced with the Database, if you change the values of the defines
//then you MUST update the database!
#define ROLE_TRAITOR "traitor"
#define ROLE_OPERATIVE "operative"
#define ROLE_CHANGELING "changeling"
#define ROLE_WIZARD "wizard"
#define ROLE_MALF "malf AI"
#define ROLE_REV "revolutionary"
#define ROLE_ALIEN "xenomorph"
#define ROLE_PAI "pAI"
#define ROLE_CULTIST "cultist"
#define ROLE_BLOB "blob"
#define ROLE_NINJA "space ninja"
#define ROLE_MONKEY "monkey"
#define ROLE_GANG "gangster"
#define ROLE_ABDUCTOR "abductor"
#define ROLE_REVENANT "revenant"
#define ROLE_HOG_GOD "hand of god: god"
#define ROLE_HOG_CULTIST "hand of god: cultist"
#define ROLE_DEVIL "devil"
#define ROLE_SERVANT_OF_RATVAR "servant of Ratvar"
//Missing assignment means it's not a gamemode specific role, IT'S NOT A BUG OR ERROR.
//The gamemode specific ones are just so the gamemodes can query whether a player is old enough
//(in game days played) to play that role
var/global/list/special_roles = list(
ROLE_TRAITOR = /datum/game_mode/traitor,
ROLE_OPERATIVE = /datum/game_mode/nuclear,
ROLE_CHANGELING = /datum/game_mode/changeling,
ROLE_WIZARD = /datum/game_mode/wizard,
ROLE_MALF,
ROLE_REV = /datum/game_mode/revolution,
ROLE_ALIEN,
ROLE_PAI,
ROLE_CULTIST = /datum/game_mode/cult,
ROLE_BLOB = /datum/game_mode/blob,
ROLE_NINJA,
ROLE_MONKEY = /datum/game_mode/monkey,
ROLE_GANG = /datum/game_mode/gang,
ROLE_REVENANT,
ROLE_ABDUCTOR = /datum/game_mode/abduction,
ROLE_HOG_GOD = /datum/game_mode/hand_of_god,
ROLE_HOG_CULTIST = /datum/game_mode/hand_of_god,
ROLE_DEVIL = /datum/game_mode/devil,
ROLE_SERVANT_OF_RATVAR = /datum/game_mode/clockwork_cult,
)
+34
View File
@@ -0,0 +1,34 @@
/*
Defines for use in saycode and text formatting.
Currently contains speech spans and message modes
*/
//Message modes. Each one defines a radio channel, more or less.
#define MODE_HEADSET "headset"
#define MODE_ROBOT "robot"
#define MODE_R_HAND "right hand"
#define MODE_L_HAND "left hand"
#define MODE_INTERCOM "intercom"
#define MODE_BINARY "binary"
#define MODE_WHISPER "whisper"
#define MODE_DEPARTMENT "department"
#define MODE_ALIEN "alientalk"
#define MODE_HOLOPAD "holopad"
#define MODE_CHANGELING "changeling"
//Spans. Robot speech, italics, etc. Applied in compose_message().
#define SPAN_ROBOT "robot"
#define SPAN_YELL "yell"
#define SPAN_ITALICS "italics"
#define SPAN_SANS "sans"
#define SPAN_PAPYRUS "papyrus"
#define SPAN_REALLYBIG "reallybig"
#define SPAN_COMMAND "command_headset"
//bitflag #defines for return value of the radio() proc.
#define ITALICS 1
#define REDUCE_RANGE 2
#define NOPASS 4
// A link given to ghost alice to follow bob
#define FOLLOW_LINK(alice, bob) "<a href=?src=\ref[alice];follow=\ref[bob]>(F)</a>"
+31
View File
@@ -0,0 +1,31 @@
//shuttle mode defines
#define SHUTTLE_IDLE 0
#define SHUTTLE_RECALL 1
#define SHUTTLE_CALL 2
#define SHUTTLE_DOCKED 3
#define SHUTTLE_STRANDED 4
#define SHUTTLE_ESCAPE 5
#define SHUTTLE_ENDGAME 6
#define EMERGENCY_IDLE_OR_RECALLED (SSshuttle.emergency && ((SSshuttle.emergency.mode == SHUTTLE_IDLE) || (SSshuttle.emergency.mode == SHUTTLE_RECALL)))
#define EMERGENCY_ESCAPED_OR_ENDGAMED (SSshuttle.emergency && ((SSshuttle.emergency.mode == SHUTTLE_ESCAPE) || (SSshuttle.emergency.mode == SHUTTLE_ENDGAME)))
#define EMERGENCY_AT_LEAST_DOCKED (SSshuttle.emergency && SSshuttle.emergency.mode != SHUTTLE_IDLE && SSshuttle.emergency.mode != SHUTTLE_RECALL && SSshuttle.emergency.mode != SHUTTLE_CALL)
// Shuttle return values
#define SHUTTLE_NOT_A_DOCKING_PORT "not_a_docking_port"
#define SHUTTLE_DWIDTH_TOO_LARGE "docking_width_too_large"
#define SHUTTLE_WIDTH_TOO_LARGE "width_too_large"
#define SHUTTLE_DHEIGHT_TOO_LARGE "docking_height_too_large"
#define SHUTTLE_HEIGHT_TOO_LARGE "height_too_large"
#define SHUTTLE_ALREADY_DOCKED "we_are_already_docked"
#define SHUTTLE_SOMEONE_ELSE_DOCKED "someone_else_docked"
//Launching Shuttles to Centcomm
#define NOLAUNCH -1
#define UNLAUNCHED 0
#define ENDGAME_LAUNCHED 1
#define EARLY_LAUNCHED 2
// Ripples, effects that signal a shuttle's arrival
#define SHUTTLE_RIPPLE_TIME 100
#define SHUTTLE_RIPPLE_FADEIN 50
+27
View File
@@ -0,0 +1,27 @@
#define SEE_INVISIBLE_MINIMUM 5
#define SEE_INVISIBLE_NOLIGHTING 15 //to not see the lighting objects. Used for nightvision and observer with darkness toggled.
#define INVISIBILITY_LIGHTING 20
#define SEE_INVISIBLE_LIVING 25
#define SEE_INVISIBLE_LEVEL_ONE 35 //currently unused
#define INVISIBILITY_LEVEL_ONE 35 //currently unused
#define SEE_INVISIBLE_LEVEL_TWO 45 //currently unused
#define INVISIBILITY_LEVEL_TWO 45 //currently unused
#define INVISIBILITY_OBSERVER 60
#define SEE_INVISIBLE_OBSERVER 60
#define INVISIBILITY_MAXIMUM 100 //the maximum allowed for "real" objects
#define INVISIBILITY_ABSTRACT 101 //only used for abstract objects (e.g. spacevine_controller), things that are not really there.
#define BORGMESON 1
#define BORGTHERM 2
#define BORGXRAY 4
#define BORGMATERIAL 8
+26
View File
@@ -0,0 +1,26 @@
/*
Used with the various stat variables (mob, machines)
*/
//mob/var/stat things
#define CONSCIOUS 0
#define UNCONSCIOUS 1
#define DEAD 2
//mob disabilities stat
#define BLIND 1
#define MUTE 2
#define DEAF 4
#define NEARSIGHT 8
#define FAT 32
#define HUSK 64
#define NOCLONE 128
#define CLUMSY 256
// bitflags for machine stat variable
#define BROKEN 1
#define NOPOWER 2
#define POWEROFF 4 // tbd
#define MAINT 8 // under maintaince
#define EMPED 16 // temporary broken by EMP pulse
+8
View File
@@ -0,0 +1,8 @@
#define CAT_NONE ""
#define CAT_WEAPON "Weaponry"
#define CAT_AMMO "Ammunition"
#define CAT_ROBOT "Robots"
#define CAT_FOOD "Food"
#define CAT_MISC "Misc"
#define CAT_PRIMAL "Tribal"
+4
View File
@@ -0,0 +1,4 @@
#define UI_INTERACTIVE 2 // Green/Interactive
#define UI_UPDATE 1 // Orange/Updates Only
#define UI_DISABLED 0 // Red/Disabled
#define UI_CLOSE -1 // Closed
+7
View File
@@ -0,0 +1,7 @@
#define TICK_LIMIT_RUNNING 85
#define TICK_LIMIT_TO_RUN 80
#define TICK_LIMIT_MC 84
#define TICK_LIMIT_MC_INIT 100
#define TICK_CHECK ( world.tick_usage > CURRENT_TICKLIMIT ? stoplag() : 0 )
#define CHECK_TICK if (world.tick_usage > CURRENT_TICKLIMIT) stoplag()
+44
View File
@@ -0,0 +1,44 @@
#define WIRE_ACTIVATE "activate"
#define WIRE_AI "ai"
#define WIRE_ALARM "alarm"
#define WIRE_AVOIDANCE "avoidance"
#define WIRE_BACKUP1 "backup1"
#define WIRE_BACKUP2 "backup2"
#define WIRE_BEACON "beacon"
#define WIRE_BOLTS "bolts"
#define WIRE_BOOM "boom"
#define WIRE_CAMERA "camera"
#define WIRE_CONTRABAND "contraband"
#define WIRE_DELAY "delay"
#define WIRE_DISABLE "disable"
#define WIRE_DISARM "disarm"
#define WIRE_ELECTRIFY "electrify"
#define WIRE_HACK "hack"
#define WIRE_IDSCAN "idscan"
#define WIRE_INTERFACE "interface"
#define WIRE_LAWSYNC "lawsync"
#define WIRE_LIGHT "light"
#define WIRE_LIMIT "limit"
#define WIRE_LOADCHECK "loadcheck"
#define WIRE_LOCKDOWN "lockdown"
#define WIRE_MOTOR1 "motor1"
#define WIRE_MOTOR2 "motor2"
#define WIRE_OPEN "open"
#define WIRE_PANIC "panic"
#define WIRE_POWER "power"
#define WIRE_POWER1 "power1"
#define WIRE_POWER2 "power2"
#define WIRE_PROCEED "proceed"
#define WIRE_RX "recieve"
#define WIRE_SAFETY "safety"
#define WIRE_SHOCK "shock"
#define WIRE_SIGNAL "signal"
#define WIRE_SPEAKER "speaker"
#define WIRE_STRENGTH "strength"
#define WIRE_THROW "throw"
#define WIRE_TIMING "timing"
#define WIRE_TX "transmit"
#define WIRE_UNBOLT "unbolt"
#define WIRE_ZAP "zap"
#define WIRE_ZAP1 "zap1"
#define WIRE_ZAP2 "zap2"
+78
View File
@@ -0,0 +1,78 @@
//print a warning message to world.log
#define WARNING(MSG) warning("[MSG] in [__FILE__] at line [__LINE__] src: [src] usr: [usr].")
/proc/warning(msg)
world.log << "## WARNING: [msg]"
//not an error or a warning, but worth to mention on the world log, just in case.
#define NOTICE(MSG) notice(MSG)
/proc/notice(msg)
world.log << "## NOTICE: [msg]"
//print a testing-mode debug message to world.log
/proc/testing(msg)
#ifdef TESTING
world.log << "## TESTING: [msg]"
#endif
/proc/log_admin(text)
admin_log.Add(text)
if (config.log_admin)
diary << "\[[time_stamp()]]ADMIN: [text]"
/proc/log_adminsay(text)
if (config.log_adminchat)
log_admin("ASAY: [text]")
/proc/log_dsay(text)
if (config.log_adminchat)
log_admin("DSAY: [text]")
/proc/log_game(text)
if (config.log_game)
diary << "\[[time_stamp()]]GAME: [text]"
/proc/log_vote(text)
if (config.log_vote)
diary << "\[[time_stamp()]]VOTE: [text]"
/proc/log_access(text)
if (config.log_access)
diary << "\[[time_stamp()]]ACCESS: [text]"
/proc/log_say(text)
if (config.log_say)
diary << "\[[time_stamp()]]SAY: [text]"
/proc/log_prayer(text)
if (config.log_prayer)
diary << "\[[time_stamp()]]PRAY: [text]"
/proc/log_law(text)
if (config.log_law)
diary << "\[[time_stamp()]]LAW: [text]"
/proc/log_ooc(text)
if (config.log_ooc)
diary << "\[[time_stamp()]]OOC: [text]"
/proc/log_whisper(text)
if (config.log_whisper)
diary << "\[[time_stamp()]]WHISPER: [text]"
/proc/log_emote(text)
if (config.log_emote)
diary << "\[[time_stamp()]]EMOTE: [text]"
/proc/log_attack(text)
if (config.log_attack)
diaryofmeanpeople << "\[[time_stamp()]]ATTACK: [text]"
/proc/log_pda(text)
if (config.log_pda)
diary << "\[[time_stamp()]]PDA: [text]"
/proc/log_comment(text)
if (config.log_pda)
//reusing the PDA option because I really don't think news comments are worth a config option
diary << "\[[time_stamp()]]COMMENT: [text]"
+41
View File
@@ -0,0 +1,41 @@
#define pick_list(FILE, KEY) (pick(strings(FILE, KEY)))
#define pick_list_replacements(FILE, KEY) (strings_replacement(FILE, KEY))
#define json_load(FILE) (json_decode(file2text(FILE)))
var/global/list/string_cache
var/global/string_filename_current_key
/proc/strings_replacement(filename, key)
load_strings_file(filename)
if((filename in string_cache) && (key in string_cache[filename]))
var/response = pick(string_cache[filename][key])
var/regex/r = regex("@pick\\((\\D+?)\\)", "g")
response = r.Replace(response, /proc/strings_subkey_lookup)
return response
else
CRASH("strings list not found: strings/[filename], index=[key]")
/proc/strings(filename as text, key as text)
load_strings_file(filename)
if((filename in string_cache) && (key in string_cache[filename]))
return string_cache[filename][key]
else
CRASH("strings list not found: strings/[filename], index=[key]")
/proc/strings_subkey_lookup(match, group1)
return pick_list(string_filename_current_key, group1)
/proc/load_strings_file(filename)
string_filename_current_key = filename
if(filename in string_cache)
return //no work to do
if(!string_cache)
string_cache = new
if(fexists("strings/[filename]"))
string_cache[filename] = json_load("strings/[filename]")
else
CRASH("file not found: strings/[filename]")
+36
View File
@@ -0,0 +1,36 @@
#define YOUNG 4
/client/proc/join_date_check(y,m,d)
var/DBQuery/query = dbcon.NewQuery("SELECT DATEDIFF(Now(),'[y]-[m]-[d]')")
if(!query.Execute())
world.log << "SQL ERROR doing datediff. Error : \[[query.ErrorMsg()]\]\n"
return FALSE
if(query.NextRow())
var/diff = text2num(query.item[1])
if(diff < YOUNG)
var/msg = "(IP: [address], ID: [computer_id]) is a new BYOND account made on [y]-[m]-[d]."
if(diff < 0)
msg += " They are also apparently from the future."
message_admins("[key_name_admin(src)] [msg]")
return TRUE
#undef YOUNG
/client/proc/findJoinDate()
var/http[] = world.Export("http://byond.com/members/[src.ckey]?format=text")
if(!http)
world.log << "Failed to connect to byond age check for [src.ckey]"
return FALSE
var/F = file2text(http["CONTENT"])
if(F)
var/regex/R = regex("joined = \"(\\d{4})-(\\d{2})-(\\d{2})\"")
if(!R.Find(F))
CRASH("Age check regex failed")
var/y = R.group[1]
var/m = R.group[2]
var/d = R.group[3]
return join_date_check(y,m,d)
+44
View File
@@ -0,0 +1,44 @@
/proc/cmp_numeric_dsc(a,b)
return b - a
/proc/cmp_numeric_asc(a,b)
return a - b
/proc/cmp_text_asc(a,b)
return sorttext(b,a)
/proc/cmp_text_dsc(a,b)
return sorttext(a,b)
/proc/cmp_name_asc(atom/a, atom/b)
return sorttext(b.name, a.name)
/proc/cmp_name_dsc(atom/a, atom/b)
return sorttext(a.name, b.name)
var/cmp_field = "name"
/proc/cmp_records_asc(datum/data/record/a, datum/data/record/b)
return sorttext(b.fields[cmp_field], a.fields[cmp_field])
/proc/cmp_records_dsc(datum/data/record/a, datum/data/record/b)
return sorttext(a.fields[cmp_field], b.fields[cmp_field])
/proc/cmp_ckey_asc(client/a, client/b)
return sorttext(b.ckey, a.ckey)
/proc/cmp_ckey_dsc(client/a, client/b)
return sorttext(a.ckey, b.ckey)
/proc/cmp_subsystem_init(datum/subsystem/a, datum/subsystem/b)
return b.init_order - a.init_order
/proc/cmp_subsystem_display(datum/subsystem/a, datum/subsystem/b)
if(a.display_order == b.display_order)
return sorttext(b.name, a.name)
return a.display_order - b.display_order
/proc/cmp_subsystem_priority(datum/subsystem/a, datum/subsystem/b)
return a.priority - b.priority
/proc/cmp_clientcolour_priority(datum/client_colour/A, datum/client_colour/B)
return B.priority - A.priority
+78
View File
@@ -0,0 +1,78 @@
//checks if a file exists and contains text
//returns text as a string if these conditions are met
/proc/return_file_text(filename)
if(fexists(filename) == 0)
throw EXCEPTION("return_file_text(): File not found")
return
var/text = file2text(filename)
if(!text)
throw EXCEPTION("return_file_text(): File empty")
return
return text
//Sends resource files to client cache
/client/proc/getFiles()
for(var/file in args)
src << browse_rsc(file)
/client/proc/browse_files(root="data/logs/", max_iterations=10, list/valid_extensions=list(".txt",".log",".htm"))
var/path = root
for(var/i=0, i<max_iterations, i++)
var/list/choices = flist(path)
if(path != root)
choices.Insert(1,"/")
var/choice = input(src,"Choose a file to access:","Download",null) as null|anything in choices
switch(choice)
if(null)
return
if("/")
path = root
continue
path += choice
if(copytext(path,-1,0) != "/") //didn't choose a directory, no need to iterate again
break
var/extension = copytext(path,-4,0)
if( !fexists(path) || !(extension in valid_extensions) )
src << "<font color='red'>Error: browse_files(): File not found/Invalid file([path]).</font>"
return
return path
#define FTPDELAY 200 //200 tick delay to discourage spam
/* This proc is a failsafe to prevent spamming of file requests.
It is just a timer that only permits a download every [FTPDELAY] ticks.
This can be changed by modifying FTPDELAY's value above.
PLEASE USE RESPONSIBLY, Some log files can reach sizes of 4MB! */
/client/proc/file_spam_check()
var/time_to_wait = fileaccess_timer - world.time
if(time_to_wait > 0)
src << "<font color='red'>Error: file_spam_check(): Spam. Please wait [round(time_to_wait/10)] seconds.</font>"
return 1
fileaccess_timer = world.time + FTPDELAY
return 0
#undef FTPDELAY
/proc/pathwalk(path)
var/list/jobs = list(path)
var/list/filenames = list()
while(jobs.len)
var/current_dir = pop(jobs)
var/list/new_filenames = flist(current_dir)
for(var/new_filename in new_filenames)
// if filename ends in / it is a directory, append to currdir
if(findtext(new_filename, "/", -1))
jobs += current_dir + new_filename
else
filenames += current_dir + new_filename
return filenames
/proc/pathflatten(path)
return replacetext(path, "/", "_")
+446
View File
@@ -0,0 +1,446 @@
//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a
#define RANGE_TURFS(RADIUS, CENTER) \
block( \
locate(max(CENTER.x-(RADIUS),1), max(CENTER.y-(RADIUS),1), CENTER.z), \
locate(min(CENTER.x+(RADIUS),world.maxx), min(CENTER.y+(RADIUS),world.maxy), CENTER.z) \
)
#define Z_TURFS(ZLEVEL) block(locate(1,1,ZLEVEL), locate(world.maxx, world.maxy, ZLEVEL))
/proc/get_area(atom/A)
if (!istype(A))
return
for(A, A && !isarea(A), A=A.loc); //semicolon is for the empty statement
return A
/proc/get_area_master(O)
var/area/A = get_area(O)
if(A && A.master)
A = A.master
return A
/proc/get_area_name(N) //get area by its name
for(var/area/A in world)
if(A.name == N)
return A
return 0
/proc/get_areas_in_range(dist=0, atom/center=usr)
if(!dist)
var/turf/T = get_turf(center)
return T ? list(T.loc) : list()
if(!center)
return list()
var/list/turfs = RANGE_TURFS(dist, center)
var/list/areas = list()
for(var/V in turfs)
var/turf/T = V
areas |= T.loc
return areas
// Like view but bypasses luminosity check
/proc/get_hear(range, atom/source)
var/lum = source.luminosity
source.luminosity = 6
var/list/heard = view(range, source)
source.luminosity = lum
return heard
/proc/alone_in_area(area/the_area, mob/must_be_alone, check_type = /mob/living/carbon)
var/area/our_area = get_area_master(the_area)
for(var/C in living_mob_list)
if(!istype(C, check_type))
continue
if(C == must_be_alone)
continue
if(our_area == get_area_master(C))
return 0
return 1
//We used to use linear regression to approximate the answer, but Mloc realized this was actually faster.
//And lo and behold, it is, and it's more accurate to boot.
/proc/cheap_hypotenuse(Ax,Ay,Bx,By)
return sqrt(abs(Ax - Bx)**2 + abs(Ay - By)**2) //A squared + B squared = C squared
/proc/circlerange(center=usr,radius=3)
var/turf/centerturf = get_turf(center)
var/list/turfs = new/list()
var/rsq = radius * (radius+0.5)
for(var/atom/T in range(radius, centerturf))
var/dx = T.x - centerturf.x
var/dy = T.y - centerturf.y
if(dx*dx + dy*dy <= rsq)
turfs += T
//turfs += centerturf
return turfs
/proc/circleview(center=usr,radius=3)
var/turf/centerturf = get_turf(center)
var/list/atoms = new/list()
var/rsq = radius * (radius+0.5)
for(var/atom/A in view(radius, centerturf))
var/dx = A.x - centerturf.x
var/dy = A.y - centerturf.y
if(dx*dx + dy*dy <= rsq)
atoms += A
//turfs += centerturf
return atoms
/proc/get_dist_euclidian(atom/Loc1 as turf|mob|obj,atom/Loc2 as turf|mob|obj)
var/dx = Loc1.x - Loc2.x
var/dy = Loc1.y - Loc2.y
var/dist = sqrt(dx**2 + dy**2)
return dist
/proc/circlerangeturfs(center=usr,radius=3)
var/turf/centerturf = get_turf(center)
var/list/turfs = new/list()
var/rsq = radius * (radius+0.5)
for(var/turf/T in range(radius, centerturf))
var/dx = T.x - centerturf.x
var/dy = T.y - centerturf.y
if(dx*dx + dy*dy <= rsq)
turfs += T
return turfs
/proc/circleviewturfs(center=usr,radius=3) //Is there even a diffrence between this proc and circlerangeturfs()?
var/turf/centerturf = get_turf(center)
var/list/turfs = new/list()
var/rsq = radius * (radius+0.5)
for(var/turf/T in view(radius, centerturf))
var/dx = T.x - centerturf.x
var/dy = T.y - centerturf.y
if(dx*dx + dy*dy <= rsq)
turfs += T
return turfs
//This is the new version of recursive_mob_check, used for say().
//The other proc was left intact because morgue trays use it.
//Sped this up again for real this time
/proc/recursive_hear_check(O)
var/list/processing_list = list(O)
. = list()
while(processing_list.len)
var/atom/A = processing_list[1]
if(A.flags & HEAR)
. += A
processing_list.Cut(1, 2)
processing_list += A.contents
// Better recursive loop, technically sort of not actually recursive cause that shit is retarded, enjoy.
//No need for a recursive limit either
/proc/recursive_mob_check(atom/O,client_check=1,sight_check=1,include_radio=1)
var/list/processing_list = list(O)
var/list/processed_list = list()
var/list/found_mobs = list()
while(processing_list.len)
var/atom/A = processing_list[1]
var/passed = 0
if(ismob(A))
var/mob/A_tmp = A
passed=1
if(client_check && !A_tmp.client)
passed=0
if(sight_check && !isInSight(A_tmp, O))
passed=0
else if(include_radio && istype(A, /obj/item/device/radio))
passed=1
if(sight_check && !isInSight(A, O))
passed=0
if(passed)
found_mobs |= A
for(var/atom/B in A)
if(!processed_list[B])
processing_list |= B
processing_list.Cut(1, 2)
processed_list[A] = A
return found_mobs
/proc/get_hearers_in_view(R, atom/source)
// Returns a list of hearers in view(R) from source (ignoring luminosity). Used in saycode.
var/turf/T = get_turf(source)
var/list/hear = list()
if(!T)
return hear
var/list/range = get_hear(R, T)
for(var/atom/movable/A in range)
hear |= recursive_hear_check(A)
return hear
/proc/get_mobs_in_radio_ranges(list/obj/item/device/radio/radios)
set background = BACKGROUND_ENABLED
. = list()
// Returns a list of mobs who can hear any of the radios given in @radios
for(var/obj/item/device/radio/R in radios)
if(R)
. |= get_hearers_in_view(R.canhear_range, R)
#define SIGN(X) ((X<0)?-1:1)
/proc/inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5)
var/turf/T
if(X1==X2)
if(Y1==Y2)
return 1 //Light cannot be blocked on same tile
else
var/s = SIGN(Y2-Y1)
Y1+=s
while(Y1!=Y2)
T=locate(X1,Y1,Z)
if(T.opacity)
return 0
Y1+=s
else
var/m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1))
var/b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles
var/signX = SIGN(X2-X1)
var/signY = SIGN(Y2-Y1)
if(X1<X2)
b+=m
while(X1!=X2 || Y1!=Y2)
if(round(m*X1+b-Y1))
Y1+=signY //Line exits tile vertically
else
X1+=signX //Line exits tile horizontally
T=locate(X1,Y1,Z)
if(T.opacity)
return 0
return 1
#undef SIGN
/proc/isInSight(atom/A, atom/B)
var/turf/Aturf = get_turf(A)
var/turf/Bturf = get_turf(B)
if(!Aturf || !Bturf)
return 0
if(inLineOfSight(Aturf.x,Aturf.y, Bturf.x,Bturf.y,Aturf.z))
return 1
else
return 0
/proc/get_cardinal_step_away(atom/start, atom/finish) //returns the position of a step from start away from finish, in one of the cardinal directions
//returns only NORTH, SOUTH, EAST, or WEST
var/dx = finish.x - start.x
var/dy = finish.y - start.y
if(abs(dy) > abs (dx)) //slope is above 1:1 (move horizontally in a tie)
if(dy > 0)
return get_step(start, SOUTH)
else
return get_step(start, NORTH)
else
if(dx > 0)
return get_step(start, WEST)
else
return get_step(start, EAST)
/proc/try_move_adjacent(atom/movable/AM)
var/turf/T = get_turf(AM)
for(var/direction in cardinal)
if(AM.Move(get_step(T, direction)))
break
/proc/get_mob_by_key(key)
for(var/mob/M in mob_list)
if(M.ckey == lowertext(key))
return M
return null
// Will return a list of active candidates. It increases the buffer 5 times until it finds a candidate which is active within the buffer.
/proc/get_candidates(be_special_type, afk_bracket=3000, var/jobbanType)
var/list/candidates = list()
// Keep looping until we find a non-afk candidate within the time bracket (we limit the bracket to 10 minutes (6000))
while(!candidates.len && afk_bracket < 6000)
for(var/mob/dead/observer/G in player_list)
if(G.client != null)
if(!(G.mind && G.mind.current && G.mind.current.stat != DEAD))
if(!G.client.is_afk(afk_bracket) && (be_special_type in G.client.prefs.be_special))
if (jobbanType)
if(!(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate")))
candidates += G.client
else
candidates += G.client
afk_bracket += 600 // Add a minute to the bracket, for every attempt
return candidates
/proc/ScreenText(obj/O, maptext="", screen_loc="CENTER-7,CENTER-7", maptext_height=480, maptext_width=480)
if(!isobj(O))
O = new /obj/screen/text()
O.maptext = maptext
O.maptext_height = maptext_height
O.maptext_width = maptext_width
O.screen_loc = screen_loc
return O
/proc/Show2Group4Delay(obj/O, list/group, delay=0)
if(!isobj(O))
return
if(!group)
group = clients
for(var/client/C in group)
C.screen += O
if(delay)
spawn(delay)
for(var/client/C in group)
C.screen -= O
/proc/flick_overlay(image/I, list/show_to, duration)
for(var/client/C in show_to)
C.images += I
spawn(duration)
for(var/client/C in show_to)
C.images -= I
/proc/get_active_player_count(var/alive_check = 0, var/afk_check = 0, var/human_check = 0)
// Get active players who are playing in the round
var/active_players = 0
for(var/i = 1; i <= player_list.len; i++)
var/mob/M = player_list[i]
if(M && M.client)
if(alive_check && M.stat)
continue
else if(afk_check && M.client.is_afk())
continue
else if(human_check && !istype(M, /mob/living/carbon/human))
continue
else if(istype(M, /mob/new_player)) // exclude people in the lobby
continue
else if(isobserver(M)) // Ghosts are fine if they were playing once (didn't start as observers)
var/mob/dead/observer/O = M
if(O.started_as_observer) // Exclude people who started as observers
continue
active_players++
return active_players
/datum/projectile_data
var/src_x
var/src_y
var/time
var/distance
var/power_x
var/power_y
var/dest_x
var/dest_y
/datum/projectile_data/New(var/src_x, var/src_y, var/time, var/distance, \
var/power_x, var/power_y, var/dest_x, var/dest_y)
src.src_x = src_x
src.src_y = src_y
src.time = time
src.distance = distance
src.power_x = power_x
src.power_y = power_y
src.dest_x = dest_x
src.dest_y = dest_y
/proc/projectile_trajectory(src_x, src_y, rotation, angle, power)
// returns the destination (Vx,y) that a projectile shot at [src_x], [src_y], with an angle of [angle],
// rotated at [rotation] and with the power of [power]
// Thanks to VistaPOWA for this function
var/power_x = power * cos(angle)
var/power_y = power * sin(angle)
var/time = 2* power_y / 10 //10 = g
var/distance = time * power_x
var/dest_x = src_x + distance*sin(rotation);
var/dest_y = src_y + distance*cos(rotation);
return new /datum/projectile_data(src_x, src_y, time, distance, power_x, power_y, dest_x, dest_y)
/proc/pollCandidates(var/Question, var/jobbanType, var/datum/game_mode/gametypeCheck, var/be_special_flag = 0, var/poll_time = 300)
var/list/mob/dead/observer/candidates = list()
var/time_passed = world.time
if (!Question)
Question = "Would you like to be a special role?"
for(var/mob/dead/observer/G in player_list)
if(!G.key || !G.client)
continue
if(be_special_flag)
if(!(G.client.prefs) || !(be_special_flag in G.client.prefs.be_special))
continue
if (gametypeCheck)
if(!gametypeCheck.age_check(G.client))
continue
if (jobbanType)
if(jobban_isbanned(G, jobbanType) || jobban_isbanned(G, "Syndicate"))
continue
spawn(0)
G << 'sound/misc/notice2.ogg' //Alerting them to their consideration
switch(askuser(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No", StealFocus=0, Timeout=poll_time))
if(1)
G << "<span class='notice'>Choice registered: Yes.</span>"
if((world.time-time_passed)>poll_time)
G << "<span class='danger'>Sorry, you were too late for the consideration!</span>"
G << 'sound/machines/buzz-sigh.ogg'
else
candidates += G
if(2)
G << "<span class='danger'>Choice registered: No.</span>"
sleep(poll_time)
//Check all our candidates, to make sure they didn't log off during the wait period.
for(var/mob/dead/observer/G in candidates)
if(!G.key || !G.client)
candidates.Remove(G)
return candidates
/proc/makeBody(mob/dead/observer/G_found) // Uses stripped down and bastardized code from respawn character
if(!G_found || !G_found.key)
return
//First we spawn a dude.
var/mob/living/carbon/human/new_character = new(pick(latejoin))//The mob being spawned.
G_found.client.prefs.copy_to(new_character)
new_character.dna.update_dna_identity()
new_character.key = G_found.key
return new_character
+84
View File
@@ -0,0 +1,84 @@
//////////////////////////
/////Initial Building/////
//////////////////////////
/proc/make_datum_references_lists()
//hair
init_sprite_accessory_subtypes(/datum/sprite_accessory/hair, hair_styles_list, hair_styles_male_list, hair_styles_female_list)
//facial hair
init_sprite_accessory_subtypes(/datum/sprite_accessory/facial_hair, facial_hair_styles_list, facial_hair_styles_male_list, facial_hair_styles_female_list)
//underwear
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, underwear_list, underwear_m, underwear_f)
//undershirt
init_sprite_accessory_subtypes(/datum/sprite_accessory/undershirt, undershirt_list, undershirt_m, undershirt_f)
//socks
init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, socks_list)
//lizard bodyparts (blizzard intensifies)
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, body_markings_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, tails_list_lizard)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/lizard, animated_tails_list_lizard)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, tails_list_human)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails_animated/human, animated_tails_list_human)
init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts, snouts_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, horns_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, ears_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, wings_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings_open, wings_open_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, frills_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, spines_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines_animated, animated_spines_list)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, r_wings_list,roundstart = TRUE)
//Species
for(var/spath in subtypesof(/datum/species))
var/datum/species/S = new spath()
if(S.roundstart)
roundstart_species[S.id] = S.type
species_list[S.id] = S.type
//Surgeries
for(var/path in subtypesof(/datum/surgery))
surgeries_list += new path()
//Materials
for(var/path in subtypesof(/datum/material))
var/datum/material/D = new path()
materials_list[D.id] = D
//Techs
for(var/path in subtypesof(/datum/tech))
var/datum/tech/D = new path()
tech_list[D.id] = D
init_subtypes(/datum/crafting_recipe, crafting_recipes)
/* // Uncomment to debug chemical reaction list.
/client/verb/debug_chemical_list()
for (var/reaction in chemical_reactions_list)
. += "chemical_reactions_list\[\"[reaction]\"\] = \"[chemical_reactions_list[reaction]]\"\n"
if(islist(chemical_reactions_list[reaction]))
var/list/L = chemical_reactions_list[reaction]
for(var/t in L)
. += " has: [t]\n"
world << .
*/
//creates every subtype of prototype (excluding prototype) and adds it to list L.
//if no list/L is provided, one is created.
/proc/init_subtypes(prototype, list/L)
if(!istype(L))
L = list()
for(var/path in subtypesof(prototype))
L += new path()
return L
//returns a list of paths to every subtype of prototype (excluding prototype)
//if no list/L is provided, one is created.
/proc/init_paths(prototype, list/L)
if(!istype(L))
L = list()
for(var/path in subtypesof(prototype))
L+= path
return L
+389
View File
@@ -0,0 +1,389 @@
//generic (by snowflake) tile smoothing code; smooth your icons with this!
/*
Each tile is divided in 4 corners, each corner has an image associated to it; the tile is then overlayed by these 4 images
To use this, just set your atom's 'smooth' var to 1. If your atom can be moved/unanchored, set its 'can_be_unanchored' var to 1.
If you don't want your atom's icon to smooth with anything but atoms of the same type, set the list 'canSmoothWith' to null;
Otherwise, put all types you want the atom icon to smooth with in 'canSmoothWith' INCLUDING THE TYPE OF THE ATOM ITSELF.
Each atom has its own icon file with all the possible corner states. See 'smooth_wall.dmi' for a template.
DIAGONAL SMOOTHING INSTRUCTIONS
To make your atom smooth diagonally you need all the proper icon states (see 'smooth_wall.dmi' for a template) and
to add the 'SMOOTH_DIAGONAL' flag to the atom's smooth var (in addition to either SMOOTH_TRUE or SMOOTH_MORE).
For turfs, what appears under the diagonal corners depends on the turf that was in the same position previously: if you make a wall on
a plating floor, you will see plating under the diagonal wall corner, if it was space, you will see space.
If you wish to map a diagonal wall corner with a fixed underlay, you must configure the turf's 'fixed_underlay' list var, like so:
fixed_underlay = list("icon"='icon_file.dmi', "icon_state"="iconstatename")
A non null 'fixed_underlay' list var will skip copying the previous turf appearance and always use the list. If the list is
not set properly, the underlay will default to regular floor plating.
To see an example of a diagonal wall, see '/turf/closed/wall/shuttle' and its subtypes.
*/
//Redefinitions of the diagonal directions so they can be stored in one var without conflicts
#define N_NORTH 2
#define N_SOUTH 4
#define N_EAST 16
#define N_WEST 256
#define N_NORTHEAST 32
#define N_NORTHWEST 512
#define N_SOUTHEAST 64
#define N_SOUTHWEST 1024
#define SMOOTH_FALSE 0 //not smooth
#define SMOOTH_TRUE 1 //smooths with exact specified types or just itself
#define SMOOTH_MORE 2 //smooths with all subtypes of specified types or just itself (this value can replace SMOOTH_TRUE)
#define SMOOTH_DIAGONAL 4 //if atom should smooth diagonally, this should be present in 'smooth' var
#define SMOOTH_BORDER 8 //atom will smooth with the borders of the map
#define NULLTURF_BORDER 123456789
#define DEFAULT_UNDERLAY_ICON 'icons/turf/floors.dmi'
#define DEFAULT_UNDERLAY_ICON_STATE "plating"
#define DEFAULT_UNDERLAY_IMAGE image(DEFAULT_UNDERLAY_ICON, DEFAULT_UNDERLAY_ICON_STATE)
/atom/var/smooth = SMOOTH_FALSE
/atom/var/top_left_corner
/atom/var/top_right_corner
/atom/var/bottom_left_corner
/atom/var/bottom_right_corner
/atom/var/list/canSmoothWith = null // TYPE PATHS I CAN SMOOTH WITH~~~~~ If this is null and atom is smooth, it smooths only with itself
/atom/movable/var/can_be_unanchored = 0
/turf/var/list/fixed_underlay = null
/proc/calculate_adjacencies(atom/A)
if(!A.loc)
return 0
var/adjacencies = 0
var/atom/movable/AM
if(istype(A, /atom/movable))
AM = A
if(AM.can_be_unanchored && !AM.anchored)
return 0
for(var/direction in cardinal)
AM = find_type_in_direction(A, direction)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
adjacencies |= 1 << direction
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= 1 << direction
if(adjacencies & N_NORTH)
if(adjacencies & N_WEST)
AM = find_type_in_direction(A, NORTHWEST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
adjacencies |= N_NORTHWEST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_NORTHWEST
if(adjacencies & N_EAST)
AM = find_type_in_direction(A, NORTHEAST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
adjacencies |= N_NORTHEAST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_NORTHEAST
if(adjacencies & N_SOUTH)
if(adjacencies & N_WEST)
AM = find_type_in_direction(A, SOUTHWEST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
adjacencies |= N_SOUTHWEST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_SOUTHWEST
if(adjacencies & N_EAST)
AM = find_type_in_direction(A, SOUTHEAST)
if(AM == NULLTURF_BORDER)
if((A.smooth & SMOOTH_BORDER))
adjacencies |= N_SOUTHEAST
else if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_SOUTHEAST
return adjacencies
/proc/smooth_icon(atom/A)
if(qdeleted(A))
return
if(!A || !A.smooth)
return
spawn(0)
if((A.smooth & SMOOTH_TRUE) || (A.smooth & SMOOTH_MORE))
var/adjacencies = calculate_adjacencies(A)
if(A.smooth & SMOOTH_DIAGONAL)
A.diagonal_smooth(adjacencies)
else
cardinal_smooth(A, adjacencies)
/atom/proc/diagonal_smooth(adjacencies)
switch(adjacencies)
if(N_NORTH|N_WEST)
replace_smooth_overlays("d1-se-0","d2-se","d3-se","d4-se")
if(N_NORTH|N_EAST)
replace_smooth_overlays("d1-sw","d2-sw-0","d3-sw","d4-sw")
if(N_SOUTH|N_WEST)
replace_smooth_overlays("d1-ne","d2-ne","d3-ne-0","d4-ne")
if(N_SOUTH|N_EAST)
replace_smooth_overlays("d1-nw","d2-nw","d3-nw","d4-nw-0")
if(N_NORTH|N_WEST|N_NORTHWEST)
replace_smooth_overlays("d1-se-1","d2-se","d3-se","d4-se")
if(N_NORTH|N_EAST|N_NORTHEAST)
replace_smooth_overlays("d1-sw","d2-sw-1","d3-sw","d4-sw")
if(N_SOUTH|N_WEST|N_SOUTHWEST)
replace_smooth_overlays("d1-ne","d2-ne","d3-ne-1","d4-ne")
if(N_SOUTH|N_EAST|N_SOUTHEAST)
replace_smooth_overlays("d1-nw","d2-nw","d3-nw","d4-nw-1")
else
cardinal_smooth(src, adjacencies)
return
icon_state = ""
return adjacencies
//only walls should have a need to handle underlays
/turf/closed/wall/diagonal_smooth(adjacencies)
adjacencies = reverse_ndir(..())
if(adjacencies)
underlays.Cut()
if(fixed_underlay)
if(fixed_underlay["space"])
underlays += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=src.layer)
else
underlays += image(fixed_underlay["icon"], fixed_underlay["icon_state"], layer=src.layer)
else
var/turf/T = get_step(src, turn(adjacencies, 180))
if(T && T.density)
T = get_step(src, turn(adjacencies, 135))
if(T && T.density)
T = get_step(src, turn(adjacencies, 225))
if(istype(T, /turf/open/space))
underlays += image('icons/turf/space.dmi', SPACE_ICON_STATE, layer=src.layer)
else if(T && !T.density && !T.smooth)
underlays += T
else
underlays += DEFAULT_UNDERLAY_IMAGE
/proc/cardinal_smooth(atom/A, adjacencies)
//NW CORNER
var/nw = "1-i"
if((adjacencies & N_NORTH) && (adjacencies & N_WEST))
if(adjacencies & N_NORTHWEST)
nw = "1-f"
else
nw = "1-nw"
else
if(adjacencies & N_NORTH)
nw = "1-n"
else if(adjacencies & N_WEST)
nw = "1-w"
//NE CORNER
var/ne = "2-i"
if((adjacencies & N_NORTH) && (adjacencies & N_EAST))
if(adjacencies & N_NORTHEAST)
ne = "2-f"
else
ne = "2-ne"
else
if(adjacencies & N_NORTH)
ne = "2-n"
else if(adjacencies & N_EAST)
ne = "2-e"
//SW CORNER
var/sw = "3-i"
if((adjacencies & N_SOUTH) && (adjacencies & N_WEST))
if(adjacencies & N_SOUTHWEST)
sw = "3-f"
else
sw = "3-sw"
else
if(adjacencies & N_SOUTH)
sw = "3-s"
else if(adjacencies & N_WEST)
sw = "3-w"
//SE CORNER
var/se = "4-i"
if((adjacencies & N_SOUTH) && (adjacencies & N_EAST))
if(adjacencies & N_SOUTHEAST)
se = "4-f"
else
se = "4-se"
else
if(adjacencies & N_SOUTH)
se = "4-s"
else if(adjacencies & N_EAST)
se = "4-e"
if(A.top_left_corner != nw)
A.overlays -= A.top_left_corner
A.top_left_corner = nw
A.add_overlay(nw)
if(A.top_right_corner != ne)
A.overlays -= A.top_right_corner
A.top_right_corner = ne
A.add_overlay(ne)
if(A.bottom_right_corner != sw)
A.overlays -= A.bottom_right_corner
A.bottom_right_corner = sw
A.add_overlay(sw)
if(A.bottom_left_corner != se)
A.overlays -= A.bottom_left_corner
A.bottom_left_corner = se
A.add_overlay(se)
/proc/find_type_in_direction(atom/source, direction)
var/turf/target_turf = get_step(source, direction)
if(!target_turf)
return NULLTURF_BORDER
if(source.canSmoothWith)
var/atom/A
if(source.smooth & SMOOTH_MORE)
for(var/a_type in source.canSmoothWith)
if( istype(target_turf, a_type) )
return target_turf
A = locate(a_type) in target_turf
if(A)
return A
return null
for(var/a_type in source.canSmoothWith)
if(a_type == target_turf.type)
return target_turf
A = locate(a_type) in target_turf
if(A && A.type == a_type)
return A
return null
else
if(isturf(source))
return source.type == target_turf.type ? target_turf : null
var/atom/A = locate(source.type) in target_turf
return A && A.type == source.type ? A : null
//Icon smoothing helpers
/proc/smooth_zlevel(var/zlevel, now = FALSE)
var/list/away_turfs = block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel))
for(var/V in away_turfs)
var/turf/T = V
if(T.smooth)
if(now)
smooth_icon(T)
else
queue_smooth(T)
for(var/R in T)
var/atom/A = R
if(A.smooth)
if(now)
smooth_icon(A)
else
queue_smooth(A)
/atom/proc/clear_smooth_overlays()
overlays -= top_left_corner
top_left_corner = null
overlays -= top_right_corner
top_right_corner = null
overlays -= bottom_right_corner
bottom_right_corner = null
overlays -= bottom_left_corner
bottom_left_corner = null
/atom/proc/replace_smooth_overlays(nw, ne, sw, se)
clear_smooth_overlays()
top_left_corner = nw
add_overlay(nw)
top_right_corner = ne
add_overlay(ne)
bottom_left_corner = sw
add_overlay(sw)
bottom_right_corner = se
add_overlay(se)
/proc/reverse_ndir(ndir)
switch(ndir)
if(N_NORTH)
return NORTH
if(N_SOUTH)
return SOUTH
if(N_WEST)
return WEST
if(N_EAST)
return EAST
if(N_NORTHWEST)
return NORTHWEST
if(N_NORTHEAST)
return NORTHEAST
if(N_SOUTHEAST)
return SOUTHEAST
if(N_SOUTHWEST)
return SOUTHWEST
if(N_NORTH|N_WEST)
return NORTHWEST
if(N_NORTH|N_EAST)
return NORTHEAST
if(N_SOUTH|N_WEST)
return SOUTHWEST
if(N_SOUTH|N_EAST)
return SOUTHEAST
if(N_NORTH|N_WEST|N_NORTHWEST)
return NORTHWEST
if(N_NORTH|N_EAST|N_NORTHEAST)
return NORTHEAST
if(N_SOUTH|N_WEST|N_SOUTHWEST)
return SOUTHWEST
if(N_SOUTH|N_EAST|N_SOUTHEAST)
return SOUTHEAST
else
return 0
//SSicon_smooth
/proc/ss_smooth_icon(atom/A)
if(qdeleted(A))
return
if(!istype(A) || (A && !A.smooth))
return
if((A.smooth & SMOOTH_TRUE) || (A.smooth & SMOOTH_MORE))
var/adjacencies = calculate_adjacencies(A)
if(A.smooth & SMOOTH_DIAGONAL)
A.diagonal_smooth(adjacencies)
else
cardinal_smooth(A, adjacencies)
//SSicon_smooth
/proc/queue_smooth_neighbors(atom/A)
for(var/V in orange(1,A))
var/atom/T = V
if(T.smooth)
queue_smooth(T)
//SSicon_smooth
/proc/queue_smooth(atom/A)
if(SSicon_smooth)
SSicon_smooth.smooth_queue[A] = A
SSicon_smooth.can_fire = 1
else
smooth_icon(A)
//Example smooth wall
/turf/closed/wall/smooth
name = "smooth wall"
icon = 'icons/turf/smooth_wall.dmi'
icon_state = "smooth"
walltype = "shuttle"
smooth = SMOOTH_TRUE|SMOOTH_DIAGONAL|SMOOTH_BORDER
canSmoothWith = null
File diff suppressed because it is too large Load Diff
+388
View File
@@ -0,0 +1,388 @@
/*
* Holds procs to help with list operations
* Contains groups:
* Misc
* Sorting
*/
/*
* Misc
*/
//Returns a list in plain english as a string
/proc/english_list(list/input, nothing_text = "nothing", and_text = " and ", comma_text = ", ", final_comma_text = "" )
var/total = input.len
if (!total)
return "[nothing_text]"
else if (total == 1)
return "[input[1]]"
else if (total == 2)
return "[input[1]][and_text][input[2]]"
else
var/output = ""
var/index = 1
while (index < total)
if (index == total - 1)
comma_text = final_comma_text
output += "[input[index]][comma_text]"
index++
return "[output][and_text][input[index]]"
//Returns list element or null. Should prevent "index out of bounds" error.
/proc/listgetindex(list/L, index)
if(istype(L))
if(isnum(index) && IsInteger(index))
if(IsInRange(index,1,L.len))
return L[index]
else if(index in L)
return L[index]
return
//Return either pick(list) or null if list is not of type /list or is empty
/proc/safepick(list/L)
if(istype(L) && L.len)
return pick(L)
//Checks if the list is empty
/proc/isemptylist(list/L)
if(!L.len)
return 1
return 0
//Checks for specific types in a list
/proc/is_type_in_list(atom/A, list/L)
if(!L || !L.len || !A)
return 0
for(var/type in L)
if(istype(A, type))
return 1
return 0
//Checks for specific types in specifically structured (Assoc "type" = TRUE) lists ('typecaches')
/proc/is_type_in_typecache(atom/A, list/L)
if(!L || !L.len || !A)
return 0
return L[A.type]
//Like typesof() or subtypesof(), but returns a typecache instead of a list
/proc/typecacheof(path, ignore_root_path)
if(ispath(path))
var/list/types = ignore_root_path ? subtypesof(path) : typesof(path)
var/list/L = list()
for(var/T in types)
L[T] = TRUE
return L
else if(islist(path))
var/list/pathlist = path
var/list/L = list()
if(ignore_root_path)
for(var/P in pathlist)
for(var/T in subtypesof(P))
L[T] = TRUE
else
for(var/P in pathlist)
for(var/T in typesof(P))
L[T] = TRUE
return L
//Empties the list by setting the length to 0. Hopefully the elements get garbage collected
/proc/clearlist(list/list)
if(istype(list))
list.len = 0
return
//Removes any null entries from the list
/proc/listclearnulls(list/L)
if(istype(L))
var/i=1
for(var/thing in L)
if(thing != null)
++i
continue
L.Cut(i,i+1)
/*
* Returns list containing all the entries from first list that are not present in second.
* If skiprep = 1, repeated elements are treated as one.
* If either of arguments is not a list, returns null
*/
/proc/difflist(list/first, list/second, skiprep=0)
if(!islist(first) || !islist(second))
return
var/list/result = new
if(skiprep)
for(var/e in first)
if(!(e in result) && !(e in second))
result += e
else
result = first - second
return result
/*
* Returns list containing entries that are in either list but not both.
* If skipref = 1, repeated elements are treated as one.
* If either of arguments is not a list, returns null
*/
/proc/uniquemergelist(list/first, list/second, skiprep=0)
if(!islist(first) || !islist(second))
return
var/list/result = new
if(skiprep)
result = difflist(first, second, skiprep)+difflist(second, first, skiprep)
else
result = first ^ second
return result
//Pretends to pick an element based on its weight but really just seems to pick a random element.
/proc/pickweight(list/L)
var/total = 0
var/item
for (item in L)
if (!L[item])
L[item] = 1
total += L[item]
total = rand(1, total)
for (item in L)
total -=L [item]
if (total <= 0)
return item
return null
//Pick a random element from the list and remove it from the list.
/proc/pick_n_take(list/L)
if(L.len)
var/picked = rand(1,L.len)
. = L[picked]
L.Cut(picked,picked+1) //Cut is far more efficient that Remove()
//Returns the top(last) element from the list and removes it from the list (typical stack function)
/proc/pop(list/L)
if(L.len)
. = L[L.len]
L.len--
/proc/popleft(list/L)
if(L.len)
. = L[1]
L.Cut(1,2)
/proc/sorted_insert(list/L, thing, comparator)
var/pos = L.len
while(pos > 0 && call(comparator)(thing, L[pos]) > 0)
pos--
L.Insert(pos+1, thing)
// Returns the next item in a list
/proc/next_list_item(item, list/L)
var/i
i = L.Find(item)
if(i == L.len)
i = 1
else
i++
return L[i]
// Returns the previous item in a list
/proc/previous_list_item(item, list/L)
var/i
i = L.Find(item)
if(i == 1)
i = L.len
else
i--
return L[i]
/*
* Sorting
*/
/*
//Reverses the order of items in the list
/proc/reverselist(list/input)
var/list/output = list()
for(var/i = input.len; i >= 1; i--)
output += input[i]
return output
*/
//Randomize: Return the list in a random order
/proc/shuffle(list/L)
if(!L)
return
L = L.Copy()
for(var/i=1, i<L.len, ++i)
L.Swap(i,rand(i,L.len))
return L
//Return a list with no duplicate entries
/proc/uniqueList(list/L)
. = list()
for(var/i in L)
. |= i
//for sorting clients or mobs by ckey
/proc/sortKey(list/L, order=1)
return sortTim(L, order >= 0 ? /proc/cmp_ckey_asc : /proc/cmp_ckey_dsc)
//Specifically for record datums in a list.
/proc/sortRecord(list/L, field = "name", order = 1)
cmp_field = field
return sortTim(L, order >= 0 ? /proc/cmp_records_asc : /proc/cmp_records_dsc)
//any value in a list
/proc/sortList(list/L, cmp=/proc/cmp_text_asc)
return sortTim(L.Copy(), cmp)
//uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
/proc/sortNames(list/L, order=1)
return sortTim(L, order >= 0 ? /proc/cmp_name_asc : /proc/cmp_name_dsc)
//Converts a bitfield to a list of numbers (or words if a wordlist is provided)
/proc/bitfield2list(bitfield = 0, list/wordlist)
var/list/r = list()
if(istype(wordlist,/list))
var/max = min(wordlist.len,16)
var/bit = 1
for(var/i=1, i<=max, i++)
if(bitfield & bit)
r += wordlist[i]
bit = bit << 1
else
for(var/bit=1, bit<=65535, bit = bit << 1)
if(bitfield & bit)
r += bit
return r
// Returns the key based on the index
#define KEYBYINDEX(L, index) (((index <= L:len) && (index > 0)) ? L[index] : null)
/proc/count_by_type(list/L, type)
var/i = 0
for(var/T in L)
if(istype(T, type))
i++
return i
/proc/find_record(field, value, list/L)
for(var/datum/data/record/R in L)
if(R.fields[field] == value)
return R
//Move a single element from position fromIndex within a list, to position toIndex
//All elements in the range [1,toIndex) before the move will be before the pivot afterwards
//All elements in the range [toIndex, L.len+1) before the move will be after the pivot afterwards
//In other words, it's as if the range [fromIndex,toIndex) have been rotated using a <<< operation common to other languages.
//fromIndex and toIndex must be in the range [1,L.len+1]
//This will preserve associations ~Carnie
/proc/moveElement(list/L, fromIndex, toIndex)
if(fromIndex == toIndex || fromIndex+1 == toIndex) //no need to move
return
if(fromIndex > toIndex)
++fromIndex //since a null will be inserted before fromIndex, the index needs to be nudged right by one
L.Insert(toIndex, null)
L.Swap(fromIndex, toIndex)
L.Cut(fromIndex, fromIndex+1)
//Move elements [fromIndex,fromIndex+len) to [toIndex-len, toIndex)
//Same as moveElement but for ranges of elements
//This will preserve associations ~Carnie
/proc/moveRange(list/L, fromIndex, toIndex, len=1)
var/distance = abs(toIndex - fromIndex)
if(len >= distance) //there are more elements to be moved than the distance to be moved. Therefore the same result can be achieved (with fewer operations) by moving elements between where we are and where we are going. The result being, our range we are moving is shifted left or right by dist elements
if(fromIndex <= toIndex)
return //no need to move
fromIndex += len //we want to shift left instead of right
for(var/i=0, i<distance, ++i)
L.Insert(fromIndex, null)
L.Swap(fromIndex, toIndex)
L.Cut(toIndex, toIndex+1)
else
if(fromIndex > toIndex)
fromIndex += len
for(var/i=0, i<len, ++i)
L.Insert(toIndex, null)
L.Swap(fromIndex, toIndex)
L.Cut(fromIndex, fromIndex+1)
//Move elements from [fromIndex, fromIndex+len) to [toIndex, toIndex+len)
//Move any elements being overwritten by the move to the now-empty elements, preserving order
//Note: if the two ranges overlap, only the destination order will be preserved fully, since some elements will be within both ranges ~Carnie
/proc/swapRange(list/L, fromIndex, toIndex, len=1)
var/distance = abs(toIndex - fromIndex)
if(len > distance) //there is an overlap, therefore swapping each element will require more swaps than inserting new elements
if(fromIndex < toIndex)
toIndex += len
else
fromIndex += len
for(var/i=0, i<distance, ++i)
L.Insert(fromIndex, null)
L.Swap(fromIndex, toIndex)
L.Cut(toIndex, toIndex+1)
else
if(toIndex > fromIndex)
var/a = toIndex
toIndex = fromIndex
fromIndex = a
for(var/i=0, i<len, ++i)
L.Swap(fromIndex++, toIndex++)
//replaces reverseList ~Carnie
/proc/reverseRange(list/L, start=1, end=0)
if(L.len)
start = start % L.len
end = end % (L.len+1)
if(start <= 0)
start += L.len
if(end <= 0)
end += L.len + 1
--end
while(start < end)
L.Swap(start++,end--)
return L
//return first thing in L which has var/varname == value
//this is typecaste as list/L, but you could actually feed it an atom instead.
//completely safe to use
/proc/getElementByVar(list/L, varname, value)
varname = "[varname]"
for(var/datum/D in L)
if(D.vars.Find(varname))
if(D.vars[varname] == value)
return D
//remove all nulls from a list
/proc/removeNullsFromList(list/L)
while(L.Remove(null))
continue
return L
//Copies a list, and all lists inside it recusively
//Does not copy any other reference type
/proc/deepCopyList(list/l)
if(!islist(l))
return l
. = l.Copy()
for(var/i = 1 to l.len)
if(islist(.[i]))
.[i] = .(.[i])
//Picks from the list, with some safeties, and returns the "default" arg if it fails
#define DEFAULTPICK(L, default) ((istype(L, /list) && L:len) ? pick(L) : default)
+167
View File
@@ -0,0 +1,167 @@
// Credits to Nickr5 for the useful procs I've taken from his library resource.
var/const/E = 2.71828183
var/const/Sqrt2 = 1.41421356
// List of square roots for the numbers 1-100.
var/list/sqrtTable = list(1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10)
/proc/sign(x)
return x!=0?x/abs(x):0
/proc/Atan2(x, y)
if(!x && !y) return 0
var/a = arccos(x / sqrt(x*x + y*y))
return y >= 0 ? a : -a
/proc/Ceiling(x, y=1)
return -round(-x / y) * y
#define Clamp(CLVALUE,CLMIN,CLMAX) ( max( (CLMIN), min((CLVALUE), (CLMAX)) ) )
// cotangent
/proc/Cot(x)
return 1 / Tan(x)
// cosecant
/proc/Csc(x)
return 1 / sin(x)
/proc/Default(a, b)
return a ? a : b
// Greatest Common Divisor - Euclid's algorithm
/proc/Gcd(a, b)
return b ? Gcd(b, a % b) : a
/proc/Inverse(x)
return 1 / x
/proc/IsAboutEqual(a, b, deviation = 0.1)
return abs(a - b) <= deviation
/proc/IsEven(x)
return x % 2 == 0
// Returns true if val is from min to max, inclusive.
/proc/IsInRange(val, min, max)
return min <= val && val <= max
/proc/IsInteger(x)
return round(x) == x
/proc/IsOdd(x)
return !IsEven(x)
/proc/IsMultiple(x, y)
return x % y == 0
// Least Common Multiple
/proc/Lcm(a, b)
return abs(a) / Gcd(a, b) * abs(b)
// Performs a linear interpolation between a and b.
// Note that amount=0 returns a, amount=1 returns b, and
// amount=0.5 returns the mean of a and b.
/proc/Lerp(a, b, amount = 0.5)
return a + (b - a) * amount
//Calculates the sum of a list of numbers.
/proc/Sum(var/list/data)
. = 0
for(var/val in data)
.+= val
//Calculates the mean of a list of numbers.
/proc/Mean(var/list/data)
. = Sum(data) / (data.len)
// Returns the nth root of x.
/proc/Root(n, x)
return x ** (1 / n)
// secant
/proc/Sec(x)
return 1 / cos(x)
// The quadratic formula. Returns a list with the solutions, or an empty list
// if they are imaginary.
/proc/SolveQuadratic(a, b, c)
ASSERT(a)
. = list()
var/d = b*b - 4 * a * c
var/bottom = 2 * a
if(d < 0) return
var/root = sqrt(d)
. += (-b + root) / bottom
if(!d) return
. += (-b - root) / bottom
// tangent
/proc/Tan(x)
return sin(x) / cos(x)
/proc/ToDegrees(radians)
// 180 / Pi
return radians * 57.2957795
/proc/ToRadians(degrees)
// Pi / 180
return degrees * 0.0174532925
// Will filter out extra rotations and negative rotations
// E.g: 540 becomes 180. -180 becomes 180.
/proc/SimplifyDegrees(degrees)
degrees = degrees % 360
if(degrees < 0)
degrees += 360
return degrees
// min is inclusive, max is exclusive
/proc/Wrap(val, min, max)
var/d = max - min
var/t = round((val - min) / d)
return val - (t * d)
//A logarithm that converts an integer to a number scaled between 0 and 1 (can be tweaked to be higher).
//Currently, this is used for hydroponics-produce sprite transforming, but could be useful for other transform functions.
/proc/TransformUsingVariable(input, inputmaximum, scaling_modifier = 0)
var/inputToDegrees = (input/inputmaximum)*180 //Converting from a 0 -> 100 scale to a 0 -> 180 scale. The 0 -> 180 scale corresponds to degrees
var/size_factor = ((-cos(inputToDegrees) +1) /2) //returns a value from 0 to 1
return size_factor + scaling_modifier //scale mod of 0 results in a number from 0 to 1. A scale modifier of +0.5 returns 0.5 to 1.5
//world<< "Transform multiplier of [src] is [size_factor + scaling_modifer]"
//converts a uniform distributed random number into a normal distributed one
//since this method produces two random numbers, one is saved for subsequent calls
//(making the cost negligble for every second call)
//This will return +/- decimals, situated about mean with standard deviation stddev
//68% chance that the number is within 1stddev
//95% chance that the number is within 2stddev
//98% chance that the number is within 3stddev...etc
var/gaussian_next
#define ACCURACY 10000
/proc/gaussian(mean, stddev)
var/R1;var/R2;var/working
if(gaussian_next != null)
R1 = gaussian_next
gaussian_next = null
else
do
R1 = rand(-ACCURACY,ACCURACY)/ACCURACY
R2 = rand(-ACCURACY,ACCURACY)/ACCURACY
working = R1*R1 + R2*R2
while(working >= 1 || working==0)
working = sqrt(-2 * log(working) / working)
R1 *= working
gaussian_next = R2 * working
return (mean + stddev * R1)
#undef ACCURACY
+153
View File
@@ -0,0 +1,153 @@
/matrix/proc/TurnTo(old_angle, new_angle)
. = new_angle - old_angle
Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT
/atom/proc/SpinAnimation(speed = 10, loops = -1, clockwise = 1, segments = 3)
if(!segments)
return
var/segment = 360/segments
if(!clockwise)
segment = -segment
var/list/matrices = list()
for(var/i in 1 to segments-1)
var/matrix/M = matrix(transform)
M.Turn(segment*i)
matrices += M
var/matrix/last = matrix(transform)
matrices += last
speed /= segments
animate(src, transform = matrices[1], time = speed, loops)
for(var/i in 2 to segments) //2 because 1 is covered above
animate(transform = matrices[i], time = speed)
//doesn't have an object argument because this is "Stacking" with the animate call above
//3 billion% intentional
//Dumps the matrix data in format a-f
/matrix/proc/tolist()
. = list()
. += a
. += b
. += c
. += d
. += e
. += f
//Dumps the matrix data in a matrix-grid format
/*
a d 0
b e 0
c f 1
*/
/matrix/proc/togrid()
. = list()
. += a
. += d
. += 0
. += b
. += e
. += 0
. += c
. += f
. += 1
//The X pixel offset of this matrix
/matrix/proc/get_x_shift()
. = c
//The Y pixel offset of this matrix
/matrix/proc/get_y_shift()
. = f
// Color matrices:
//Luma coefficients suggested for HDTVs. If you change these, make sure they add up to 1.
#define LUMR 0.2126
#define LUMG 0.7152
#define LUMB 0.0722
//Still need color matrix addition, negation, and multiplication.
//Returns an identity color matrix which does nothing
/proc/color_identity()
return list(1,0,0, 0,1,0, 0,0,1)
//Moves all colors angle degrees around the color wheel while maintaining intensity of the color and not affecting whites
//TODO: Need a version that only affects one color (ie shift red to blue but leave greens and blues alone)
/proc/color_rotation(angle)
if(angle == 0)
return color_identity()
angle = Clamp(angle, -180, 180)
var/cos = cos(angle)
var/sin = sin(angle)
var/constA = 0.143
var/constB = 0.140
var/constC = -0.283
return list(
LUMR + cos * (1-LUMR) + sin * -LUMR, LUMR + cos * -LUMR + sin * constA, LUMR + cos * -LUMR + sin * -(1-LUMR),
LUMG + cos * -LUMG + sin * -LUMG, LUMG + cos * (1-LUMG) + sin * constB, LUMG + cos * -LUMG + sin * LUMG,
LUMB + cos * -LUMB + sin * (1-LUMB), LUMB + cos * -LUMB + sin * constC, LUMB + cos * (1-LUMB) + sin * LUMB
)
//Makes everything brighter or darker without regard to existing color or brightness
/proc/color_brightness(power)
power = Clamp(power, -255, 255)
power = power/255
return list(1,0,0, 0,1,0, 0,0,1, power,power,power)
/var/list/delta_index = list(
0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11,
0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24,
0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42,
0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68,
0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98,
1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54,
1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25,
2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8,
4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0,
7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8,
10.0)
//Exxagerates or removes brightness
/proc/color_contrast(value)
value = Clamp(value, -100, 100)
if(value == 0)
return color_identity()
var/x = 0
if (value < 0)
x = 127 + value / 100 * 127;
else
x = value % 1
if(x == 0)
x = delta_index[value]
else
x = delta_index[value] * (1-x) + delta_index[value+1] * x//use linear interpolation for more granularity.
x = x * 127 + 127
var/mult = x / 127
var/add = 0.5 * (127-x) / 255
return list(mult,0,0, 0,mult,0, 0,0,mult, add,add,add)
//Exxagerates or removes colors
/proc/color_saturation(value as num)
if(value == 0)
return color_identity()
value = Clamp(value, -100, 100)
if(value > 0)
value *= 3
var/x = 1 + value / 100
var/inv = 1 - x
var/R = LUMR * inv
var/G = LUMG * inv
var/B = LUMB * inv
return list(R + x,R,R, G,G + x,G, B,B,B + x)
#undef LUMR
#undef LUMG
#undef LUMB
+362
View File
@@ -0,0 +1,362 @@
/proc/random_blood_type()
return pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
/proc/random_eye_color()
switch(pick(20;"brown",20;"hazel",20;"grey",15;"blue",15;"green",1;"amber",1;"albino"))
if("brown")
return "630"
if("hazel")
return "542"
if("grey")
return pick("666","777","888","999","aaa","bbb","ccc")
if("blue")
return "36c"
if("green")
return "060"
if("amber")
return "fc0"
if("albino")
return pick("c","d","e","f") + pick("0","1","2","3","4","5","6","7","8","9") + pick("0","1","2","3","4","5","6","7","8","9")
else
return "000"
/proc/random_underwear(gender)
if(!underwear_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/underwear, underwear_list, underwear_m, underwear_f)
switch(gender)
if(MALE)
return pick(underwear_m)
if(FEMALE)
return pick(underwear_f)
else
return pick(underwear_list)
/proc/random_undershirt(gender)
if(!undershirt_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/undershirt, undershirt_list, undershirt_m, undershirt_f)
switch(gender)
if(MALE)
return pick(undershirt_m)
if(FEMALE)
return pick(undershirt_f)
else
return pick(undershirt_list)
/proc/random_socks()
if(!socks_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, socks_list)
return pick(socks_list)
/proc/random_features()
if(!tails_list_human.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, tails_list_human)
if(!tails_list_lizard.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, tails_list_lizard)
if(!snouts_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts, snouts_list)
if(!horns_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, horns_list)
if(!ears_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, horns_list)
if(!frills_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, frills_list)
if(!spines_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, spines_list)
if(!body_markings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, body_markings_list)
if(!wings_list.len)
init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, wings_list)
//For now we will always return none for tail_human and ears.
return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), "tail_lizard" = pick(tails_list_lizard), "tail_human" = "None", "wings" = "None", "snout" = pick(snouts_list), "horns" = pick(horns_list), "ears" = "None", "frills" = pick(frills_list), "spines" = pick(spines_list), "body_markings" = pick(body_markings_list)))
/proc/random_hair_style(gender)
switch(gender)
if(MALE)
return pick(hair_styles_male_list)
if(FEMALE)
return pick(hair_styles_female_list)
else
return pick(hair_styles_list)
/proc/random_facial_hair_style(gender)
switch(gender)
if(MALE)
return pick(facial_hair_styles_male_list)
if(FEMALE)
return pick(facial_hair_styles_female_list)
else
return pick(facial_hair_styles_list)
/proc/random_unique_name(gender, attempts_to_find_unique_name=10)
for(var/i=1, i<=attempts_to_find_unique_name, i++)
if(gender==FEMALE)
. = capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
else
. = capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
if(i != attempts_to_find_unique_name && !findname(.))
break
/proc/random_unique_lizard_name(gender, attempts_to_find_unique_name=10)
for(var/i=1, i<=attempts_to_find_unique_name, i++)
. = capitalize(lizard_name(gender))
if(i != attempts_to_find_unique_name && !findname(.))
break
/proc/random_skin_tone()
return pick(skin_tones)
var/list/skin_tones = list(
"albino",
"caucasian1",
"caucasian2",
"caucasian3",
"latino",
"mediterranean",
"asian1",
"asian2",
"arab",
"indian",
"african1",
"african2"
)
var/global/list/species_list[0]
var/global/list/roundstart_species[0]
/proc/age2agedescription(age)
switch(age)
if(0 to 1)
return "infant"
if(1 to 3)
return "toddler"
if(3 to 13)
return "child"
if(13 to 19)
return "teenager"
if(19 to 30)
return "young adult"
if(30 to 45)
return "adult"
if(45 to 60)
return "middle-aged"
if(60 to 70)
return "aging"
if(70 to INFINITY)
return "elderly"
else
return "unknown"
/*
Proc for attack log creation, because really why not
1 argument is the actor
2 argument is the target of action
3 is the description of action(like punched, throwed, or any other verb)
4 should it make adminlog note or not
5 is the tool with which the action was made(usually item) 5 and 6 are very similar(5 have "by " before it, that it) and are separated just to keep things in a bit more in order
6 is additional information, anything that needs to be added
*/
/proc/add_logs(mob/user, mob/target, what_done, object=null, addition=null)
var/newhealthtxt = ""
var/coordinates = ""
var/turf/attack_location = get_turf(target)
if(attack_location)
coordinates = "([attack_location.x],[attack_location.y],[attack_location.z])"
if(target && isliving(target))
var/mob/living/L = target
newhealthtxt = " (NEWHP: [L.health])"
if(user && ismob(user))
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
if(user.mind)
user.mind.attack_log += text("\[[time_stamp()]\] <font color='red'>[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
if(target && ismob(target))
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
if(target.mind)
target.mind.attack_log += text("\[[time_stamp()]\] <font color='orange'>[target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
log_attack("[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]")
/proc/do_mob(mob/user , mob/target, time = 30, uninterruptible = 0, progress = 1)
if(!user || !target)
return 0
var/user_loc = user.loc
var/drifting = 0
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = 1
var/target_loc = target.loc
var/holding = user.get_active_hand()
var/datum/progressbar/progbar
if (progress)
progbar = new(user, time, target)
var/endtime = world.time+time
var/starttime = world.time
. = 1
while (world.time < endtime)
stoplag()
if (progress)
progbar.update(world.time - starttime)
if(!user || !target)
. = 0
break
if(uninterruptible)
continue
if(drifting && !user.inertia_dir)
drifting = 0
user_loc = user.loc
if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying )
. = 0
break
if (progress)
qdel(progbar)
/proc/do_after(mob/user, delay, needhand = 1, atom/target = null, progress = 1)
if(!user)
return 0
var/atom/Tloc = null
if(target)
Tloc = target.loc
var/atom/Uloc = user.loc
var/drifting = 0
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = 1
var/holding = user.get_active_hand()
var/holdingnull = 1 //User's hand started out empty, check for an empty hand
if(holding)
holdingnull = 0 //Users hand started holding something, check to see if it's still holding that
var/datum/progressbar/progbar
if (progress)
progbar = new(user, delay, target)
var/endtime = world.time + delay
var/starttime = world.time
. = 1
while (world.time < endtime)
stoplag()
if (progress)
progbar.update(world.time - starttime)
if(drifting && !user.inertia_dir)
drifting = 0
Uloc = user.loc
if(!user || user.stat || user.weakened || user.stunned || (!drifting && user.loc != Uloc))
. = 0
break
if(Tloc && (!target || Tloc != target.loc))
. = 0
break
if(needhand)
//This might seem like an odd check, but you can still need a hand even when it's empty
//i.e the hand is used to pull some item/tool out of the construction
if(!holdingnull)
if(!holding)
. = 0
break
if(user.get_active_hand() != holding)
. = 0
break
if (progress)
qdel(progbar)
/proc/do_after_mob(mob/user, var/list/targets, time = 30, uninterruptible = 0, progress = 1)
if(!user || !targets)
return 0
if(!islist(targets))
targets = list(targets)
var/user_loc = user.loc
var/drifting = 0
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = 1
var/list/originalloc = list()
for(var/atom/target in targets)
originalloc[target] = target.loc
var/holding = user.get_active_hand()
var/datum/progressbar/progbar
if(progress)
progbar = new(user, time, targets[1])
var/endtime = world.time + time
var/starttime = world.time
. = 1
mainloop:
while(world.time < endtime)
sleep(1)
if(progress)
progbar.update(world.time - starttime)
if(!user || !targets)
. = 0
break
if(uninterruptible)
continue
if(drifting && !user.inertia_dir)
drifting = 0
user_loc = user.loc
for(var/atom/target in targets)
if((!drifting && user_loc != user.loc) || originalloc[target] != target.loc || user.get_active_hand() != holding || user.incapacitated() || user.lying )
. = 0
break mainloop
if(progbar)
qdel(progbar)
/proc/is_species(A, species_datum)
. = FALSE
if(ishuman(A))
var/mob/living/carbon/human/H = A
if(H.dna && istype(H.dna.species, species_datum))
. = TRUE
/proc/deadchat_broadcast(message, mob/follow_target=null, speaker_key=null, message_type=DEADCHAT_REGULAR)
for(var/mob/M in player_list)
var/datum/preferences/prefs
if(M.client && M.client.prefs)
prefs = M.client.prefs
else
prefs = new
var/adminoverride = 0
if(M.client && M.client.holder && (prefs.chat_toggles & CHAT_DEAD))
adminoverride = 1
if(istype(M, /mob/new_player) && !adminoverride)
continue
if(M.stat != DEAD && !adminoverride)
continue
if(speaker_key && speaker_key in prefs.ignoring)
continue
switch(message_type)
if(DEADCHAT_DEATHRATTLE)
if(prefs.toggles & DISABLE_DEATHRATTLE)
continue
if(DEADCHAT_ARRIVALRATTLE)
if(prefs.toggles & DISABLE_ARRIVALRATTLE)
continue
if(istype(M, /mob/dead/observer) && follow_target)
var/link = FOLLOW_LINK(M, follow_target)
M << "[link] [message]"
else
M << "[message]"
+225
View File
@@ -0,0 +1,225 @@
/proc/lizard_name(gender)
if(gender == MALE)
return "[pick(lizard_names_male)]-[pick(lizard_names_male)]"
else
return "[pick(lizard_names_female)]-[pick(lizard_names_female)]"
var/church_name = null
/proc/church_name()
if (church_name)
return church_name
var/name = ""
name += pick("Holy", "United", "First", "Second", "Last")
if (prob(20))
name += " Space"
name += " " + pick("Church", "Cathedral", "Body", "Worshippers", "Movement", "Witnesses")
name += " of [religion_name()]"
return name
var/command_name = null
/proc/command_name()
if (command_name)
return command_name
var/name = "Central Command"
command_name = name
return name
/proc/change_command_name(name)
command_name = name
return name
var/religion_name = null
/proc/religion_name()
if (religion_name)
return religion_name
var/name = ""
name += pick("bee", "science", "edu", "captain", "assistant", "monkey", "alien", "space", "unit", "sprocket", "gadget", "bomb", "revolution", "beyond", "station", "goon", "robot", "ivor", "hobnob")
name += pick("ism", "ia", "ology", "istism", "ites", "ick", "ian", "ity")
return capitalize(name)
/proc/station_name()
if(station_name)
return station_name
if(config && config.station_name)
station_name = config.station_name
else
station_name = new_station_name()
if(config && config.server_name)
world.name = "[config.server_name][config.server_name==station_name ? "" : ": [station_name]"]"
else
world.name = station_name
return station_name
/proc/new_station_name()
var/random = rand(1,5)
var/name = ""
var/new_station_name = ""
//Rare: Pre-Prefix
if (prob(10))
name = pick(station_prefixes)
new_station_name = name + " "
name = ""
// Prefix
for(var/holiday_name in SSevent.holidays)
if(holiday_name == "Friday the 13th")
random = 13
var/datum/holiday/holiday = SSevent.holidays[holiday_name]
name = holiday.getStationPrefix()
//get normal name
if(!name)
name = pick(station_names)
if(name)
new_station_name += name + " "
// Suffix
name = pick(station_suffixes)
new_station_name += name + " "
// ID Number
switch(random)
if(1)
new_station_name += "[rand(1, 99)]"
if(2)
new_station_name += pick(greek_letters)
if(3)
new_station_name += pick(roman_numerals)
if(4)
new_station_name += pick(phonetic_alphabet)
if(5)
new_station_name += pick(numbers_as_words)
if(13)
new_station_name += pick("13","XIII","Thirteen")
return new_station_name
var/syndicate_name = null
/proc/syndicate_name()
if (syndicate_name)
return syndicate_name
var/name = ""
// Prefix
name += pick("Clandestine", "Prima", "Blue", "Zero-G", "Max", "Blasto", "Waffle", "North", "Omni", "Newton", "Cyber", "Bonk", "Gene", "Gib")
// Suffix
if (prob(80))
name += " "
// Full
if (prob(60))
name += pick("Syndicate", "Consortium", "Collective", "Corporation", "Group", "Holdings", "Biotech", "Industries", "Systems", "Products", "Chemicals", "Enterprises", "Family", "Creations", "International", "Intergalactic", "Interplanetary", "Foundation", "Positronics", "Hive")
// Broken
else
name += pick("Syndi", "Corp", "Bio", "System", "Prod", "Chem", "Inter", "Hive")
name += pick("", "-")
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Code")
// Small
else
name += pick("-", "*", "")
name += pick("Tech", "Sun", "Co", "Tek", "X", "Inc", "Gen", "Star", "Dyne", "Code", "Hive")
syndicate_name = name
return name
//Traitors and traitor silicons will get these. Revs will not.
var/syndicate_code_phrase//Code phrase for traitors.
var/syndicate_code_response//Code response for traitors.
/*
Should be expanded.
How this works:
Instead of "I'm looking for James Smith," the traitor would say "James Smith" as part of a conversation.
Another traitor may then respond with: "They enjoy running through the void-filled vacuum of the derelict."
The phrase should then have the words: James Smith.
The response should then have the words: run, void, and derelict.
This way assures that the code is suited to the conversation and is unpredicatable.
Obviously, some people will be better at this than others but in theory, everyone should be able to do it and it only enhances roleplay.
Can probably be done through "{ }" but I don't really see the practical benefit.
One example of an earlier system is commented below.
/N
*/
/proc/generate_code_phrase()//Proc is used for phrase and response in master_controller.dm
var/code_phrase = ""//What is returned when the proc finishes.
var/words = pick(//How many words there will be. Minimum of two. 2, 4 and 5 have a lesser chance of being selected. 3 is the most likely.
50; 2,
200; 3,
50; 4,
25; 5
)
var/safety[] = list(1,2,3)//Tells the proc which options to remove later on.
var/nouns[] = list("love","hate","anger","peace","pride","sympathy","bravery","loyalty","honesty","integrity","compassion","charity","success","courage","deceit","skill","beauty","brilliance","pain","misery","beliefs","dreams","justice","truth","faith","liberty","knowledge","thought","information","culture","trust","dedication","progress","education","hospitality","leisure","trouble","friendships", "relaxation")
var/drinks[] = list("vodka and tonic","gin fizz","bahama mama","manhattan","black Russian","whiskey soda","long island tea","margarita","Irish coffee"," manly dwarf","Irish cream","doctor's delight","Beepksy Smash","tequila sunrise","brave bull","gargle blaster","bloody mary","whiskey cola","white Russian","vodka martini","martini","Cuba libre","kahlua","vodka","wine","moonshine")
var/locations[] = teleportlocs.len ? teleportlocs : drinks//if null, defaults to drinks instead.
var/names[] = list()
for(var/datum/data/record/t in data_core.general)//Picks from crew manifest.
names += t.fields["name"]
var/maxwords = words//Extra var to check for duplicates.
for(words,words>0,words--)//Randomly picks from one of the choices below.
if(words==1&&(1 in safety)&&(2 in safety))//If there is only one word remaining and choice 1 or 2 have not been selected.
safety = list(pick(1,2))//Select choice 1 or 2.
else if(words==1&&maxwords==2)//Else if there is only one word remaining (and there were two originally), and 1 or 2 were chosen,
safety = list(3)//Default to list 3
switch(pick(safety))//Chance based on the safety list.
if(1)//1 and 2 can only be selected once each to prevent more than two specific names/places/etc.
switch(rand(1,2))//Mainly to add more options later.
if(1)
if(names.len&&prob(70))
code_phrase += pick(names)
else
if(prob(10))
code_phrase += pick(lizard_name(MALE),lizard_name(FEMALE))
else
code_phrase += pick(pick(first_names_male,first_names_female))
code_phrase += " "
code_phrase += pick(last_names)
if(2)
code_phrase += pick(get_all_jobs())//Returns a job.
safety -= 1
if(2)
switch(rand(1,2))//Places or things.
if(1)
code_phrase += pick(drinks)
if(2)
code_phrase += pick(locations)
safety -= 2
if(3)
switch(rand(1,3))//Nouns, adjectives, verbs. Can be selected more than once.
if(1)
code_phrase += pick(nouns)
if(2)
code_phrase += pick(adjectives)
if(3)
code_phrase += pick(verbs)
if(words==1)
code_phrase += "."
else
code_phrase += ", "
return code_phrase
+14
View File
@@ -0,0 +1,14 @@
// Ensure the frequency is within bounds of what it should be sending/recieving at
/proc/sanitize_frequency(frequency, free = FALSE)
. = round(frequency)
if(free)
. = Clamp(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ)
else
. = Clamp(frequency, MIN_FREQ, MAX_FREQ)
if(!(. % 2)) // Ensure the last digit is an odd number
. += 1
// Format frequency by moving the decimal.
/proc/format_frequency(frequency)
frequency = text2num(frequency)
return "[round(frequency / 10)].[frequency % 10]"
+74
View File
@@ -0,0 +1,74 @@
//general stuff
/proc/sanitize_integer(number, min=0, max=1, default=0)
if(isnum(number))
number = round(number)
if(min <= number && number <= max)
return number
return default
/proc/sanitize_text(text, default="")
if(istext(text))
return text
return default
/proc/sanitize_inlist(value, list/List, default)
if(value in List)
return value
if(default)
return default
if(List && List.len)
return pick(List)
//more specialised stuff
/proc/sanitize_gender(gender,neuter=0,plural=0, default="male")
switch(gender)
if(MALE, FEMALE)
return gender
if(NEUTER)
if(neuter)
return gender
else
return default
if(PLURAL)
if(plural)
return gender
else
return default
return default
/proc/sanitize_hexcolor(color, desired_format=3, include_crunch=0, default)
var/crunch = include_crunch ? "#" : ""
if(!istext(color))
color = ""
var/start = 1 + (text2ascii(color,1)==35)
var/len = length(color)
var/step_size = 1 + ((len+1)-start != desired_format)
. = ""
for(var/i=start, i<=len, i+=step_size)
var/ascii = text2ascii(color,i)
switch(ascii)
if(48 to 57)
. += ascii2text(ascii) //numbers 0 to 9
if(97 to 102)
. += ascii2text(ascii) //letters a to f
if(65 to 70)
. += ascii2text(ascii+32) //letters A to F - translates to lowercase
else
break
if(length(.) != desired_format)
if(default)
return default
return crunch + repeat_string(desired_format, "0")
return crunch + .
/proc/sanitize_ooccolor(color)
var/list/HSL = rgb2hsl(hex2num(copytext(color,2,4)),hex2num(copytext(color,4,6)),hex2num(copytext(color,6,8)))
HSL[3] = min(HSL[3],0.4)
var/list/RGB = hsl2rgb(arglist(HSL))
return "#[num2hex(RGB[1],2)][num2hex(RGB[2],2)][num2hex(RGB[3],2)]"
+16
View File
@@ -0,0 +1,16 @@
//simple insertion sort - generally faster than merge for runs of 7 or smaller
/proc/sortInsert(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex=0)
if(L && L.len >= 2)
fromIndex = fromIndex % L.len
toIndex = toIndex % (L.len+1)
if(fromIndex <= 0)
fromIndex += L.len
if(toIndex <= 0)
toIndex += L.len + 1
sortInstance.L = L
sortInstance.cmp = cmp
sortInstance.associative = associative
sortInstance.binarySort(fromIndex, toIndex, fromIndex)
return L
+16
View File
@@ -0,0 +1,16 @@
//merge-sort - gernerally faster than insert sort, for runs of 7 or larger
/proc/sortMerge(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex)
if(L && L.len >= 2)
fromIndex = fromIndex % L.len
toIndex = toIndex % (L.len+1)
if(fromIndex <= 0)
fromIndex += L.len
if(toIndex <= 0)
toIndex += L.len + 1
sortInstance.L = L
sortInstance.cmp = cmp
sortInstance.associative = associative
sortInstance.mergeSort(fromIndex, toIndex)
return L
+17
View File
@@ -0,0 +1,17 @@
//TimSort interface
/proc/sortTim(list/L, cmp=/proc/cmp_numeric_asc, associative, fromIndex=1, toIndex=0)
if(L && L.len >= 2)
fromIndex = fromIndex % L.len
toIndex = toIndex % (L.len+1)
if(fromIndex <= 0)
fromIndex += L.len
if(toIndex <= 0)
toIndex += L.len + 1
sortInstance.L = L
sortInstance.cmp = cmp
sortInstance.associative = associative
sortInstance.timSort(fromIndex, toIndex)
return L
+656
View File
@@ -0,0 +1,656 @@
//These are macros used to reduce on proc calls
#define fetchElement(L, i) (associative) ? L[L[i]] : L[i]
//Minimum sized sequence that will be merged. Anything smaller than this will use binary-insertion sort.
//Should be a power of 2
#define MIN_MERGE 32
//When we get into galloping mode, we stay there until both runs win less often than MIN_GALLOP consecutive times.
#define MIN_GALLOP 7
//This is a global instance to allow much of this code to be reused. The interfaces are kept seperately
var/datum/sortInstance/sortInstance = new()
/datum/sortInstance
//The array being sorted.
var/list/L
//The comparator proc-reference
var/cmp = /proc/cmp_numeric_asc
//whether we are sorting list keys (0: L[i]) or associated values (1: L[L[i]])
var/associative = 0
//This controls when we get *into* galloping mode. It is initialized to MIN_GALLOP.
//The mergeLo and mergeHi methods nudge it higher for random data, and lower for highly structured data.
var/minGallop = MIN_GALLOP
//Stores information regarding runs yet to be merged.
//Run i starts at runBase[i] and extends for runLen[i] elements.
//runBase[i] + runLen[i] == runBase[i+1]
//var/stackSize
var/list/runBases = list()
var/list/runLens = list()
proc/timSort(start, end)
runBases.Cut()
runLens.Cut()
var/remaining = end - start
//If array is small, do a 'mini-TimSort' with no merges
if(remaining < MIN_MERGE)
var/initRunLen = countRunAndMakeAscending(start, end)
binarySort(start, end, start+initRunLen)
return
//March over the array finding natural runs
//Extend any short natural runs to runs of length minRun
var/minRun = minRunLength(remaining)
do
//identify next run
var/runLen = countRunAndMakeAscending(start, end)
//if run is short, extend to min(minRun, remaining)
if(runLen < minRun)
var/force = (remaining <= minRun) ? remaining : minRun
binarySort(start, start+force, start+runLen)
runLen = force
//add data about run to queue
runBases.Add(start)
runLens.Add(runLen)
//maybe merge
mergeCollapse()
//Advance to find next run
start += runLen
remaining -= runLen
while(remaining > 0)
//Merge all remaining runs to complete sort
//ASSERT(start == end)
mergeForceCollapse();
//ASSERT(runBases.len == 1)
//reset minGallop, for successive calls
minGallop = MIN_GALLOP
return L
/*
Sorts the specified portion of the specified array using a binary
insertion sort. This is the best method for sorting small numbers
of elements. It requires O(n log n) compares, but O(n^2) data
movement (worst case).
If the initial part of the specified range is already sorted,
this method can take advantage of it: the method assumes that the
elements in range [lo,start) are already sorted
lo the index of the first element in the range to be sorted
hi the index after the last element in the range to be sorted
start the index of the first element in the range that is not already known to be sorted
*/
proc/binarySort(lo, hi, start)
//ASSERT(lo <= start && start <= hi)
if(start <= lo)
start = lo + 1
for(,start < hi, ++start)
var/pivot = fetchElement(L,start)
//set left and right to the index where pivot belongs
var/left = lo
var/right = start
//ASSERT(left <= right)
//[lo, left) elements <= pivot < [right, start) elements
//in other words, find where the pivot element should go using bisection search
while(left < right)
var/mid = (left + right) >> 1 //round((left+right)/2)
if(call(cmp)(fetchElement(L,mid), pivot) > 0)
right = mid
else
left = mid+1
//ASSERT(left == right)
moveElement(L, start, left) //move pivot element to correct location in the sorted range
/*
Returns the length of the run beginning at the specified position and reverses the run if it is back-to-front
A run is the longest ascending sequence with:
a[lo] <= a[lo + 1] <= a[lo + 2] <= ...
or the longest descending sequence with:
a[lo] > a[lo + 1] > a[lo + 2] > ...
For its intended use in a stable mergesort, the strictness of the
definition of "descending" is needed so that the call can safely
reverse a descending sequence without violating stability.
*/
proc/countRunAndMakeAscending(lo, hi)
//ASSERT(lo < hi)
var/runHi = lo + 1
if(runHi >= hi)
return 1
var/last = fetchElement(L,lo)
var/current = fetchElement(L,runHi++)
if(call(cmp)(current, last) < 0)
while(runHi < hi)
last = current
current = fetchElement(L,runHi)
if(call(cmp)(current, last) >= 0)
break
++runHi
reverseRange(L, lo, runHi)
else
while(runHi < hi)
last = current
current = fetchElement(L,runHi)
if(call(cmp)(current, last) < 0)
break
++runHi
return runHi - lo
//Returns the minimum acceptable run length for an array of the specified length.
//Natural runs shorter than this will be extended with binarySort
proc/minRunLength(n)
//ASSERT(n >= 0)
var/r = 0 //becomes 1 if any bits are shifted off
while(n >= MIN_MERGE)
r |= (n & 1)
n >>= 1
return n + r
//Examines the stack of runs waiting to be merged and merges adjacent runs until the stack invariants are reestablished:
// runLen[i-3] > runLen[i-2] + runLen[i-1]
// runLen[i-2] > runLen[i-1]
//This method is called each time a new run is pushed onto the stack.
//So the invariants are guaranteed to hold for i<stackSize upon entry to the method
proc/mergeCollapse()
while(runBases.len >= 2)
var/n = runBases.len - 1
if(n > 1 && runLens[n-1] <= runLens[n] + runLens[n+1])
if(runLens[n-1] < runLens[n+1])
--n
mergeAt(n)
else if(runLens[n] <= runLens[n+1])
mergeAt(n)
else
break //Invariant is established
//Merges all runs on the stack until only one remains.
//Called only once, to finalise the sort
proc/mergeForceCollapse()
while(runBases.len >= 2)
var/n = runBases.len - 1
if(n > 1 && runLens[n-1] < runLens[n+1])
--n
mergeAt(n)
//Merges the two consecutive runs at stack indices i and i+1
//Run i must be the penultimate or antepenultimate run on the stack
//In other words, i must be equal to stackSize-2 or stackSize-3
proc/mergeAt(i)
//ASSERT(runBases.len >= 2)
//ASSERT(i >= 1)
//ASSERT(i == runBases.len - 1 || i == runBases.len - 2)
var/base1 = runBases[i]
var/base2 = runBases[i+1]
var/len1 = runLens[i]
var/len2 = runLens[i+1]
//ASSERT(len1 > 0 && len2 > 0)
//ASSERT(base1 + len1 == base2)
//Record the legth of the combined runs. If i is the 3rd last run now, also slide over the last run
//(which isn't involved in this merge). The current run (i+1) goes away in any case.
runLens[i] += runLens[i+1]
runLens.Cut(i+1, i+2)
runBases.Cut(i+1, i+2)
//Find where the first element of run2 goes in run1.
//Prior elements in run1 can be ignored (because they're already in place)
var/k = gallopRight(fetchElement(L,base2), base1, len1, 0)
//ASSERT(k >= 0)
base1 += k
len1 -= k
if(len1 == 0)
return
//Find where the last element of run1 goes in run2.
//Subsequent elements in run2 can be ignored (because they're already in place)
len2 = gallopLeft(fetchElement(L,base1 + len1 - 1), base2, len2, len2-1)
//ASSERT(len2 >= 0)
if(len2 == 0)
return
//Merge remaining runs, using tmp array with min(len1, len2) elements
if(len1 <= len2)
mergeLo(base1, len1, base2, len2)
else
mergeHi(base1, len1, base2, len2)
/*
Locates the position to insert key within the specified sorted range
If the range contains elements equal to key, this will return the index of the LEFTMOST of those elements
key the element to be inserted into the sorted range
base the index of the first element of the sorted range
len the length of the sorted range, must be greater than 0
hint the offset from base at which to begin the search, such that 0 <= hint < len; i.e. base <= hint < base+hint
Returns the index at which to insert element 'key'
*/
proc/gallopLeft(key, base, len, hint)
//ASSERT(len > 0 && hint >= 0 && hint < len)
var/lastOffset = 0
var/offset = 1
if(call(cmp)(key, fetchElement(L,base+hint)) > 0)
var/maxOffset = len - hint
while(offset < maxOffset && call(cmp)(key, fetchElement(L,base+hint+offset)) > 0)
lastOffset = offset
offset = (offset << 1) + 1
if(offset > maxOffset)
offset = maxOffset
lastOffset += hint
offset += hint
else
var/maxOffset = hint + 1
while(offset < maxOffset && call(cmp)(key, fetchElement(L,base+hint-offset)) <= 0)
lastOffset = offset
offset = (offset << 1) + 1
if(offset > maxOffset)
offset = maxOffset
var/temp = lastOffset
lastOffset = hint - offset
offset = hint - temp
//ASSERT(-1 <= lastOffset && lastOffset < offset && offset <= len)
//Now L[base+lastOffset] < key <= L[base+offset], so key belongs somewhere to the right of lastOffset but no farther than
//offset. Do a binary search with invariant L[base+lastOffset-1] < key <= L[base+offset]
++lastOffset
while(lastOffset < offset)
var/m = lastOffset + ((offset - lastOffset) >> 1)
if(call(cmp)(key, fetchElement(L,base+m)) > 0)
lastOffset = m + 1
else
offset = m
//ASSERT(lastOffset == offset)
return offset
/**
* Like gallopLeft, except that if the range contains an element equal to
* key, gallopRight returns the index after the rightmost equal element.
*
* @param key the key whose insertion point to search for
* @param a the array in which to search
* @param base the index of the first element in the range
* @param len the length of the range; must be > 0
* @param hint the index at which to begin the search, 0 <= hint < n.
* The closer hint is to the result, the faster this method will run.
* @param c the comparator used to order the range, and to search
* @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k]
*/
proc/gallopRight(key, base, len, hint)
//ASSERT(len > 0 && hint >= 0 && hint < len)
var/offset = 1
var/lastOffset = 0
if(call(cmp)(key, fetchElement(L,base+hint)) < 0) //key <= L[base+hint]
var/maxOffset = hint + 1 //therefore we want to insert somewhere in the range [base,base+hint] = [base+,base+(hint+1))
while(offset < maxOffset && call(cmp)(key, fetchElement(L,base+hint-offset)) < 0) //we are iterating backwards
lastOffset = offset
offset = (offset << 1) + 1 //1 3 7 15
//if(offset <= 0) //int overflow, not an issue here since we are using floats
// offset = maxOffset
if(offset > maxOffset)
offset = maxOffset
var/temp = lastOffset
lastOffset = hint - offset
offset = hint - temp
else //key > L[base+hint]
var/maxOffset = len - hint //therefore we want to insert somewhere in the range (base+hint,base+len) = [base+hint+1, base+hint+(len-hint))
while(offset < maxOffset && call(cmp)(key, fetchElement(L,base+hint+offset)) >= 0)
lastOffset = offset
offset = (offset << 1) + 1
//if(offset <= 0) //int overflow, not an issue here since we are using floats
// offset = maxOffset
if(offset > maxOffset)
offset = maxOffset
lastOffset += hint
offset += hint
//ASSERT(-1 <= lastOffset && lastOffset < offset && offset <= len)
++lastOffset
while(lastOffset < offset)
var/m = lastOffset + ((offset - lastOffset) >> 1)
if(call(cmp)(key, fetchElement(L,base+m)) < 0) //key <= L[base+m]
offset = m
else //key > L[base+m]
lastOffset = m + 1
//ASSERT(lastOffset == offset)
return offset
//Merges two adjacent runs in-place in a stable fashion.
//For performance this method should only be called when len1 <= len2!
proc/mergeLo(base1, len1, base2, len2)
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
var/cursor1 = base1
var/cursor2 = base2
//degenerate cases
if(len2 == 1)
moveElement(L, cursor2, cursor1)
return
if(len1 == 1)
moveElement(L, cursor1, cursor2+len2)
return
//Move first element of second run
moveElement(L, cursor2++, cursor1++)
--len2
outer:
while(1)
var/count1 = 0 //# of times in a row that first run won
var/count2 = 0 // " " " " " " second run won
//do the straightfoward thin until one run starts winning consistently
do
//ASSERT(len1 > 1 && len2 > 0)
if(call(cmp)(fetchElement(L,cursor2), fetchElement(L,cursor1)) < 0)
moveElement(L, cursor2++, cursor1++)
--len2
++count2
count1 = 0
if(len2 == 0)
break outer
else
++cursor1
++count1
count2 = 0
if(--len1 == 1)
break outer
while((count1 | count2) < minGallop)
//one run is winning consistently so galloping may provide huge benifits
//so try galloping, until such time as the run is no longer consistently winning
do
//ASSERT(len1 > 1 && len2 > 0)
count1 = gallopRight(fetchElement(L,cursor2), cursor1, len1, 0)
if(count1)
cursor1 += count1
len1 -= count1
if(len1 <= 1)
break outer
moveElement(L, cursor2, cursor1)
++cursor2
++cursor1
if(--len2 == 0)
break outer
count2 = gallopLeft(fetchElement(L,cursor1), cursor2, len2, 0)
if(count2)
moveRange(L, cursor2, cursor1, count2)
cursor2 += count2
cursor1 += count2
len2 -= count2
if(len2 == 0)
break outer
++cursor1
if(--len1 == 1)
break outer
--minGallop
while((count1|count2) > MIN_GALLOP)
if(minGallop < 0)
minGallop = 0
minGallop += 2; // Penalize for leaving gallop mode
if(len1 == 1)
//ASSERT(len2 > 0)
moveElement(L, cursor1, cursor2+len2)
//else
//ASSERT(len2 == 0)
//ASSERT(len1 > 1)
proc/mergeHi(base1, len1, base2, len2)
//ASSERT(len1 > 0 && len2 > 0 && base1 + len1 == base2)
var/cursor1 = base1 + len1 - 1 //start at end of sublists
var/cursor2 = base2 + len2 - 1
//degenerate cases
if(len2 == 1)
moveElement(L, base2, base1)
return
if(len1 == 1)
moveElement(L, base1, cursor2+1)
return
moveElement(L, cursor1--, cursor2-- + 1)
--len1
outer:
while(1)
var/count1 = 0 //# of times in a row that first run won
var/count2 = 0 // " " " " " " second run won
//do the straightfoward thing until one run starts winning consistently
do
//ASSERT(len1 > 0 && len2 > 1)
if(call(cmp)(fetchElement(L,cursor2), fetchElement(L,cursor1)) < 0)
moveElement(L, cursor1--, cursor2-- + 1)
--len1
++count1
count2 = 0
if(len1 == 0)
break outer
else
--cursor2
--len2
++count2
count1 = 0
if(len2 == 1)
break outer
while((count1 | count2) < minGallop)
//one run is winning consistently so galloping may provide huge benifits
//so try galloping, until such time as the run is no longer consistently winning
do
//ASSERT(len1 > 0 && len2 > 1)
count1 = len1 - gallopRight(fetchElement(L,cursor2), base1, len1, len1-1) //should cursor1 be base1?
if(count1)
cursor1 -= count1
moveRange(L, cursor1+1, cursor2+1, count1) //cursor1+1 == cursor2 by definition
cursor2 -= count1
len1 -= count1
if(len1 == 0)
break outer
--cursor2
if(--len2 == 1)
break outer
count2 = len2 - gallopLeft(fetchElement(L,cursor1), cursor1+1, len2, len2-1)
if(count2)
cursor2 -= count2
len2 -= count2
if(len2 <= 1)
break outer
moveElement(L, cursor1--, cursor2-- + 1)
--len1
if(len1 == 0)
break outer
--minGallop
while((count1|count2) > MIN_GALLOP)
if(minGallop < 0)
minGallop = 0
minGallop += 2 // Penalize for leaving gallop mode
if(len2 == 1)
//ASSERT(len1 > 0)
cursor1 -= len1
moveRange(L, cursor1+1, cursor2+1, len1)
//else
//ASSERT(len1 == 0)
//ASSERT(len2 > 0)
proc/mergeSort(start, end)
var/remaining = end - start
//If array is small, do an insertion sort
if(remaining < MIN_MERGE)
//var/initRunLen = countRunAndMakeAscending(start, end)
binarySort(start, end, start/*+initRunLen*/)
return
var/minRun = minRunLength(remaining)
do
var/runLen = (remaining <= minRun) ? remaining : minRun
binarySort(start, start+runLen, start)
//add data about run to queue
runBases.Add(start)
runLens.Add(runLen)
//Advance to find next run
start += runLen
remaining -= runLen
while(remaining > 0)
while(runBases.len >= 2)
var/n = runBases.len - 1
if(n > 1 && runLens[n-1] <= runLens[n] + runLens[n+1])
if(runLens[n-1] < runLens[n+1])
--n
mergeAt2(n)
else if(runLens[n] <= runLens[n+1])
mergeAt2(n)
else
break //Invariant is established
while(runBases.len >= 2)
var/n = runBases.len - 1
if(n > 1 && runLens[n-1] < runLens[n+1])
--n
mergeAt2(n)
return L
proc/mergeAt2(i)
var/cursor1 = runBases[i]
var/cursor2 = runBases[i+1]
var/end1 = cursor1+runLens[i]
var/end2 = cursor2+runLens[i+1]
var/val1 = fetchElement(L,cursor1)
var/val2 = fetchElement(L,cursor2)
while(1)
if(call(cmp)(val1,val2) < 0)
if(++cursor1 >= end1)
break
val1 = fetchElement(L,cursor1)
else
moveElement(L,cursor2,cursor1)
++cursor2
if(++cursor2 >= end2)
break
++end1
++cursor1
//if(++cursor1 >= end1)
// break
val2 = fetchElement(L,cursor2)
//Record the legth of the combined runs. If i is the 3rd last run now, also slide over the last run
//(which isn't involved in this merge). The current run (i+1) goes away in any case.
runLens[i] += runLens[i+1]
runLens.Cut(i+1, i+2)
runBases.Cut(i+1, i+2)
#undef MIN_GALLOP
#undef MIN_MERGE
#undef fetchElement
+471
View File
@@ -0,0 +1,471 @@
/*
* Holds procs designed to help with filtering text
* Contains groups:
* SQL sanitization/formating
* Text sanitization
* Text searches
* Text modification
* Misc
*/
/*
* SQL sanitization
*/
// Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts.
/proc/sanitizeSQL(t as text)
var/sqltext = dbcon.Quote(t);
return copytext(sqltext, 2, lentext(sqltext));//Quote() adds quotes around input, we already do that
/proc/format_table_name(table as text)
return sqlfdbktableprefix + table
/*
* Text sanitization
*/
//Simply removes < and > and limits the length of the message
/proc/strip_html_simple(t,limit=MAX_MESSAGE_LEN)
var/list/strip_chars = list("<",">")
t = copytext(t,1,limit)
for(var/char in strip_chars)
var/index = findtext(t, char)
while(index)
t = copytext(t, 1, index) + copytext(t, index+1)
index = findtext(t, char)
return t
//Removes a few problematic characters
/proc/sanitize_simple(t,list/repl_chars = list("\n"="#","\t"="#"))
for(var/char in repl_chars)
var/index = findtext(t, char)
while(index)
t = copytext(t, 1, index) + repl_chars[char] + copytext(t, index+1)
index = findtext(t, char, index+1)
return t
//Runs byond's sanitization proc along-side sanitize_simple
/proc/sanitize(t,list/repl_chars = null)
return html_encode(sanitize_simple(t,repl_chars))
//Runs sanitize and strip_html_simple
//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '&lt;' after sanitize() calls byond's html_encode()
/proc/strip_html(t,limit=MAX_MESSAGE_LEN)
return copytext((sanitize(strip_html_simple(t))),1,limit)
//Runs byond's sanitization proc along-side strip_html_simple
//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '&lt;' that html_encode() would cause
/proc/adminscrub(t,limit=MAX_MESSAGE_LEN)
return copytext((html_encode(strip_html_simple(t))),1,limit)
//Returns null if there is any bad text in the string
/proc/reject_bad_text(text, max_length=512)
if(length(text) > max_length)
return //message too long
var/non_whitespace = 0
for(var/i=1, i<=length(text), i++)
switch(text2ascii(text,i))
if(62,60,92,47)
return //rejects the text if it contains these bad characters: <, >, \ or /
if(127 to 255)
return //rejects weird letters like
if(0 to 31)
return //more weird stuff
if(32)
continue //whitespace
else
non_whitespace = 1
if(non_whitespace)
return text //only accepts the text if it has some non-spaces
// Used to get a properly sanitized input, of max_length
/proc/stripped_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN)
var/name = input(user, message, title, default) as text|null
return trim(html_encode(name), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into &lt;)
// Used to get a properly sanitized multiline input, of max_length
/proc/stripped_multiline_input(mob/user, message = "", title = "", default = "", max_length=MAX_MESSAGE_LEN)
var/name = input(user, message, title, default) as message|null
return html_encode(trim(name, max_length))
//Filters out undesirable characters from names
/proc/reject_bad_name(t_in, allow_numbers=0, max_length=MAX_NAME_LEN)
if(!t_in || length(t_in) > max_length)
return //Rejects the input if it is null or if it is longer then the max length allowed
var/number_of_alphanumeric = 0
var/last_char_group = 0
var/t_out = ""
for(var/i=1, i<=length(t_in), i++)
var/ascii_char = text2ascii(t_in,i)
switch(ascii_char)
// A .. Z
if(65 to 90) //Uppercase Letters
t_out += ascii2text(ascii_char)
number_of_alphanumeric++
last_char_group = 4
// a .. z
if(97 to 122) //Lowercase Letters
if(last_char_group<2)
t_out += ascii2text(ascii_char-32) //Force uppercase first character
else
t_out += ascii2text(ascii_char)
number_of_alphanumeric++
last_char_group = 4
// 0 .. 9
if(48 to 57) //Numbers
if(!last_char_group)
continue //suppress at start of string
if(!allow_numbers)
continue
t_out += ascii2text(ascii_char)
number_of_alphanumeric++
last_char_group = 3
// ' - .
if(39,45,46) //Common name punctuation
if(!last_char_group)
continue
t_out += ascii2text(ascii_char)
last_char_group = 2
// ~ | @ : # $ % & * +
if(126,124,64,58,35,36,37,38,42,43) //Other symbols that we'll allow (mainly for AI)
if(!last_char_group)
continue //suppress at start of string
if(!allow_numbers)
continue
t_out += ascii2text(ascii_char)
last_char_group = 2
//Space
if(32)
if(last_char_group <= 1)
continue //suppress double-spaces and spaces at start of string
t_out += ascii2text(ascii_char)
last_char_group = 1
else
return
if(number_of_alphanumeric < 2)
return //protects against tiny names like "A" and also names like "' ' ' ' ' ' ' '"
if(last_char_group == 1)
t_out = copytext(t_out,1,length(t_out)) //removes the last character (in this case a space)
for(var/bad_name in list("space","floor","wall","r-wall","monkey","unknown","inactive ai")) //prevents these common metagamey names
if(cmptext(t_out,bad_name))
return //(not case sensitive)
return t_out
//html_encode helper proc that returns the smallest non null of two numbers
//or 0 if they're both null (needed because of findtext returning 0 when a value is not present)
/proc/non_zero_min(a, b)
if(!a)
return b
if(!b)
return a
return (a < b ? a : b)
/*
* Text searches
*/
//Checks the beginning of a string for a specified sub-string
//Returns the position of the substring or 0 if it was not found
/proc/dd_hasprefix(text, prefix)
var/start = 1
var/end = length(prefix) + 1
return findtext(text, prefix, start, end)
//Checks the beginning of a string for a specified sub-string. This proc is case sensitive
//Returns the position of the substring or 0 if it was not found
/proc/dd_hasprefix_case(text, prefix)
var/start = 1
var/end = length(prefix) + 1
return findtextEx(text, prefix, start, end)
//Checks the end of a string for a specified substring.
//Returns the position of the substring or 0 if it was not found
/proc/dd_hassuffix(text, suffix)
var/start = length(text) - length(suffix)
if(start)
return findtext(text, suffix, start, null)
return
//Checks the end of a string for a specified substring. This proc is case sensitive
//Returns the position of the substring or 0 if it was not found
/proc/dd_hassuffix_case(text, suffix)
var/start = length(text) - length(suffix)
if(start)
return findtextEx(text, suffix, start, null)
//Adds 'u' number of zeros ahead of the text 't'
/proc/add_zero(t, u)
while (length(t) < u)
t = "0[t]"
return t
//Adds 'u' number of spaces ahead of the text 't'
/proc/add_lspace(t, u)
while(length(t) < u)
t = " [t]"
return t
//Adds 'u' number of spaces behind the text 't'
/proc/add_tspace(t, u)
while(length(t) < u)
t = "[t] "
return t
//Returns a string with reserved characters and spaces before the first letter removed
/proc/trim_left(text)
for (var/i = 1 to length(text))
if (text2ascii(text, i) > 32)
return copytext(text, i)
return ""
//Returns a string with reserved characters and spaces after the last letter removed
/proc/trim_right(text)
for (var/i = length(text), i > 0, i--)
if (text2ascii(text, i) > 32)
return copytext(text, 1, i + 1)
return ""
//Returns a string with reserved characters and spaces before the first word and after the last word removed.
/proc/trim(text, max_length)
if(max_length)
text = copytext(text, 1, max_length)
return trim_left(trim_right(text))
//Returns a string with the first element of the string capitalized.
/proc/capitalize(t as text)
return uppertext(copytext(t, 1, 2)) + copytext(t, 2)
//Centers text by adding spaces to either side of the string.
/proc/dd_centertext(message, length)
var/new_message = message
var/size = length(message)
var/delta = length - size
if(size == length)
return new_message
if(size > length)
return copytext(new_message, 1, length + 1)
if(delta == 1)
return new_message + " "
if(delta % 2)
new_message = " " + new_message
delta--
var/spaces = add_lspace("",delta/2-1)
return spaces + new_message + spaces
//Limits the length of the text. Note: MAX_MESSAGE_LEN and MAX_NAME_LEN are widely used for this purpose
/proc/dd_limittext(message, length)
var/size = length(message)
if(size <= length)
return message
return copytext(message, 1, length + 1)
/proc/stringmerge(text,compare,replace = "*")
//This proc fills in all spaces with the "replace" var (* by default) with whatever
//is in the other string at the same spot (assuming it is not a replace char).
//This is used for fingerprints
var/newtext = text
if(lentext(text) != lentext(compare))
return 0
for(var/i = 1, i < lentext(text), i++)
var/a = copytext(text,i,i+1)
var/b = copytext(compare,i,i+1)
//if it isn't both the same letter, or if they are both the replacement character
//(no way to know what it was supposed to be)
if(a != b)
if(a == replace) //if A is the replacement char
newtext = copytext(newtext,1,i) + b + copytext(newtext, i+1)
else if(b == replace) //if B is the replacement char
newtext = copytext(newtext,1,i) + a + copytext(newtext, i+1)
else //The lists disagree, Uh-oh!
return 0
return newtext
/proc/stringpercent(text,character = "*")
//This proc returns the number of chars of the string that is the character
//This is used for detective work to determine fingerprint completion.
if(!text || !character)
return 0
var/count = 0
for(var/i = 1, i <= lentext(text), i++)
var/a = copytext(text,i,i+1)
if(a == character)
count++
return count
/proc/reverse_text(text = "")
var/new_text = ""
for(var/i = length(text); i > 0; i--)
new_text += copytext(text, i, i+1)
return new_text
var/list/zero_character_only = list("0")
var/list/hex_characters = list("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f")
var/list/alphabet = list("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z")
var/list/binary = list("0","1")
/proc/random_string(length, list/characters)
. = ""
for(var/i=1, i<=length, i++)
. += pick(characters)
/proc/repeat_string(times, string="")
. = ""
for(var/i=1, i<=times, i++)
. += string
/proc/random_short_color()
return random_string(3, hex_characters)
/proc/random_color()
return random_string(6, hex_characters)
/proc/add_zero2(t, u)
var/temp1
while (length(t) < u)
t = "0[t]"
temp1 = t
if (length(t) > u)
temp1 = copytext(t,2,u+1)
return temp1
//merges non-null characters (3rd argument) from "from" into "into". Returns result
//e.g. into = "Hello World"
// from = "Seeya______"
// returns"Seeya World"
//The returned text is always the same length as into
//This was coded to handle DNA gene-splicing.
/proc/merge_text(into, from, null_char="_")
. = ""
if(!istext(into))
into = ""
if(!istext(from))
from = ""
var/null_ascii = istext(null_char) ? text2ascii(null_char,1) : null_char
var/previous = 0
var/start = 1
var/end = length(into) + 1
for(var/i=1, i<end, i++)
var/ascii = text2ascii(from, i)
if(ascii == null_ascii)
if(previous != 1)
. += copytext(from, start, i)
start = i
previous = 1
else
if(previous != 0)
. += copytext(into, start, i)
start = i
previous = 0
if(previous == 0)
. += copytext(from, start, end)
else
. += copytext(into, start, end)
//finds the first occurrence of one of the characters from needles argument inside haystack
//it may appear this can be optimised, but it really can't. findtext() is so much faster than anything you can do in byondcode.
//stupid byond :(
/proc/findchar(haystack, needles, start=1, end=0)
var/temp
var/len = length(needles)
for(var/i=1, i<=len, i++)
temp = findtextEx(haystack, ascii2text(text2ascii(needles,i)), start, end) //Note: ascii2text(text2ascii) is faster than copytext()
if(temp)
end = temp
return end
/proc/parsepencode(t, mob/user=null, signfont=SIGNFONT)
if(length(t) < 1) //No input means nothing needs to be parsed
return
t = replacetext(t, "\[center\]", "<center>")
t = replacetext(t, "\[/center\]", "</center>")
t = replacetext(t, "\[br\]", "<BR>")
t = replacetext(t, "\[b\]", "<B>")
t = replacetext(t, "\[/b\]", "</B>")
t = replacetext(t, "\[i\]", "<I>")
t = replacetext(t, "\[/i\]", "</I>")
t = replacetext(t, "\[u\]", "<U>")
t = replacetext(t, "\[/u\]", "</U>")
t = replacetext(t, "\[large\]", "<font size=\"4\">")
t = replacetext(t, "\[/large\]", "</font>")
if(user)
t = replacetext(t, "\[sign\]", "<font face=\"[signfont]\"><i>[user.real_name]</i></font>")
else
t = replacetext(t, "\[sign\]", "")
t = replacetext(t, "\[field\]", "<span class=\"paper_field\"></span>")
t = replacetext(t, "\[*\]", "<li>")
t = replacetext(t, "\[hr\]", "<HR>")
t = replacetext(t, "\[small\]", "<font size = \"1\">")
t = replacetext(t, "\[/small\]", "</font>")
t = replacetext(t, "\[list\]", "<ul>")
t = replacetext(t, "\[/list\]", "</ul>")
return t
/proc/char_split(t)
. = list()
for(var/x in 1 to length(t))
. += copytext(t,x,x+1)
var/list/rot13_lookup = list()
/proc/generate_rot13_lookup()
var/letters = alphabet.Copy()
for(var/c in alphabet)
letters += uppertext(c)
for(var/char in letters)
var/ascii_char = text2ascii(char, 1)
var/index
switch(ascii_char)
// A - Z
if(65 to 90)
index = 65
// a - z
if(97 to 122)
index = 97
var/d = ascii_char - index
d += 13
if(d >= 26)
d -= 26
ascii_char = index + d
var/translated_char = ascii2text(ascii_char)
rot13_lookup[char] = translated_char
/proc/rot13(t_in)
if(!rot13_lookup.len)
generate_rot13_lookup()
var/t_out = ""
for(var/i in 1 to length(t_in))
var/char = copytext(t_in, i, i + 1)
if(char in rot13_lookup)
t_out += rot13_lookup[char]
else
t_out += char
return t_out
+25
View File
@@ -0,0 +1,25 @@
//Returns the world time in english
/proc/worldtime2text()
return gameTimestamp("hh:mm")
/proc/time_stamp(format = "hh:mm:ss")
return time2text(world.timeofday, format)
/proc/gameTimestamp(format = "hh:mm:ss") // Get the game time in text
return time2text(world.time - timezoneOffset + 432000, format)
/* Returns 1 if it is the selected month and day */
/proc/isDay(month, day)
if(isnum(month) && isnum(day))
var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month
var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day
if(month == MM && day == DD)
return 1
// Uncomment this out when debugging!
//else
//return 1
//returns timestamp in a sql and ISO 8601 friendly format
/proc/SQLtime()
return time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
+588
View File
@@ -0,0 +1,588 @@
/*
* Holds procs designed to change one type of value, into another.
* Contains:
* hex2num & num2hex
* file2list
* angle2dir
* angle2text
* worldtime2text
* text2dir_extended & dir2text_short
*/
//Returns an integer given a hex input, supports negative values "-ff"
//skips preceding invalid characters
//breaks when hittin invalid characters thereafter
/proc/hex2num(hex)
. = 0
if(istext(hex))
var/negative = 0
var/len = length(hex)
for(var/i=1, i<=len, i++)
var/num = text2ascii(hex,i)
switch(num)
if(48 to 57)
num -= 48 //0-9
if(97 to 102)
num -= 87 //a-f
if(65 to 70)
num -= 55 //A-F
if(45)
negative = 1//-
else
if(num)
break
else
continue
. *= 16
. += num
if(negative)
. *= -1
return .
//Returns the hex value of a decimal number
//len == length of returned string
//if len < 0 then the returned string will be as long as it needs to be to contain the data
//Only supports positive numbers
//if an invalid number is provided, it assumes num==0
//Note, unlike previous versions, this one works from low to high <-- that way
/proc/num2hex(num, len=2)
if(!isnum(num))
num = 0
num = round(abs(num))
. = ""
var/i=0
while(1)
if(len<=0)
if(!num)
break
else
if(i>=len)
break
var/remainder = num/16
num = round(remainder)
remainder = (remainder - num) * 16
switch(remainder)
if(9,8,7,6,5,4,3,2,1)
. = "[remainder]" + .
if(10,11,12,13,14,15)
. = ascii2text(remainder+87) + .
else
. = "0" + .
i++
return .
//Splits the text of a file at seperator and returns them in a list.
/proc/file2list(filename, seperator="\n")
return splittext(return_file_text(filename),seperator)
//Turns a direction into text
/proc/dir2text(direction)
switch(direction)
if(1)
return "north"
if(2)
return "south"
if(4)
return "east"
if(8)
return "west"
if(5)
return "northeast"
if(6)
return "southeast"
if(9)
return "northwest"
if(10)
return "southwest"
else
return
//Turns text into proper directions
/proc/text2dir(direction)
switch(uppertext(direction))
if("NORTH")
return 1
if("SOUTH")
return 2
if("EAST")
return 4
if("WEST")
return 8
if("NORTHEAST")
return 5
if("NORTHWEST")
return 9
if("SOUTHEAST")
return 6
if("SOUTHWEST")
return 10
else
return
//Converts an angle (degrees) into an ss13 direction
/proc/angle2dir(degree)
degree = SimplifyDegrees(degree)
if(degree < 45)
return NORTH
if(degree < 90)
return NORTHEAST
if(degree < 135)
return EAST
if(degree < 180)
return SOUTHEAST
if(degree < 225)
return SOUTH
if(degree < 270)
return SOUTHWEST
if(degree < 315)
return WEST
return NORTH|WEST
//returns the north-zero clockwise angle in degrees, given a direction
/proc/dir2angle(D)
switch(D)
if(NORTH)
return 0
if(SOUTH)
return 180
if(EAST)
return 90
if(WEST)
return 270
if(NORTHEAST)
return 45
if(SOUTHEAST)
return 135
if(NORTHWEST)
return 315
if(SOUTHWEST)
return 225
else
return null
//Returns the angle in english
/proc/angle2text(degree)
return dir2text(angle2dir(degree))
//Converts a blend_mode constant to one acceptable to icon.Blend()
/proc/blendMode2iconMode(blend_mode)
switch(blend_mode)
if(BLEND_MULTIPLY)
return ICON_MULTIPLY
if(BLEND_ADD)
return ICON_ADD
if(BLEND_SUBTRACT)
return ICON_SUBTRACT
else
return ICON_OVERLAY
//Converts a rights bitfield into a string
/proc/rights2text(rights, seperator="", list/adds, list/subs)
if(rights & R_BUILDMODE)
. += "[seperator]+BUILDMODE"
if(rights & R_ADMIN)
. += "[seperator]+ADMIN"
if(rights & R_BAN)
. += "[seperator]+BAN"
if(rights & R_FUN)
. += "[seperator]+FUN"
if(rights & R_SERVER)
. += "[seperator]+SERVER"
if(rights & R_DEBUG)
. += "[seperator]+DEBUG"
if(rights & R_POSSESS)
. += "[seperator]+POSSESS"
if(rights & R_PERMISSIONS)
. += "[seperator]+PERMISSIONS"
if(rights & R_STEALTH)
. += "[seperator]+STEALTH"
if(rights & R_REJUVINATE)
. += "[seperator]+REJUVINATE"
if(rights & R_VAREDIT)
. += "[seperator]+VAREDIT"
if(rights & R_SOUNDS)
. += "[seperator]+SOUND"
if(rights & R_SPAWN)
. += "[seperator]+SPAWN"
for(var/verbpath in adds)
. += "[seperator]+[verbpath]"
for(var/verbpath in subs)
. += "[seperator]-[verbpath]"
return .
/proc/ui_style2icon(ui_style)
switch(ui_style)
if("Retro")
return 'icons/mob/screen_retro.dmi'
if("Plasmafire")
return 'icons/mob/screen_plasmafire.dmi'
if("Slimecore")
return 'icons/mob/screen_slimecore.dmi'
if("Operative")
return 'icons/mob/screen_operative.dmi'
else
return 'icons/mob/screen_midnight.dmi'
//colour formats
/proc/rgb2hsl(red, green, blue)
red /= 255;green /= 255;blue /= 255;
var/max = max(red,green,blue)
var/min = min(red,green,blue)
var/range = max-min
var/hue=0;var/saturation=0;var/lightness=0;
lightness = (max + min)/2
if(range != 0)
if(lightness < 0.5)
saturation = range/(max+min)
else
saturation = range/(2-max-min)
var/dred = ((max-red)/(6*max)) + 0.5
var/dgreen = ((max-green)/(6*max)) + 0.5
var/dblue = ((max-blue)/(6*max)) + 0.5
if(max==red)
hue = dblue - dgreen
else if(max==green)
hue = dred - dblue + (1/3)
else
hue = dgreen - dred + (2/3)
if(hue < 0)
hue++
else if(hue > 1)
hue--
return list(hue, saturation, lightness)
/proc/hsl2rgb(hue, saturation, lightness)
var/red;var/green;var/blue;
if(saturation == 0)
red = lightness * 255
green = red
blue = red
else
var/a;var/b;
if(lightness < 0.5)
b = lightness*(1+saturation)
else
b = (lightness+saturation) - (saturation*lightness)
a = 2*lightness - b
red = round(255 * hue2rgb(a, b, hue+(1/3)))
green = round(255 * hue2rgb(a, b, hue))
blue = round(255 * hue2rgb(a, b, hue-(1/3)))
return list(red, green, blue)
/proc/hue2rgb(a, b, hue)
if(hue < 0)
hue++
else if(hue > 1)
hue--
if(6*hue < 1)
return (a+(b-a)*6*hue)
if(2*hue < 1)
return b
if(3*hue < 2)
return (a+(b-a)*((2/3)-hue)*6)
return a
// Very ugly, BYOND doesn't support unix time and rounding errors make it really hard to convert it to BYOND time.
// returns "YYYY-MM-DD" by default
/proc/unix2date(timestamp, seperator = "-")
if(timestamp < 0)
return 0 //Do not accept negative values
var/year = 1970 //Unix Epoc begins 1970-01-01
var/dayInSeconds = 86400 //60secs*60mins*24hours
var/daysInYear = 365 //Non Leap Year
var/daysInLYear = daysInYear + 1//Leap year
var/days = round(timestamp / dayInSeconds) //Days passed since UNIX Epoc
var/tmpDays = days + 1 //If passed (timestamp < dayInSeconds), it will return 0, so add 1
var/monthsInDays = list() //Months will be in here ***Taken from the PHP source code***
var/month = 1 //This will be the returned MONTH NUMBER.
var/day //This will be the returned day number.
while(tmpDays > daysInYear) //Start adding years to 1970
year++
if(isLeap(year))
tmpDays -= daysInLYear
else
tmpDays -= daysInYear
if(isLeap(year)) //The year is a leap year
monthsInDays = list(-1,30,59,90,120,151,181,212,243,273,304,334)
else
monthsInDays = list(0,31,59,90,120,151,181,212,243,273,304,334)
var/mDays = 0;
var/monthIndex = 0;
for(var/m in monthsInDays)
monthIndex++
if(tmpDays > m)
mDays = m
month = monthIndex
day = tmpDays - mDays //Setup the date
return "[year][seperator][((month < 10) ? "0[month]" : month)][seperator][((day < 10) ? "0[day]" : day)]"
/*
var/list/test_times = list("December" = 1323522004, "August" = 1123522004, "January" = 1011522004,
"Jan Leap" = 946684800, "Jan Normal" = 978307200, "New Years Eve" = 1009670400,
"New Years" = 1009836000, "New Years 2" = 1041372000, "New Years 3" = 1104530400,
"July Month End" = 744161003, "July Month End 12" = 1343777003, "End July" = 1091311200)
for(var/t in test_times)
world.log << "TEST: [t] is [unix2date(test_times[t])]"
*/
/proc/isLeap(y)
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
// A copy of text2dir, extended to accept one and two letter
// directions, and to clearly return 0 otherwise.
/proc/text2dir_extended(direction)
switch(uppertext(direction))
if("NORTH", "N")
return 1
if("SOUTH", "S")
return 2
if("EAST", "E")
return 4
if("WEST", "W")
return 8
if("NORTHEAST", "NE")
return 5
if("NORTHWEST", "NW")
return 9
if("SOUTHEAST", "SE")
return 6
if("SOUTHWEST", "SW")
return 10
else
return 0
// A copy of dir2text, which returns the short one or two letter
// directions used in tube icon states.
/proc/dir2text_short(direction)
switch(direction)
if(1)
return "N"
if(2)
return "S"
if(4)
return "E"
if(8)
return "W"
if(5)
return "NE"
if(6)
return "SE"
if(9)
return "NW"
if(10)
return "SW"
else
return
//Turns a Body_parts_covered bitfield into a list of organ/limb names.
//(I challenge you to find a use for this)
/proc/body_parts_covered2organ_names(bpc)
var/list/covered_parts = list()
if(!bpc)
return 0
if(bpc & FULL_BODY)
covered_parts |= list("l_arm","r_arm","head","chest","l_leg","r_leg")
else
if(bpc & HEAD)
covered_parts |= list("head")
if(bpc & CHEST)
covered_parts |= list("chest")
if(bpc & GROIN)
covered_parts |= list("chest")
if(bpc & ARMS)
covered_parts |= list("l_arm","r_arm")
else
if(bpc & ARM_LEFT)
covered_parts |= list("l_arm")
if(bpc & ARM_RIGHT)
covered_parts |= list("r_arm")
if(bpc & HANDS)
covered_parts |= list("l_arm","r_arm")
else
if(bpc & HAND_LEFT)
covered_parts |= list("l_arm")
if(bpc & HAND_RIGHT)
covered_parts |= list("r_arm")
if(bpc & LEGS)
covered_parts |= list("l_leg","r_leg")
else
if(bpc & LEG_LEFT)
covered_parts |= list("l_leg")
if(bpc & LEG_RIGHT)
covered_parts |= list("r_leg")
if(bpc & FEET)
covered_parts |= list("l_leg","r_leg")
else
if(bpc & FOOT_LEFT)
covered_parts |= list("l_leg")
if(bpc & FOOT_RIGHT)
covered_parts |= list("r_leg")
return covered_parts
//adapted from http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
/proc/heat2colour(temp)
return rgb(heat2colour_r(temp), heat2colour_g(temp), heat2colour_b(temp))
/proc/heat2colour_r(temp)
temp /= 100
if(temp <= 66)
. = 255
else
. = max(0, min(255, 329.698727446 * (temp - 60) ** -0.1332047592))
/proc/heat2colour_g(temp)
temp /= 100
if(temp <= 66)
. = max(0, min(255, 99.4708025861 * log(temp) - 161.1195681661))
else
. = max(0, min(255, 288.1221685293 * ((temp - 60) ** -0.075148492)))
/proc/heat2colour_b(temp)
temp /= 100
if(temp >= 66)
. = 255
else
if(temp <= 16)
. = 0
else
. = max(0, min(255, 138.5177312231 * log(temp - 10) - 305.0447927307))
/proc/color2hex(color) //web colors
if(!color)
return "#000000"
switch(color)
if("white")
return "#FFFFFF"
if("black")
return "#000000"
if("gray")
return "#808080"
if("brown")
return "#A52A2A"
if("red")
return "#FF0000"
if("darkred")
return "#8B0000"
if("crimson")
return "#DC143C"
if("orange")
return "#FFA500"
if("yellow")
return "#FFFF00"
if("green")
return "#008000"
if("lime")
return "#00FF00"
if("darkgreen")
return "#006400"
if("cyan")
return "#00FFFF"
if("blue")
return "#0000FF"
if("navy")
return "#000080"
if("teal")
return "#008080"
if("purple")
return "#800080"
if("indigo")
return "#4B0082"
else
return "#FFFFFF"
//This is a weird one:
//It returns a list of all var names found in the string
//These vars must be in the [var_name] format
//It's only a proc because it's used in more than one place
//Takes a string and a datum
//The string is well, obviously the string being checked
//The datum is used as a source for var names, to check validity
//Otherwise every single word could technically be a variable!
/proc/string2listofvars(var/t_string, var/datum/var_source)
if(!t_string || !var_source)
return list()
. = list()
var/var_found = findtext(t_string,"\[") //Not the actual variables, just a generic "should we even bother" check
if(var_found)
//Find var names
// "A dog said hi [name]!"
// splittext() --> list("A dog said hi ","name]!"
// jointext() --> "A dog said hi name]!"
// splittext() --> list("A","dog","said","hi","name]!")
t_string = replacetext(t_string,"\[","\[ ")//Necessary to resolve "word[var_name]" scenarios
var/list/list_value = splittext(t_string,"\[")
var/intermediate_stage = jointext(list_value, null)
list_value = splittext(intermediate_stage," ")
for(var/value in list_value)
if(findtext(value,"]"))
value = splittext(value,"]") //"name]!" --> list("name","!")
for(var/A in value)
if(var_source.vars.Find(A))
. += A
//assumes format #RRGGBB #rrggbb
/proc/color_hex2num(A)
if(!A)
return 0
var/R = hex2num(copytext(A,2,4))
var/G = hex2num(copytext(A,4,6))
var/B = hex2num(copytext(A,6,0))
return R+G+B
//Converts a positive interger to its roman numeral equivilent. Ignores any decimals.
//Numbers over 3999 will display with extra "M"s (don't tell the Romans) and can get comically long, so be careful.
/proc/num2roman(A)
var/list/values = list("M" = 1000, "CM" = 900, "D" = 500, "CD" = 400, "C" = 100, "XC" = 90, "L" = 50, "XL" = 40, "X" = 10, "IX" = 9, "V" = 5, "IV" = 4, "I" = 1)
if(!A || !isnum(A))
return 0
while(A >= 1)
for(var/i in values)
if(A >= values[i])
. += i
A -= values[i]
break
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,21 @@
/*
This is a smart+stupid method of maintaining paths during refactors.
At this point in time we have more maps than ever, and our tools just aren't that great.
So instead of repathing all the maps...
Keep the old path defined, just as an empty type with that path, and then define it's
parent_type as the new path, effectively maintaining the object/mob w/e without having
to touch all the maps, avoiding all those nasty conflicts!
Ideally the old paths would be cleaned out as mappers go about their usual routine of
updating old maps.
tl;dr TYPEFUCKERY, because fuck updating all these maps
Example:
/obj/structure/bed/chair/janicart/secway
parent_type = /obj/vehicle/secway
*/
+64
View File
@@ -0,0 +1,64 @@
#define DEBUG //Enables byond profiling and full runtime logs - note, this may also be defined in your .dme file
//Enables in-depth debug messages to runtime log (used for debugging)
//#define TESTING //By using the testing("message") proc you can create debug-feedback for people with this
//uncommented, but not visible in the release version)
#define PRELOAD_RSC 1 /*set to:
0 to allow using external resources or on-demand behaviour;
1 to use the default behaviour;
2 for preloading absolutely everything;
*/
#define BACKGROUND_ENABLED 0 // The default value for all uses of set background. Set background can cause gradual lag and is recommended you only turn this on if necessary.
// 1 will enable set background. 0 will disable set background.
#define INACTIVITY_KICK 6000 //10 minutes in ticks (approx.)
//ADMIN STUFF
#define ROUNDSTART_LOGOUT_REPORT_TIME 6000 //Amount of time (in deciseconds) after the rounds starts, that the player disconnect report is issued.
#define SPAM_TRIGGER_WARNING 5 //Number of identical messages required before the spam-prevention will warn you to stfu
#define SPAM_TRIGGER_AUTOMUTE 10 //Number of identical messages required before the spam-prevention will automute you
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
#define MAX_MESSAGE_LEN 1024
#define MAX_NAME_LEN 26
#define MAX_BROADCAST_LEN 512
#define MAX_CHARTER_LEN 50
//MINOR TWEAKS/MISC
#define AGE_MIN 17 //youngest a character can be
#define AGE_MAX 85 //oldest a character can be
#define SHOES_SLOWDOWN 0 //How much shoes slow you down by default. Negative values speed you up
#define POCKET_STRIP_DELAY 40 //time taken (in deciseconds) to search somebody's pockets
#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
#define HUNGER_FACTOR 0.1 //factor at which mob nutrition decreases
#define REAGENTS_METABOLISM 0.4 //How many units of reagent are consumed per tick, by default.
#define REAGENTS_EFFECT_MULTIPLIER (REAGENTS_METABOLISM / 0.4) // By defining the effect multiplier this way, it'll exactly adjust all effects according to how they originally were with the 0.4 metabolism
#define MAX_STACK_AMOUNT_METAL 50
#define MAX_STACK_AMOUNT_GLASS 50
#define MAX_STACK_AMOUNT_RODS 60
// AI Toggles
#define AI_CAMERA_LUMINOSITY 5
#define AI_VOX 1 // Comment out if you don't want VOX to be enabled and have players download the voice sounds.
//Additional code for the above flags.
#ifdef TESTING
#warn compiling in TESTING mode. testing() debug messages will be visible.
#endif
//Update this whenever you need to take advantage of more recent byond features
#define MIN_COMPILER_VERSION 510
#if DM_VERSION < MIN_COMPILER_VERSION
//Don't forget to update this part
#error Your version of BYOND is too out-of-date to compile this project. Go to byond.com/download and update.
#error You need version 510 or higher
#endif
#ifndef SERVERTOOLS
#define SERVERTOOLS 0
#endif
+39
View File
@@ -0,0 +1,39 @@
var/datum/configuration/config = null
var/datum/protected_configuration/protected_config = null
var/host = null
var/join_motd = null
var/station_name = null
var/game_version = "/tg/ Station 13"
var/changelog_hash = ""
var/ooc_allowed = 1 // used with admin verbs to disable ooc - not a config option apparently
var/dooc_allowed = 1
var/abandon_allowed = 1
var/enter_allowed = 1
var/guests_allowed = 1
var/shuttle_frozen = 0
var/shuttle_left = 0
var/tinted_weldhelh = 1
// Debug is used exactly once (in living.dm) but is commented out in a lot of places. It is not set anywhere and only checked.
// Debug2 is used in conjunction with a lot of admin verbs and therefore is actually legit.
var/Debug = 0 // global debug switch
var/Debug2 = 0
//Server API key
var/global/comms_key = "default_pwd"
var/global/comms_allowed = 0 //By default, the server does not allow messages to be sent to it, unless the key is strong enough (this is to prevent misconfigured servers from becoming vulnerable)
//Cross server communications
var/global/cross_address = "byond://" //This needs to be global as the message sent contains the comms key.
var/global/cross_allowed = 0 //Don't bother attempting to send if the address wasn't set.
//This was a define, but I changed it to a variable so it can be changed in-game.(kept the all-caps definition because... code...) -Errorage
var/MAX_EX_DEVESTATION_RANGE = 3
var/MAX_EX_HEAVY_RANGE = 7
var/MAX_EX_LIGHT_RANGE = 14
var/MAX_EX_FLASH_RANGE = 14
var/MAX_EX_FLAME_RANGE = 14
+12
View File
@@ -0,0 +1,12 @@
// MySQL configuration
var/sqladdress = "localhost"
var/sqlport = "3306"
var/sqlfdbkdb = "test"
var/sqlfdbklogin = "root"
var/sqlfdbkpass = ""
var/sqlfdbktableprefix = "erro_" //backwords compatibility with downstream server hosts
//Database connections
//A connection is established on world creation. Ideally, the connection dies when the server restarts (After feedback logging.).
var/DBConnection/dbcon = new() //Feedback database (New database)
+5
View File
@@ -0,0 +1,5 @@
var/master_mode = "traitor"//"extended"
var/secret_force_mode = "secret" // if this is anything but "secret", the secret rotation will forceably choose this mode
var/wavesecret = 0 // meteor mode, delays wave progression, terrible name
var/datum/station_state/start_state = null // Used in round-end report
+28
View File
@@ -0,0 +1,28 @@
//////////////
var/NEARSIGHTBLOCK = 0
var/EPILEPSYBLOCK = 0
var/COUGHBLOCK = 0
var/TOURETTESBLOCK = 0
var/NERVOUSBLOCK = 0
var/BLINDBLOCK = 0
var/DEAFBLOCK = 0
var/HULKBLOCK = 0
var/TELEBLOCK = 0
var/FIREBLOCK = 0
var/XRAYBLOCK = 0
var/CLUMSYBLOCK = 0
var/STRANGEBLOCK = 0
var/RACEBLOCK = 0
var/list/bad_se_blocks
var/list/good_se_blocks
var/list/op_se_blocks
var/NULLED_SE
var/NULLED_UI
var/list/global_mutations = list() // list of hidden mutation things
var/list/bad_mutations = list()
var/list/good_mutations = list()
var/list/not_good_mutations = list()
+156
View File
@@ -0,0 +1,156 @@
//Preferences stuff
//Hairstyles
var/global/list/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name
var/global/list/hair_styles_male_list = list() //stores only hair names
var/global/list/hair_styles_female_list = list() //stores only hair names
var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessory/facial_hair indexed by name
var/global/list/facial_hair_styles_male_list = list() //stores only hair names
var/global/list/facial_hair_styles_female_list = list() //stores only hair names
//Underwear
var/global/list/underwear_list = list() //stores /datum/sprite_accessory/underwear indexed by name
var/global/list/underwear_m = list() //stores only underwear name
var/global/list/underwear_f = list() //stores only underwear name
//Undershirts
var/global/list/undershirt_list = list() //stores /datum/sprite_accessory/undershirt indexed by name
var/global/list/undershirt_m = list() //stores only undershirt name
var/global/list/undershirt_f = list() //stores only undershirt name
//Socks
var/global/list/socks_list = list() //stores /datum/sprite_accessory/socks indexed by name
//Lizard Bits (all datum lists indexed by name)
var/global/list/body_markings_list = list()
var/global/list/tails_list_lizard = list()
var/global/list/animated_tails_list_lizard = list()
var/global/list/snouts_list = list()
var/global/list/horns_list = list()
var/global/list/frills_list = list()
var/global/list/spines_list = list()
var/global/list/animated_spines_list = list()
//Mutant Human bits
var/global/list/tails_list_human = list()
var/global/list/animated_tails_list_human = list()
var/global/list/ears_list = list()
var/global/list/wings_list = list()
var/global/list/wings_open_list = list()
var/global/list/r_wings_list = list()
var/global/list/ghost_forms_with_directions_list = list("ghost") //stores the ghost forms that support directional sprites
var/global/list/ghost_forms_with_accessories_list = list("ghost") //stores the ghost forms that support hair and other such things
//Backpacks
#define GBACKPACK "Grey Backpack"
#define GSATCHEL "Grey Satchel"
#define GDUFFLEBAG "Grey Dufflebag"
#define LSATCHEL "Leather Satchel"
#define DBACKPACK "Department Backpack"
#define DSATCHEL "Department Satchel"
#define DDUFFLEBAG "Department Dufflebag"
var/global/list/backbaglist = list(DBACKPACK, DSATCHEL, DDUFFLEBAG, GBACKPACK, GSATCHEL, GDUFFLEBAG, LSATCHEL)
//Female Uniforms
var/global/list/female_clothing_icons = list()
//radical shit
var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF")
var/list/scarySounds = list('sound/weapons/thudswoosh.ogg','sound/weapons/Taser.ogg','sound/weapons/armbomb.ogg','sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg','sound/voice/hiss5.ogg','sound/voice/hiss6.ogg','sound/effects/Glassbr1.ogg','sound/effects/Glassbr2.ogg','sound/effects/Glassbr3.ogg','sound/items/Welder.ogg','sound/items/Welder2.ogg','sound/machines/airlock.ogg','sound/effects/clownstep1.ogg','sound/effects/clownstep2.ogg')
// Reference list for disposal sort junctions. Set the sortType variable on disposal sort junctions to
// the index of the sort department that you want. For example, sortType set to 2 will reroute all packages
// tagged for the Cargo Bay.
/* List of sortType codes for mapping reference
0 Waste
1 Disposals
2 Cargo Bay
3 QM Office
4 Engineering
5 CE Office
6 Atmospherics
7 Security
8 HoS Office
9 Medbay
10 CMO Office
11 Chemistry
12 Research
13 RD Office
14 Robotics
15 HoP Office
16 Library
17 Chapel
18 Theatre
19 Bar
20 Kitchen
21 Hydroponics
22 Janitor
23 Genetics
*/
var/list/TAGGERLOCATIONS = list("Disposals",
"Cargo Bay", "QM Office", "Engineering", "CE Office",
"Atmospherics", "Security", "HoS Office", "Medbay",
"CMO Office", "Chemistry", "Research", "RD Office",
"Robotics", "HoP Office", "Library", "Chapel", "Theatre",
"Bar", "Kitchen", "Hydroponics", "Janitor Closet","Genetics")
var/global/list/guitar_notes = flist("sound/guitar/")
var/global/list/station_prefixes = list("", "Imperium", "Heretical", "Cuban",
"Psychic", "Elegant", "Common", "Uncommon", "Rare", "Unique",
"Houseruled", "Religious", "Atheist", "Traditional", "Houseruled",
"Mad", "Super", "Ultra", "Secret", "Top Secret", "Deep", "Death",
"Zybourne", "Central", "Main", "Government", "Uoi", "Fat",
"Automated", "Experimental", "Augmented")
var/global/list/station_names = list("", "Stanford", "Dorf", "Alium",
"Prefix", "Clowning", "Aegis", "Ishimura", "Scaredy", "Death-World",
"Mime", "Honk", "Rogue", "MacRagge", "Ultrameens", "Safety", "Paranoia",
"Explosive", "Neckbear", "Donk", "Muppet", "North", "West", "East",
"South", "Slant-ways", "Widdershins", "Rimward", "Expensive",
"Procreatory", "Imperial", "Unidentified", "Immoral", "Carp", "Ork",
"Pete", "Control", "Nettle", "Aspie", "Class", "Crab", "Fist",
"Corrogated","Skeleton","Race", "Fatguy", "Gentleman", "Capitalist",
"Communist", "Bear", "Beard", "Derp", "Space", "Spess", "Star", "Moon",
"System", "Mining", "Neckbeard", "Research", "Supply", "Military",
"Orbital", "Battle", "Science", "Asteroid", "Home", "Production",
"Transport", "Delivery", "Extraplanetary", "Orbital", "Correctional",
"Robot", "Hats", "Pizza")
var/global/list/station_suffixes = list("Station", "Frontier",
"Suffix", "Death-trap", "Space-hulk", "Lab", "Hazard","Spess Junk",
"Fishery", "No-Moon", "Tomb", "Crypt", "Hut", "Monkey", "Bomb",
"Trade Post", "Fortress", "Village", "Town", "City", "Edition", "Hive",
"Complex", "Base", "Facility", "Depot", "Outpost", "Installation",
"Drydock", "Observatory", "Array", "Relay", "Monitor", "Platform",
"Construct", "Hangar", "Prison", "Center", "Port", "Waystation",
"Factory", "Waypoint", "Stopover", "Hub", "HQ", "Office", "Object",
"Fortification", "Colony", "Planet-Cracker", "Roost", "Fat Camp",
"Airstrip")
var/global/list/greek_letters = list("Alpha", "Beta", "Gamma", "Delta",
"Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda", "Mu",
"Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi",
"Chi", "Psi", "Omega")
var/global/list/roman_numerals = list("I", "II", "III", "IV", "V", "VI",
"VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI",
"XVII", "XVIII", "XIX", "XX")
var/global/list/phonetic_alphabet = list("Alpha", "Bravo", "Charlie",
"Delta", "Echo", "Foxtrot", "Golf", "Hotel", "India", "Juliet",
"Kilo", "Lima", "Mike", "November", "Oscar", "Papa", "Quebec",
"Romeo", "Sierra", "Tango", "Uniform", "Victor", "Whiskey", "X-ray",
"Yankee", "Zulu")
var/global/list/numbers_as_words = list("One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve",
"Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen",
"Eighteen", "Nineteen")
/proc/generate_number_strings()
var/list/L
for(var/i in 1 to 99)
L += "[i]"
return L
var/global/list/station_numerals = greek_letters + roman_numerals + phonetic_alphabet + numbers_as_words + generate_number_strings()
+66
View File
@@ -0,0 +1,66 @@
#define Z_NORTH 1
#define Z_EAST 2
#define Z_SOUTH 3
#define Z_WEST 4
var/list/cardinal = list( NORTH, SOUTH, EAST, WEST )
var/list/alldirs = list(NORTH, SOUTH, EAST, WEST, NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)
var/list/diagonals = list(NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST)
//This list contains the z-level numbers which can be accessed via space travel and the percentile chances to get there.
//(Exceptions: extended, sandbox and nuke) -Errorage
//Was list("3" = 30, "4" = 70).
//Spacing should be a reliable method of getting rid of a body -- Urist.
//Go away Urist, I'm restoring this to the longer list. ~Errorage
var/list/accessable_z_levels = list(1,3,4,5,6,7) //Keep this to six maps, repeating z-levels is ok if needed
var/global/list/global_map = null
//list/global_map = list(list(1,5),list(4,3))//an array of map Z levels.
//Resulting sector map looks like
//|_1_|_4_|
//|_5_|_3_|
//
//1 - SS13
//4 - Derelict
//3 - AI satellite
//5 - empty space
var/list/landmarks_list = list() //list of all landmarks created
var/list/start_landmarks_list = list() //list of all spawn points created
var/list/department_security_spawns = list() //list of all department security spawns
var/list/generic_event_spawns = list() //list of all spawns for events
var/list/monkeystart = list()
var/list/wizardstart = list()
var/list/newplayer_start = list()
var/list/latejoin = list()
var/list/prisonwarp = list() //prisoners go to these
var/list/holdingfacility = list() //captured people go here
var/list/xeno_spawn = list()//Aliens spawn at these.
var/list/tdome1 = list()
var/list/tdome2 = list()
var/list/tdomeobserve = list()
var/list/tdomeadmin = list()
var/list/prisonsecuritywarp = list() //prison security goes to these
var/list/prisonwarped = list() //list of players already warped
var/list/blobstart = list()
var/list/secequipment = list()
var/list/deathsquadspawn = list()
var/list/emergencyresponseteamspawn = list()
var/list/ruin_landmarks = list()
//away missions
var/list/awaydestinations = list() //a list of landmarks that the warpgate can take you to
//used by jump-to-area etc. Updated by area/updateName()
var/list/sortedAreas = list()
//List of preloaded templates
var/list/datum/map_template/map_templates = list()
var/list/datum/map_template/ruins_templates = list()
var/list/datum/map_template/space_ruins_templates = list()
var/list/datum/map_template/lava_ruins_templates = list()
var/list/datum/map_template/shuttle_templates = list()
var/list/datum/map_template/shelter_templates = list()
+15
View File
@@ -0,0 +1,15 @@
var/list/clients = list() //all clients
var/list/admins = list() //all clients whom are admins
var/list/deadmins = list() //all clients who have used the de-admin verb.
var/list/directory = list() //all ckeys with associated client
var/list/stealthminID = list() //reference list with IDs that store ckeys, for stealthmins
//Since it didn't really belong in any other category, I'm putting this here
//This is for procs to replace all the goddamn 'in world's that are chilling around the code
var/global/list/player_list = list() //all mobs **with clients attached**. Excludes /mob/new_player
var/global/list/mob_list = list() //all mobs, including clientless
var/global/list/living_mob_list = list() //all alive mobs, including clientless. Excludes /mob/new_player
var/global/list/dead_mob_list = list() //all dead mobs, including clientless. Excludes /mob/new_player
var/global/list/joined_player_list = list() //all clients that have joined the game at round-start or as a latejoin.
var/global/list/silicon_mobs = list() //all silicon mobs
+21
View File
@@ -0,0 +1,21 @@
var/list/ai_names = file2list("config/names/ai.txt")
var/list/wizard_first = file2list("config/names/wizardfirst.txt")
var/list/wizard_second = file2list("config/names/wizardsecond.txt")
var/list/ninja_titles = file2list("config/names/ninjatitle.txt")
var/list/ninja_names = file2list("config/names/ninjaname.txt")
var/list/commando_names = file2list("config/names/death_commando.txt")
var/list/first_names_male = file2list("config/names/first_male.txt")
var/list/first_names_female = file2list("config/names/first_female.txt")
var/list/last_names = file2list("config/names/last.txt")
var/list/lizard_names_male = file2list("config/names/lizard_male.txt")
var/list/lizard_names_female = file2list("config/names/lizard_female.txt")
var/list/clown_names = file2list("config/names/clown.txt")
var/list/mime_names = file2list("config/names/mime.txt")
var/list/carp_names = file2list("config/names/carp.txt")
var/list/golem_names = file2list("config/names/golem.txt")
var/list/verbs = file2list("config/names/verbs.txt")
var/list/adjectives = file2list("config/names/adjectives.txt")
//loaded on startup because of "
//would include in rsc if ' was used
+26
View File
@@ -0,0 +1,26 @@
var/global/list/cable_list = list() //Index for all cables, so that powernets don't have to look through the entire world all the time
var/global/list/portals = list() //list of all /obj/effect/portal
var/global/list/airlocks = list() //list of all airlocks
var/global/list/mechas_list = list() //list of all mechs. Used by hostile mobs target tracking.
var/global/list/shuttle_caller_list = list() //list of all communication consoles and AIs, for automatic shuttle calls when there are none.
var/global/list/machines = list() //NOTE: this is a list of ALL machines now. The processing machines list is SSmachine.processing !
var/global/list/syndicate_shuttle_boards = list() //important to keep track of for managing nukeops war declarations.
var/global/list/navbeacons = list() //list of all bot nagivation beacons, used for patrolling.
var/global/list/deliverybeacons = list() //list of all MULEbot delivery beacons.
var/global/list/deliverybeacontags = list() //list of all tags associated with delivery beacons.
var/global/list/nuke_list = list()
var/global/list/nuke_tiles = list() //list of all turfs that turn to animated red grids when a nuke is triggered
var/global/list/chemical_reactions_list //list of all /datum/chemical_reaction datums. Used during chemical reactions
var/global/list/chemical_reagents_list //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
var/global/list/materials_list = list() //list of all /datum/material datums indexed by material id.
var/global/list/tech_list = list() //list of all /datum/tech datums indexed by id.
var/global/list/surgeries_list = list() //list of all surgeries by name, associated with their path.
var/global/list/crafting_recipes = list() //list of all table craft recipes
var/global/list/rcd_list = list() //list of Rapid Construction Devices.
var/global/list/apcs_list = list() //list of all Area Power Controller machines, seperate from machines for powernet speeeeeeed.
var/global/list/tracked_implants = list() //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented...
var/global/list/poi_list = list() //list of points of interest for observe/follow
var/global/list/pinpointer_list = list() //list of all pinpointers. Used to change stuff they are pointing to all at once.
// A list of all zombie_infection organs, for any mass "animation"
var/global/list/zombie_infection_list = list()
+15
View File
@@ -0,0 +1,15 @@
var/diary = null
var/diaryofmeanpeople = null
var/href_logfile = null
var/list/bombers = list( )
var/list/admin_log = list ( )
var/list/lastsignalers = list( ) //keeps last 100 signals here in format: "[src] used \ref[src] @ location [src.loc]: [freq]/[code]"
var/list/lawchanges = list( ) //Stores who uploaded laws to which silicon-based lifeform, and what the law was
var/list/combatlog = list()
var/list/IClog = list()
var/list/OOClog = list()
var/list/adminlog = list()
var/list/active_turfs_startlist = list()
+22
View File
@@ -0,0 +1,22 @@
var/admin_notice = "" // Admin notice that all clients see when joining the server
var/timezoneOffset = 0 // The difference betwen midnight (of the host computer) and 0 world.ticks.
// For FTP requests. (i.e. downloading runtime logs.)
// However it'd be ok to use for accessing attack logs and such too, which are even laggier.
var/fileaccess_timer = 0
var/TAB = "&nbsp;&nbsp;&nbsp;&nbsp;"
var/map_ready = 0
/*
basically, this will be used to avoid initialize() being called twice for objects
initialize() is necessary because the map is instanced on a turf-by-turf basis
i.e. all obj on a turf are instanced, then all mobs on that turf, before moving to the next turf (starting bottom-left)
This means if we want to say, get any neighbouring objects in New(), only objects to the south and west will exist yet.
Therefore, we'd need to use spawn() inside New() to wait for the surrounding turf contents to be instanced
However, using lots of spawn() has a severe performance impact, and often results in spaghetti-code
map_ready will be set to 1 when world/New() is called (which happens just after the map is instanced)
*/
+10
View File
@@ -0,0 +1,10 @@
var/global/datum/datacore/data_core = null
//var/global/defer_powernet_rebuild = 0 // true if net rebuild will be called manually after an event
//Noble idea, but doing this made GC fail. The gains from waiting on deffering are lost by using del()
var/CELLRATE = 0.002 // multiplier for watts per tick <> cell storage (eg: .002 means if there is a load of 1000 watts, 20 units will be taken from a cell per second)
var/CHARGELEVEL = 0.001 // Cap for how fast cells charge, as a percentage-per-tick (.001 means cellcharge is capped to 1% per second)
var/list/powernets = list()
var/map_name = "Unknown" //The name of the map that is loaded. Assigned in world/New()
+1
View File
@@ -0,0 +1 @@
#define CLICKCATCHER_PLANE -99
+97
View File
@@ -0,0 +1,97 @@
/*
Adjacency proc for determining touch range
This is mostly to determine if a user can enter a square for the purposes of touching something.
Examples include reaching a square diagonally or reaching something on the other side of a glass window.
This is calculated by looking for border items, or in the case of clicking diagonally from yourself, dense items.
This proc will NOT notice if you are trying to attack a window on the other side of a dense object in its turf. There is a window helper for that.
Note that in all cases the neighbor is handled simply; this is usually the user's mob, in which case it is up to you
to check that the mob is not inside of something
*/
/atom/proc/Adjacent(atom/neighbor) // basic inheritance, unused
return 0
// Not a sane use of the function and (for now) indicative of an error elsewhere
/area/Adjacent(var/atom/neighbor)
CRASH("Call to /area/Adjacent(), unimplemented proc")
/*
Adjacency (to turf):
* If you are in the same turf, always true
* If you are vertically/horizontally adjacent, ensure there are no border objects
* If you are diagonally adjacent, ensure you can pass through at least one of the mutually adjacent square.
* Passing through in this case ignores anything with the LETPASSTHROW pass flag, such as tables, racks, and morgue trays.
*/
/turf/Adjacent(var/atom/neighbor, var/atom/target = null)
var/turf/T0 = get_turf(neighbor)
if(T0 == src) //same turf
return 1
if(get_dist(src,T0) > 1) //too far
return 0
// Non diagonal case
if(T0.x == x || T0.y == y)
// Check for border blockages
return T0.ClickCross(get_dir(T0,src), border_only = 1) && src.ClickCross(get_dir(src,T0), border_only = 1, target_atom = target)
// Diagonal case
var/in_dir = get_dir(T0,src) // eg. northwest (1+8) = 9 (00001001)
var/d1 = in_dir&3 // eg. north (1+8)&3 (0000 0011) = 1 (0000 0001)
var/d2 = in_dir&12 // eg. west (1+8)&12 (0000 1100) = 8 (0000 1000)
for(var/d in list(d1,d2))
if(!T0.ClickCross(d, border_only = 1))
continue // could not leave T0 in that direction
var/turf/T1 = get_step(T0,d)
if(!T1 || T1.density || !T1.ClickCross(get_dir(T1,T0) | get_dir(T1,src), border_only = 0)) //let's check both directions at once
continue // couldn't enter or couldn't leave T1
if(!src.ClickCross(get_dir(src,T1), border_only = 1, target_atom = target))
continue // could not enter src
return 1 // we don't care about our own density
return 0
/*
Adjacency (to anything else):
* Must be on a turf
*/
/atom/movable/Adjacent(var/atom/neighbor)
if(neighbor == loc) return 1
if(!isturf(loc)) return 0
if(loc.Adjacent(neighbor,src)) return 1
return 0
// This is necessary for storage items not on your person.
/obj/item/Adjacent(var/atom/neighbor, var/recurse = 1)
if(neighbor == loc) return 1
if(istype(loc,/obj/item))
if(recurse > 0)
return loc.Adjacent(neighbor,recurse - 1)
return 0
return ..()
/*
This checks if you there is uninterrupted airspace between that turf and this one.
This is defined as any dense ON_BORDER object, or any dense object without LETPASSTHROW.
The border_only flag allows you to not objects (for source and destination squares)
*/
/turf/proc/ClickCross(target_dir, border_only, target_atom = null)
for(var/obj/O in src)
if( !O.density || O == target_atom || (O.pass_flags & LETPASSTHROW)) //check if there's a dense object present on the turf
continue // LETPASSTHROW is used for anything you can click through (or the firedoor special case, see above)
if( O.flags&ON_BORDER) // windows are on border, check them first
if( O.dir & target_dir || O.dir & (O.dir-1) ) // full tile windows are just diagonals mechanically
return 0 //O.dir&(O.dir-1) is false for any cardinal direction, but true for diagonal ones
else if( !border_only ) // dense, not on border, cannot pass over
return 0
return 1
+177
View File
@@ -0,0 +1,177 @@
/*
AI ClickOn()
Note currently ai restrained() returns 0 in all cases,
therefore restrained code has been removed
The AI can double click to move the camera (this was already true but is cleaner),
or double click a mob to track them.
Note that AI have no need for the adjacency proc, and so this proc is a lot cleaner.
*/
/mob/living/silicon/ai/DblClickOn(var/atom/A, params)
if(client.click_intercept)
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
return
if(control_disabled || stat) return
if(ismob(A))
ai_actual_track(A)
else
A.move_camera_by_click()
/mob/living/silicon/ai/ClickOn(var/atom/A, params)
if(world.time <= next_click)
return
next_click = world.time + 1
if(client.click_intercept)
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
return
if(control_disabled || stat)
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
if(controlled_mech) //Are we piloting a mech? Placed here so the modifiers are not overridden.
controlled_mech.click_action(A, src, params) //Override AI normal click behavior.
return
return
if(modifiers["shift"])
ShiftClickOn(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
if(world.time <= next_move)
return
if(aicamera.in_camera_mode)
aicamera.camera_mode_off()
aicamera.captureimage(A, usr)
return
if(waypoint_mode)
set_waypoint(A)
waypoint_mode = 0
return
/*
AI restrained() currently does nothing
if(restrained())
RestrainedClickOn(A)
else
*/
A.attack_ai(src)
/*
AI has no need for the UnarmedAttack() and RangedAttack() procs,
because the AI code is not generic; attack_ai() is used instead.
The below is only really for safety, or you can alter the way
it functions and re-insert it above.
*/
/mob/living/silicon/ai/UnarmedAttack(atom/A)
A.attack_ai(src)
/mob/living/silicon/ai/RangedAttack(atom/A)
A.attack_ai(src)
/atom/proc/attack_ai(mob/user)
return
/*
Since the AI handles shift, ctrl, and alt-click differently
than anything else in the game, atoms have separate procs
for AI shift, ctrl, and alt clicking.
*/
/mob/living/silicon/ai/CtrlShiftClickOn(var/atom/A)
A.AICtrlShiftClick(src)
/mob/living/silicon/ai/ShiftClickOn(var/atom/A)
A.AIShiftClick(src)
/mob/living/silicon/ai/CtrlClickOn(var/atom/A)
A.AICtrlClick(src)
/mob/living/silicon/ai/AltClickOn(var/atom/A)
A.AIAltClick(src)
/*
The following criminally helpful code is just the previous code cleaned up;
I have no idea why it was in atoms.dm instead of respective files.
*/
/* Questions: Instead of an Emag check on every function, can we not add to airlocks onclick if emag return? */
/* Atom Procs */
/atom/proc/AICtrlClick()
return
/atom/proc/AIAltClick(mob/living/silicon/ai/user)
AltClick(user)
return
/atom/proc/AIShiftClick()
return
/atom/proc/AICtrlShiftClick()
return
/* Airlocks */
/obj/machinery/door/airlock/AICtrlClick() // Bolts doors
if(emagged)
return
if(locked)
Topic("aiEnable=4", list("aiEnable"="4"), 1)// 1 meaning no window (consistency!)
else
Topic("aiDisable=4", list("aiDisable"="4"), 1)
return
/obj/machinery/door/airlock/AIAltClick() // Eletrifies doors.
if(emagged)
return
if(!secondsElectrified)
// permenant shock
Topic("aiEnable=6", list("aiEnable"="6"), 1) // 1 meaning no window (consistency!)
else
// disable/6 is not in Topic; disable/5 disables both temporary and permenant shock
Topic("aiDisable=5", list("aiDisable"="5"), 1)
return
/obj/machinery/door/airlock/AIShiftClick() // Opens and closes doors!
if(emagged)
return
if(density)
Topic("aiEnable=7", list("aiEnable"="7"), 1) // 1 meaning no window (consistency!)
else
Topic("aiDisable=7", list("aiDisable"="7"), 1)
return
/obj/machinery/door/airlock/AICtrlShiftClick() // Sets/Unsets Emergency Access Override
if(emagged)
return
if(!emergency)
Topic("aiEnable=11", list("aiEnable"="11"), 1) // 1 meaning no window (consistency!)
else
Topic("aiDisable=11", list("aiDisable"="11"), 1)
return
/* APC */
/obj/machinery/power/apc/AICtrlClick() // turns off/on APCs.
toggle_breaker()
add_fingerprint(usr)
/* AI Turrets */
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets
toggle_lethal()
add_fingerprint(usr)
/obj/machinery/turretid/AICtrlClick() //turns off/on Turrets
toggle_on()
add_fingerprint(usr)
//
// Override TurfAdjacent for AltClicking
//
/mob/living/silicon/ai/TurfAdjacent(var/turf/T)
return (cameranet && cameranet.checkTurfVis(T))
+45
View File
@@ -0,0 +1,45 @@
/client
var/list/atom/selected_target[2]
/client/MouseDown(object, location, control, params)
var/delay = mob.CanMobAutoclick(object, location, params)
if(delay)
selected_target[1] = object
selected_target[2] = params
while(selected_target[1])
Click(selected_target[1], location, control, selected_target[2])
sleep(delay)
/client/MouseUp(object, location, control, params)
selected_target[1] = null
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
if(selected_target[1] && over_object.IsAutoclickable())
selected_target[1] = over_object
selected_target[2] = params
/mob/proc/CanMobAutoclick(object, location, params)
/mob/living/carbon/CanMobAutoclick(atom/object, location, params)
if(!object.IsAutoclickable())
return
var/obj/item/h = get_active_hand()
if(h)
. = h.CanItemAutoclick(object, location, params)
/obj/item/proc/CanItemAutoclick(object, location, params)
/obj/item/weapon/gun
var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds
/obj/item/weapon/gun/CanItemAutoclick(object, location, params)
. = automatic
/atom/proc/IsAutoclickable()
. = 1
/obj/screen/IsAutoclickable()
. = 0
/obj/screen/click_catcher/IsAutoclickable()
. = 1
+356
View File
@@ -0,0 +1,356 @@
/*
Click code cleanup
~Sayu
*/
// 1 decisecond click delay (above and beyond mob/next_move)
//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move()
/mob/var/next_click = 0
// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or -
/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by
//Delays the mob's next click/action by num deciseconds
// eg: 10-3 = 7 deciseconds of delay
// eg: 10*0.5 = 5 deciseconds of delay
// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK
/mob/proc/changeNext_move(num)
next_move = world.time + ((num+next_move_adjust)*next_move_modifier)
/*
Before anything else, defer these calls to a per-mobtype handler. This allows us to
remove istype() spaghetti code, but requires the addition of other handler procs to simplify it.
Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however,
that's a lot of code duplication and is hard to maintain.
Note that this proc can be overridden, and is in the case of screen objects.
*/
/atom/Click(location,control,params)
usr.ClickOn(src, params)
/atom/DblClick(location,control,params)
usr.DblClickOn(src,params)
/*
Standard mob ClickOn()
Handles exceptions: Buildmode, middle click, modified clicks, mech actions
After that, mostly just check your state, check whether you're holding an item,
check whether you're adjacent to the target, then pass off the click to whoever
is recieving it.
The most common are:
* mob/UnarmedAttack(atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves
* atom/attackby(item,user) - used only when adjacent
* item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent
* mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed
*/
/mob/proc/ClickOn( atom/A, params )
if(world.time <= next_click)
return
next_click = world.time + 1
if(client.click_intercept)
if(call(client.click_intercept, "InterceptClickOn")(src, params, A))
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["middle"])
ShiftMiddleClickOn(A)
return
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
if(modifiers["shift"])
ShiftClickOn(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
if(incapacitated(ignore_restraints = 1))
return
face_atom(A)
if(next_move > world.time) // in the year 2000...
return
if(istype(loc,/obj/mecha))
var/obj/mecha/M = loc
return M.click_action(A,src,params)
if(restrained())
changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow
RestrainedClickOn(A)
return
if(in_throw_mode)
throw_item(A)
return
var/obj/item/W = get_active_hand()
if(W == A)
W.attack_self(src)
if(hand)
update_inv_l_hand(0)
else
update_inv_r_hand(0)
return
// operate three levels deep here (item in backpack in src; item in box in backpack in src, not any deeper)
if(!isturf(A) && A == loc || (A in contents) || (A.loc in contents) || (A.loc && (A.loc.loc in contents)))
// No adjacency needed
if(W)
var/resolved = A.attackby(W,src)
if(!resolved && A && W)
W.afterattack(A,src,1,params) // 1 indicates adjacency
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A)
return
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
// Allows you to click on a box's contents, if that box is on the ground, but no deeper than that
if(isturf(A) || isturf(A.loc) || (A.loc && isturf(A.loc.loc)))
if(A.Adjacent(src)) // see adjacent.dm
if(W)
// Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example)
var/resolved = A.attackby(W,src,params)
if(!resolved && A && W)
W.afterattack(A,src,1,params) // 1: clicking something Adjacent
else
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
UnarmedAttack(A, 1)
return
else // non-adjacent click
if(W)
W.afterattack(A,src,0,params) // 0: not Adjacent
else
RangedAttack(A, params)
// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click)
/mob/proc/DblClickOn(atom/A, params)
return
/*
Translates into attack_hand, etc.
Note: proximity_flag here is used to distinguish between normal usage (flag=1),
and usage when clicking on things telekinetically (flag=0). This proc will
not be called at ranged except with telekinesis.
proximity_flag is not currently passed to attack_hand, and is instead used
in human click code to allow glove touches only at melee range.
*/
/mob/proc/UnarmedAttack(atom/A, proximity_flag)
if(ismob(A))
changeNext_move(CLICK_CD_MELEE)
return
/*
Ranged unarmed attack:
This currently is just a default for all mobs, involving
laser eyes and telekinesis. You could easily add exceptions
for things like ranged glove touches, spitting alien acid/neurotoxin,
animals lunging, etc.
*/
/mob/proc/RangedAttack(atom/A, params)
/*
Restrained ClickOn
Used when you are handcuffed and click things.
Not currently used by anything but could easily be.
*/
/mob/proc/RestrainedClickOn(atom/A)
return
/*
Middle click
Only used for swapping hands
*/
/mob/proc/MiddleClickOn(atom/A)
return
/mob/living/carbon/MiddleClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
swap_hand()
/mob/living/simple_animal/drone/MiddleClickOn(atom/A)
swap_hand()
// In case of use break glass
/*
/atom/proc/MiddleClick(mob/M as mob)
return
*/
/*
Shift click
For most mobs, examine.
This is overridden in ai.dm
*/
/mob/proc/ShiftClickOn(atom/A)
A.ShiftClick(src)
return
/atom/proc/ShiftClick(mob/user)
if(user.client && user.client.eye == user || user.client.eye == user.loc)
user.examinate(src)
return
/*
Ctrl click
For most objects, pull
*/
/mob/proc/CtrlClickOn(atom/A)
A.CtrlClick(src)
return
/atom/proc/CtrlClick(mob/user)
var/mob/living/ML = user
if(istype(ML))
ML.pulled(src)
/*
Alt click
Unused except for AI
*/
/mob/proc/AltClickOn(atom/A)
A.AltClick(src)
return
/mob/living/carbon/AltClickOn(atom/A)
if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src))
next_click = world.time + 5
mind.changeling.chosen_sting.try_to_sting(src, A)
else
..()
/atom/proc/AltClick(mob/user)
var/turf/T = get_turf(src)
if(T && user.TurfAdjacent(T))
if(user.listed_turf == T)
user.listed_turf = null
else
user.listed_turf = T
user.client.statpanel = T.name
return
/mob/proc/TurfAdjacent(turf/T)
return T.Adjacent(src)
/*
Control+Shift click
Unused except for AI
*/
/mob/proc/CtrlShiftClickOn(atom/A)
A.CtrlShiftClick(src)
return
/mob/proc/ShiftMiddleClickOn(atom/A)
src.pointed(A)
return
/atom/proc/CtrlShiftClick(mob/user)
return
/*
Misc helpers
Laser Eyes: as the name implies, handles this since nothing else does currently
face_atom: turns the mob towards what you clicked on
*/
/mob/proc/LaserEyes(atom/A)
return
/mob/living/LaserEyes(atom/A)
changeNext_move(CLICK_CD_RANGE)
var/turf/T = get_turf(src)
var/turf/U = get_turf(A)
var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc )
LE.icon = 'icons/effects/genetics.dmi'
LE.icon_state = "eyelasers"
playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1)
LE.firer = src
LE.def_zone = get_organ_target()
LE.original = A
LE.current = T
LE.yo = U.y - T.y
LE.xo = U.x - T.x
LE.fire()
// Simple helper to face what you clicked on, in case it should be needed in more than one place
/mob/proc/face_atom(atom/A)
if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y )
return
var/dx = A.x - x
var/dy = A.y - y
if(!dx && !dy) // Wall items are graphically shifted but on the floor
if(A.pixel_y > 16)
setDir(NORTH)
else if(A.pixel_y < -16)
setDir(SOUTH)
else if(A.pixel_x > 16)
setDir(EAST)
else if(A.pixel_x < -16)
setDir(WEST)
return
if(abs(dx) < abs(dy))
if(dy > 0)
setDir(NORTH)
else
setDir(SOUTH)
else
if(dx > 0)
setDir(EAST)
else
setDir(WEST)
/obj/screen/click_catcher
icon = 'icons/mob/screen_gen.dmi'
icon_state = "click_catcher"
plane = CLICKCATCHER_PLANE
mouse_opacity = 2
screen_loc = "CENTER-7,CENTER-7"
/obj/screen/click_catcher/proc/MakeGreed()
. = list()
for(var/i = 0, i<15, i++)
for(var/j = 0, j<15, j++)
var/obj/screen/click_catcher/CC = new()
CC.screen_loc = "NORTH-[i],EAST-[j]"
. += CC
/obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
if(modifiers["middle"] && istype(usr, /mob/living/carbon))
var/mob/living/carbon/C = usr
C.swap_hand()
else
var/turf/T = screen_loc2turf(screen_loc, get_turf(usr))
if(T)
T.Click(location, control, params)
. = 1
+159
View File
@@ -0,0 +1,159 @@
/*
Cyborg ClickOn()
Cyborgs have no range restriction on attack_robot(), because it is basically an AI click.
However, they do have a range restriction on item use, so they cannot do without the
adjacency code.
*/
/mob/living/silicon/robot/ClickOn(var/atom/A, var/params)
if(world.time <= next_click)
return
next_click = world.time + 1
if(client.click_intercept)
if(call(client.click_intercept,"InterceptClickOn")(src,params,A))
return
if(stat || lockcharge || weakened || stunned || paralysis)
return
var/list/modifiers = params2list(params)
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
if(modifiers["middle"])
MiddleClickOn(A)
return
if(modifiers["shift"])
ShiftClickOn(A)
return
if(modifiers["alt"]) // alt and alt-gr (rightalt)
AltClickOn(A)
return
if(modifiers["ctrl"])
CtrlClickOn(A)
return
if(next_move >= world.time)
return
face_atom(A) // change direction to face what you clicked on
/*
cyborg restrained() currently does nothing
if(restrained())
RestrainedClickOn(A)
return
*/
if(aicamera.in_camera_mode) //Cyborg picture taking
aicamera.camera_mode_off()
aicamera.captureimage(A, usr)
return
var/obj/item/W = get_active_hand()
// Cyborgs have no range-checking unless there is item use
if(!W)
A.attack_robot(src)
return
// buckled cannot prevent machine interlinking but stops arm movement
if( buckled || incapacitated())
return
if(W == A)
W.attack_self(src)
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents)
if(A == loc || (A in loc) || (A in contents))
// No adjacency checks
var/resolved = A.attackby(W,src, params)
if(!resolved && A && W)
W.afterattack(A,src,1,params)
return
if(!isturf(loc))
return
// cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc))
if(isturf(A) || isturf(A.loc))
if(A.Adjacent(src)) // see adjacent.dm
var/resolved = A.attackby(W, src, params)
if(!resolved && A && W)
W.afterattack(A, src, 1, params)
return
else
W.afterattack(A, src, 0, params)
return
return
//Middle click cycles through selected modules.
/mob/living/silicon/robot/MiddleClickOn(atom/A)
cycle_modules()
return
//Give cyborgs hotkey clicks without breaking existing uses of hotkey clicks
// for non-doors/apcs
/mob/living/silicon/robot/CtrlShiftClickOn(atom/A)
A.BorgCtrlShiftClick(src)
/mob/living/silicon/robot/ShiftClickOn(atom/A)
A.BorgShiftClick(src)
/mob/living/silicon/robot/CtrlClickOn(atom/A)
A.BorgCtrlClick(src)
/mob/living/silicon/robot/AltClickOn(atom/A)
A.BorgAltClick(src)
/atom/proc/BorgCtrlShiftClick(mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlShiftClick(user)
/obj/machinery/door/airlock/BorgCtrlShiftClick() // Sets/Unsets Emergency Access Override Forwards to AI code.
AICtrlShiftClick()
/atom/proc/BorgShiftClick(mob/living/silicon/robot/user) //forward to human click if not overriden
ShiftClick(user)
/obj/machinery/door/airlock/BorgShiftClick() // Opens and closes doors! Forwards to AI code.
AIShiftClick()
/atom/proc/BorgCtrlClick(mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlClick(user)
/obj/machinery/door/airlock/BorgCtrlClick() // Bolts doors. Forwards to AI code.
AICtrlClick()
/obj/machinery/power/apc/BorgCtrlClick() // turns off/on APCs. Forwards to AI code.
AICtrlClick()
/obj/machinery/turretid/BorgCtrlClick() //turret control on/off. Forwards to AI code.
AICtrlClick()
/atom/proc/BorgAltClick(mob/living/silicon/robot/user)
AltClick(user)
return
/obj/machinery/door/airlock/BorgAltClick() // Eletrifies doors. Forwards to AI code.
AIAltClick()
/obj/machinery/turretid/BorgAltClick() //turret lethal on/off. Forwards to AI code.
AIAltClick()
/*
As with AI, these are not used in click code,
because the code for robots is specific, not generic.
If you would like to add advanced features to robot
clicks, you can do so here, but you will have to
change attack_robot() above to the proper function
*/
/mob/living/silicon/robot/UnarmedAttack(atom/A)
A.attack_robot(src)
/mob/living/silicon/robot/RangedAttack(atom/A)
A.attack_robot(src)
/atom/proc/attack_robot(mob/user)
attack_ai(user)
return
+19
View File
@@ -0,0 +1,19 @@
/*
MouseDrop:
Called on the atom you're dragging. In a lot of circumstances we want to use the
recieving object instead, so that's the default action. This allows you to drag
almost anything into a trash can.
*/
/atom/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
if(!usr || !over) return
if(over == src)
return usr.client.Click(src, src_location, src_control, params)
if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows
over.MouseDrop_T(src,usr)
return
// recieve a mousedrop
/atom/proc/MouseDrop_T(atom/dropping, mob/user)
return
+8
View File
@@ -0,0 +1,8 @@
/mob/camera/god/UnarmedAttack(atom/A)
A.attack_god(src)
/mob/camera/god/RangedAttack(atom/A)
A.attack_god(src)
/atom/proc/attack_god(mob/user)
return
+140
View File
@@ -0,0 +1,140 @@
/*
These defines specificy screen locations. For more information, see the byond documentation on the screen_loc var.
The short version:
Everything is encoded as strings because apparently that's how Byond rolls.
"1,1" is the bottom left square of the user's screen. This aligns perfectly with the turf grid.
"1:2,3:4" is the square (1,3) with pixel offsets (+2, +4); slightly right and slightly above the turf grid.
Pixel offsets are used so you don't perfectly hide the turf under them, that would be crappy.
In addition, the keywords NORTH, SOUTH, EAST, WEST and CENTER can be used to represent their respective
screen borders. NORTH-1, for example, is the row just below the upper edge. Useful if you want your
UI to scale with screen size.
The size of the user's screen is defined by client.view (indirectly by world.view), in our case "15x15".
Therefore, the top right corner (except during admin shenanigans) is at "15,15"
*/
//Lower left, persistant menu
#define ui_inventory "WEST:6,SOUTH:5"
//Middle left indicators
#define ui_lingchemdisplay "WEST:6,CENTER-1:15"
#define ui_lingstingdisplay "WEST:6,CENTER-3:11"
#define ui_crafting "12:-10,1:5"
#define ui_devilsouldisplay "WEST:6,CENTER-1:15"
//Lower center, persistant menu
#define ui_sstore1 "CENTER-5:10,SOUTH:5"
#define ui_id "CENTER-4:12,SOUTH:5"
#define ui_belt "CENTER-3:14,SOUTH:5"
#define ui_back "CENTER-2:14,SOUTH:5"
#define ui_rhand "CENTER:-16,SOUTH:5"
#define ui_lhand "CENTER: 16,SOUTH:5"
#define ui_equip "CENTER:-16,SOUTH+1:5"
#define ui_swaphand1 "CENTER:-16,SOUTH+1:5"
#define ui_swaphand2 "CENTER: 16,SOUTH+1:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
#define ui_borg_sensor "CENTER-3:16, SOUTH:5" //borgs
#define ui_borg_lamp "CENTER-4:16, SOUTH:5" //borgies
#define ui_borg_thrusters "CENTER-5:16, SOUTH:5"//borgies
#define ui_inv1 "CENTER-2:16,SOUTH:5" //borgs
#define ui_inv2 "CENTER-1 :16,SOUTH:5" //borgs
#define ui_inv3 "CENTER :16,SOUTH:5" //borgs
#define ui_borg_module "CENTER+1:16,SOUTH:5"
#define ui_borg_store "CENTER+2:16,SOUTH:5" //borgs
#define ui_borg_camera "CENTER+3:21,SOUTH:5" //borgs
#define ui_borg_album "CENTER+4:21,SOUTH:5" //borgs
#define ui_monkey_head "CENTER-4:13,SOUTH:5" //monkey
#define ui_monkey_mask "CENTER-3:14,SOUTH:5" //monkey
#define ui_monkey_back "CENTER-2:15,SOUTH:5" //monkey
#define ui_alien_storage_l "CENTER-2:14,SOUTH:5"//alien
#define ui_alien_storage_r "CENTER+1:18,SOUTH:5"//alien
#define ui_drone_drop "CENTER+1:18,SOUTH:5" //maintenance drones
#define ui_drone_pull "CENTER+2:2,SOUTH:5" //maintenance drones
#define ui_drone_storage "CENTER-2:14,SOUTH:5" //maintenance drones
#define ui_drone_head "CENTER-3:14,SOUTH:5" //maintenance drones
//Lower right, persistant menu
#define ui_drop_throw "EAST-1:28,SOUTH+1:7"
#define ui_pull_resist "EAST-2:26,SOUTH+1:7"
#define ui_movi "EAST-2:26,SOUTH:5"
#define ui_acti "EAST-3:24,SOUTH:5"
#define ui_zonesel "EAST-1:28,SOUTH:5"
#define ui_acti_alt "EAST-1:28,SOUTH:5" //alternative intent switcher for when the interface is hidden (F12)
#define ui_borg_pull "EAST-2:26,SOUTH+1:7"
#define ui_borg_radio "EAST-1:28,SOUTH+1:7"
#define ui_borg_intents "EAST-2:26,SOUTH:5"
//Upper-middle right (alerts)
#define ui_alert1 "EAST-1:28,CENTER+5:27"
#define ui_alert2 "EAST-1:28,CENTER+4:25"
#define ui_alert3 "EAST-1:28,CENTER+3:23"
#define ui_alert4 "EAST-1:28,CENTER+2:21"
#define ui_alert5 "EAST-1:28,CENTER+1:19"
//Middle right (status indicators)
#define ui_healthdoll "EAST-1:28,CENTER-2:13"
#define ui_health "EAST-1:28,CENTER-1:15"
#define ui_internal "EAST-1:28,CENTER:17"
//borgs and aliens
#define ui_alien_nightvision "EAST-1:28,CENTER:17"
#define ui_borg_health "EAST-1:28,CENTER-1:15" //borgs have the health display where humans have the pressure damage indicator.
#define ui_alien_health "EAST-1:28,CENTER-1:15" //aliens have the health display where humans have the pressure damage indicator.
#define ui_alienplasmadisplay "EAST-1:28,CENTER-2:15"
// AI
#define ui_ai_core "SOUTH:6,WEST"
#define ui_ai_camera_list "SOUTH:6,WEST+1"
#define ui_ai_track_with_camera "SOUTH:6,WEST+2"
#define ui_ai_camera_light "SOUTH:6,WEST+3"
#define ui_ai_crew_monitor "SOUTH:6,WEST+4"
#define ui_ai_crew_manifest "SOUTH:6,WEST+5"
#define ui_ai_alerts "SOUTH:6,WEST+6"
#define ui_ai_announcement "SOUTH:6,WEST+7"
#define ui_ai_shuttle "SOUTH:6,WEST+8"
#define ui_ai_state_laws "SOUTH:6,WEST+9"
#define ui_ai_pda_send "SOUTH:6,WEST+10"
#define ui_ai_pda_log "SOUTH:6,WEST+11"
#define ui_ai_take_picture "SOUTH:6,WEST+12"
#define ui_ai_view_images "SOUTH:6,WEST+13"
#define ui_ai_sensor "SOUTH:6,WEST+14"
//Pop-up inventory
#define ui_shoes "WEST+1:8,SOUTH:5"
#define ui_iclothing "WEST:6,SOUTH+1:7"
#define ui_oclothing "WEST+1:8,SOUTH+1:7"
#define ui_gloves "WEST+2:10,SOUTH+1:7"
#define ui_glasses "WEST:6,SOUTH+2:9"
#define ui_mask "WEST+1:8,SOUTH+2:9"
#define ui_ears "WEST+2:10,SOUTH+2:9"
#define ui_head "WEST+1:8,SOUTH+3:11"
//Ghosts
#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:16"
#define ui_ghost_orbit "SOUTH:6,CENTER-1:16"
#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:16"
#define ui_ghost_teleport "SOUTH:6,CENTER+1:16"
//Hand of God, god
#define ui_deityhealth "EAST-1:28,CENTER-2:13"
#define ui_deitypower "EAST-1:28,CENTER-1:15"
#define ui_deityfollowers "EAST-1:28,CENTER:17"
+129
View File
@@ -0,0 +1,129 @@
/obj/screen/movable/action_button
var/datum/action/linked_action
screen_loc = null
/obj/screen/movable/action_button/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
moved = 0
usr.update_action_buttons() //redraw buttons that are no longer considered "moved"
return 1
if(usr.next_move >= world.time) // Is this needed ?
return
linked_action.Trigger()
return 1
//Hide/Show Action Buttons ... Button
/obj/screen/movable/action_button/hide_toggle
name = "Hide Buttons"
icon = 'icons/mob/actions.dmi'
icon_state = "bg_default"
var/hidden = 0
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
var/list/modifiers = params2list(params)
if(modifiers["shift"])
moved = 0
return 1
usr.hud_used.action_buttons_hidden = !usr.hud_used.action_buttons_hidden
hidden = usr.hud_used.action_buttons_hidden
if(hidden)
name = "Show Buttons"
else
name = "Hide Buttons"
UpdateIcon()
usr.update_action_buttons()
/obj/screen/movable/action_button/hide_toggle/proc/InitialiseIcon(mob/living/user)
if(isalien(user))
icon_state = "bg_alien"
else
icon_state = "bg_default"
UpdateIcon()
return
/obj/screen/movable/action_button/hide_toggle/proc/UpdateIcon()
cut_overlays()
var/image/img = image(icon, src, hidden ? "show" : "hide")
add_overlay(img)
return
/obj/screen/movable/action_button/MouseEntered(location,control,params)
openToolTip(usr,src,params,title = name,content = desc)
/obj/screen/movable/action_button/MouseExited()
closeToolTip(usr)
/mob/proc/update_action_buttons_icon()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
//This is the proc used to update all the action buttons.
/mob/proc/update_action_buttons(reload_screen)
if(!hud_used || !client)
return
if(hud_used.hud_shown != HUD_STYLE_STANDARD)
return
var/button_number = 0
if(hud_used.action_buttons_hidden)
for(var/datum/action/A in actions)
A.button.screen_loc = null
if(reload_screen)
client.screen += A.button
else
for(var/datum/action/A in actions)
button_number++
A.UpdateButtonIcon()
var/obj/screen/movable/action_button/B = A.button
if(!B.moved)
B.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number)
else
B.screen_loc = B.moved
if(reload_screen)
client.screen += B
if(!button_number)
hud_used.hide_actions_toggle.screen_loc = null
return
if(!hud_used.hide_actions_toggle.moved)
hud_used.hide_actions_toggle.screen_loc = hud_used.ButtonNumberToScreenCoords(button_number+1)
else
hud_used.hide_actions_toggle.screen_loc = hud_used.hide_actions_toggle.moved
if(reload_screen)
client.screen += hud_used.hide_actions_toggle
#define AB_MAX_COLUMNS 10
/datum/hud/proc/ButtonNumberToScreenCoords(number) // TODO : Make this zero-indexed for readabilty
var/row = round((number - 1)/AB_MAX_COLUMNS)
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
var/coord_col = "+[col-1]"
var/coord_col_offset = 4 + 2 * col
var/coord_row = "[row ? -row : "+0"]"
return "WEST[coord_col]:[coord_col_offset],NORTH[coord_row]:-6"
/datum/hud/proc/SetButtonCoords(obj/screen/button,number)
var/row = round((number-1)/AB_MAX_COLUMNS)
var/col = ((number - 1)%(AB_MAX_COLUMNS)) + 1
var/x_offset = 32*(col-1) + 4 + 2*col
var/y_offset = -32*(row+1) + 26
var/matrix/M = matrix()
M.Translate(x_offset,y_offset)
button.transform = M
+218
View File
@@ -0,0 +1,218 @@
/obj/screen/ai
icon = 'icons/mob/screen_ai.dmi'
/obj/screen/ai/aicore
name = "AI core"
icon_state = "ai_core"
/obj/screen/ai/aicore/Click()
var/mob/living/silicon/ai/AI = usr
AI.view_core()
/obj/screen/ai/camera_list
name = "Show Camera List"
icon_state = "camera"
/obj/screen/ai/camera_list/Click()
var/mob/living/silicon/ai/AI = usr
var/camera = input(AI, "Choose which camera you want to view", "Cameras") as null|anything in AI.get_camera_list()
AI.ai_camera_list(camera)
/obj/screen/ai/camera_track
name = "Track With Camera"
icon_state = "track"
/obj/screen/ai/camera_track/Click()
var/mob/living/silicon/ai/AI = usr
var/target_name = input(AI, "Choose who you want to track", "Tracking") as null|anything in AI.trackable_mobs()
AI.ai_camera_track(target_name)
/obj/screen/ai/camera_light
name = "Toggle Camera Light"
icon_state = "camera_light"
/obj/screen/ai/camera_light/Click()
var/mob/living/silicon/ai/AI = usr
AI.toggle_camera_light()
/obj/screen/ai/crew_monitor
name = "Crew Monitoring Console"
icon_state = "crew_monitor"
/obj/screen/ai/crew_monitor/Click()
var/mob/living/silicon/ai/AI = usr
crewmonitor.show(AI)
/obj/screen/ai/crew_manifest
name = "Crew Manifest"
icon_state = "manifest"
/obj/screen/ai/crew_manifest/Click()
var/mob/living/silicon/ai/AI = usr
AI.ai_roster()
/obj/screen/ai/alerts
name = "Show Alerts"
icon_state = "alerts"
/obj/screen/ai/alerts/Click()
var/mob/living/silicon/ai/AI = usr
AI.ai_alerts()
/obj/screen/ai/announcement
name = "Make Announcement"
icon_state = "announcement"
/obj/screen/ai/announcement/Click()
var/mob/living/silicon/ai/AI = usr
AI.announcement()
/obj/screen/ai/call_shuttle
name = "Call Emergency Shuttle"
icon_state = "call_shuttle"
/obj/screen/ai/call_shuttle/Click()
var/mob/living/silicon/ai/AI = usr
AI.ai_call_shuttle()
/obj/screen/ai/state_laws
name = "State Laws"
icon_state = "state_laws"
/obj/screen/ai/state_laws/Click()
var/mob/living/silicon/ai/AI = usr
AI.checklaws()
/obj/screen/ai/pda_msg_send
name = "PDA - Send Message"
icon_state = "pda_send"
/obj/screen/ai/pda_msg_send/Click()
var/mob/living/silicon/ai/AI = usr
AI.cmd_send_pdamesg(usr)
/obj/screen/ai/pda_msg_show
name = "PDA - Show Message Log"
icon_state = "pda_receive"
/obj/screen/ai/pda_msg_show/Click()
var/mob/living/silicon/ai/AI = usr
AI.cmd_show_message_log(usr)
/obj/screen/ai/image_take
name = "Take Image"
icon_state = "take_picture"
/obj/screen/ai/image_take/Click()
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.aicamera.toggle_camera_mode()
else if(isrobot(usr))
var/mob/living/silicon/robot/R = usr
R.aicamera.toggle_camera_mode()
/obj/screen/ai/image_view
name = "View Images"
icon_state = "view_images"
/obj/screen/ai/image_view/Click()
if(isAI(usr))
var/mob/living/silicon/ai/AI = usr
AI.aicamera.viewpictures()
else if(isrobot(usr))
var/mob/living/silicon/robot/R = usr
R.aicamera.viewpictures()
/obj/screen/ai/sensors
name = "Sensor Augmentation"
icon_state = "ai_sensor"
/obj/screen/ai/sensors/Click()
var/mob/living/silicon/S = usr
S.sensor_mode()
/datum/hud/ai/New(mob/owner)
..()
var/obj/screen/using
//AI core
using = new /obj/screen/ai/aicore()
using.screen_loc = ui_ai_core
static_inventory += using
//Camera list
using = new /obj/screen/ai/camera_list()
using.screen_loc = ui_ai_camera_list
static_inventory += using
//Track
using = new /obj/screen/ai/camera_track()
using.screen_loc = ui_ai_track_with_camera
static_inventory += using
//Camera light
using = new /obj/screen/ai/camera_light()
using.screen_loc = ui_ai_camera_light
static_inventory += using
//Crew Monitoring
using = new /obj/screen/ai/crew_monitor()
using.screen_loc = ui_ai_crew_monitor
static_inventory += using
//Crew Manifest
using = new /obj/screen/ai/crew_manifest()
using.screen_loc = ui_ai_crew_manifest
static_inventory += using
//Alerts
using = new /obj/screen/ai/alerts()
using.screen_loc = ui_ai_alerts
static_inventory += using
//Announcement
using = new /obj/screen/ai/announcement()
using.screen_loc = ui_ai_announcement
static_inventory += using
//Shuttle
using = new /obj/screen/ai/call_shuttle()
using.screen_loc = ui_ai_shuttle
static_inventory += using
//Laws
using = new /obj/screen/ai/state_laws()
using.screen_loc = ui_ai_state_laws
static_inventory += using
//PDA message
using = new /obj/screen/ai/pda_msg_send()
using.screen_loc = ui_ai_pda_send
static_inventory += using
//PDA log
using = new /obj/screen/ai/pda_msg_show()
using.screen_loc = ui_ai_pda_log
static_inventory += using
//Take image
using = new /obj/screen/ai/image_take()
using.screen_loc = ui_ai_take_picture
static_inventory += using
//View images
using = new /obj/screen/ai/image_view()
using.screen_loc = ui_ai_view_images
static_inventory += using
//Medical/Security sensors
using = new /obj/screen/ai/sensors()
using.screen_loc = ui_ai_sensor
static_inventory += using
/mob/living/silicon/ai/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/ai(src)
+413
View File
@@ -0,0 +1,413 @@
//A system to manage and display alerts on screen without needing you to do it yourself
//PUBLIC - call these wherever you want
/mob/proc/throw_alert(category, type, severity, obj/new_master)
/* Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already
category is a text string. Each mob may only have one alert per category; the previous one will be replaced
path is a type path of the actual alert type to throw
severity is an optional number that will be placed at the end of the icon_state for this alert
For example, high pressure's icon_state is "highpressure" and can be serverity 1 or 2 to get "highpressure1" or "highpressure2"
new_master is optional and sets the alert's icon state to "template" in the ui_style icons with the master as an overlay.
Clicks are forwarded to master */
if(!category)
return
var/obj/screen/alert/alert
if(alerts[category])
alert = alerts[category]
if(new_master && new_master != alert.master)
WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [alert.master]")
clear_alert(category)
return .()
else if(alert.type != type)
clear_alert(category)
return .()
else if(!severity || severity == alert.severity)
if(alert.timeout)
clear_alert(category)
return .()
else //no need to update
return 0
else
alert = PoolOrNew(type)
if(new_master)
var/old_layer = new_master.layer
new_master.layer = FLOAT_LAYER
alert.overlays += new_master
new_master.layer = old_layer
alert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts()
alert.master = new_master
else
alert.icon_state = "[initial(alert.icon_state)][severity]"
alert.severity = severity
alerts[category] = alert
if(client && hud_used)
hud_used.reorganize_alerts()
alert.transform = matrix(32, 6, MATRIX_TRANSLATE)
animate(alert, transform = matrix(), time = 2.5, easing = CUBIC_EASING)
if(alert.timeout)
spawn(alert.timeout)
if(alert.timeout && alerts[category] == alert && world.time >= alert.timeout)
clear_alert(category)
alert.timeout = world.time + alert.timeout - world.tick_lag
return alert
// Proc to clear an existing alert.
/mob/proc/clear_alert(category)
var/obj/screen/alert/alert = alerts[category]
if(!alert)
return 0
alerts -= category
if(client && hud_used)
hud_used.reorganize_alerts()
client.screen -= alert
qdel(alert)
/obj/screen/alert
icon = 'icons/mob/screen_alert.dmi'
icon_state = "default"
name = "Alert"
desc = "Something seems to have gone wrong with this alert, so report this bug please"
mouse_opacity = 1
var/timeout = 0 //If set to a number, this alert will clear itself after that many deciseconds
var/severity = 0
var/alerttooltipstyle = ""
/obj/screen/alert/MouseEntered(location,control,params)
openToolTip(usr,src,params,title = name,content = desc,theme = alerttooltipstyle)
/obj/screen/alert/MouseExited()
closeToolTip(usr)
//Gas alerts
/obj/screen/alert/oxy
name = "Choking (No O2)"
desc = "You're not getting enough oxygen. Find some good air before you pass out! \
The box in your backpack has an oxygen tank and breath mask in it."
icon_state = "oxy"
/obj/screen/alert/too_much_oxy
name = "Choking (O2)"
desc = "There's too much oxygen in the air, and you're breathing it in! Find some good air before you pass out!"
icon_state = "too_much_oxy"
/obj/screen/alert/not_enough_co2
name = "Choking (No CO2)"
desc = "You're not getting enough carbon dioxide. Find some good air before you pass out!"
icon_state = "not_enough_co2"
/obj/screen/alert/too_much_co2
name = "Choking (CO2)"
desc = "There's too much carbon dioxide in the air, and you're breathing it in! Find some good air before you pass out!"
icon_state = "too_much_co2"
/obj/screen/alert/not_enough_tox
name = "Choking (No Plasma)"
desc = "You're not getting enough plasma. Find some good air before you pass out!"
icon_state = "not_enough_tox"
/obj/screen/alert/tox_in_air
name = "Choking (Plasma)"
desc = "There's highly flammable, toxic plasma in the air and you're breathing it in. Find some fresh air. \
The box in your backpack has an oxygen tank and gas mask in it."
icon_state = "tox_in_air"
//End gas alerts
/obj/screen/alert/fat
name = "Fat"
desc = "You ate too much food, lardass. Run around the station and lose some weight."
icon_state = "fat"
/obj/screen/alert/hungry
name = "Hungry"
desc = "Some food would be good right about now."
icon_state = "hungry"
/obj/screen/alert/starving
name = "Starving"
desc = "You're severely malnourished. The hunger pains make moving around a chore."
icon_state = "starving"
/obj/screen/alert/hot
name = "Too Hot"
desc = "You're flaming hot! Get somewhere cooler and take off any insulating clothing like a fire suit."
icon_state = "hot"
/obj/screen/alert/cold
name = "Too Cold"
desc = "You're freezing cold! Get somewhere warmer and take off any insulating clothing like a space suit."
icon_state = "cold"
/obj/screen/alert/lowpressure
name = "Low Pressure"
desc = "The air around you is hazardously thin. A space suit would protect you."
icon_state = "lowpressure"
/obj/screen/alert/highpressure
name = "High Pressure"
desc = "The air around you is hazardously thick. A fire suit would protect you."
icon_state = "highpressure"
/obj/screen/alert/blind
name = "Blind"
desc = "You can't see! This may be caused by a genetic defect, eye trauma, being unconscious, \
or something covering your eyes."
icon_state = "blind"
/obj/screen/alert/high
name = "High"
desc = "Whoa man, you're tripping balls! Careful you don't get addicted... if you aren't already."
icon_state = "high"
/obj/screen/alert/drunk //Not implemented
name = "Drunk"
desc = "All that alcohol you've been drinking is impairing your speech, motor skills, and mental cognition. Make sure to act like it."
icon_state = "drunk"
/obj/screen/alert/embeddedobject
name = "Embedded Object"
desc = "Something got lodged into your flesh and is causing major bleeding. It might fall out with time, but surgery is the safest way. \
If you're feeling frisky, click yourself in help intent to pull the object out."
icon_state = "embeddedobject"
/obj/screen/alert/embeddedobject/Click()
if(isliving(usr))
var/mob/living/carbon/human/M = usr
return M.help_shake_act(M)
/obj/screen/alert/asleep
name = "Asleep"
desc = "You've fallen asleep. Wait a bit and you should wake up. Unless you don't, considering how helpless you are."
icon_state = "asleep"
/obj/screen/alert/weightless
name = "Weightless"
desc = "Gravity has ceased affecting you, and you're floating around aimlessly. You'll need something large and heavy, like a \
wall or lattice, to push yourself off if you want to move. A jetpack would enable free range of motion. A pair of \
magboots would let you walk around normally on the floor. Barring those, you can throw things, use a fire extinguisher, \
or shoot a gun to move around via Newton's 3rd Law of Motion."
icon_state = "weightless"
/obj/screen/alert/fire
name = "On Fire"
desc = "You're on fire. Stop, drop and roll to put the fire out or move to a vacuum area."
icon_state = "fire"
/obj/screen/alert/fire/Click()
if(isliving(usr))
var/mob/living/L = usr
return L.resist()
//ALIENS
/obj/screen/alert/alien_tox
name = "Plasma"
desc = "There's flammable plasma in the air. If it lights up, you'll be toast."
icon_state = "alien_tox"
alerttooltipstyle = "alien"
/obj/screen/alert/alien_fire
// This alert is temporarily gonna be thrown for all hot air but one day it will be used for literally being on fire
name = "Too Hot"
desc = "It's too hot! Flee to space or at least away from the flames. Standing on weeds will heal you."
icon_state = "alien_fire"
alerttooltipstyle = "alien"
/obj/screen/alert/alien_vulnerable
name = "Severed Matriarchy"
desc = "Your queen has been killed, you will suffer movement penalties and loss of hivemind. A new queen cannot be made until you recover."
icon_state = "alien_noqueen"
alerttooltipstyle = "alien"
//BLOBS
/obj/screen/alert/nofactory
name = "No Factory"
desc = "You have no factory, and are slowly dying!"
icon_state = "blobbernaut_nofactory"
alerttooltipstyle = "blob"
//GUARDIANS
/obj/screen/alert/cancharge
name = "Charge Ready"
desc = "You are ready to charge at a location!"
icon_state = "guardian_charge"
alerttooltipstyle = "parasite"
/obj/screen/alert/canstealth
name = "Stealth Ready"
desc = "You are ready to enter stealth!"
icon_state = "guardian_canstealth"
alerttooltipstyle = "parasite"
/obj/screen/alert/instealth
name = "In Stealth"
desc = "You are in stealth and your next attack will do bonus damage!"
icon_state = "guardian_instealth"
alerttooltipstyle = "parasite"
//SILICONS
/obj/screen/alert/nocell
name = "Missing Power Cell"
desc = "Unit has no power cell. No modules available until a power cell is reinstalled. Robotics may provide assistance."
icon_state = "nocell"
/obj/screen/alert/emptycell
name = "Out of Power"
desc = "Unit's power cell has no charge remaining. No modules available until power cell is recharged. \
Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite."
icon_state = "emptycell"
/obj/screen/alert/lowcell
name = "Low Charge"
desc = "Unit's power cell is running low. Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite."
icon_state = "lowcell"
//Need to cover all use cases - emag, illegal upgrade module, malf AI hack, traitor cyborg
/obj/screen/alert/hacked
name = "Hacked"
desc = "Hazardous non-standard equipment detected. Please ensure any usage of this equipment is in line with unit's laws, if any."
icon_state = "hacked"
/obj/screen/alert/locked
name = "Locked Down"
desc = "Unit has been remotely locked down. Usage of a Robotics Control Console like the one in the Research Director's \
office by your AI master or any qualified human may resolve this matter. Robotics may provide further assistance if necessary."
icon_state = "locked"
/obj/screen/alert/newlaw
name = "Law Update"
desc = "Laws have potentially been uploaded to or removed from this unit. Please be aware of any changes \
so as to remain in compliance with the most up-to-date laws."
icon_state = "newlaw"
timeout = 300
//MECHS
/obj/screen/alert/low_mech_integrity
name = "Mech Damaged"
desc = "Mech integrity is low."
icon_state = "low_mech_integrity"
//GHOSTS
//TODO: expand this system to replace the pollCandidates/CheckAntagonist/"choose quickly"/etc Yes/No messages
/obj/screen/alert/notify_cloning
name = "Revival"
desc = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!"
icon_state = "template"
timeout = 300
/obj/screen/alert/notify_cloning/Click()
if(!usr || !usr.client) return
var/mob/dead/observer/G = usr
G.reenter_corpse()
/obj/screen/alert/notify_action
name = "Body created"
desc = "A body was created. You can enter it."
icon_state = "template"
timeout = 300
var/atom/target = null
var/action = NOTIFY_JUMP
/obj/screen/alert/notify_action/Click()
if(!usr || !usr.client) return
if(!target) return
var/mob/dead/observer/G = usr
if(!istype(G)) return
switch(action)
if(NOTIFY_ATTACK)
target.attack_ghost(G)
if(NOTIFY_JUMP)
var/turf/T = get_turf(target)
if(T && isturf(T))
G.loc = T
if(NOTIFY_ORBIT)
G.ManualFollow(target)
//OBJECT-BASED
/obj/screen/alert/restrained/buckled
name = "Buckled"
desc = "You've been buckled to something. Click the alert to unbuckle unless you're handcuffed."
/obj/screen/alert/restrained/handcuffed
name = "Handcuffed"
desc = "You're handcuffed and can't act. If anyone drags you, you won't be able to move. Click the alert to free yourself."
/obj/screen/alert/restrained/legcuffed
name = "Legcuffed"
desc = "You're legcuffed, which slows you down considerably. Click the alert to free yourself."
/obj/screen/alert/restrained/Click()
if(isliving(usr))
var/mob/living/L = usr
return L.resist()
// PRIVATE = only edit, use, or override these if you're editing the system as a whole
// Re-render all alerts - also called in /datum/hud/show_hud() because it's needed there
/datum/hud/proc/reorganize_alerts()
var/list/alerts = mymob.alerts
var/icon_pref
if(!hud_shown)
for(var/i = 1, i <= alerts.len, i++)
mymob.client.screen -= alerts[alerts[i]]
return 1
for(var/i = 1, i <= alerts.len, i++)
var/obj/screen/alert/alert = alerts[alerts[i]]
if(alert.icon_state == "template")
if(!icon_pref)
icon_pref = ui_style2icon(mymob.client.prefs.UI_style)
alert.icon = icon_pref
switch(i)
if(1)
. = ui_alert1
if(2)
. = ui_alert2
if(3)
. = ui_alert3
if(4)
. = ui_alert4
if(5)
. = ui_alert5 // Right now there's 5 slots
else
. = ""
alert.screen_loc = .
mymob.client.screen |= alert
return 1
/mob
var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly
/obj/screen/alert/Click(location, control, params)
if(!usr || !usr.client)
return
var/paramslist = params2list(params)
if(paramslist["shift"]) // screen objects don't do the normal Click() stuff so we'll cheat
usr << "<span class='boldnotice'>[name]</span> - <span class='info'>[desc]</span>"
return
if(master)
return usr.client.Click(master, location, control, params)
/obj/screen/alert/Destroy()
..()
severity = 0
master = null
screen_loc = ""
return QDEL_HINT_PUTINPOOL //Don't destroy me, I have a family!
+142
View File
@@ -0,0 +1,142 @@
/obj/screen/alien
icon = 'icons/mob/screen_alien.dmi'
/obj/screen/alien/leap
name = "toggle leap"
icon_state = "leap_off"
/obj/screen/alien/leap/Click()
if(istype(usr, /mob/living/carbon/alien/humanoid/hunter))
var/mob/living/carbon/alien/humanoid/hunter/AH = usr
AH.toggle_leap()
/obj/screen/alien/nightvision
name = "toggle night-vision"
icon_state = "nightvision1"
screen_loc = ui_alien_nightvision
/obj/screen/alien/nightvision/Click()
var/mob/living/carbon/alien/A = usr
var/obj/effect/proc_holder/alien/nightvisiontoggle/T = locate() in A.abilities
if(T)
T.fire(A)
/obj/screen/alien/plasma_display
icon = 'icons/mob/screen_gen.dmi'
icon_state = "power_display2"
name = "plasma stored"
screen_loc = ui_alienplasmadisplay
/datum/hud/alien/New(mob/living/carbon/alien/humanoid/owner)
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
//equippable shit
//hands
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "right hand"
inv_box.icon = 'icons/mob/screen_alien.dmi'
inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
static_inventory += inv_box
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "left hand"
inv_box.icon = 'icons/mob/screen_alien.dmi'
inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
static_inventory += inv_box
//begin buttons
using = new /obj/screen/swap_hand()
using.icon = 'icons/mob/screen_alien.dmi'
using.icon_state = "swap_1"
using.screen_loc = ui_swaphand1
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = 'icons/mob/screen_alien.dmi'
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
static_inventory += using
using = new /obj/screen/act_intent/alien()
using.icon_state = mymob.a_intent
static_inventory += using
action_intent = using
if(istype(mymob, /mob/living/carbon/alien/humanoid/hunter))
var/mob/living/carbon/alien/humanoid/hunter/H = mymob
H.leap_icon = new /obj/screen/alien/leap()
H.leap_icon.screen_loc = ui_alien_storage_r
static_inventory += H.leap_icon
using = new /obj/screen/drop()
using.icon = 'icons/mob/screen_alien.dmi'
using.screen_loc = ui_drop_throw
static_inventory += using
using = new /obj/screen/resist()
using.icon = 'icons/mob/screen_alien.dmi'
using.screen_loc = ui_pull_resist
hotkeybuttons += using
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = 'icons/mob/screen_alien.dmi'
throw_icon.screen_loc = ui_drop_throw
hotkeybuttons += throw_icon
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_alien.dmi'
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_pull_resist
static_inventory += pull_icon
//begin indicators
healths = new /obj/screen/healths/alien()
infodisplay += healths
nightvisionicon = new /obj/screen/alien/nightvision()
infodisplay += nightvisionicon
alien_plasma_display = new /obj/screen/alien/plasma_display()
infodisplay += alien_plasma_display
zone_select = new /obj/screen/zone_sel/alien()
zone_select.update_icon(mymob)
static_inventory += zone_select
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/alien/persistant_inventory_update()
if(!mymob)
return
var/mob/living/carbon/alien/humanoid/H = mymob
if(hud_version != HUD_STYLE_NOHUD)
if(H.r_hand)
H.r_hand.screen_loc = ui_rhand
H.client.screen += H.r_hand
if(H.l_hand)
H.l_hand.screen_loc = ui_lhand
H.client.screen += H.l_hand
else
if(H.r_hand)
H.r_hand.screen_loc = null
if(H.l_hand)
H.l_hand.screen_loc = null
/mob/living/carbon/alien/humanoid/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/alien(src)
+29
View File
@@ -0,0 +1,29 @@
/datum/hud/larva/New(mob/owner)
..()
var/obj/screen/using
using = new /obj/screen/act_intent/alien()
using.icon_state = mymob.a_intent
static_inventory += using
action_intent = using
healths = new /obj/screen/healths/alien()
infodisplay += healths
nightvisionicon = new /obj/screen/alien/nightvision()
nightvisionicon.screen_loc = ui_alien_nightvision
infodisplay += nightvisionicon
pull_icon = new /obj/screen/pull()
pull_icon.icon = 'icons/mob/screen_alien.dmi'
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_pull_resist
hotkeybuttons += pull_icon
zone_select = new /obj/screen/zone_sel/alien()
zone_select.update_icon(mymob)
static_inventory += zone_select
/mob/living/carbon/alien/larva/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/larva(src)
+175
View File
@@ -0,0 +1,175 @@
/obj/screen/blob
icon = 'icons/mob/blob.dmi'
/obj/screen/blob/MouseEntered(location,control,params)
openToolTip(usr,src,params,title = name,content = desc, theme = "blob")
/obj/screen/blob/MouseExited()
closeToolTip(usr)
/obj/screen/blob/BlobHelp
icon_state = "ui_help"
name = "Blob Help"
desc = "Help on playing blob!"
/obj/screen/blob/BlobHelp/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.blob_help()
/obj/screen/blob/JumpToNode
icon_state = "ui_tonode"
name = "Jump to Node"
desc = "Moves your camera to a selected blob node."
/obj/screen/blob/JumpToNode/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.jump_to_node()
/obj/screen/blob/JumpToCore
icon_state = "ui_tocore"
name = "Jump to Core"
desc = "Moves your camera to your blob core."
/obj/screen/blob/JumpToCore/MouseEntered(location,control,params)
if(isovermind(usr))
var/mob/camera/blob/B = usr
if(!B.placed)
openToolTip(usr,src,params,title = "Place Blob Core",content = "Attempt to place your blob core at this location.", theme = "blob")
else
..()
/obj/screen/blob/JumpToCore/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
if(!B.placed)
B.place_blob_core(B.base_point_rate, 0)
B.transport_core()
/obj/screen/blob/Blobbernaut
icon_state = "ui_blobbernaut"
name = "Produce Blobbernaut (40)"
desc = "Produces a strong, smart blobbernaut from a factory blob for 40 points.<br>The factory blob used will become fragile and unable to produce spores."
/obj/screen/blob/Blobbernaut/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.create_blobbernaut()
/obj/screen/blob/ResourceBlob
icon_state = "ui_resource"
name = "Produce Resource Blob (40)"
desc = "Produces a resource blob for 40 points.<br>Resource blobs will give you points every few seconds."
/obj/screen/blob/ResourceBlob/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.create_resource()
/obj/screen/blob/NodeBlob
icon_state = "ui_node"
name = "Produce Node Blob (60)"
desc = "Produces a node blob for 60 points.<br>Node blobs will expand and activate nearby resource and factory blobs."
/obj/screen/blob/NodeBlob/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.create_node()
/obj/screen/blob/FactoryBlob
icon_state = "ui_factory"
name = "Produce Factory Blob (60)"
desc = "Produces a factory blob for 60 points.<br>Factory blobs will produce spores every few seconds."
/obj/screen/blob/FactoryBlob/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.create_factory()
/obj/screen/blob/ReadaptChemical
icon_state = "ui_chemswap"
name = "Readapt Chemical (40)"
desc = "Randomly rerolls your chemical for 40 points."
/obj/screen/blob/ReadaptChemical/MouseEntered(location,control,params)
if(isovermind(usr))
var/mob/camera/blob/B = usr
if(B.free_chem_rerolls)
openToolTip(usr,src,params,title = "Readapt Chemical (FREE)",content = "Randomly rerolls your chemical for free.", theme = "blob")
else
..()
/obj/screen/blob/ReadaptChemical/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.chemical_reroll()
/obj/screen/blob/RelocateCore
icon_state = "ui_swap"
name = "Relocate Core (80)"
desc = "Swaps a node and your core for 80 points."
/obj/screen/blob/RelocateCore/Click()
if(isovermind(usr))
var/mob/camera/blob/B = usr
B.relocate_core()
/datum/hud/blob_overmind/New(mob/owner)
..()
var/obj/screen/using
blobpwrdisplay = new /obj/screen()
blobpwrdisplay.name = "blob power"
blobpwrdisplay.icon_state = "block"
blobpwrdisplay.screen_loc = ui_health
blobpwrdisplay.mouse_opacity = 0
blobpwrdisplay.layer = ABOVE_HUD_LAYER
infodisplay += blobpwrdisplay
healths = new /obj/screen/healths/blob()
infodisplay += healths
using = new /obj/screen/blob/BlobHelp()
using.screen_loc = "WEST:6,NORTH:-3"
static_inventory += using
using = new /obj/screen/blob/JumpToNode()
using.screen_loc = ui_inventory
static_inventory += using
using = new /obj/screen/blob/JumpToCore()
using.screen_loc = ui_zonesel
static_inventory += using
using = new /obj/screen/blob/Blobbernaut()
using.screen_loc = ui_belt
static_inventory += using
using = new /obj/screen/blob/ResourceBlob()
using.screen_loc = ui_back
static_inventory += using
using = new /obj/screen/blob/NodeBlob()
using.screen_loc = ui_lhand
static_inventory += using
using = new /obj/screen/blob/FactoryBlob()
using.screen_loc = ui_rhand
static_inventory += using
using = new /obj/screen/blob/ReadaptChemical()
using.screen_loc = ui_storage1
static_inventory += using
using = new /obj/screen/blob/RelocateCore()
using.screen_loc = ui_storage2
static_inventory += using
/mob/camera/blob/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/blob_overmind(src)
+13
View File
@@ -0,0 +1,13 @@
/datum/hud/blobbernaut/New(mob/owner)
..()
blobpwrdisplay = new /obj/screen/healths/blob/naut/core()
infodisplay += blobpwrdisplay
healths = new /obj/screen/healths/blob/naut()
infodisplay += healths
/mob/living/simple_animal/hostile/blob/blobbernaut/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/blobbernaut(src)
+82
View File
@@ -0,0 +1,82 @@
//Soul counter is stored with the humans, it does weird when you place it here apparently...
/datum/hud/devil/New(mob/owner, ui_style = 'icons/mob/screen_midnight.dmi')
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drone_drop
static_inventory += using
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_drone_pull
static_inventory += pull_icon
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "right hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
static_inventory += inv_box
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "left hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
static_inventory += inv_box
using = new /obj/screen/inventory()
using.name = "hand"
using.icon = ui_style
using.icon_state = "swap_1_m"
using.screen_loc = ui_swaphand1
using.layer = HUD_LAYER
static_inventory += using
using = new /obj/screen/inventory()
using.name = "hand"
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
using.layer = HUD_LAYER
static_inventory += using
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
lingchemdisplay = new /obj/screen/ling/chems()
devilsouldisplay = new /obj/screen/devil/soul_counter
infodisplay += devilsouldisplay
/datum/hud/devil/persistant_inventory_update()
if(!mymob)
return
var/mob/living/carbon/true_devil/D = mymob
if(hud_version != HUD_STYLE_NOHUD)
if(D.r_hand)
D.r_hand.screen_loc = ui_rhand
D.client.screen += D.r_hand
if(D.l_hand)
D.l_hand.screen_loc = ui_lhand
D.client.screen += D.l_hand
else
if(D.r_hand)
D.r_hand.screen_loc = null
if(D.l_hand)
D.l_hand.screen_loc = null
/mob/living/carbon/true_devil/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/devil(src, ui_style2icon(client.prefs.UI_style))
+111
View File
@@ -0,0 +1,111 @@
/datum/hud/drone/New(mob/owner, ui_style = 'icons/mob/screen_midnight.dmi')
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drone_drop
static_inventory += using
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_drone_pull
static_inventory += pull_icon
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "right hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
static_inventory += inv_box
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "left hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "internal storage"
inv_box.icon = ui_style
inv_box.icon_state = "suit_storage"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_drone_storage
inv_box.slot_id = slot_drone_storage
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head/mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_drone_head
inv_box.slot_id = slot_head
static_inventory += inv_box
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1_m"
using.screen_loc = ui_swaphand1
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
static_inventory += using
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
using = new /obj/screen/inventory/craft
using.icon = ui_style
static_inventory += using
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/drone/persistant_inventory_update()
if(!mymob)
return
var/mob/living/simple_animal/drone/D = mymob
if(hud_shown)
if(D.internal_storage)
D.internal_storage.screen_loc = ui_drone_storage
D.client.screen += D.internal_storage
if(D.head)
D.head.screen_loc = ui_drone_head
D.client.screen += D.head
else
if(D.internal_storage)
D.internal_storage.screen_loc = null
if(D.head)
D.head.screen_loc = null
if(hud_version != HUD_STYLE_NOHUD)
if(D.r_hand)
D.r_hand.screen_loc = ui_rhand
D.client.screen += D.r_hand
if(D.l_hand)
D.l_hand.screen_loc = ui_lhand
D.client.screen += D.l_hand
else
if(D.r_hand)
D.r_hand.screen_loc = null
if(D.l_hand)
D.l_hand.screen_loc = null
/mob/living/simple_animal/drone/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/drone(src, ui_style2icon(client.prefs.UI_style))
+108
View File
@@ -0,0 +1,108 @@
/mob
var/list/screens = list()
/mob/proc/overlay_fullscreen(category, type, severity)
var/obj/screen/fullscreen/screen
if(screens[category])
screen = screens[category]
if(screen.type != type)
clear_fullscreen(category, FALSE)
return .()
else if(!severity || severity == screen.severity)
return null
else
screen = PoolOrNew(type)
screen.icon_state = "[initial(screen.icon_state)][severity]"
screen.severity = severity
screens[category] = screen
if(client && stat != DEAD)
client.screen += screen
return screen
/mob/proc/clear_fullscreen(category, animated = 10)
var/obj/screen/fullscreen/screen = screens[category]
if(!screen)
return
screens -= category
if(animated)
spawn(0)
animate(screen, alpha = 0, time = animated)
sleep(animated)
if(client)
client.screen -= screen
qdel(screen)
else
if(client)
client.screen -= screen
qdel(screen)
/mob/proc/clear_fullscreens()
for(var/category in screens)
clear_fullscreen(category)
/mob/proc/hide_fullscreens()
if(client)
for(var/category in screens)
client.screen -= screens[category]
/mob/proc/reload_fullscreen()
if(client && stat != DEAD) //dead mob do not see any of the fullscreen overlays that he has.
for(var/category in screens)
client.screen |= screens[category]
/obj/screen/fullscreen
icon = 'icons/mob/screen_full.dmi'
icon_state = "default"
screen_loc = "CENTER-7,CENTER-7"
layer = FULLSCREEN_LAYER
mouse_opacity = 0
var/severity = 0
/obj/screen/fullscreen/Destroy()
..()
severity = 0
return QDEL_HINT_PUTINPOOL
/obj/screen/fullscreen/brute
icon_state = "brutedamageoverlay"
layer = UI_DAMAGE_LAYER
/obj/screen/fullscreen/oxy
icon_state = "oxydamageoverlay"
layer = UI_DAMAGE_LAYER
/obj/screen/fullscreen/crit
icon_state = "passage"
layer = CRIT_LAYER
/obj/screen/fullscreen/blind
icon_state = "blackimageoverlay"
layer = BLIND_LAYER
/obj/screen/fullscreen/impaired
icon_state = "impairedoverlay"
/obj/screen/fullscreen/blurry
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "blurry"
/obj/screen/fullscreen/flash
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "flash"
/obj/screen/fullscreen/flash/noise
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "noise"
/obj/screen/fullscreen/high
icon = 'icons/mob/screen_gen.dmi'
screen_loc = "WEST,SOUTH to EAST,NORTH"
icon_state = "druggy"
+63
View File
@@ -0,0 +1,63 @@
//Used for normal mobs that have hands.
/datum/hud/dextrous/New(mob/living/owner, ui_style = 'icons/mob/screen_midnight.dmi')
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drone_drop
static_inventory += using
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "right hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
static_inventory += inv_box
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "left hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
static_inventory += inv_box
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1_m"
using.screen_loc = ui_swaphand1
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
static_inventory += using
mymob.client.screen = list()
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/dextrous/persistant_inventory_update()
if(!mymob)
return
var/mob/living/D = mymob
if(hud_version != HUD_STYLE_NOHUD)
if(D.r_hand)
D.r_hand.screen_loc = ui_rhand
D.client.screen += D.r_hand
if(D.l_hand)
D.l_hand.screen_loc = ui_lhand
D.client.screen += D.l_hand
else
if(D.r_hand)
D.r_hand.screen_loc = null
if(D.l_hand)
D.l_hand.screen_loc = null
+74
View File
@@ -0,0 +1,74 @@
/obj/screen/ghost
icon = 'icons/mob/screen_ghost.dmi'
/obj/screen/ghost/MouseEntered()
flick(icon_state + "_anim", src)
/obj/screen/ghost/jumptomob
name = "Jump to mob"
icon_state = "jumptomob"
/obj/screen/ghost/jumptomob/Click()
var/mob/dead/observer/G = usr
G.jumptomob()
/obj/screen/ghost/orbit
name = "Orbit"
icon_state = "orbit"
/obj/screen/ghost/orbit/Click()
var/mob/dead/observer/G = usr
G.follow()
/obj/screen/ghost/reenter_corpse
name = "Reenter corpse"
icon_state = "reenter_corpse"
/obj/screen/ghost/reenter_corpse/Click()
var/mob/dead/observer/G = usr
G.reenter_corpse()
/obj/screen/ghost/teleport
name = "Teleport"
icon_state = "teleport"
/obj/screen/ghost/teleport/Click()
var/mob/dead/observer/G = usr
G.dead_tele()
/datum/hud/ghost/New(mob/owner)
..()
var/mob/dead/observer/G = mymob
if(!G.client.prefs.ghost_hud)
mymob.client.screen = null
return
var/obj/screen/using
using = new /obj/screen/ghost/jumptomob()
using.screen_loc = ui_ghost_jumptomob
static_inventory += using
using = new /obj/screen/ghost/orbit()
using.screen_loc = ui_ghost_orbit
static_inventory += using
using = new /obj/screen/ghost/reenter_corpse()
using.screen_loc = ui_ghost_reenter_corpse
static_inventory += using
using = new /obj/screen/ghost/teleport()
using.screen_loc = ui_ghost_teleport
static_inventory += using
/datum/hud/ghost/show_hud()
var/mob/dead/observer/G = mymob
mymob.client.screen = list()
if(!G.client.prefs.ghost_hud)
return
mymob.client.screen += static_inventory
/mob/dead/observer/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/ghost(src)
+96
View File
@@ -0,0 +1,96 @@
/datum/hud/guardian/New(mob/living/simple_animal/hostile/guardian/owner)
..()
var/obj/screen/using
healths = new /obj/screen/healths/guardian()
infodisplay += healths
using = new /obj/screen/guardian/Manifest()
using.screen_loc = ui_rhand
static_inventory += using
using = new /obj/screen/guardian/Recall()
using.screen_loc = ui_lhand
static_inventory += using
using = new owner.toggle_button_type()
using.screen_loc = ui_storage1
static_inventory += using
using = new /obj/screen/guardian/ToggleLight()
using.screen_loc = ui_inventory
static_inventory += using
using = new /obj/screen/guardian/Communicate()
using.screen_loc = ui_back
static_inventory += using
/mob/living/simple_animal/hostile/guardian/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/guardian(src)
/obj/screen/guardian
icon = 'icons/mob/guardian.dmi'
/obj/screen/guardian/Manifest
icon_state = "manifest"
name = "Manifest"
desc = "Spring forth into battle!"
/obj/screen/guardian/Manifest/Click()
if(isguardian(usr))
var/mob/living/simple_animal/hostile/guardian/G = usr
G.Manifest()
/obj/screen/guardian/Recall
icon_state = "recall"
name = "Recall"
desc = "Return to your user."
/obj/screen/guardian/Recall/Click()
if(isguardian(usr))
var/mob/living/simple_animal/hostile/guardian/G = usr
G.Recall()
/obj/screen/guardian/ToggleMode
icon_state = "toggle"
name = "Toggle Mode"
desc = "Switch between ability modes."
/obj/screen/guardian/ToggleMode/Click()
if(isguardian(usr))
var/mob/living/simple_animal/hostile/guardian/G = usr
G.ToggleMode()
/obj/screen/guardian/ToggleMode/Inactive
icon_state = "notoggle" //greyed out so it doesn't look like it'll work
/obj/screen/guardian/ToggleMode/Assassin
icon_state = "stealth"
name = "Toggle Stealth"
desc = "Enter or exit stealth."
/obj/screen/guardian/Communicate
icon_state = "communicate"
name = "Communicate"
desc = "Communicate telepathically with your user."
/obj/screen/guardian/Communicate/Click()
if(isguardian(usr))
var/mob/living/simple_animal/hostile/guardian/G = usr
G.Communicate()
/obj/screen/guardian/ToggleLight
icon_state = "light"
name = "Toggle Light"
desc = "Glow like star dust."
/obj/screen/guardian/ToggleLight/Click()
if(isguardian(usr))
var/mob/living/simple_animal/hostile/guardian/G = usr
G.ToggleLight()
+208
View File
@@ -0,0 +1,208 @@
/*
The hud datum
Used to show and hide huds for all the different mob types,
including inventories and item quick actions.
*/
/datum/hud
var/mob/mymob
var/hud_shown = 1 //Used for the HUD toggle (F12)
var/hud_version = 1 //Current displayed version of the HUD
var/inventory_shown = 1 //the inventory
var/show_intent_icons = 0
var/hotkey_ui_hidden = 0 //This is to hide the buttons that can be used via hotkeys. (hotkeybuttons list of buttons)
var/obj/screen/ling/chems/lingchemdisplay
var/obj/screen/ling/sting/lingstingdisplay
var/obj/screen/blobpwrdisplay
var/obj/screen/alien_plasma_display
var/obj/screen/devil/soul_counter/devilsouldisplay
var/obj/screen/deity_power_display
var/obj/screen/deity_follower_display
var/obj/screen/nightvisionicon
var/obj/screen/action_intent
var/obj/screen/zone_select
var/obj/screen/pull_icon
var/obj/screen/throw_icon
var/obj/screen/module_store_icon
var/list/static_inventory = list() //the screen objects which are static
var/list/toggleable_inventory = list() //the screen objects which can be hidden
var/list/obj/screen/hotkeybuttons = list() //the buttons that can be used via hotkeys
var/list/infodisplay = list() //the screen objects that display mob info (health, alien plasma, etc...)
var/list/screenoverlays = list() //the screen objects used as whole screen overlays (flash, damageoverlay, etc...)
var/list/inv_slots[slots_amt] // /obj/screen/inventory objects, ordered by their slot ID.
var/obj/screen/movable/action_button/hide_toggle/hide_actions_toggle
var/action_buttons_hidden = 0
var/obj/screen/healths
var/obj/screen/healthdoll
var/obj/screen/internals
/datum/hud/New(mob/owner)
mymob = owner
hide_actions_toggle = new
hide_actions_toggle.InitialiseIcon(mymob)
/datum/hud/Destroy()
if(mymob.hud_used == src)
mymob.hud_used = null
qdel(hide_actions_toggle)
hide_actions_toggle = null
qdel(module_store_icon)
module_store_icon = null
if(static_inventory.len)
for(var/thing in static_inventory)
qdel(thing)
static_inventory.Cut()
inv_slots.Cut()
action_intent = null
zone_select = null
pull_icon = null
if(toggleable_inventory.len)
for(var/thing in toggleable_inventory)
qdel(thing)
toggleable_inventory.Cut()
if(hotkeybuttons.len)
for(var/thing in hotkeybuttons)
qdel(thing)
hotkeybuttons.Cut()
throw_icon = null
if(infodisplay.len)
for(var/thing in infodisplay)
qdel(thing)
infodisplay.Cut()
healths = null
healthdoll = null
internals = null
lingchemdisplay = null
devilsouldisplay = null
lingstingdisplay = null
blobpwrdisplay = null
alien_plasma_display = null
deity_power_display = null
deity_follower_display = null
nightvisionicon = null
if(screenoverlays.len)
for(var/thing in screenoverlays)
qdel(thing)
screenoverlays.Cut()
mymob = null
return ..()
/mob/proc/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud(src)
//Version denotes which style should be displayed. blank or 0 means "next version"
/datum/hud/proc/show_hud(version = 0)
if(!ismob(mymob))
return 0
if(!mymob.client)
return 0
mymob.client.screen = list()
var/display_hud_version = version
if(!display_hud_version) //If 0 or blank, display the next hud version
display_hud_version = hud_version + 1
if(display_hud_version > HUD_VERSIONS) //If the requested version number is greater than the available versions, reset back to the first version
display_hud_version = 1
switch(display_hud_version)
if(HUD_STYLE_STANDARD) //Default HUD
hud_shown = 1 //Governs behavior of other procs
if(static_inventory.len)
mymob.client.screen += static_inventory
if(toggleable_inventory.len && inventory_shown)
mymob.client.screen += toggleable_inventory
if(hotkeybuttons.len && !hotkey_ui_hidden)
mymob.client.screen += hotkeybuttons
if(infodisplay.len)
mymob.client.screen += infodisplay
mymob.client.screen += hide_actions_toggle
if(action_intent)
action_intent.screen_loc = initial(action_intent.screen_loc) //Restore intent selection to the original position
if(HUD_STYLE_REDUCED) //Reduced HUD
hud_shown = 0 //Governs behavior of other procs
if(static_inventory.len)
mymob.client.screen -= static_inventory
if(toggleable_inventory.len)
mymob.client.screen -= toggleable_inventory
if(hotkeybuttons.len)
mymob.client.screen -= hotkeybuttons
if(infodisplay.len)
mymob.client.screen += infodisplay
//These ones are a part of 'static_inventory', 'toggleable_inventory' or 'hotkeybuttons' but we want them to stay
if(inv_slots[slot_l_hand])
mymob.client.screen += inv_slots[slot_l_hand] //we want the hands to be visible
if(inv_slots[slot_r_hand])
mymob.client.screen += inv_slots[slot_r_hand] //we want the hands to be visible
if(action_intent)
mymob.client.screen += action_intent //we want the intent switcher visible
action_intent.screen_loc = ui_acti_alt //move this to the alternative position, where zone_select usually is.
if(HUD_STYLE_NOHUD) //No HUD
hud_shown = 0 //Governs behavior of other procs
if(static_inventory.len)
mymob.client.screen -= static_inventory
if(toggleable_inventory.len)
mymob.client.screen -= toggleable_inventory
if(hotkeybuttons.len)
mymob.client.screen -= hotkeybuttons
if(infodisplay.len)
mymob.client.screen -= infodisplay
hud_version = display_hud_version
persistant_inventory_update()
mymob.update_action_buttons(1)
reorganize_alerts()
mymob.reload_fullscreen()
/datum/hud/human/show_hud(version = 0)
..()
hidden_inventory_update()
/datum/hud/robot/show_hud(version = 0)
..()
update_robot_modules_display()
/datum/hud/proc/hidden_inventory_update()
return
/datum/hud/proc/persistant_inventory_update()
return
//Triggered when F12 is pressed (Unless someone changed something in the DMF)
/mob/verb/button_pressed_F12()
set name = "F12"
set hidden = 1
if(hud_used && client)
hud_used.show_hud() //Shows the next hud preset
usr << "<span class ='info'>Switched HUD mode. Press F12 to toggle.</span>"
else
usr << "<span class ='warning'>This mob type does not use a HUD.</span>"
+414
View File
@@ -0,0 +1,414 @@
/obj/screen/human
icon = 'icons/mob/screen_midnight.dmi'
/obj/screen/human/toggle
name = "toggle"
icon_state = "toggle"
/obj/screen/human/toggle/Click()
if(usr.hud_used.inventory_shown)
usr.hud_used.inventory_shown = 0
usr.client.screen -= usr.hud_used.toggleable_inventory
else
usr.hud_used.inventory_shown = 1
usr.client.screen += usr.hud_used.toggleable_inventory
usr.hud_used.hidden_inventory_update()
/obj/screen/human/equip
name = "equip"
icon_state = "act_equip"
/obj/screen/human/equip/Click()
if(istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
return 1
var/mob/living/carbon/human/H = usr
H.quick_equip()
/obj/screen/devil
invisibility = INVISIBILITY_ABSTRACT
/obj/screen/devil/soul_counter
icon = 'icons/mob/screen_gen.dmi'
name = "souls owned"
icon_state = "Devil-6"
screen_loc = ui_devilsouldisplay
/obj/screen/devil/soul_counter/proc/update_counter(souls = 0)
invisibility = 0
maptext = "<div align='center' valign='middle' style='position:relative; top:0px; left:6px'><font color='#FF0000'>[souls]</font></div>"
switch(souls)
if(0,null)
icon_state = "Devil-1"
if(1,2)
icon_state = "Devil-2"
if(3 to 5)
icon_state = "Devil-3"
if(6 to 8)
icon_state = "Devil-4"
if(9 to INFINITY)
icon_state = "Devil-5"
else
icon_state = "Devil-6"
/obj/screen/devil/soul_counter/proc/clear()
invisibility = INVISIBILITY_ABSTRACT
/obj/screen/ling
invisibility = INVISIBILITY_ABSTRACT
/obj/screen/ling/sting
name = "current sting"
screen_loc = ui_lingstingdisplay
/obj/screen/ling/sting/Click()
var/mob/living/carbon/U = usr
U.unset_sting()
/obj/screen/ling/chems
name = "chemical storage"
icon_state = "power_display"
screen_loc = ui_lingchemdisplay
/mob/living/carbon/human/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/human(src, ui_style2icon(client.prefs.UI_style))
/datum/hud/human/New(mob/living/carbon/human/owner, ui_style = 'icons/mob/screen_midnight.dmi')
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
using = new /obj/screen/inventory/craft
using.icon = ui_style
static_inventory += using
using = new /obj/screen/act_intent()
using.icon_state = mymob.a_intent
static_inventory += using
action_intent = using
using = new /obj/screen/mov_intent()
using.icon = ui_style
using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
using.screen_loc = ui_movi
static_inventory += using
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "i_clothing"
inv_box.icon = ui_style
inv_box.slot_id = slot_w_uniform
inv_box.icon_state = "uniform"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_iclothing
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "o_clothing"
inv_box.icon = ui_style
inv_box.slot_id = slot_wear_suit
inv_box.icon_state = "suit"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_oclothing
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "right hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
static_inventory += inv_box
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "left hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
static_inventory += inv_box
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1"
using.screen_loc = ui_swaphand1
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "id"
inv_box.icon = ui_style
inv_box.icon_state = "id"
// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_id
inv_box.slot_id = slot_wear_id
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_mask
inv_box.slot_id = slot_wear_mask
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.icon_state = "back"
// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_back
inv_box.slot_id = slot_back
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "storage1"
inv_box.icon = ui_style
inv_box.icon_state = "pocket"
// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_storage1
inv_box.slot_id = slot_l_store
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "storage2"
inv_box.icon = ui_style
inv_box.icon_state = "pocket"
// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_storage2
inv_box.slot_id = slot_r_store
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "suit storage"
inv_box.icon = ui_style
inv_box.icon_state = "suit_storage"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_sstore1
inv_box.slot_id = slot_s_store
static_inventory += inv_box
using = new /obj/screen/resist()
using.icon = ui_style
using.screen_loc = ui_pull_resist
hotkeybuttons += using
using = new /obj/screen/human/toggle()
using.icon = ui_style
using.screen_loc = ui_inventory
static_inventory += using
using = new /obj/screen/human/equip()
using.icon = ui_style
using.screen_loc = ui_equip
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "gloves"
inv_box.icon = ui_style
inv_box.icon_state = "gloves"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_gloves
inv_box.slot_id = slot_gloves
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "eyes"
inv_box.icon = ui_style
inv_box.icon_state = "glasses"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_glasses
inv_box.slot_id = slot_glasses
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "ears"
inv_box.icon = ui_style
inv_box.icon_state = "ears"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_ears
inv_box.slot_id = slot_ears
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head"
inv_box.icon = ui_style
inv_box.icon_state = "head"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_head
inv_box.slot_id = slot_head
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "shoes"
inv_box.icon = ui_style
inv_box.icon_state = "shoes"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_shoes
inv_box.slot_id = slot_shoes
toggleable_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "belt"
inv_box.icon = ui_style
inv_box.icon_state = "belt"
// inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_belt
inv_box.slot_id = slot_belt
static_inventory += inv_box
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = ui_style
throw_icon.screen_loc = ui_drop_throw
hotkeybuttons += throw_icon
internals = new /obj/screen/internals()
infodisplay += internals
healths = new /obj/screen/healths()
infodisplay += healths
healthdoll = new /obj/screen/healthdoll()
infodisplay += healthdoll
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_pull_resist
static_inventory += pull_icon
lingchemdisplay = new /obj/screen/ling/chems()
infodisplay += lingchemdisplay
lingstingdisplay = new /obj/screen/ling/sting()
infodisplay += lingstingdisplay
devilsouldisplay = new /obj/screen/devil/soul_counter
infodisplay += devilsouldisplay
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
static_inventory += zone_select
inventory_shown = 0
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/human/hidden_inventory_update()
if(!mymob)
return
var/mob/living/carbon/human/H = mymob
if(inventory_shown && hud_shown)
if(H.shoes)
H.shoes.screen_loc = ui_shoes
H.client.screen += H.shoes
if(H.gloves)
H.gloves.screen_loc = ui_gloves
H.client.screen += H.gloves
if(H.ears)
H.ears.screen_loc = ui_ears
H.client.screen += H.ears
if(H.glasses)
H.glasses.screen_loc = ui_glasses
H.client.screen += H.glasses
if(H.w_uniform)
H.w_uniform.screen_loc = ui_iclothing
H.client.screen += H.w_uniform
if(H.wear_suit)
H.wear_suit.screen_loc = ui_oclothing
H.client.screen += H.wear_suit
if(H.wear_mask)
H.wear_mask.screen_loc = ui_mask
H.client.screen += H.wear_mask
if(H.head)
H.head.screen_loc = ui_head
H.client.screen += H.head
else
if(H.shoes) H.shoes.screen_loc = null
if(H.gloves) H.gloves.screen_loc = null
if(H.ears) H.ears.screen_loc = null
if(H.glasses) H.glasses.screen_loc = null
if(H.w_uniform) H.w_uniform.screen_loc = null
if(H.wear_suit) H.wear_suit.screen_loc = null
if(H.wear_mask) H.wear_mask.screen_loc = null
if(H.head) H.head.screen_loc = null
/datum/hud/human/persistant_inventory_update()
if(!mymob)
return
var/mob/living/carbon/human/H = mymob
if(hud_shown)
if(H.s_store)
H.s_store.screen_loc = ui_sstore1
H.client.screen += H.s_store
if(H.wear_id)
H.wear_id.screen_loc = ui_id
H.client.screen += H.wear_id
if(H.belt)
H.belt.screen_loc = ui_belt
H.client.screen += H.belt
if(H.back)
H.back.screen_loc = ui_back
H.client.screen += H.back
if(H.l_store)
H.l_store.screen_loc = ui_storage1
H.client.screen += H.l_store
if(H.r_store)
H.r_store.screen_loc = ui_storage2
H.client.screen += H.r_store
else
if(H.s_store)
H.s_store.screen_loc = null
if(H.wear_id)
H.wear_id.screen_loc = null
if(H.belt)
H.belt.screen_loc = null
if(H.back)
H.back.screen_loc = null
if(H.l_store)
H.l_store.screen_loc = null
if(H.r_store)
H.r_store.screen_loc = null
if(hud_version != HUD_STYLE_NOHUD)
if(H.r_hand)
H.r_hand.screen_loc = ui_rhand
H.client.screen += H.r_hand
if(H.l_hand)
H.l_hand.screen_loc = ui_lhand
H.client.screen += H.l_hand
else
if(H.r_hand)
H.r_hand.screen_loc = null
if(H.l_hand)
H.l_hand.screen_loc = null
/mob/living/carbon/human/verb/toggle_hotkey_verbs()
set category = "OOC"
set name = "Toggle hotkey buttons"
set desc = "This disables or enables the user interface buttons which can be used with hotkeys."
if(hud_used.hotkey_ui_hidden)
client.screen += hud_used.hotkeybuttons
hud_used.hotkey_ui_hidden = 0
else
client.screen -= hud_used.hotkeybuttons
hud_used.hotkey_ui_hidden = 1
+159
View File
@@ -0,0 +1,159 @@
/datum/hud/monkey/New(mob/living/carbon/monkey/owner, ui_style = 'icons/mob/screen_midnight.dmi')
..()
var/obj/screen/using
var/obj/screen/inventory/inv_box
using = new /obj/screen/act_intent()
using.icon = ui_style
using.icon_state = mymob.a_intent
using.screen_loc = ui_acti
static_inventory += using
action_intent = using
using = new /obj/screen/mov_intent()
using.icon = ui_style
using.icon_state = (mymob.m_intent == "run" ? "running" : "walking")
using.screen_loc = ui_movi
static_inventory += using
using = new /obj/screen/drop()
using.icon = ui_style
using.screen_loc = ui_drop_throw
static_inventory += using
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "right hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_r"
inv_box.screen_loc = ui_rhand
inv_box.slot_id = slot_r_hand
static_inventory += inv_box
inv_box = new /obj/screen/inventory/hand()
inv_box.name = "left hand"
inv_box.icon = ui_style
inv_box.icon_state = "hand_l"
inv_box.screen_loc = ui_lhand
inv_box.slot_id = slot_l_hand
static_inventory += inv_box
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_1_m" //extra wide!
using.screen_loc = ui_swaphand1
static_inventory += using
using = new /obj/screen/swap_hand()
using.icon = ui_style
using.icon_state = "swap_2"
using.screen_loc = ui_swaphand2
static_inventory += using
inv_box = new /obj/screen/inventory()
inv_box.name = "mask"
inv_box.icon = ui_style
inv_box.icon_state = "mask"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_mask
inv_box.slot_id = slot_wear_mask
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "head"
inv_box.icon = ui_style
inv_box.icon_state = "head"
// inv_box.icon_full = "template"
inv_box.screen_loc = ui_monkey_head
inv_box.slot_id = slot_head
static_inventory += inv_box
inv_box = new /obj/screen/inventory()
inv_box.name = "back"
inv_box.icon = ui_style
inv_box.icon_state = "back"
inv_box.icon_full = "template_small"
inv_box.screen_loc = ui_back
inv_box.slot_id = slot_back
static_inventory += inv_box
throw_icon = new /obj/screen/throw_catch()
throw_icon.icon = ui_style
throw_icon.screen_loc = ui_drop_throw
hotkeybuttons += throw_icon
internals = new /obj/screen/internals()
infodisplay += internals
healths = new /obj/screen/healths()
infodisplay += healths
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon(mymob)
pull_icon.screen_loc = ui_pull_resist
static_inventory += pull_icon
lingchemdisplay = new /obj/screen/ling/chems()
infodisplay += lingchemdisplay
lingstingdisplay = new /obj/screen/ling/sting()
infodisplay += lingstingdisplay
zone_select = new /obj/screen/zone_sel()
zone_select.icon = ui_style
zone_select.update_icon(mymob)
static_inventory += zone_select
mymob.client.screen = list()
using = new /obj/screen/resist()
using.icon = ui_style
using.screen_loc = ui_pull_resist
hotkeybuttons += using
for(var/obj/screen/inventory/inv in (static_inventory + toggleable_inventory))
if(inv.slot_id)
inv.hud = src
inv_slots[inv.slot_id] = inv
inv.update_icon()
/datum/hud/monkey/persistant_inventory_update()
if(!mymob)
return
var/mob/living/carbon/monkey/M = mymob
if(hud_shown)
if(M.back)
M.back.screen_loc = ui_back
M.client.screen += M.back
if(M.wear_mask)
M.wear_mask.screen_loc = ui_monkey_mask
M.client.screen += M.wear_mask
if(M.head)
M.head.screen_loc = ui_monkey_head
M.client.screen += M.head
else
if(M.back)
M.back.screen_loc = null
if(M.wear_mask)
M.wear_mask.screen_loc = null
if(M.head)
M.head.screen_loc = null
if(hud_version != HUD_STYLE_NOHUD)
if(M.r_hand)
M.r_hand.screen_loc = ui_rhand
M.client.screen += M.r_hand
if(M.l_hand)
M.l_hand.screen_loc = ui_lhand
M.client.screen += M.l_hand
else
if(M.r_hand)
M.r_hand.screen_loc = null
if(M.l_hand)
M.l_hand.screen_loc = null
/mob/living/carbon/monkey/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/monkey(src, ui_style2icon(client.prefs.UI_style))
@@ -0,0 +1,85 @@
//////////////////////////
//Movable Screen Objects//
// By RemieRichards //
//////////////////////////
//Movable Screen Object
//Not tied to the grid, places it's center where the cursor is
/obj/screen/movable
var/snap2grid = FALSE
var/moved = FALSE
//Snap Screen Object
//Tied to the grid, snaps to the nearest turf
/obj/screen/movable/snap
snap2grid = TRUE
/obj/screen/movable/MouseDrop(over_object, src_location, over_location, src_control, over_control, params)
var/list/PM = params2list(params)
//No screen-loc information? abort.
if(!PM || !PM["screen-loc"])
return
//Split screen-loc up into X+Pixel_X and Y+Pixel_Y
var/list/screen_loc_params = splittext(PM["screen-loc"], ",")
//Split X+Pixel_X up into list(X, Pixel_X)
var/list/screen_loc_X = splittext(screen_loc_params[1],":")
//Split Y+Pixel_Y up into list(Y, Pixel_Y)
var/list/screen_loc_Y = splittext(screen_loc_params[2],":")
if(snap2grid) //Discard Pixel Values
screen_loc = "[screen_loc_X[1]],[screen_loc_Y[1]]"
else //Normalise Pixel Values (So the object drops at the center of the mouse, not 16 pixels off)
var/pix_X = text2num(screen_loc_X[2]) - 16
var/pix_Y = text2num(screen_loc_Y[2]) - 16
screen_loc = "[screen_loc_X[1]]:[pix_X],[screen_loc_Y[1]]:[pix_Y]"
moved = screen_loc
//Debug procs
/client/proc/test_movable_UI()
set category = "Debug"
set name = "Spawn Movable UI Object"
var/obj/screen/movable/M = new()
M.name = "Movable UI Object"
M.icon_state = "block"
M.maptext = "Movable"
M.maptext_width = 64
var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Movable UI Object") as text
if(!screen_l)
return
M.screen_loc = screen_l
screen += M
/client/proc/test_snap_UI()
set category = "Debug"
set name = "Spawn Snap UI Object"
var/obj/screen/movable/snap/S = new()
S.name = "Snap UI Object"
S.icon_state = "block"
S.maptext = "Snap"
S.maptext_width = 64
var/screen_l = input(usr,"Where on the screen? (Formatted as 'X,Y' e.g: '1,1' for bottom left)","Spawn Snap UI Object") as text
if(!screen_l)
return
S.screen_loc = screen_l
screen += S
+41
View File
@@ -0,0 +1,41 @@
/datum/hud/brain/show_hud(version = 0)
if(!ismob(mymob))
return 0
if(!mymob.client)
return 0
mymob.client.screen = list()
mymob.client.screen += mymob.client.void
/mob/living/carbon/brain/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/brain(src)
/datum/hud/hog_god/New(mob/owner)
..()
healths = new /obj/screen/healths/deity()
infodisplay += healths
deity_power_display = new /obj/screen/deity_power_display()
infodisplay += deity_power_display
deity_follower_display = new /obj/screen/deity_follower_display()
infodisplay += deity_follower_display
/mob/camera/god/create_mob_hud()
if(client && !hud_used)
hud_used = new /datum/hud/hog_god(src)
/obj/screen/deity_power_display
name = "Faith"
icon_state = "deity_power"
screen_loc = ui_deitypower
layer = HUD_LAYER
/obj/screen/deity_follower_display
name = "Followers"
icon_state = "deity_followers"
screen_loc = ui_deityfollowers
layer = HUD_LAYER

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