Files
Bubberstation/code/__HELPERS/game.dm
Shadowlight213 435fbb4653 Fix
2015-10-18 16:24:26 -07:00

440 lines
12 KiB
Plaintext

//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
/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_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/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/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.
/proc/recursive_hear_check(atom/O)
var/list/processing_list = list(O)
var/list/processed_list = list()
var/list/found_atoms = list()
while(processing_list.len)
var/atom/A = processing_list[1]
if(A.flags & HEAR)
found_atoms |= 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_atoms
// 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_flag=0,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) && (G.client.prefs.be_special & be_special_flag))
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()
// 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(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 & be_special_flag))
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(alert(G,Question,"Please answer in [poll_time/10] seconds!","Yes","No"))
if("Yes")
G << "<span class='notice'>Choice registered: Yes.</span>"
if((world.time-time_passed)>poll_time)//If more than 30 game seconds passed.
G << "<span class='danger'>Sorry, you were too late for the consideration!</span>"
G << 'sound/machines/buzz-sigh.ogg'
return
candidates += G
if("No")
G << "<span class='danger'>Choice registered: No.</span>"
return
else
return
sleep(poll_time)
//Check all our candidates, to make sure they didn't log off during the 30 second 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