initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -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()
|
||||
@@ -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
|
||||
@@ -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--
|
||||
@@ -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()
|
||||
@@ -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"
|
||||
@@ -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
|
||||
*/
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
#define SUCCESSFUL_SPAWN 2
|
||||
#define NOT_ENOUGH_PLAYERS 3
|
||||
#define MAP_ERROR 4
|
||||
#define WAITING_FOR_SOMETHING 5
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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))
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -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))
|
||||
@@ -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]"
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
#define MIN_FREE_FREQ 1201
|
||||
#define MAX_FREE_FREQ 1599
|
||||
|
||||
#define MIN_FREQ 1441
|
||||
#define MAX_FREQ 1489
|
||||
@@ -0,0 +1,3 @@
|
||||
#define SOLID 1
|
||||
#define LIQUID 2
|
||||
#define GAS 3
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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>"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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"
|
||||
@@ -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]"
|
||||
|
||||
@@ -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]")
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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, "/", "_")
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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]"
|
||||
@@ -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
|
||||
@@ -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]"
|
||||
@@ -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)]"
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 '<' 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 '<' 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 <)
|
||||
|
||||
// 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
|
||||
@@ -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")
|
||||
@@ -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
|
||||
|
||||
*/
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
@@ -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 = " "
|
||||
|
||||
|
||||
|
||||
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)
|
||||
*/
|
||||
@@ -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()
|
||||
@@ -0,0 +1 @@
|
||||
#define CLICKCATCHER_PLANE -99
|
||||
@@ -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
|
||||
@@ -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))
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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!
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
@@ -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))
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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>"
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user