oops
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
|
||||
/datum/action/item_action/zoom_speed_action
|
||||
name = "Toggle Zooming Speed"
|
||||
icon_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
button_icon_state = "projectile"
|
||||
background_icon_state = "bg_tech"
|
||||
|
||||
/datum/action/item_action/zoom_lock_action
|
||||
name = "Switch Zoom Mode"
|
||||
icon_icon = 'icons/mob/actions/actions_items.dmi'
|
||||
button_icon_state = "zoom_mode"
|
||||
background_icon_state = "bg_tech"
|
||||
@@ -0,0 +1,170 @@
|
||||
#define MONKEYS_ESCAPED 1
|
||||
#define MONKEYS_LIVED 2
|
||||
#define MONKEYS_DIED 3
|
||||
#define DISEASE_LIVED 4
|
||||
|
||||
/datum/antagonist/monkey
|
||||
name = "Monkey"
|
||||
job_rank = ROLE_MONKEY
|
||||
roundend_category = "monkeys"
|
||||
var/datum/objective_team/monkey/monkey_team
|
||||
|
||||
/datum/antagonist/monkey/on_gain()
|
||||
. = ..()
|
||||
SSticker.mode.ape_infectees += owner
|
||||
owner.special_role = "Infected Monkey"
|
||||
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever
|
||||
if(!owner.current.HasDisease(D))
|
||||
D.affected_mob = owner
|
||||
owner.current.viruses += D
|
||||
else
|
||||
QDEL_NULL(D)
|
||||
|
||||
/datum/antagonist/monkey/greet()
|
||||
to_chat(owner, "<b>You are a monkey now!</b>")
|
||||
to_chat(owner, "<b>Bite humans to infect them, follow the orders of the monkey leaders, and help fellow monkeys!</b>")
|
||||
to_chat(owner, "<b>Ensure at least one infected monkey escapes on the Emergency Shuttle!</b>")
|
||||
to_chat(owner, "<b><i>As an intelligent monkey, you know how to use technology and how to ventcrawl while wearing things.</i></b>")
|
||||
to_chat(owner, "<b>You can use :k to talk to fellow monkeys!</b>")
|
||||
SEND_SOUND(owner.current, sound('sound/ambience/antag/monkey.ogg'))
|
||||
|
||||
/datum/antagonist/monkey/on_removal()
|
||||
. = ..()
|
||||
owner.special_role = null
|
||||
SSticker.mode.ape_infectees -= owner
|
||||
|
||||
var/datum/disease/D = (/datum/disease/transformation/jungle_fever in owner.current.viruses)
|
||||
if(D)
|
||||
D.cure()
|
||||
|
||||
/datum/antagonist/monkey/create_team(datum/objective_team/monkey/new_team)
|
||||
if(!new_team)
|
||||
for(var/datum/antagonist/monkey/N in get_antagonists(/datum/antagonist/monkey, TRUE))
|
||||
if(N.monkey_team)
|
||||
monkey_team = N.monkey_team
|
||||
return
|
||||
monkey_team = new /datum/objective_team/monkey
|
||||
monkey_team.update_objectives()
|
||||
return
|
||||
if(!istype(new_team))
|
||||
stack_trace("Wrong team type passed to [type] initialization.")
|
||||
monkey_team = new_team
|
||||
|
||||
/datum/antagonist/monkey/proc/forge_objectives()
|
||||
if(monkey_team)
|
||||
owner.objectives |= monkey_team.objectives
|
||||
|
||||
/datum/antagonist/monkey/leader
|
||||
name = "Monkey Leader"
|
||||
|
||||
/datum/antagonist/monkey/leader/on_gain()
|
||||
. = ..()
|
||||
var/datum/disease/D = (/datum/disease/transformation/jungle_fever in owner.current.viruses)
|
||||
if(D)
|
||||
D.visibility_flags = HIDDEN_SCANNER|HIDDEN_PANDEMIC
|
||||
var/obj/item/organ/heart/freedom/F = new
|
||||
F.Insert(owner.current, drop_if_replaced = FALSE)
|
||||
SSticker.mode.ape_leaders += owner
|
||||
owner.special_role = "Monkey Leader"
|
||||
|
||||
/datum/antagonist/monkey/leader/on_removal()
|
||||
. = ..()
|
||||
SSticker.mode.ape_leaders -= owner
|
||||
var/obj/item/organ/heart/H = new
|
||||
H.Insert(owner.current, drop_if_replaced = FALSE) //replace freedom heart with normal heart
|
||||
|
||||
/datum/antagonist/monkey/leader/greet()
|
||||
to_chat(owner, "<B><span class='notice'>You are the Jungle Fever patient zero!!</B></span>")
|
||||
to_chat(owner, "<b>You have been planted onto this station by the Animal Rights Consortium.</b>")
|
||||
to_chat(owner, "<b>Soon the disease will transform you into an ape. Afterwards, you will be able spread the infection to others with a bite.</b>")
|
||||
to_chat(owner, "<b>While your infection strain is undetectable by scanners, any other infectees will show up on medical equipment.</b>")
|
||||
to_chat(owner, "<b>Your mission will be deemed a success if any of the live infected monkeys reach CentCom.</b>")
|
||||
to_chat(owner, "<b>As an initial infectee, you will be considered a 'leader' by your fellow monkeys.</b>")
|
||||
to_chat(owner, "<b>You can use :k to talk to fellow monkeys!</b>")
|
||||
SEND_SOUND(owner.current, sound('sound/ambience/antag/monkey.ogg'))
|
||||
|
||||
/datum/objective/monkey
|
||||
explanation_text = "Ensure that infected monkeys escape on the emergency shuttle!"
|
||||
martyr_compatible = TRUE
|
||||
var/monkeys_to_win = 1
|
||||
var/escaped_monkeys = 0
|
||||
|
||||
/datum/objective/monkey/check_completion()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
|
||||
if (M.HasDisease(D) && (M.onCentCom() || M.onSyndieBase()))
|
||||
escaped_monkeys++
|
||||
if(escaped_monkeys >= monkeys_to_win)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/monkey
|
||||
name = "Monkeys"
|
||||
|
||||
/datum/objective_team/monkey/proc/update_objectives()
|
||||
objectives = list()
|
||||
var/datum/objective/monkey/O = new /datum/objective/monkey()
|
||||
O.team = src
|
||||
objectives += O
|
||||
return
|
||||
|
||||
/datum/objective_team/monkey/proc/infected_monkeys_alive()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/monkey/proc/infected_monkeys_escaped()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/monkey/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D) && (M.onCentCom() || M.onSyndieBase()))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/monkey/proc/infected_humans_escaped()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/human/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D) && (M.onCentCom() || M.onSyndieBase()))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/monkey/proc/infected_humans_alive()
|
||||
var/datum/disease/D = new /datum/disease/transformation/jungle_fever()
|
||||
for(var/mob/living/carbon/human/M in GLOB.alive_mob_list)
|
||||
if(M.HasDisease(D))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/objective_team/monkey/proc/get_result()
|
||||
if(infected_monkeys_escaped())
|
||||
return MONKEYS_ESCAPED
|
||||
if(infected_monkeys_alive())
|
||||
return MONKEYS_LIVED
|
||||
if(infected_humans_alive() || infected_humans_escaped())
|
||||
return DISEASE_LIVED
|
||||
return MONKEYS_DIED
|
||||
|
||||
/datum/objective_team/monkey/roundend_report()
|
||||
var/list/parts = list()
|
||||
switch(get_result())
|
||||
if(MONKEYS_ESCAPED)
|
||||
parts += "<span class='greentext big'><B>Monkey Major Victory!</B></span>"
|
||||
parts += "<span class='greentext'><B>Central Command and [station_name()] were taken over by the monkeys! Ook ook!</B></span>"
|
||||
if(MONKEYS_LIVED)
|
||||
parts += "<FONT size = 3><B>Monkey Minor Victory!</B></FONT>"
|
||||
parts += "<span class='greentext'><B>[station_name()] was taken over by the monkeys! Ook ook!</B></span>"
|
||||
if(DISEASE_LIVED)
|
||||
parts += "<span class='redtext big'><B>Monkey Minor Defeat!</B></span>"
|
||||
parts += "<span class='redtext'><B>All the monkeys died, but the disease lives on! The future is uncertain.</B></span>"
|
||||
if(MONKEYS_DIED)
|
||||
parts += "<span class='redtext big'><B>Monkey Major Defeat!</B></span>"
|
||||
parts += "<span class='redtext'><B>All the monkeys died, and Jungle Fever was wiped out!</B></span>"
|
||||
if(LAZYLEN(SSticker.mode.ape_leaders))
|
||||
parts += "<span class='header'>The monkey leaders were:</span>"
|
||||
parts += printplayerlist(SSticker.mode.ape_leaders)
|
||||
if(LAZYLEN(SSticker.mode.ape_infectees))
|
||||
parts += "<span class='header'>The monkeys were:</span>"
|
||||
parts += printplayerlist(SSticker.mode.ape_infectees)
|
||||
return "<div class='panel redborder'>[parts.Join("<br>")]</div>"
|
||||
@@ -0,0 +1,40 @@
|
||||
/datum/component/cleaning
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
|
||||
/datum/component/cleaning/Initialize()
|
||||
if(!ismovableatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("[type] added to a [parent.type]")
|
||||
RegisterSignal(list(COMSIG_MOVABLE_MOVED), .proc/Clean)
|
||||
|
||||
/datum/component/cleaning/proc/Clean()
|
||||
var/atom/movable/AM = parent
|
||||
var/turf/tile = AM.loc
|
||||
if(!isturf(tile))
|
||||
return
|
||||
|
||||
tile.clean_blood()
|
||||
for(var/A in tile)
|
||||
if(is_cleanable(A))
|
||||
qdel(A)
|
||||
else if(istype(A, /obj/item))
|
||||
var/obj/item/cleaned_item = A
|
||||
cleaned_item.clean_blood()
|
||||
else if(ishuman(A))
|
||||
var/mob/living/carbon/human/cleaned_human = A
|
||||
if(cleaned_human.lying)
|
||||
if(cleaned_human.head)
|
||||
cleaned_human.head.clean_blood()
|
||||
cleaned_human.update_inv_head()
|
||||
if(cleaned_human.wear_suit)
|
||||
cleaned_human.wear_suit.clean_blood()
|
||||
cleaned_human.update_inv_wear_suit()
|
||||
else if(cleaned_human.w_uniform)
|
||||
cleaned_human.w_uniform.clean_blood()
|
||||
cleaned_human.update_inv_w_uniform()
|
||||
if(cleaned_human.shoes)
|
||||
cleaned_human.shoes.clean_blood()
|
||||
cleaned_human.update_inv_shoes()
|
||||
cleaned_human.clean_blood()
|
||||
cleaned_human.wash_cream()
|
||||
to_chat(cleaned_human, "<span class='danger'>[AM] cleans your face!</span>")
|
||||
@@ -0,0 +1,239 @@
|
||||
//Designed for things that need precision trajectories like projectiles.
|
||||
//Don't use this for anything that you don't absolutely have to use this with (like projectiles!) because it isn't worth using a datum unless you need accuracy down to decimal places in pixels.
|
||||
|
||||
#define RETURN_PRECISE_POSITION(A) new /datum/position(A)
|
||||
#define RETURN_PRECISE_POINT(A) new /datum/point(A)
|
||||
|
||||
/datum/position //For positions with map x/y/z and pixel x/y so you don't have to return lists. Could use addition/subtraction in the future I guess.
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
var/pixel_x = 0
|
||||
var/pixel_y = 0
|
||||
|
||||
/datum/position/proc/valid()
|
||||
return x && y && z && !isnull(pixel_x) && !isnull(pixel_y)
|
||||
|
||||
/datum/position/New(_x = 0, _y = 0, _z = 0, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/point.
|
||||
if(istype(_x, /datum/point))
|
||||
var/datum/point/P = _x
|
||||
var/turf/T = P.return_turf()
|
||||
_x = T.x
|
||||
_y = T.y
|
||||
_z = T.z
|
||||
_pixel_x = P.return_px()
|
||||
_pixel_y = P.return_py()
|
||||
else if(isatom(_x))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
x = _x
|
||||
y = _y
|
||||
z = _z
|
||||
pixel_x = _pixel_x
|
||||
pixel_y = _pixel_y
|
||||
|
||||
/datum/position/proc/return_turf()
|
||||
return locate(x, y, z)
|
||||
|
||||
/datum/position/proc/return_px()
|
||||
return pixel_x
|
||||
|
||||
/datum/position/proc/return_py()
|
||||
return pixel_y
|
||||
|
||||
/datum/position/proc/return_point()
|
||||
return new /datum/point(src)
|
||||
|
||||
/proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below.
|
||||
var/datum/point/P = new
|
||||
P.x = round(a.x + (b.x - a.x) / 2, 1)
|
||||
P.y = round(a.y + (b.y - a.y) / 2, 1)
|
||||
P.z = a.z
|
||||
return P
|
||||
|
||||
/proc/pixel_length_between_points(datum/point/a, datum/point/b)
|
||||
return sqrt(((b.x - a.x) ** 2) + ((b.y - a.y) ** 2))
|
||||
|
||||
/proc/angle_between_points(datum/point/a, datum/point/b)
|
||||
return ATAN2((b.y - a.y), (b.x - a.x))
|
||||
|
||||
/datum/point //A precise point on the map in absolute pixel locations based on world.icon_size. Pixels are FROM THE EDGE OF THE MAP!
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
var/z = 0
|
||||
|
||||
/datum/point/proc/valid()
|
||||
return x && y && z
|
||||
|
||||
/datum/point/proc/copy_to(datum/point/p = new)
|
||||
p.x = x
|
||||
p.y = y
|
||||
p.z = z
|
||||
return p
|
||||
|
||||
/datum/point/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0) //first argument can also be a /datum/position or /atom.
|
||||
if(istype(_x, /datum/position))
|
||||
var/datum/position/P = _x
|
||||
_x = P.x
|
||||
_y = P.y
|
||||
_z = P.z
|
||||
_pixel_x = P.pixel_x
|
||||
_pixel_y = P.pixel_y
|
||||
else if(istype(_x, /atom))
|
||||
var/atom/A = _x
|
||||
_x = A.x
|
||||
_y = A.y
|
||||
_z = A.z
|
||||
_pixel_x = A.pixel_x
|
||||
_pixel_y = A.pixel_y
|
||||
initialize_location(_x, _y, _z, _pixel_x, _pixel_y)
|
||||
|
||||
/datum/point/proc/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
if(!isnull(tile_x))
|
||||
x = ((tile_x - 1) * world.icon_size) + world.icon_size / 2 + p_x
|
||||
if(!isnull(tile_y))
|
||||
y = ((tile_y - 1) * world.icon_size) + world.icon_size / 2+ p_y
|
||||
if(!isnull(tile_z))
|
||||
z = tile_z
|
||||
|
||||
/datum/point/proc/return_turf()
|
||||
return locate(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_coordinates() //[turf_x, turf_y, z]
|
||||
return list(CEILING(x / world.icon_size, 1), CEILING(y / world.icon_size, 1), z)
|
||||
|
||||
/datum/point/proc/return_position()
|
||||
return new /datum/position(src)
|
||||
|
||||
/datum/point/proc/return_px()
|
||||
return MODULUS(x, world.icon_size) - 16
|
||||
|
||||
/datum/point/proc/return_py()
|
||||
return MODULUS(y, world.icon_size) - 16
|
||||
|
||||
/datum/point/proc/mapcheck()
|
||||
. = FALSE
|
||||
var/maxx = world.icon_size * world.maxx
|
||||
var/maxy = world.icon_size * world.maxy
|
||||
var/move_zx = 0
|
||||
var/move_zy = 0
|
||||
if(x < 0)
|
||||
x += maxx
|
||||
move_zx -= 1
|
||||
if(y < 0)
|
||||
y += maxy
|
||||
move_zy -= 1
|
||||
if(x > maxx)
|
||||
x -= maxx
|
||||
move_zx += 1
|
||||
if(y > maxy)
|
||||
y -= maxy
|
||||
move_zy += 1
|
||||
var/datum/space_level/S = GLOB.z_levels_list["[z]"]
|
||||
if(move_zx != 0)
|
||||
var/datum/space_level/L = S.neigbours["[move_zx < 0? WEST : EAST]"]
|
||||
z = L.z_value
|
||||
. = TRUE
|
||||
if(move_zy != 0)
|
||||
var/datum/space_level/L = S.neigbours["[move_zy < 0? SOUTH : NORTH]"]
|
||||
z = L.z_value
|
||||
. = TRUE
|
||||
|
||||
/datum/point/vector
|
||||
var/speed = 32 //pixels per iteration
|
||||
var/iteration = 0
|
||||
var/angle = 0
|
||||
var/mpx = 0 //calculated x/y movement amounts to prevent having to do trig every step.
|
||||
var/mpy = 0
|
||||
var/starting_x = 0 //just like before, pixels from EDGE of map! This is set in initialize_location().
|
||||
var/starting_y = 0
|
||||
var/starting_z = 0
|
||||
|
||||
/datum/point/vector/New(_x, _y, _z, _pixel_x = 0, _pixel_y = 0, _angle, _speed)
|
||||
..()
|
||||
initialize_trajectory(_speed, _angle)
|
||||
|
||||
/datum/point/vector/initialize_location(tile_x, tile_y, tile_z, p_x = 0, p_y = 0)
|
||||
. = ..()
|
||||
starting_x = x
|
||||
starting_y = y
|
||||
starting_z = z
|
||||
|
||||
/datum/point/vector/copy_to(datum/point/vector/v = new)
|
||||
..(v)
|
||||
v.speed = speed
|
||||
v.iteration = iteration
|
||||
v.angle = angle
|
||||
v.mpx = mpx
|
||||
v.mpy = mpy
|
||||
v.starting_x = starting_x
|
||||
v.starting_y = starting_y
|
||||
v.starting_z = starting_z
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/initialize_trajectory(pixel_speed, new_angle)
|
||||
if(!isnull(pixel_speed))
|
||||
speed = pixel_speed
|
||||
set_angle(new_angle)
|
||||
|
||||
/datum/point/vector/proc/set_angle(new_angle) //calculations use "byond angle" where north is 0 instead of 90, and south is 180 instead of 270.
|
||||
if(isnull(angle))
|
||||
return
|
||||
angle = new_angle
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/update_offsets()
|
||||
mpx = sin(angle) * speed
|
||||
mpy = cos(angle) * speed
|
||||
|
||||
/datum/point/vector/proc/set_speed(new_speed)
|
||||
if(isnull(new_speed) || speed == new_speed)
|
||||
return
|
||||
speed = new_speed
|
||||
update_offsets()
|
||||
|
||||
/datum/point/vector/proc/increment(multiplier = 1)
|
||||
iteration++
|
||||
x += mpx * 1
|
||||
y += mpy * 1
|
||||
if(mapcheck())
|
||||
on_z_change()
|
||||
|
||||
/datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE)
|
||||
var/datum/point/vector/v = copy_to()
|
||||
if(force_simulate)
|
||||
for(var/i in 1 to amount)
|
||||
v.increment(multiplier)
|
||||
else
|
||||
v.increment(multiplier * amount)
|
||||
return v
|
||||
|
||||
/datum/point/vector/proc/on_z_change()
|
||||
return
|
||||
|
||||
/datum/point/vector/processed //pixel_speed is per decisecond.
|
||||
var/last_process = 0
|
||||
var/last_move = 0
|
||||
var/paused = FALSE
|
||||
|
||||
/datum/point/vector/processed/Destroy()
|
||||
STOP_PROCESSING(SSprojectiles, src)
|
||||
|
||||
/datum/point/vector/processed/proc/start()
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
START_PROCESSING(SSprojectiles, src)
|
||||
|
||||
/datum/point/vector/processed/process()
|
||||
if(paused)
|
||||
last_move += world.time - last_process
|
||||
last_process = world.time
|
||||
return
|
||||
var/needed_time = world.time - last_move
|
||||
last_process = world.time
|
||||
last_move = world.time
|
||||
increment(needed_time)
|
||||
Reference in New Issue
Block a user