Merge branch 'incremental_tg' r4967 (27/10/2012) into bs12_with_tgport

Conflicts:
	baystation12.dme
	code/__HELPERS/game.dm
	code/__HELPERS/type2type.dm
	code/datums/helper_datums/getrev.dm
	code/game/atoms.dm
	code/game/gamemodes/events.dm
	code/game/machinery/atmo_control.dm
	code/game/machinery/atmoalter/area_atmos_computer.dm
	code/game/machinery/computer/HolodeckControl.dm
	code/game/machinery/computer/atmos_alert.dm
	code/game/machinery/computer/card.dm
	code/game/machinery/computer/cloning.dm
	code/game/machinery/computer/computer.dm
	code/game/machinery/computer/pod.dm
	code/game/machinery/computer/prisoner.dm
	code/game/machinery/computer/syndicate_shuttle.dm
	code/game/machinery/newscaster.dm
	code/game/machinery/spaceheater.dm
	code/game/machinery/telecomms/broadcaster.dm
	code/game/machinery/telecomms/logbrowser.dm
	code/game/machinery/telecomms/machine_interactions.dm
	code/game/machinery/telecomms/telemonitor.dm
	code/game/machinery/telecomms/traffic_control.dm
	code/game/machinery/wishgranter.dm
	code/game/objects/items/devices/uplinks.dm
	code/game/objects/items/stacks/stack.dm
	code/game/objects/objs.dm
	code/modules/DetectiveWork/detective_work.dm
	code/modules/admin/IsBanned.dm
	code/modules/admin/admin.dm
	code/modules/admin/verbs/adminsay.dm
	code/modules/admin/verbs/getlogs.dm
	code/modules/awaymissions/zlevel.dm
	code/modules/client/client procs.dm
	code/modules/clothing/masks/miscellaneous.dm
	code/modules/clothing/spacesuits/miscellaneous.dm
	code/modules/flufftext/TextFilters.dm
	code/modules/mining/machine_processing.dm
	code/modules/mining/machine_stacking.dm
	code/modules/mining/mine_items.dm
	code/modules/mining/mint.dm
	code/modules/mining/satchel_ore_boxdm.dm
	code/modules/mob/living/carbon/monkey/life.dm
	code/modules/mob/living/living_defense.dm
	code/modules/mob/living/simple_animal/friendly/corgi.dm
	code/modules/mob/mob.dm
	code/modules/paperwork/filingcabinet.dm
	code/modules/paperwork/photocopier.dm
	code/modules/power/gravitygenerator.dm
	html/changelog.html
	icons/mob/head.dmi
	icons/mob/human_face.dmi
	icons/mob/mask.dmi
	icons/mob/suit.dmi
	icons/obj/clothing/hats.dmi
	icons/obj/clothing/masks.dmi
	icons/obj/clothing/suits.dmi

Signed-off-by: Cael_Aislinn <cael_aislinn@yahoo.com.au>
This commit is contained in:
Cael_Aislinn
2012-12-28 01:03:14 +10:00
250 changed files with 9936 additions and 10091 deletions
-16
View File
@@ -1,16 +0,0 @@
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
-30
View File
@@ -1,30 +0,0 @@
var/command_name = null
/proc/command_name()
if (command_name)
return command_name
var/name = "Central Command"
/*
if (prob(10))
name += pick("Super", "Ultra")
name += " "
// Prefix
if (name)
name += pick("", "Central", "System", "Home", "Primary", "Alpha", "Friend", "Science", "Renegade")
else
name += pick("Central", "System", "Home", "Primary", "Alpha", "Friend", "Science", "Renegade")
if (name)
name += " "
// Suffix
name += pick("Federation", "Command", "Alliance", "Unity", "Empire", "Confederation", "Kingdom", "Monarchy", "Complex", "Protectorate", "Commonwealth", "Imperium", "Republic")
*/
command_name = name
return name
/proc/change_command_name(var/name)
command_name = name
return name
-322
View File
@@ -1,322 +0,0 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/proc/dopage(src,target)
var/href_list
var/href
href_list = params2list("src=\ref[src]&[target]=1")
href = "src=\ref[src];[target]=1"
src:temphtml = null
src:Topic(href, href_list)
return null
/proc/get_area(O)
var/atom/location = O
var/i
for(i=1, i<=20, i++)
if(isarea(location))
return location
else if (istype(location))
location = location.loc
else
return null
return 0
/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/in_range(source, user)
if(get_dist(source, user) <= 1)
return 1
return 0 //not in range and not telekinetic
// Like view but bypasses luminosity check
/proc/hear(var/range, var/atom/source)
var/lum = source.luminosity
source.luminosity = 6
var/list/heard = view(range, source)
source.luminosity = lum
return heard
//Magic constants obtained by using linear regression on right-angled triangles of sides 0<x<1, 0<y<1
//They should approximate pythagoras theorem well enough for our needs.
#define k1 0.934
#define k2 0.427
/proc/cheap_hypotenuse(Ax,Ay,Bx,By) // T is just the second atom to check distance to center with
var/dx = abs(Ax - Bx) //sides of right-angled triangle
var/dy = abs(Ay - By)
if(dx>=dy) return (k1*dx) + (k2*dy) //No sqrt or powers :)
else return (k1*dx) + (k2*dy)
#undef k1
#undef k2
/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
//var/debug_mob = 0
// Will recursively loop through an atom's contents and check for mobs, then it will loop through every atom in that atom's contents.
// It will keep doing this until it checks every content possible. This will fix any problems with mobs, that are inside objects,
// being unable to hear people due to being in a box within a bag.
/proc/recursive_mob_check(var/atom/O, var/list/L = list(), var/recursion_limit = 3, var/client_check = 1, var/sight_check = 1, var/include_radio = 1)
//debug_mob += O.contents.len
if(!recursion_limit)
return L
for(var/atom/A in O.contents)
if(ismob(A))
var/mob/M = A
if(client_check && !M.client)
L = recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
continue
if(sight_check && !isInSight(A, O))
continue
L |= M
//world.log << "[recursion_limit] = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])"
else if(include_radio && istype(A, /obj/item/device/radio))
if(sight_check && !isInSight(A, O))
continue
L |= A
if(isobj(A) || ismob(A))
L = recursive_mob_check(A, L, recursion_limit - 1, client_check, sight_check, include_radio)
return L
// The old system would loop through lists for a total of 5000 per function call, in an empty server.
// This new system will loop at around 1000 in an empty server.
/proc/get_mobs_in_view(var/R, var/atom/source)
// Returns a list of mobs in range of R from source. Used in radio and say code.
var/turf/T = get_turf(source)
var/list/hear = list()
if(!T)
return hear
var/list/range = hear(R, T)
for(var/atom/A in range)
if(ismob(A))
var/mob/M = A
if(M.client)
hear += M
//world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])"
else if(istype(A, /obj/item/device/radio))
hear += A
if(isobj(A) || ismob(A))
hear = recursive_mob_check(A, hear, 3, 1, 0, 1)
return hear
/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios, var/level = 0)
. = list()
// Returns a list of mobs who can hear any of the radios given in @radios
var/list/speaker_coverage = list()
for(var/obj/item/device/radio/R in radios)
// This is usually for headsets, which only the wearer can hear.
if(R.canhear_range == 0)
if(ismob(R.loc))
. |= R.loc
continue
var/turf/speaker = get_turf(R)
if(speaker)
for(var/turf/T in hear(R.canhear_range,speaker))
speaker_coverage += T
// Try to find all the players who can hear the message
for(var/mob/M in player_list)
var/turf/ear = get_turf(M)
if(ear && (level == 0 || level == ear.z))
if(ear in speaker_coverage)
. |= M
return .
#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(var/atom/A, var/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/get_mob_by_key(var/key)
for(var/mob/M in mob_list)
if(M.ckey == lowertext(key))
return M
return null
proc/check_can_reach(atom/user, atom/target)
if(!in_range(user,target))
return 0
return CanReachThrough(get_turf(user), get_turf(target), target)
//dummy caching, used to speed up reach checks
var/list/DummyCache = list()
/proc/CanReachThrough(turf/srcturf, turf/targetturf, atom/target)
var/obj/item/weapon/dummy/D = locate() in DummyCache
if(!D)
D = new /obj/item/weapon/dummy( srcturf )
else
DummyCache.Remove(D)
D.loc = srcturf
if(targetturf.density && targetturf != get_turf(target))
return 0
//Now, check objects to block exit that are on the border
for(var/obj/border_obstacle in srcturf)
if(border_obstacle.flags & ON_BORDER)
if(!border_obstacle.CheckExit(D, targetturf))
D.loc = null
DummyCache.Add(D)
return 0
//Next, check objects to block entry that are on the border
for(var/obj/border_obstacle in targetturf)
if((border_obstacle.flags & ON_BORDER) && (target != border_obstacle))
if(!border_obstacle.CanPass(D, srcturf, 1, 0))
D.loc = null
DummyCache.Add(D)
return 0
D.loc = null
DummyCache.Add(D)
return 1
-146
View File
@@ -1,146 +0,0 @@
//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() //List of all logged in players **with clients attached** (Based on mob reference)
var/global/list/admin_list = list() //List of all logged in admins (Based on mob reference)
var/global/list/mob_list = list() //List of all mobs, including clientless
var/global/list/living_mob_list = list() //List of all living mobs, including clientless
var/global/list/dead_mob_list = list() //List of all dead mobs, including clientless
var/global/list/client_list = list() //List of all clients, based on ckey
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/hair_styles_list = list() //stores /datum/sprite_accessory/hair indexed by name
var/global/list/facial_hair_styles_list = list() //stores /datum/sprite_accessory/facial_hair indexed by name
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/landmarks_list = list() //list of all landmarks created
//////////////////////////
/////Initial Building/////
//////////////////////////
//Realistically, these should never be run, but ideally, they should only be run once at round-start
/proc/make_datum_references_lists()
var/list/paths
//Hair - Initialise all /datum/sprite_accessory/hair into an list indexed by hair-style name
paths = typesof(/datum/sprite_accessory/hair) - /datum/sprite_accessory/hair
for(var/path in paths)
var/datum/sprite_accessory/hair/H = new path()
hair_styles_list[H.name] = H
//Facial Hair - Initialise all /datum/sprite_accessory/facial_hair into an list indexed by facialhair-style name
paths = typesof(/datum/sprite_accessory/facial_hair) - /datum/sprite_accessory/facial_hair
for(var/path in paths)
var/datum/sprite_accessory/facial_hair/H = new path()
facial_hair_styles_list[H.name] = H
proc/make_player_list()//Global proc that rebuilds the player list
for(var/mob/p in player_list)//Clears out everyone that logged out
if(!(p.client))
player_list -= p
for(var/mob/M in world)//Adds everyone that has logged in
if(M.client)
player_list += M
proc/make_admin_list()//Rebuild that shit to try and avoid issues with stealthmins
admin_list = list()
for(var/client/C in client_list)
if(C && C.holder)
admin_list += C
proc/make_mob_list()
for(var/mob/p in mob_list)
if(!p)//If it's a null reference, remove it
mob_list -= p
for(var/mob/M in world)
mob_list += M
proc/make_extra_mob_list()
for(var/mob/p in living_mob_list)
if(!p)
living_mob_list -= p
if(p.stat == DEAD)//Transfer
living_mob_list -= p
dead_mob_list += p
for(var/mob/p in dead_mob_list)
if(!p)
dead_mob_list -= p
if(p.stat != DEAD)
dead_mob_list -= p
living_mob_list += p
for(var/mob/M in world)
if(M.stat == DEAD)
living_mob_list += M
else
dead_mob_list += M
//Alright, this proc should NEVER be called in the code, ever. This is more of an 'oh god everything is broken'-emergency button.
proc/rebuild_mob_lists()
player_list = list()
admin_list = list()
mob_list = list()
living_mob_list = list()
dead_mob_list = list()
client_list = list()
for(var/mob/M in world)
mob_list += M
if(M.client)
player_list += M
if(M.stat != DEAD)
living_mob_list += M
else
dead_mob_list += M
for(var/client/C)
client_list += C.ckey
if(C.holder)
admin_list += C
proc/add_to_mob_list(var/mob/A)//Adds an individual mob
if(A)
mob_list |= A
if(istype(A,/mob/new_player))//New players are only on the mob list, but not the dead/living
return
else
if(A.stat == 2)
dead_mob_list |= A
if(A.stat != 2)
living_mob_list |= A
// if(A.client)
// player_list |= A
proc/remove_from_mob_list(var/mob/R)//Removes an individual mob
mob_list -= R
if(R.stat == 2)
dead_mob_list -= R
if(R.stat != 2)
living_mob_list -= R
// if(R.client)
// player_list -= R
proc/make_client_list()//Rebuilds client list
for(var/mob/c in client_list)
if(!c.client)
client_list -= c.ckey
for(var/mob/M in world)
if(M.client)
client_list += M.ckey
/*/obj/item/listdebug//Quick debugger for the global lists
icon = 'icons/obj/assemblies.dmi'
icon_state = "radio-igniter-tank"
/obj/item/listdebug/attack_self()
switch(input("Which list?") in list("Players","Admins","Mobs","Living Mobs","Dead Mobs", "Clients"))
if("Players")
usr << dd_list2text(player_list,",")
if("Admins")
usr << dd_list2text(admin_list,",")
if("Mobs")
usr << dd_list2text(mob_list,",")
if("Living Mobs")
usr << dd_list2text(living_mob_list,",")
if("Dead Mobs")
usr << dd_list2text(dead_mob_list,",")
if("Clients")
usr << dd_list2text(client_list,",")*/
-307
View File
@@ -1,307 +0,0 @@
/*
* Holds procs to help with list operations
* Contains groups:
* Misc
* Sorting
*/
/*
* Misc
*/
//Returns a list in plain english as a string
/proc/english_list(var/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(var/list/list,index)
if(istype(list) && list.len)
if(isnum(index))
if(InRange(index,1,list.len))
return list[index]
else if(index in list)
return list[index]
return
proc/islist(list/list)
if(istype(list))
return 1
return 0
//Return either pick(list) or null if list is not of type /list or is empty
proc/safepick(list/list)
if(!islist(list) || !list.len)
return
return pick(list)
//Checks if the list is empty
proc/isemptylist(list/list)
if(!list.len)
return 1
return 0
//Checks for specific types in a list
/proc/is_type_in_list(var/atom/A, var/list/L)
for(var/type in L)
if(istype(A, type))
return 1
return 0
//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/list)
if(istype(list))
while(null in list)
list -= null
return
/*
* 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(var/list/first, var/list/second, var/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(var/list/first, var/list/second, var/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/listfrom)
if (listfrom.len > 0)
var/picked = pick(listfrom)
listfrom -= picked
return picked
return null
//Returns the top(last) element from the list and removes it from the list (typical stack function)
/proc/pop(list/listfrom)
if (listfrom.len > 0)
var/picked = listfrom[listfrom.len]
listfrom.len--
return picked
return null
/*
* Sorting
*/
//Reverses the order of items in the list (Turning a stack into a queue)
/proc/reverselist(var/list/input)
var/list/output = new/list()
for(var/A in input)
output += A
return output
//Randomize: Return the list in a random order
/proc/shuffle(var/list/shufflelist)
if(!shufflelist)
return
var/list/new_list = list()
var/list/old_list = shufflelist.Copy()
while(old_list.len)
var/item = pick(old_list)
new_list += item
old_list -= item
return new_list
//Return a list with no duplicate entries
/proc/uniquelist(var/list/L)
var/list/K = list()
for(var/item in L)
if(!(item in K))
K += item
return K
//Mergesort: divides up the list into halves to begin the sort
/proc/sortKey(var/list/client/L, var/order = 1)
if(isnull(L) || L.len < 2)
return L
var/middle = L.len / 2 + 1
return mergeKey(sortKey(L.Copy(0,middle)), sortKey(L.Copy(middle)), order)
//Mergsort: does the actual sorting and returns the results back to sortAtom
/proc/mergeKey(var/list/client/L, var/list/client/R, var/order = 1)
var/Li=1
var/Ri=1
var/list/result = new()
while(Li <= L.len && Ri <= R.len)
var/client/rL = L[Li]
var/client/rR = R[Ri]
if(sorttext(rL.ckey, rR.ckey) == order)
result += L[Li++]
else
result += R[Ri++]
if(Li <= L.len)
return (result + L.Copy(Li, 0))
return (result + R.Copy(Ri, 0))
//Mergesort: divides up the list into halves to begin the sort
/proc/sortAtom(var/list/atom/L, var/order = 1)
if(isnull(L) || L.len < 2)
return L
var/middle = L.len / 2 + 1
return mergeAtoms(sortAtom(L.Copy(0,middle)), sortAtom(L.Copy(middle)), order)
//Mergsort: does the actual sorting and returns the results back to sortAtom
/proc/mergeAtoms(var/list/atom/L, var/list/atom/R, var/order = 1)
var/Li=1
var/Ri=1
var/list/result = new()
while(Li <= L.len && Ri <= R.len)
var/atom/rL = L[Li]
var/atom/rR = R[Ri]
if(sorttext(rL.name, rR.name) == order)
result += L[Li++]
else
result += R[Ri++]
if(Li <= L.len)
return (result + L.Copy(Li, 0))
return (result + R.Copy(Ri, 0))
//Mergesort: Specifically for record datums in a list.
/proc/sortRecord(var/list/datum/data/record/L, var/field = "name", var/order = 1)
if(isnull(L))
return list()
if(L.len < 2)
return L
var/middle = L.len / 2 + 1
return mergeRecordLists(sortRecord(L.Copy(0, middle), field, order), sortRecord(L.Copy(middle), field, order), field, order)
//Mergsort: does the actual sorting and returns the results back to sortRecord
/proc/mergeRecordLists(var/list/datum/data/record/L, var/list/datum/data/record/R, var/field = "name", var/order = 1)
var/Li=1
var/Ri=1
var/list/result = new()
if(!isnull(L) && !isnull(R))
while(Li <= L.len && Ri <= R.len)
var/datum/data/record/rL = L[Li]
if(isnull(rL))
L -= rL
continue
var/datum/data/record/rR = R[Ri]
if(isnull(rR))
R -= rR
continue
if(sorttext(rL.fields[field], rR.fields[field]) == order)
result += L[Li++]
else
result += R[Ri++]
if(Li <= L.len)
return (result + L.Copy(Li, 0))
return (result + R.Copy(Ri, 0))
//Mergesort: any value in a list
/proc/sortList(var/list/L)
if(L.len < 2)
return L
var/middle = L.len / 2 + 1 // Copy is first,second-1
return mergeLists(sortList(L.Copy(0,middle)), sortList(L.Copy(middle))) //second parameter null = to end of list
//Mergsorge: uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
/proc/sortNames(var/list/L)
var/list/Q = new()
for(var/atom/x in L)
Q[x.name] = x
return sortList(Q)
/proc/mergeLists(var/list/L, var/list/R)
var/Li=1
var/Ri=1
var/list/result = new()
while(Li <= L.len && Ri <= R.len)
if(sorttext(L[Li], R[Ri]) < 1)
result += R[Ri++]
else
result += L[Li++]
if(Li <= L.len)
return (result + L.Copy(Li, 0))
return (result + R.Copy(Ri, 0))
//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
-311
View File
@@ -1,311 +0,0 @@
/*
* Holds procs designed to help with filtering text
* Contains groups:
* SQL sanitization
* 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(var/t as text)
var/sanitized_text = dd_replacetext(t, "'", "\\'")
sanitized_text = dd_replacetext(sanitized_text, "\"", "\\\"")
return sanitized_text
/*
* Text sanitization
*/
//Simply removes < and > and limits the length of the message
/proc/strip_html_simple(var/t,var/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(var/t,var/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)
return t
//Runs byond's sanitization proc along-side sanitize_simple
/proc/sanitize(var/t,var/list/repl_chars = null)
return html_encode(sanitize_simple(t,repl_chars))
//Runs sanitize and strip_html_simple
//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '&lt;' after sanitize() calls byond's html_encode()
/proc/strip_html(var/t,var/limit=MAX_MESSAGE_LEN)
return copytext((sanitize(strip_html_simple(t))),1,limit)
//Runs byond's sanitization proc along-side strip_html_simple
//I believe strip_html_simple() is required to run first to prevent '<' from displaying as '&lt;' that html_encode() would cause
/proc/adminscrub(var/t,var/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(var/text, var/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 sanitized input.
/proc/stripped_input(var/mob/user, var/message = "", var/title = "", var/default = "", var/max_length=MAX_MESSAGE_LEN)
var/name = input(user, message, title, default)
return strip_html_simple(name, max_length)
//Filters out undesirable characters from names
/proc/reject_bad_name(var/t_in, var/allow_numbers=0, var/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
/*
* 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)
/*
* Text modification
*/
//Search and replace a sub-string within a string
/proc/dd_replacetext(text, search_string, replacement_string)
if(!text || !istext(text) || !search_string || !istext(search_string) || !istext(replacement_string))
return null
var/textList = dd_text2list(text, search_string)
return dd_list2text(textList, replacement_string)
//Search and replace a case sensitive sub-string within a string
/proc/dd_replacetext_case(text, search_string, replacement_string)
var/textList = dd_text2list(text, search_string)
return dd_list2text(textList, replacement_string)
//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)
return trim_left(trim_right(text))
//Returns a string with the first element of the string capitalized.
/proc/capitalize(var/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)
/*
* Misc
*/
/proc/stringsplit(txt, character)
var/cur_text = txt
var/last_found = 1
var/found_char = findtext(cur_text,character)
var/list/list = list()
if(found_char)
var/fs = copytext(cur_text,last_found,found_char)
list += fs
last_found = found_char+length(character)
found_char = findtext(cur_text,character,last_found)
while(found_char)
var/found_string = copytext(cur_text,last_found,found_char)
last_found = found_char+length(character)
list += found_string
found_char = findtext(cur_text,character,last_found)
list += copytext(cur_text,last_found,length(cur_text)+1)
return list
/proc/stringmerge(var/text,var/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(var/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
-266
View File
@@ -1,266 +0,0 @@
/*
* Holds procs designed to change one type of value, into another.
* Contains:
* hex2num & num2hex
* text2list & list2text
* file2list
* angle2dir
* angle2text
* worldtime2text
*/
//Returns an integer given a hex input
/proc/hex2num(hex)
if (!( istext(hex) ))
return
var/num = 0
var/power = 0
var/i = null
i = length(hex)
while(i > 0)
var/char = copytext(hex, i, i + 1)
switch(char)
if("0")
//Apparently, switch works with empty statements, yay! If that doesn't work, blame me, though. -- Urist
if("9", "8", "7", "6", "5", "4", "3", "2", "1")
num += text2num(char) * 16 ** power
if("a", "A")
num += 16 ** power * 10
if("b", "B")
num += 16 ** power * 11
if("c", "C")
num += 16 ** power * 12
if("d", "D")
num += 16 ** power * 13
if("e", "E")
num += 16 ** power * 14
if("f", "F")
num += 16 ** power * 15
else
return
power++
i--
return num
//Returns the hex value of a number given a value assumed to be a base-ten value
/proc/num2hex(num, placeholder)
if (placeholder == null)
placeholder = 2
if (!( isnum(num) ))
return
if (!( num ))
return "0"
var/hex = ""
var/i = 0
while(16 ** i < num)
i++
var/power = null
power = i - 1
while(power >= 0)
var/val = round(num / 16 ** power)
num -= val * 16 ** power
switch(val)
if(9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0)
hex += text("[]", val)
if(10.0)
hex += "A"
if(11.0)
hex += "B"
if(12.0)
hex += "C"
if(13.0)
hex += "D"
if(14.0)
hex += "E"
if(15.0)
hex += "F"
else
power--
while(length(hex) < placeholder)
hex = text("0[]", hex)
return hex
//Text 'text' will be added as elements of a list when seperated by 'seperator'
/proc/dd_text2list(text, separator, var/list/withinList)
var/textlength = length(text)
var/separatorlength = length(separator)
if(withinList && !withinList.len) withinList = null
var/list/textList = new()
var/searchPosition = 1
var/findPosition = 1
var/loops = 999
while(loops) //Byond will think 1000+ iterations of a loop is an infinite loop
findPosition = findtext(text, separator, searchPosition, 0)
var/buggyText = copytext(text, searchPosition, findPosition)
if(!withinList || (buggyText in withinList)) textList += "[buggyText]"
if(!findPosition) return textList
searchPosition = findPosition + separatorlength
if(searchPosition > textlength)
textList += ""
return textList
loops--
return
//Text 'text' will be added as elements of a list when seperated by 'seperator'. The separator is case sensitive.
/proc/dd_text2list_case(text, separator, var/list/withinList)
var/textlength = length(text)
var/separatorlength = length(separator)
if(withinList && !withinList.len) withinList = null
var/list/textList = new()
var/searchPosition = 1
var/findPosition = 1
var/loops = 999
while(loops) //Byond will think 1000+ iterations of a loop is an infinite loop
findPosition = findtextEx(text, separator, searchPosition, 0)
var/buggyText = copytext(text, searchPosition, findPosition)
if(!withinList || (buggyText in withinList)) textList += "[buggyText]"
if(!findPosition) return textList
searchPosition = findPosition + separatorlength
if(searchPosition > textlength)
textList += ""
return textList
loops--
return
//Attaches each element of a list to a single string seperated by 'seperator'.
/proc/dd_list2text(var/list/the_list, separator)
var/total = the_list.len
if(!total)
return
var/count = 2
var/newText = "[the_list[1]]"
while(count <= total)
if(separator)
newText += separator
newText += "[the_list[count]]"
count++
return newText
//tg_text2list is faster then dd_text2list
//not case sensitive version
proc/tg_text2list(string, separator=",")
if(!string)
return
var/list/output = new
var/seplength = length(separator)
var/strlength = length(string)
var/prev = 1
var/index
do
index = findtext(string, separator, prev, 0)
output += copytext(string, prev, index)
if(!index)
break
prev = index+seplength
if(prev>strlength)
break
while(index)
return output
//case sensitive version
proc/tg_text2list_case(string, separator=",")
if(!string)
return
var/list/output = new
var/seplength = length(separator)
var/strlength = length(string)
var/prev = 1
var/index
do
index = findtextEx(string, separator, prev, 0)
output += copytext(string, prev, index)
if(!index)
break
prev = index+seplength
if(prev>strlength)
break
while(index)
return output
//slower then dd_list2text, but correctly processes associative lists.
proc/tg_list2text(list/list, glue=",")
if(!istype(list) || !list.len)
return
var/output
for(var/i=1 to list.len)
output += (i!=1? glue : null)+(!isnull(list["[list[i]]"])?"[list["[list[i]]"]]":"[list[i]]")
return output
//Gets a file and adds its contents to a list.
/proc/dd_file2list(file_path, separator)
var/file
if(separator == null)
separator = "\n"
if(isfile(file_path))
file = file_path
else
file = file(file_path)
return dd_text2list(file2text(file), separator)
//Turns a direction into text
/proc/dir2text(direction)
switch(direction)
if(1.0)
return "north"
if(2.0)
return "south"
if(4.0)
return "east"
if(8.0)
return "west"
if(5.0)
return "northeast"
if(6.0)
return "southeast"
if(9.0)
return "northwest"
if(10.0)
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(var/degree)
degree = ((degree+22.5)%365)
if(degree < 45) return NORTH
if(degree < 90) return NORTH|EAST
if(degree < 135) return EAST
if(degree < 180) return SOUTH|EAST
if(degree < 225) return SOUTH
if(degree < 270) return SOUTH|WEST
if(degree < 315) return WEST
return NORTH|WEST
//Returns the angle in english
/proc/angle2text(var/degree)
return dir2text(angle2dir(degree))
//Returns the world time in english
proc/worldtime2text(var/time = 0)
if(time == 0)
time = world.time
return "[round(time / 36000)+12]:[(time / 600 % 60) < 10 ? add_zero(time / 600 % 60, 1) : time / 600 % 60]"
File diff suppressed because it is too large Load Diff
-567
View File
@@ -1,567 +0,0 @@
/*
IconProcs
by Lummox JR
Check the icon_procs_readme.dm for how they work.
*/
#define TO_HEX_DIGIT(n) ascii2text((n&15) + ((n&15)<10 ? 48 : 87))
icon
proc/MakeLying()
var/icon/I = new(src,dir=SOUTH)
I.BecomeLying()
return I
proc/BecomeLying()
Turn(90)
Shift(SOUTH,6)
Shift(EAST,1)
// Multiply all alpha values by this float
proc/ChangeOpacity(opacity = 1.0)
MapColors(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,opacity, 0,0,0,0)
// Convert to grayscale
proc/GrayScale()
MapColors(0.3,0.3,0.3, 0.59,0.59,0.59, 0.11,0.11,0.11, 0,0,0)
proc/ColorTone(tone)
GrayScale()
var/list/TONE = ReadRGB(tone)
var/gray = round(TONE[1]*0.3 + TONE[2]*0.59 + TONE[3]*0.11, 1)
var/icon/upper = (255-gray) ? new(src) : null
if(gray)
MapColors(255/gray,0,0, 0,255/gray,0, 0,0,255/gray, 0,0,0)
Blend(tone, ICON_MULTIPLY)
else SetIntensity(0)
if(255-gray)
upper.Blend(rgb(gray,gray,gray), ICON_SUBTRACT)
upper.MapColors((255-TONE[1])/(255-gray),0,0,0, 0,(255-TONE[2])/(255-gray),0,0, 0,0,(255-TONE[3])/(255-gray),0, 0,0,0,0, 0,0,0,1)
Blend(upper, ICON_ADD)
// Take the minimum color of two icons; combine transparency as if blending with ICON_ADD
proc/MinColors(icon)
var/icon/I = new(src)
I.Opaque()
I.Blend(icon, ICON_SUBTRACT)
Blend(I, ICON_SUBTRACT)
// Take the maximum color of two icons; combine opacity as if blending with ICON_OR
proc/MaxColors(icon)
var/icon/I
if(isicon(icon))
I = new(icon)
else
// solid color
I = new(src)
I.Blend("#000000", ICON_OVERLAY)
I.SwapColor("#000000", null)
I.Blend(icon, ICON_OVERLAY)
var/icon/J = new(src)
J.Opaque()
I.Blend(J, ICON_SUBTRACT)
Blend(I, ICON_OR)
// make this icon fully opaque--transparent pixels become black
proc/Opaque(background = "#000000")
SwapColor(null, background)
MapColors(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,0, 0,0,0,1)
// Change a grayscale icon into a white icon where the original color becomes the alpha
// I.e., black -> transparent, gray -> translucent white, white -> solid white
proc/BecomeAlphaMask()
SwapColor(null, "#000000ff") // don't let transparent become gray
MapColors(0,0,0,0.3, 0,0,0,0.59, 0,0,0,0.11, 0,0,0,0, 1,1,1,0)
proc/UseAlphaMask(mask)
Opaque()
AddAlphaMask(mask)
proc/AddAlphaMask(mask)
var/icon/M = new(mask)
M.Blend("#ffffff", ICON_SUBTRACT)
// apply mask
Blend(M, ICON_ADD)
/*
HSV format is represented as "#hhhssvv" or "#hhhssvvaa"
Hue ranges from 0 to 0x5ff (1535)
0x000 = red
0x100 = yellow
0x200 = green
0x300 = cyan
0x400 = blue
0x500 = magenta
Saturation is from 0 to 0xff (255)
More saturation = more color
Less saturation = more gray
Value ranges from 0 to 0xff (255)
Higher value means brighter color
*/
proc/ReadRGB(rgb)
if(!rgb) return
// interpret the HSV or HSVA value
var/i=1,start=1
if(text2ascii(rgb) == 35) ++start // skip opening #
var/ch,which=0,r=0,g=0,b=0,alpha=0,usealpha
var/digits=0
for(i=start, i<=length(rgb), ++i)
ch = text2ascii(rgb, i)
if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break
++digits
if(digits == 8) break
var/single = digits < 6
if(digits != 3 && digits != 4 && digits != 6 && digits != 8) return
if(digits == 4 || digits == 8) usealpha = 1
for(i=start, digits>0, ++i)
ch = text2ascii(rgb, i)
if(ch >= 48 && ch <= 57) ch -= 48
else if(ch >= 65 && ch <= 70) ch -= 55
else if(ch >= 97 && ch <= 102) ch -= 87
else break
--digits
switch(which)
if(0)
r = (r << 4) | ch
if(single)
r |= r << 4
++which
else if(!(digits & 1)) ++which
if(1)
g = (g << 4) | ch
if(single)
g |= g << 4
++which
else if(!(digits & 1)) ++which
if(2)
b = (b << 4) | ch
if(single)
b |= b << 4
++which
else if(!(digits & 1)) ++which
if(3)
alpha = (alpha << 4) | ch
if(single) alpha |= alpha << 4
. = list(r, g, b)
if(usealpha) . += alpha
proc/ReadHSV(hsv)
if(!hsv) return
// interpret the HSV or HSVA value
var/i=1,start=1
if(text2ascii(hsv) == 35) ++start // skip opening #
var/ch,which=0,hue=0,sat=0,val=0,alpha=0,usealpha
var/digits=0
for(i=start, i<=length(hsv), ++i)
ch = text2ascii(hsv, i)
if(ch < 48 || (ch > 57 && ch < 65) || (ch > 70 && ch < 97) || ch > 102) break
++digits
if(digits == 9) break
if(digits > 7) usealpha = 1
if(digits <= 4) ++which
if(digits <= 2) ++which
for(i=start, digits>0, ++i)
ch = text2ascii(hsv, i)
if(ch >= 48 && ch <= 57) ch -= 48
else if(ch >= 65 && ch <= 70) ch -= 55
else if(ch >= 97 && ch <= 102) ch -= 87
else break
--digits
switch(which)
if(0)
hue = (hue << 4) | ch
if(digits == (usealpha ? 6 : 4)) ++which
if(1)
sat = (sat << 4) | ch
if(digits == (usealpha ? 4 : 2)) ++which
if(2)
val = (val << 4) | ch
if(digits == (usealpha ? 2 : 0)) ++which
if(3)
alpha = (alpha << 4) | ch
. = list(hue, sat, val)
if(usealpha) . += alpha
proc/HSVtoRGB(hsv)
if(!hsv) return "#000000"
var/list/HSV = ReadHSV(hsv)
if(!HSV) return "#000000"
var/hue = HSV[1]
var/sat = HSV[2]
var/val = HSV[3]
// Compress hue into easier-to-manage range
hue -= hue >> 8
if(hue >= 0x5fa) hue -= 0x5fa
var/hi,mid,lo,r,g,b
hi = val
lo = round((255 - sat) * val / 255, 1)
mid = lo + round(abs(round(hue, 510) - hue) * (hi - lo) / 255, 1)
if(hue >= 765)
if(hue >= 1275) {r=hi; g=lo; b=mid}
else if(hue >= 1020) {r=mid; g=lo; b=hi }
else {r=lo; g=mid; b=hi }
else
if(hue >= 510) {r=lo; g=hi; b=mid}
else if(hue >= 255) {r=mid; g=hi; b=lo }
else {r=hi; g=mid; b=lo }
return (HSV.len > 3) ? rgb(r,g,b,HSV[4]) : rgb(r,g,b)
proc/RGBtoHSV(rgb)
if(!rgb) return "#0000000"
var/list/RGB = ReadRGB(rgb)
if(!RGB) return "#0000000"
var/r = RGB[1]
var/g = RGB[2]
var/b = RGB[3]
var/hi = max(r,g,b)
var/lo = min(r,g,b)
var/val = hi
var/sat = hi ? round((hi-lo) * 255 / hi, 1) : 0
var/hue = 0
if(sat)
var/dir
var/mid
if(hi == r)
if(lo == b) {hue=0; dir=1; mid=g}
else {hue=1535; dir=-1; mid=b}
else if(hi == g)
if(lo == r) {hue=512; dir=1; mid=b}
else {hue=511; dir=-1; mid=r}
else if(hi == b)
if(lo == g) {hue=1024; dir=1; mid=r}
else {hue=1023; dir=-1; mid=g}
hue += dir * round((mid-lo) * 255 / (hi-lo), 1)
return hsv(hue, sat, val, (RGB.len>3 ? RGB[4] : null))
proc/hsv(hue, sat, val, alpha)
if(hue < 0 || hue >= 1536) hue %= 1536
if(hue < 0) hue += 1536
if((hue & 0xFF) == 0xFF)
++hue
if(hue >= 1536) hue = 0
if(sat < 0) sat = 0
if(sat > 255) sat = 255
if(val < 0) val = 0
if(val > 255) val = 255
. = "#"
. += TO_HEX_DIGIT(hue >> 8)
. += TO_HEX_DIGIT(hue >> 4)
. += TO_HEX_DIGIT(hue)
. += TO_HEX_DIGIT(sat >> 4)
. += TO_HEX_DIGIT(sat)
. += TO_HEX_DIGIT(val >> 4)
. += TO_HEX_DIGIT(val)
if(!isnull(alpha))
if(alpha < 0) alpha = 0
if(alpha > 255) alpha = 255
. += TO_HEX_DIGIT(alpha >> 4)
. += TO_HEX_DIGIT(alpha)
/*
Smooth blend between HSV colors
amount=0 is the first color
amount=1 is the second color
amount=0.5 is directly between the two colors
amount<0 or amount>1 are allowed
*/
proc/BlendHSV(hsv1, hsv2, amount)
var/list/HSV1 = ReadHSV(hsv1)
var/list/HSV2 = ReadHSV(hsv2)
// add missing alpha if needed
if(HSV1.len < HSV2.len) HSV1 += 255
else if(HSV2.len < HSV1.len) HSV2 += 255
var/usealpha = HSV1.len > 3
// normalize hsv values in case anything is screwy
if(HSV1[1] > 1536) HSV1[1] %= 1536
if(HSV2[1] > 1536) HSV2[1] %= 1536
if(HSV1[1] < 0) HSV1[1] += 1536
if(HSV2[1] < 0) HSV2[1] += 1536
if(!HSV1[3]) {HSV1[1] = 0; HSV1[2] = 0}
if(!HSV2[3]) {HSV2[1] = 0; HSV2[2] = 0}
// no value for one color means don't change saturation
if(!HSV1[3]) HSV1[2] = HSV2[2]
if(!HSV2[3]) HSV2[2] = HSV1[2]
// no saturation for one color means don't change hues
if(!HSV1[2]) HSV1[1] = HSV2[1]
if(!HSV2[2]) HSV2[1] = HSV1[1]
// Compress hues into easier-to-manage range
HSV1[1] -= HSV1[1] >> 8
HSV2[1] -= HSV2[1] >> 8
var/hue_diff = HSV2[1] - HSV1[1]
if(hue_diff > 765) hue_diff -= 1530
else if(hue_diff <= -765) hue_diff += 1530
var/hue = round(HSV1[1] + hue_diff * amount, 1)
var/sat = round(HSV1[2] + (HSV2[2] - HSV1[2]) * amount, 1)
var/val = round(HSV1[3] + (HSV2[3] - HSV1[3]) * amount, 1)
var/alpha = usealpha ? round(HSV1[4] + (HSV2[4] - HSV1[4]) * amount, 1) : null
// normalize hue
if(hue < 0 || hue >= 1530) hue %= 1530
if(hue < 0) hue += 1530
// decompress hue
hue += round(hue / 255)
return hsv(hue, sat, val, alpha)
/*
Smooth blend between RGB colors
amount=0 is the first color
amount=1 is the second color
amount=0.5 is directly between the two colors
amount<0 or amount>1 are allowed
*/
proc/BlendRGB(rgb1, rgb2, amount)
var/list/RGB1 = ReadRGB(rgb1)
var/list/RGB2 = ReadRGB(rgb2)
// add missing alpha if needed
if(RGB1.len < RGB2.len) RGB1 += 255
else if(RGB2.len < RGB1.len) RGB2 += 255
var/usealpha = RGB1.len > 3
var/r = round(RGB1[1] + (RGB2[1] - RGB1[1]) * amount, 1)
var/g = round(RGB1[2] + (RGB2[2] - RGB1[2]) * amount, 1)
var/b = round(RGB1[3] + (RGB2[3] - RGB1[3]) * amount, 1)
var/alpha = usealpha ? round(RGB1[4] + (RGB2[4] - RGB1[4]) * amount, 1) : null
return isnull(alpha) ? rgb(r, g, b) : rgb(r, g, b, alpha)
proc/BlendRGBasHSV(rgb1, rgb2, amount)
return HSVtoRGB(RGBtoHSV(rgb1), RGBtoHSV(rgb2), amount)
proc/HueToAngle(hue)
// normalize hsv in case anything is screwy
if(hue < 0 || hue >= 1536) hue %= 1536
if(hue < 0) hue += 1536
// Compress hue into easier-to-manage range
hue -= hue >> 8
return hue / (1530/360)
proc/AngleToHue(angle)
// normalize hsv in case anything is screwy
if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360)
var/hue = angle * (1530/360)
// Decompress hue
hue += round(hue / 255)
return hue
// positive angle rotates forward through red->green->blue
proc/RotateHue(hsv, angle)
var/list/HSV = ReadHSV(hsv)
// normalize hsv in case anything is screwy
if(HSV[1] >= 1536) HSV[1] %= 1536
if(HSV[1] < 0) HSV[1] += 1536
// Compress hue into easier-to-manage range
HSV[1] -= HSV[1] >> 8
if(angle < 0 || angle >= 360) angle -= 360 * round(angle / 360)
HSV[1] = round(HSV[1] + angle * (1530/360), 1)
// normalize hue
if(HSV[1] < 0 || HSV[1] >= 1530) HSV[1] %= 1530
if(HSV[1] < 0) HSV[1] += 1530
// decompress hue
HSV[1] += round(HSV[1] / 255)
return hsv(HSV[1], HSV[2], HSV[3], (HSV.len > 3 ? HSV[4] : null))
// Convert an rgb color to grayscale
proc/GrayScale(rgb)
var/list/RGB = ReadRGB(rgb)
var/gray = RGB[1]*0.3 + RGB[2]*0.59 + RGB[3]*0.11
return (RGB.len > 3) ? rgb(gray, gray, gray, RGB[4]) : rgb(gray, gray, gray)
// Change grayscale color to black->tone->white range
proc/ColorTone(rgb, tone)
var/list/RGB = ReadRGB(rgb)
var/list/TONE = ReadRGB(tone)
var/gray = RGB[1]*0.3 + RGB[2]*0.59 + RGB[3]*0.11
var/tone_gray = TONE[1]*0.3 + TONE[2]*0.59 + TONE[3]*0.11
if(gray <= tone_gray) return BlendRGB("#000000", tone, gray/(tone_gray || 1))
else return BlendRGB(tone, "#ffffff", (gray-tone_gray)/((255-tone_gray) || 1))
/*
Get flat icon by DarkCampainger. As it says on the tin, will return an icon with all the overlays
as a single icon. Useful for when you want to manipulate an icon via the above as overlays are not normally included.
The _flatIcons list is a cache for generated icon files.
*/
proc
getFlatIcon(atom/A, dir) // 1 = use cache, 2 = override cache, 0 = ignore cache
// Layers will be a sorted list of icons/overlays, based on the order in which they are displayed
var/list/layers = list()
// Add the atom's icon itself
if(A.icon)
// Make a copy without pixel_x/y settings
var/image/copy = image(icon=A.icon,icon_state=A.icon_state,layer=A.layer,dir=A.dir)
layers[copy] = A.layer
// dir defaults to A's dir
if(!dir) dir = A.dir
// Loop through the underlays, then overlays, sorting them into the layers list
var/list/process = A.underlays // Current list being processed
var/pSet=0 // Which list is being processed: 0 = underlays, 1 = overlays
var/curIndex=1 // index of 'current' in list being processed
var/current // Current overlay being sorted
var/currentLayer // Calculated layer that overlay appears on (special case for FLOAT_LAYER)
var/compare // The overlay 'add' is being compared against
var/cmpIndex // The index in the layers list of 'compare'
while(TRUE)
if(curIndex<=process.len)
current = process[curIndex]
if(!current) continue
currentLayer = current:layer
if(currentLayer<0) // Special case for FLY_LAYER
if(currentLayer <= -1000) return 0
if(pSet == 0) // Underlay
currentLayer = A.layer+currentLayer/1000
else // Overlay
currentLayer = A.layer+(1000+currentLayer)/1000
// Sort add into layers list
for(cmpIndex=1,cmpIndex<=layers.len,cmpIndex++)
compare = layers[cmpIndex]
if(currentLayer < layers[compare]) // Associated value is the calculated layer
layers.Insert(cmpIndex,current)
layers[current] = currentLayer
break
if(cmpIndex>layers.len) // Reached end of list without inserting
layers[current]=currentLayer // Place at end
curIndex++
if(curIndex>process.len)
if(pSet == 0) // Switch to overlays
curIndex = 1
pSet = 1
process = A.overlays
else // All done
break
// We start with a blank canvas, otherwise some icon procs crash silently
var/icon/flat = icon('icons/effects/effects.dmi', "icon_state"="nothing") // Final flattened icon
var/icon/add // Icon of overlay being added
// Current dimensions of flattened icon
var/{flatX1=1;flatX2=flat.Width();flatY1=1;flatY2=flat.Height()}
// Dimensions of overlay being added
var/{addX1;addX2;addY1;addY2}
for(var/I in layers)
if(I:icon)
if(I:icon_state)
// Has icon and state set
add = icon(I:icon, I:icon_state)
else
if(A.icon_state in icon_states(I:icon))
// Inherits icon_state from atom
add = icon(I:icon, A.icon_state)
else
// Uses default state ("")
add = icon(I:icon)
else if(I:icon_state)
// Inherits icon from atom
add = icon(A.icon, I:icon_state)
else
// Unknown
continue
// Find the new dimensions of the flat icon to fit the added overlay
addX1 = min(flatX1, I:pixel_x+1)
addX2 = max(flatX2, I:pixel_x+add.Width())
addY1 = min(flatY1, I:pixel_y+1)
addY2 = max(flatY2, I:pixel_y+add.Height())
if(addX1!=flatX1 || addX2!=flatX2 || addY1!=flatY1 || addY2!=flatY2)
// Resize the flattened icon so the new icon fits
flat.Crop(addX1-flatX1+1, addY1-flatY1+1, addX2-flatX1+1, addY2-flatY1+1)
flatX1=addX1;flatX2=addX2
flatY1=addY1;flatY2=addY2
// Blend the overlay into the flattened icon
flat.Blend(add,ICON_OVERLAY,I:pixel_x+2-flatX1,I:pixel_y+2-flatY1)
return flat
getIconMask(atom/A)//By yours truly. Creates a dynamic mask for a mob/whatever. /N
var/icon/alpha_mask = new(A.icon,A.icon_state)//So we want the default icon and icon state of A.
for(var/I in A.overlays)//For every image in overlays. var/image/I will not work, don't try it.
if(I:layer>A.layer) continue//If layer is greater than what we need, skip it.
var/icon/image_overlay = new(I:icon,I:icon_state)//Blend only works with icon objects.
//Also, icons cannot directly set icon_state. Slower than changing variables but whatever.
alpha_mask.Blend(image_overlay,ICON_OR)//OR so they are lumped together in a nice overlay.
return alpha_mask//And now return the mask.
/mob/proc/AddCamoOverlay(atom/A)//A is the atom which we are using as the overlay.
var/icon/opacity_icon = new(A.icon, A.icon_state)//Don't really care for overlays/underlays.
//Now we need to culculate overlays+underlays and add them together to form an image for a mask.
//var/icon/alpha_mask = getFlatIcon(src)//Accurate but SLOW. Not designed for running each tick. Could have other uses I guess.
var/icon/alpha_mask = getIconMask(src)//Which is why I created that proc. Also a little slow since it's blending a bunch of icons together but good enough.
opacity_icon.AddAlphaMask(alpha_mask)//Likely the main source of lag for this proc. Probably not designed to run each tick.
opacity_icon.ChangeOpacity(0.4)//Front end for MapColors so it's fast. 0.5 means half opacity and looks the best in my opinion.
for(var/i=0,i<5,i++)//And now we add it as overlays. It's faster than creating an icon and then merging it.
var/image/I = image("icon" = opacity_icon, "icon_state" = A.icon_state, "layer" = layer+0.8)//So it's above other stuff but below weapons and the like.
switch(i)//Now to determine offset so the result is somewhat blurred.
if(1) I.pixel_x--
if(2) I.pixel_x++
if(3) I.pixel_y--
if(4) I.pixel_y++
overlays += I//And finally add the overlay.
/proc/getHologramIcon(icon/A, safety=1)//If safety is on, a new icon is not created.
var/icon/flat_icon = safety ? A : new(A)//Has to be a new icon to not constantly change the same icon.
flat_icon.ColorTone(rgb(125,180,225))//Let's make it bluish.
flat_icon.ChangeOpacity(0.5)//Make it half transparent.
var/icon/alpha_mask = new('icons/effects/effects.dmi', "scanline")//Scanline effect.
flat_icon.AddAlphaMask(alpha_mask)//Finally, let's mix in a distortion effect.
return flat_icon
//For photo camera.
/proc/build_composite_icon(atom/A)
var/icon/composite = icon(A.icon, A.icon_state, A.dir, 1)
for(var/O in A.overlays)
var/image/I = O
composite.Blend(icon(I.icon, I.icon_state, I.dir, 1), ICON_OVERLAY)
return composite
-214
View File
@@ -1,214 +0,0 @@
/*
IconProcs README
A BYOND library for manipulating icons and colors
by Lummox JR
version 1.0
The IconProcs library was made to make a lot of common icon operations much easier. BYOND's icon manipulation
routines are very capable but some of the advanced capabilities like using alpha transparency can be unintuitive to beginners.
CHANGING ICONS
Several new procs have been added to the /icon datum to simplify working with icons. To use them,
remember you first need to setup an /icon var like so:
var/icon/my_icon = new('iconfile.dmi')
icon/ChangeOpacity(amount = 1)
A very common operation in DM is to try to make an icon more or less transparent. Making an icon more
transparent is usually much easier than making it less so, however. This proc basically is a frontend
for MapColors() which can change opacity any way you like, in much the same way that SetIntensity()
can make an icon lighter or darker. If amount is 0.5, the opacity of the icon will be cut in half.
If amount is 2, opacity is doubled and anything more than half-opaque will become fully opaque.
icon/GrayScale()
Converts the icon to grayscale instead of a fully colored icon. Alpha values are left intact.
icon/ColorTone(tone)
Similar to GrayScale(), this proc converts the icon to a range of black -> tone -> white, where tone is an
RGB color (its alpha is ignored). This can be used to create a sepia tone or similar effect.
See also the global ColorTone() proc.
icon/MinColors(icon)
The icon is blended with a second icon where the minimum of each RGB pixel is the result.
Transparency may increase, as if the icons were blended with ICON_ADD. You may supply a color in place of an icon.
icon/MaxColors(icon)
The icon is blended with a second icon where the maximum of each RGB pixel is the result.
Opacity may increase, as if the icons were blended with ICON_OR. You may supply a color in place of an icon.
icon/Opaque(background = "#000000")
All alpha values are set to 255 throughout the icon. Transparent pixels become black, or whatever background color you specify.
icon/BecomeAlphaMask()
You can convert a simple grayscale icon into an alpha mask to use with other icons very easily with this proc.
The black parts become transparent, the white parts stay white, and anything in between becomes a translucent shade of white.
icon/AddAlphaMask(mask)
The alpha values of the mask icon will be blended with the current icon. Anywhere the mask is opaque,
the current icon is untouched. Anywhere the mask is transparent, the current icon becomes transparent.
Where the mask is translucent, the current icon becomes more transparent.
icon/UseAlphaMask(mask, mode)
Sometimes you may want to take the alpha values from one icon and use them on a different icon.
This proc will do that. Just supply the icon whose alpha mask you want to use, and src will change
so it has the same colors as before but uses the mask for opacity.
COLOR MANAGEMENT AND HSV
RGB isn't the only way to represent color. Sometimes it's more useful to work with a model called HSV, which stands for hue, saturation, and value.
* The hue of a color describes where it is along the color wheel. It goes from red to yellow to green to
cyan to blue to magenta and back to red.
* The saturation of a color is how much color is in it. A color with low saturation will be more gray,
and with no saturation at all it is a shade of gray.
* The value of a color determines how bright it is. A high-value color is vivid, moderate value is dark,
and no value at all is black.
Just as BYOND uses "#rrggbb" to represent RGB values, a similar format is used for HSV: "#hhhssvv". The hue is three
hex digits because it ranges from 0 to 0x5FF.
* 0 to 0xFF - red to yellow
* 0x100 to 0x1FF - yellow to green
* 0x200 to 0x2FF - green to cyan
* 0x300 to 0x3FF - cyan to blue
* 0x400 to 0x4FF - blue to magenta
* 0x500 to 0x5FF - magenta to red
Knowing this, you can figure out that red is "#000ffff" in HSV format, which is hue 0 (red), saturation 255 (as colorful as possible),
value 255 (as bright as possible). Green is "#200ffff" and blue is "#400ffff".
More than one HSV color can match the same RGB color.
Here are some procs you can use for color management:
ReadRGB(rgb)
Takes an RGB string like "#ffaa55" and converts it to a list such as list(255,170,85). If an RGBA format is used
that includes alpha, the list will have a fourth item for the alpha value.
hsv(hue, sat, val, apha)
Counterpart to rgb(), this takes the values you input and converts them to a string in "#hhhssvv" or "#hhhssvvaa"
format. Alpha is not included in the result if null.
ReadHSV(rgb)
Takes an HSV string like "#100FF80" and converts it to a list such as list(256,255,128). If an HSVA format is used that
includes alpha, the list will have a fourth item for the alpha value.
RGBtoHSV(rgb)
Takes an RGB or RGBA string like "#ffaa55" and converts it into an HSV or HSVA color such as "#080aaff".
HSVtoRGB(hsv)
Takes an HSV or HSVA string like "#080aaff" and converts it into an RGB or RGBA color such as "#ff55aa".
BlendRGB(rgb1, rgb2, amount)
Blends between two RGB or RGBA colors using regular RGB blending. If amount is 0, the first color is the result;
if 1, the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well.
The returned value is an RGB or RGBA color.
BlendHSV(hsv1, hsv2, amount)
Blends between two HSV or HSVA colors using HSV blending, which tends to produce nicer results than regular RGB
blending because the brightness of the color is left intact. If amount is 0, the first color is the result; if 1,
the second color is the result. 0.5 produces an average of the two. Values outside the 0 to 1 range are allowed as well.
The returned value is an HSV or HSVA color.
BlendRGBasHSV(rgb1, rgb2, amount)
Like BlendHSV(), but the colors used and the return value are RGB or RGBA colors. The blending is done in HSV form.
HueToAngle(hue)
Converts a hue to an angle range of 0 to 360. Angle 0 is red, 120 is green, and 240 is blue.
AngleToHue(hue)
Converts an angle to a hue in the valid range.
RotateHue(hsv, angle)
Takes an HSV or HSVA value and rotates the hue forward through red, green, and blue by an angle from 0 to 360.
(Rotating red by 60° produces yellow.) The result is another HSV or HSVA color with the same saturation and value
as the original, but a different hue.
GrayScale(rgb)
Takes an RGB or RGBA color and converts it to grayscale. Returns an RGB or RGBA string.
ColorTone(rgb, tone)
Similar to GrayScale(), this proc converts an RGB or RGBA color to a range of black -> tone -> white instead of
using strict shades of gray. The tone value is an RGB color; any alpha value is ignored.
*/
/*
Get Flat Icon DEMO by DarkCampainger
This is a test for the get flat icon proc, modified approprietly for icons and their states.
Probably not a good idea to run this unless you want to see how the proc works in detail.
mob
icon = 'old_or_unused.dmi'
icon_state = "green"
Login()
// Testing image underlays
underlays += image(icon='old_or_unused.dmi',icon_state="red")
underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = 32)
underlays += image(icon='old_or_unused.dmi',icon_state="red", pixel_x = -32)
// Testing image overlays
overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = -32)
overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = 32, pixel_y = 32)
overlays += image(icon='old_or_unused.dmi',icon_state="green", pixel_x = -32, pixel_y = -32)
// Testing icon file overlays (defaults to mob's state)
overlays += '_flat_demoIcons2.dmi'
// Testing icon_state overlays (defaults to mob's icon)
overlays += "white"
// Testing dynamic icon overlays
var/icon/I = icon('old_or_unused.dmi', icon_state="aqua")
I.Shift(NORTH,16,1)
overlays+=I
// Testing dynamic image overlays
I=image(icon=I,pixel_x = -32, pixel_y = 32)
overlays+=I
// Testing object types (and layers)
overlays+=/obj/effect/overlayTest
loc = locate (10,10,1)
verb
Browse_Icon()
set name = "1. Browse Icon"
// Give it a name for the cache
var/iconName = "[ckey(src.name)]_flattened.dmi"
// Send the icon to src's local cache
src<<browse_rsc(getFlatIcon(src), iconName)
// Display the icon in their browser
src<<browse("<body bgcolor='#000000'><p><img src='[iconName]'></p></body>")
Output_Icon()
set name = "2. Output Icon"
src<<"Icon is: \icon[getFlatIcon(src)]"
Label_Icon()
set name = "3. Label Icon"
// Give it a name for the cache
var/iconName = "[ckey(src.name)]_flattened.dmi"
// Copy the file to the rsc manually
var/icon/I = fcopy_rsc(getFlatIcon(src))
// Send the icon to src's local cache
src<<browse_rsc(I, iconName)
// Update the label to show it
winset(src,"imageLabel","image='\ref[I]'");
Add_Overlay()
set name = "4. Add Overlay"
overlays += image(icon='old_or_unused.dmi',icon_state="yellow",pixel_x = rand(-64,32), pixel_y = rand(-64,32))
Stress_Test()
set name = "5. Stress Test"
for(var/i = 0 to 1000)
// The third parameter forces it to generate a new one, even if it's already cached
getFlatIcon(src,0,2)
if(prob(5))
Add_Overlay()
Browse_Icon()
Cache_Test()
set name = "6. Cache Test"
for(var/i = 0 to 1000)
getFlatIcon(src)
Browse_Icon()
obj/effect/overlayTest
icon = 'old_or_unused.dmi'
icon_state = "blue"
pixel_x = -24
pixel_y = 24
layer = TURF_LAYER // Should appear below the rest of the overlays
world
view = "7x7"
maxx = 20
maxy = 20
maxz = 1
*/
-48
View File
@@ -1,48 +0,0 @@
/proc/log_admin(text)
admin_log.Add(text)
if (config.log_admin)
diary << "\[[time_stamp()]]ADMIN: [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_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_adminsay(text)
if (config.log_adminchat)
diary << "\[[time_stamp()]]ADMINSAY: [text]"
/proc/log_adminwarn(text)
if (config.log_adminwarn)
diary << "\[[time_stamp()]]ADMINWARN: [text]"
/proc/log_pda(text)
if (config.log_pda)
diary << "\[[time_stamp()]]PDA: [text]"
-11
View File
@@ -1,11 +0,0 @@
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)
-68
View File
@@ -1,68 +0,0 @@
/proc/station_name()
if (station_name)
return station_name
var/random = rand(1,5)
var/name = ""
//Rare: Pre-Prefix
if (prob(10))
name = pick("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")
station_name = name + " "
// Prefix
switch(Holiday)
//get normal name
if(null,"",0)
name = pick("", "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")
if(name)
station_name += name + " "
//For special days like christmas, easter, new-years etc ~Carn
if("Friday the 13th")
name = pick("Mike","Friday","Evil","Myers","Murder","Deathly","Stabby")
station_name += name + " "
random = 13
else
//get the first word of the Holiday and use that
var/i = findtext(Holiday," ",1,0)
name = copytext(Holiday,1,i)
station_name += name + " "
// Suffix
name = pick("Station", "Fortress", "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")
station_name += name + " "
// ID Number
switch(random)
if(1)
station_name += "[rand(1, 99)]"
if(2)
station_name += pick("Alpha", "Beta", "Gamma", "Delta", "Epsilon", "Zeta", "Eta", "Theta", "Iota", "Kappa", "Lambda", "Mu", "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega")
if(3)
station_name += pick("II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX")
if(4)
station_name += pick("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")
if(5)
station_name += pick("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen")
if(13)
station_name += pick("13","XIII","Thirteen")
if (config && config.server_name)
world.name = "[config.server_name]: [name]"
else
world.name = station_name
return station_name
/proc/world_name(var/name)
station_name = name
if (config && config.server_name)
world.name = "[config.server_name]: [name]"
else
world.name = name
return name
+1 -4
View File
@@ -21,10 +21,7 @@ proc/sql_poll_players()
proc/sql_poll_admins()
if(!sqllogging)
return
var/admincount = 0
for (var/client/C in admin_list)
if(C)
admincount += 1
var/admincount = admins.len
var/DBConnection/dbcon = new()
dbcon.Connect("dbi:mysql:[sqldb]:[sqladdress]:[sqlport]","[sqllogin]","[sqlpass]")
if(!dbcon.IsConnected())
-197
View File
@@ -1,197 +0,0 @@
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","tequilla 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
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
/*
//This proc tests the gen above.
/client/verb/test_code_phrase()
set name = "Generate Code Phrase"
set category = "Debug"
world << "\red Code Phrase is: \black [generate_code_phrase()]"
return
This was an earlier attempt at code phrase system, aside from an even earlier attempt (and failure).
This system more or less works as intended--aside from being unfinished--but it's still very predictable.
Particularly, the phrase opening statements are pretty easy to recognize and identify when metagaming.
I think the above-used method solves this issue by using words in a sequence, providing for much greater flexibility.
/N
switch(choice)
if(1)
syndicate_code_phrase += pick("I'm looking for","Have you seen","Maybe you've seen","I'm trying to find","I'm tracking")
syndicate_code_phrase += " "
syndicate_code_phrase += pick(pick(first_names_male,first_names_female))
syndicate_code_phrase += " "
syndicate_code_phrase += pick(last_names)
syndicate_code_phrase += "."
if(2)
syndicate_code_phrase += pick("How do I get to","How do I find","Where is","Where do I find")
syndicate_code_phrase += " "
syndicate_code_phrase += pick("Escape","Engineering","Atmos","the bridge","the brig","Clown Planet","CentCom","the library","the chapel","a bathroom","Med Bay","Tool Storage","the escape shuttle","Robotics","a locker room","the living quarters","the gym","the autolathe","QM","the bar","the theater","the derelict")
syndicate_code_phrase += "?"
if(3)
if(prob(70))
syndicate_code_phrase += pick("Get me","I want","I'd like","Make me")
syndicate_code_phrase += " a "
else
syndicate_code_phrase += pick("One")
syndicate_code_phrase += " "
syndicate_code_phrase += pick("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","tequilla sunrise","brave bull","gargle blaster","bloody mary","whiskey cola","white Russian","vodka martini","martini","Cuba libre","kahlua","vodka","wine","moonshine")
syndicate_code_phrase += "."
if(4)
syndicate_code_phrase += pick("I wish I was","My dad was","His mom was","Where do I find","The hero this station needs is","I'd fuck","I wouldn't trust","Someone caught","HoS caught","Someone found","I'd wrestle","I wanna kill")
syndicate_code_phrase += " [pick("a","the")] "
syndicate_code_phrase += pick("wizard","ninja","xeno","lizard","metroid","monkey","syndicate","cyborg","clown","space carp","singularity","singulo","mime")
syndicate_code_phrase += "."
if(5)
syndicate_code_phrase += pick("Do we have","Is there","Where is","Where's","Who's")
syndicate_code_phrase += " "
syndicate_code_phrase += "[pick(get_all_jobs())]"
syndicate_code_phrase += "?"
switch(choice)
if(1)
if(prob(80))
syndicate_code_response += pick("Try looking for them near","I they ran off to","Yes. I saw them near","Nope. I'm heading to","Try searching")
syndicate_code_response += " "
syndicate_code_response += pick("Escape","Engineering","Atmos","the bridge","the brig","Clown Planet","CentCom","the library","the chapel","a bathroom","Med Bay","Tool Storage","the escape shuttle","Robotics","a locker room","the living quarters","the gym","the autolathe","QM","the bar","the theater","the derelict")
syndicate_code_response += "."
else if(prob(60))
syndicate_code_response += pick("No. I'm busy, sorry.","I don't have the time.","Not sure, maybe?","There is no time.")
else
syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*")
if(2)
if(prob(80))
syndicate_code_response += pick("Go to","Navigate to","Try","Sure, run to","Try searching","It's near","It's around")
syndicate_code_response += " the "
syndicate_code_response += pick("[pick("south","north","east","west")] maitenance door","nearby maitenance","teleporter","[pick("cold","dead")] space","morgue","vacuum","[pick("south","north","east","west")] hall ","[pick("south","north","east","west")] hallway","[pick("white","black","red","green","blue","pink","purple")] [pick("rabbit","frog","lion","tiger","panther","snake","facehugger")]")
syndicate_code_response += "."
else if(prob(60))
syndicate_code_response += pick("Try asking","Ask","Talk to","Go see","Follow","Hunt down")
syndicate_code_response += " "
if(prob(50))
syndicate_code_response += pick(pick(first_names_male,first_names_female))
syndicate_code_response += " "
syndicate_code_response += pick(last_names)
else
syndicate_code_response += " the "
syndicate_code_response += "[pic(get_all_jobs())]"
syndicate_code_response += "."
else
syndicate_code_response += pick("*shrug*","*smile*","*blink*","*sigh*","*laugh*","*nod*","*giggle*")
if(3)
if(4)
if(5)
return
*/
-24
View File
@@ -1,24 +0,0 @@
proc/time_stamp()
var/hh = text2num(time2text(world.timeofday, "hh")) // Set the hour
var/mm = text2num(time2text(world.timeofday, "mm")) // Set the minute
var/ss = text2num(time2text(world.timeofday, "ss")) // Set the second
var/ph
var/pm
var/ps
if(hh < 10) ph = "0"
if(mm < 10) pm = "0"
if(ss < 10) ps = "0"
return"[ph][hh]:[pm][mm]:[ps][ss]"
/* Returns 1 if it is the selected month and day */
proc/isDay(var/month, var/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