ASYNC EVERYTHING!
This commit is contained in:
+147
-27
@@ -1,12 +1,22 @@
|
||||
/**
|
||||
* The base type for nearly all physical objects in SS13
|
||||
|
||||
* Lots and lots of functionality lives here, although in general we are striving to move
|
||||
* as much as possible to the components/elements system
|
||||
*/
|
||||
/atom
|
||||
layer = TURF_LAYER
|
||||
plane = GAME_PLANE
|
||||
var/level = 2
|
||||
var/article // If non-null, overrides a/an/some in all cases
|
||||
appearance_flags = TILE_BOUND
|
||||
|
||||
var/level = 2
|
||||
///If non-null, overrides a/an/some in all cases
|
||||
var/article
|
||||
|
||||
///First atom flags var
|
||||
var/flags_1 = NONE
|
||||
///Intearaction flags
|
||||
var/interaction_flags_atom = NONE
|
||||
var/datum/reagents/reagents = null
|
||||
|
||||
var/flags_ricochet = NONE
|
||||
|
||||
@@ -15,35 +25,52 @@
|
||||
///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom
|
||||
var/ricochet_damage_mod = 0.33
|
||||
|
||||
//This atom's HUD (med/sec, etc) images. Associative list.
|
||||
///Reagents holder
|
||||
var/datum/reagents/reagents = null
|
||||
|
||||
///This atom's HUD (med/sec, etc) images. Associative list.
|
||||
var/list/image/hud_list = null
|
||||
//HUD images that this atom can provide.
|
||||
///HUD images that this atom can provide.
|
||||
var/list/hud_possible
|
||||
|
||||
//Value used to increment ex_act() if reactionary_explosions is on
|
||||
///Value used to increment ex_act() if reactionary_explosions is on
|
||||
var/explosion_block = 0
|
||||
|
||||
var/list/atom_colours //used to store the different colors on an atom
|
||||
//its inherent color, the colored paint applied on it, special color effect etc...
|
||||
/**
|
||||
* used to store the different colors on an atom
|
||||
*
|
||||
* its inherent color, the colored paint applied on it, special color effect etc...
|
||||
*/
|
||||
var/list/atom_colours
|
||||
|
||||
var/list/remove_overlays // a very temporary list of overlays to remove
|
||||
var/list/add_overlays // a very temporary list of overlays to add
|
||||
|
||||
var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays
|
||||
///overlays managed by update_overlays() to prevent removing overlays that weren't added by the same proc
|
||||
/// a very temporary list of overlays to remove
|
||||
var/list/remove_overlays
|
||||
/// a very temporary list of overlays to add
|
||||
var/list/add_overlays
|
||||
|
||||
///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays
|
||||
var/list/managed_vis_overlays
|
||||
///overlays managed by [update_overlays][/atom/proc/update_overlays] to prevent removing overlays that weren't added by the same proc
|
||||
var/list/managed_overlays
|
||||
|
||||
///Proximity monitor associated with this atom
|
||||
var/datum/proximity_monitor/proximity_monitor
|
||||
///Last fingerprints to touch this atom
|
||||
var/fingerprintslast
|
||||
|
||||
var/list/filter_data //For handling persistent filters
|
||||
|
||||
///Price of an item in a vending machine, overriding the base vending machine price. Define in terms of paycheck defines as opposed to raw numbers.
|
||||
var/custom_price
|
||||
///Price of an item in a vending machine, overriding the premium vending machine price. Define in terms of paycheck defines as opposed to raw numbers.
|
||||
var/custom_premium_price
|
||||
|
||||
//List of datums orbiting this atom
|
||||
var/datum/component/orbiter/orbiters
|
||||
|
||||
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
|
||||
/// Radiation insulation types
|
||||
var/rad_insulation = RAD_NO_INSULATION
|
||||
|
||||
///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.)
|
||||
@@ -72,6 +99,16 @@
|
||||
///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy()
|
||||
var/list/targeted_by
|
||||
|
||||
/**
|
||||
* Called when an atom is created in byond (built in engine proc)
|
||||
*
|
||||
* Not a lot happens here in SS13 code, as we offload most of the work to the
|
||||
* [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader
|
||||
* if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate
|
||||
* result is that the Intialize proc is called.
|
||||
*
|
||||
* We also generate a tag here if the DF_USE_TAG flag is set on the atom
|
||||
*/
|
||||
/atom/New(loc, ...)
|
||||
//atom creation method that preloads variables at creation
|
||||
if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New()
|
||||
@@ -87,24 +124,50 @@
|
||||
//we were deleted
|
||||
return
|
||||
|
||||
//Called after New if the map is being loaded. mapload = TRUE
|
||||
//Called from base of New if the map is not being loaded. mapload = FALSE
|
||||
//This base must be called or derivatives must set initialized to TRUE
|
||||
//must not sleep
|
||||
//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE
|
||||
//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm
|
||||
|
||||
//Note: the following functions don't call the base for optimization and must copypasta:
|
||||
// /turf/Initialize
|
||||
// /turf/open/space/Initialize
|
||||
|
||||
/**
|
||||
* The primary method that objects are setup in SS13 with
|
||||
*
|
||||
* we don't use New as we have better control over when this is called and we can choose
|
||||
* to delay calls or hook other logic in and so forth
|
||||
*
|
||||
* During roundstart map parsing, atoms are queued for intialization in the base atom/New(),
|
||||
* After the map has loaded, then Initalize is called on all atoms one by one. NB: this
|
||||
* is also true for loading map templates as well, so they don't Initalize until all objects
|
||||
* in the map file are parsed and present in the world
|
||||
*
|
||||
* If you're creating an object at any point after SSInit has run then this proc will be
|
||||
* immediately be called from New.
|
||||
*
|
||||
* mapload: This parameter is true if the atom being loaded is either being intialized during
|
||||
* the Atom subsystem intialization, or if the atom is being loaded from the map template.
|
||||
* If the item is being created at runtime any time after the Atom subsystem is intialized then
|
||||
* it's false.
|
||||
*
|
||||
* You must always call the parent of this proc, otherwise failures will occur as the item
|
||||
* will not be seen as initalized (this can lead to all sorts of strange behaviour, like
|
||||
* the item being completely unclickable)
|
||||
*
|
||||
* You must not sleep in this proc, or any subprocs
|
||||
*
|
||||
* Any parameters from new are passed through (excluding loc), naturally if you're loading from a map
|
||||
* there are no other arguments
|
||||
*
|
||||
* Must return an [initialization hint][INITIALIZE_HINT_NORMAL] or a runtime will occur.
|
||||
*
|
||||
* Note: the following functions don't call the base for optimization and must copypasta handling:
|
||||
* * [/turf/proc/Initialize]
|
||||
* * [/turf/open/space/proc/Initialize]
|
||||
*/
|
||||
/atom/proc/Initialize(mapload, ...)
|
||||
// SHOULD_NOT_SLEEP(TRUE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
flags_1 |= INITIALIZED_1
|
||||
|
||||
if(loc)
|
||||
SEND_SIGNAL(loc, COMSIG_ATOM_CREATED, src) /// Sends a signal that the new atom `src`, has been created at `loc`
|
||||
|
||||
//atom color stuff
|
||||
if(color)
|
||||
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
@@ -126,14 +189,34 @@
|
||||
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
|
||||
//called if Initialize returns INITIALIZE_HINT_LATELOAD
|
||||
/**
|
||||
* Late Intialization, for code that should run after all atoms have run Intialization
|
||||
*
|
||||
* To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize]
|
||||
* proc must return the hint
|
||||
* [INITIALIZE_HINT_LATELOAD] otherwise you will never be called.
|
||||
*
|
||||
* useful for doing things like finding other machines on GLOB.machines because you can guarantee
|
||||
* that all atoms will actually exist in the "WORLD" at this time and that all their Intialization
|
||||
* code has been run
|
||||
*/
|
||||
/atom/proc/LateInitialize()
|
||||
return
|
||||
set waitfor = FALSE
|
||||
|
||||
// Put your AddComponent() calls here
|
||||
/// Put your [AddComponent] calls here
|
||||
/atom/proc/ComponentInitialize()
|
||||
return
|
||||
|
||||
/**
|
||||
* Top level of the destroy chain for most atoms
|
||||
*
|
||||
* Cleans up the following:
|
||||
* * Removes alternate apperances from huds that see them
|
||||
* * qdels the reagent holder from atoms if it exists
|
||||
* * clears the orbiters list
|
||||
* * clears overlays and priority overlays
|
||||
* * clears the light object
|
||||
*/
|
||||
/atom/Destroy()
|
||||
if(alternate_appearances)
|
||||
for(var/K in alternate_appearances)
|
||||
@@ -143,6 +226,8 @@
|
||||
if(reagents)
|
||||
qdel(reagents)
|
||||
|
||||
orbiters = null // The component is attached to us normaly and will be deleted elsewhere
|
||||
|
||||
LAZYCLEARLIST(overlays)
|
||||
|
||||
for(var/i in targeted_by)
|
||||
@@ -179,6 +264,16 @@
|
||||
/atom/proc/CanPass(atom/movable/mover, turf/target)
|
||||
return !density
|
||||
|
||||
/**
|
||||
* Is this atom currently located on centcom
|
||||
*
|
||||
* Specifically, is it on the z level and within the centcom areas
|
||||
*
|
||||
* You can also be in a shuttleshuttle during endgame transit
|
||||
*
|
||||
* Used in gamemode to identify mobs who have escaped and for some other areas of the code
|
||||
* who don't want atoms where they shouldn't be
|
||||
*/
|
||||
/atom/proc/onCentCom()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
@@ -209,6 +304,13 @@
|
||||
if(T in shuttle_area)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Is the atom in any of the centcom syndicate areas
|
||||
*
|
||||
* Either in the syndie base on centcom, or any of their shuttles
|
||||
*
|
||||
* Also used in gamemode code for win conditions
|
||||
*/
|
||||
/atom/proc/onSyndieBase()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
@@ -222,6 +324,23 @@
|
||||
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Is the atom in an away mission
|
||||
*
|
||||
* Must be in the away mission z-level to return TRUE
|
||||
*
|
||||
* Also used in gamemode code for win conditions
|
||||
*/
|
||||
/atom/proc/onAwayMission()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!T)
|
||||
return FALSE
|
||||
|
||||
if(is_away_level(T.z))
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user)
|
||||
if(does_attack_animation)
|
||||
@@ -415,7 +534,7 @@
|
||||
|
||||
/// Updates the overlays of the atom
|
||||
/atom/proc/update_overlays()
|
||||
SHOULD_CALL_PARENT(1)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
. = list()
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .)
|
||||
|
||||
@@ -1161,3 +1280,4 @@
|
||||
// first of all make sure we valid
|
||||
var/mouseparams = list2params(paramslist)
|
||||
usr_client.Click(src, loc, null, mouseparams)
|
||||
return TRUE
|
||||
|
||||
+183
-106
@@ -1,5 +1,7 @@
|
||||
/atom/movable
|
||||
layer = OBJ_LAYER
|
||||
glide_size = 8
|
||||
appearance_flags = TILE_BOUND|PIXEL_SCALE
|
||||
var/last_move = null
|
||||
var/last_move_time = 0
|
||||
var/anchored = FALSE
|
||||
@@ -28,8 +30,6 @@
|
||||
var/atom/movable/moving_from_pull //attempt to resume grab after moving instead of before.
|
||||
var/list/client_mobs_in_contents // This contains all the client mobs within this container
|
||||
var/list/acted_explosions //for explosion dodging
|
||||
glide_size = 8
|
||||
appearance_flags = TILE_BOUND|PIXEL_SCALE
|
||||
var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm
|
||||
var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc.
|
||||
var/atom/movable/pulling
|
||||
@@ -59,6 +59,42 @@
|
||||
em_block = new(src, render_target)
|
||||
vis_contents += em_block
|
||||
|
||||
|
||||
/atom/movable/Destroy(force)
|
||||
QDEL_NULL(proximity_monitor)
|
||||
QDEL_NULL(language_holder)
|
||||
QDEL_NULL(em_block)
|
||||
|
||||
unbuckle_all_mobs(force = TRUE)
|
||||
|
||||
if(loc)
|
||||
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
|
||||
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
|
||||
CanAtmosPass = ATMOS_PASS_YES
|
||||
air_update_turf(TRUE)
|
||||
loc.handle_atom_del(src)
|
||||
|
||||
// if(opacity)
|
||||
// RemoveElement(/datum/element/light_blocking)
|
||||
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
|
||||
if(orbiting)
|
||||
orbiting.end_orbit(src)
|
||||
orbiting = null
|
||||
|
||||
. = ..()
|
||||
|
||||
for(var/movable_content in contents)
|
||||
qdel(movable_content)
|
||||
|
||||
LAZYCLEARLIST(client_mobs_in_contents)
|
||||
|
||||
moveToNullspace()
|
||||
|
||||
/atom/movable/proc/update_emissive_block()
|
||||
if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
|
||||
return
|
||||
@@ -114,12 +150,13 @@
|
||||
return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T)
|
||||
|
||||
/atom/movable/vv_edit_var(var_name, var_value)
|
||||
var/static/list/banned_edits = list("step_x", "step_y", "step_size")
|
||||
var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height")
|
||||
if(var_name in banned_edits)
|
||||
var/static/list/banned_edits = list("step_x" = TRUE, "step_y" = TRUE, "step_size" = TRUE, "bounds" = TRUE)
|
||||
var/static/list/careful_edits = list("bound_x" = TRUE, "bound_y" = TRUE, "bound_width" = TRUE, "bound_height" = TRUE)
|
||||
if(banned_edits[var_name])
|
||||
return FALSE //PLEASE no.
|
||||
if((var_name in careful_edits) && (var_value % world.icon_size) != 0)
|
||||
if((careful_edits[var_name]) && (var_value % world.icon_size) != 0)
|
||||
return FALSE
|
||||
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, x))
|
||||
var/turf/T = locate(var_value, y, z)
|
||||
@@ -140,13 +177,24 @@
|
||||
return TRUE
|
||||
return FALSE
|
||||
if(NAMEOF(src, loc))
|
||||
if(istype(var_value, /atom))
|
||||
if(isatom(var_value) || isnull(var_value))
|
||||
forceMove(var_value)
|
||||
return TRUE
|
||||
else if(isnull(var_value))
|
||||
moveToNullspace()
|
||||
return TRUE
|
||||
return FALSE
|
||||
if(NAMEOF(src, anchored))
|
||||
set_anchored(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, pulledby))
|
||||
set_pulledby(var_value)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, glide_size))
|
||||
set_glide_size(var_value)
|
||||
. = TRUE
|
||||
|
||||
if(!isnull(.))
|
||||
datum_flags |= DF_VAR_EDITED
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
|
||||
@@ -168,48 +216,68 @@
|
||||
AMob.grabbedby(src)
|
||||
return TRUE
|
||||
stop_pulling()
|
||||
|
||||
// SEND_SIGNAL(src, COMSIG_ATOM_START_PULL, AM, state, force)
|
||||
|
||||
if(AM.pulledby)
|
||||
log_combat(AM, AM.pulledby, "pulled from", src)
|
||||
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
|
||||
pulling = AM
|
||||
AM.pulledby = src
|
||||
AM.set_pulledby(src)
|
||||
setGrabState(state)
|
||||
if(ismob(AM))
|
||||
var/mob/M = AM
|
||||
log_combat(src, M, "grabbed", addition="passive grab")
|
||||
if(!supress_message)
|
||||
visible_message("<span class='warning'>[src] has grabbed [M] passively!</span>")
|
||||
M.visible_message("<span class='warning'>[src] grabs [M] passively.</span>", \
|
||||
"<span class='danger'>[src] grabs you passively.</span>")
|
||||
return TRUE
|
||||
|
||||
/atom/movable/proc/stop_pulling()
|
||||
if(!pulling)
|
||||
return
|
||||
pulling.pulledby = null
|
||||
pulling.set_pulledby(null)
|
||||
var/mob/living/ex_pulled = pulling
|
||||
setGrabState(GRAB_PASSIVE)
|
||||
pulling = null
|
||||
setGrabState(0)
|
||||
if(isliving(ex_pulled))
|
||||
var/mob/living/L = ex_pulled
|
||||
L.update_mobility()// mob gets up if it was lyng down in a chokehold
|
||||
|
||||
///Reports the event of the change in value of the pulledby variable.
|
||||
/atom/movable/proc/set_pulledby(new_pulledby)
|
||||
if(new_pulledby == pulledby)
|
||||
return FALSE //null signals there was a change, be sure to return FALSE if none happened here.
|
||||
. = pulledby
|
||||
pulledby = new_pulledby
|
||||
|
||||
|
||||
/atom/movable/proc/Move_Pulled(atom/A)
|
||||
if(!pulling)
|
||||
return
|
||||
return FALSE
|
||||
if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src))
|
||||
stop_pulling()
|
||||
return
|
||||
return FALSE
|
||||
if(isliving(pulling))
|
||||
var/mob/living/L = pulling
|
||||
if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it
|
||||
stop_pulling()
|
||||
return
|
||||
return FALSE
|
||||
if(A == loc && pulling.density)
|
||||
return
|
||||
if(!Process_Spacemove(get_dir(pulling.loc, A)))
|
||||
return
|
||||
step(pulling, get_dir(pulling.loc, A))
|
||||
return FALSE
|
||||
var/move_dir = get_dir(pulling.loc, A)
|
||||
if(!Process_Spacemove(move_dir))
|
||||
return FALSE
|
||||
pulling.Move(get_step(pulling.loc, move_dir), move_dir, glide_size)
|
||||
return TRUE
|
||||
|
||||
/mob/living/Move_Pulled(atom/A)
|
||||
. = ..()
|
||||
if(!. || !isliving(A))
|
||||
return
|
||||
var/mob/living/L = A
|
||||
set_pull_offsets(L, grab_state)
|
||||
|
||||
/atom/movable/proc/check_pulling()
|
||||
if(pulling)
|
||||
var/atom/movable/pullee = pulling
|
||||
@@ -229,54 +297,51 @@
|
||||
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
|
||||
pulledby.stop_pulling()
|
||||
|
||||
/atom/movable/Destroy(force)
|
||||
QDEL_NULL(proximity_monitor)
|
||||
QDEL_NULL(language_holder)
|
||||
QDEL_NULL(em_block)
|
||||
|
||||
unbuckle_all_mobs(force=1)
|
||||
/atom/movable/proc/set_glide_size(target = 8)
|
||||
// SEND_SIGNAL(src, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, target)
|
||||
glide_size = target
|
||||
|
||||
. = ..()
|
||||
for(var/m in buckled_mobs)
|
||||
var/mob/buckled_mob = m
|
||||
buckled_mob.set_glide_size(target)
|
||||
|
||||
if(loc)
|
||||
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
|
||||
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
|
||||
CanAtmosPass = ATMOS_PASS_YES
|
||||
air_update_turf(TRUE)
|
||||
loc.handle_atom_del(src)
|
||||
for(var/atom/movable/AM in contents)
|
||||
qdel(AM)
|
||||
moveToNullspace()
|
||||
invisibility = INVISIBILITY_ABSTRACT
|
||||
if(pulledby)
|
||||
pulledby.stop_pulling()
|
||||
|
||||
if(orbiting)
|
||||
orbiting.end_orbit(src)
|
||||
orbiting = null
|
||||
///Sets the anchored var and returns if it was sucessfully changed or not.
|
||||
/atom/movable/proc/set_anchored(anchorvalue)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(anchored == anchorvalue)
|
||||
return
|
||||
. = anchored
|
||||
anchored = anchorvalue
|
||||
// SEND_SIGNAL(src, COMSIG_MOVABLE_SET_ANCHORED, anchorvalue)
|
||||
|
||||
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
set waitfor = 0
|
||||
set waitfor = FALSE
|
||||
var/hitpush = TRUE
|
||||
var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
|
||||
if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH)
|
||||
hitpush = FALSE // hacky, tie this to something else or a proper workaround later
|
||||
|
||||
if(impact_signal & ~COMPONENT_MOVABLE_IMPACT_NEVERMIND) // in case a signal interceptor broke or deleted the thing before we could process our hit
|
||||
return hit_atom.hitby(src, throwingdatum = throwingdatum, hitpush = hitpush)
|
||||
if(!(impact_signal && (impact_signal & COMPONENT_MOVABLE_IMPACT_NEVERMIND))) // in case a signal interceptor broke or deleted the thing before we could process our hit
|
||||
return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush)
|
||||
|
||||
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum)
|
||||
if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO))))
|
||||
step(src, AM.dir)
|
||||
..()
|
||||
|
||||
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE)
|
||||
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
|
||||
if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY))
|
||||
return
|
||||
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, messy_throw)
|
||||
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, gentle)
|
||||
|
||||
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE) //If this returns FALSE then callback will not be called.
|
||||
///If this returns FALSE then callback will not be called.
|
||||
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE, quickstart = TRUE)
|
||||
. = FALSE
|
||||
|
||||
if(QDELETED(src))
|
||||
CRASH("Qdeleted thing being thrown around.")
|
||||
|
||||
if (!target || speed <= 0)
|
||||
return
|
||||
|
||||
@@ -288,7 +353,7 @@
|
||||
|
||||
//They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw?
|
||||
if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2)
|
||||
var/user_momentum = thrower.movement_delay()
|
||||
var/user_momentum = thrower.movement_delay() //cached_multiplicative_slowdown
|
||||
if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead.
|
||||
user_momentum = world.tick_lag
|
||||
|
||||
@@ -312,19 +377,13 @@
|
||||
|
||||
. = TRUE // No failure conditions past this point.
|
||||
|
||||
var/datum/thrownthing/TT = new()
|
||||
TT.thrownthing = src
|
||||
TT.target = target
|
||||
TT.target_turf = get_turf(target)
|
||||
TT.init_dir = get_dir(src, target)
|
||||
TT.maxrange = range
|
||||
TT.speed = speed
|
||||
TT.thrower = thrower
|
||||
TT.diagonals_first = diagonals_first
|
||||
TT.force = force
|
||||
TT.callback = callback
|
||||
if(!QDELETED(thrower))
|
||||
TT.target_zone = thrower.zone_selected
|
||||
var/target_zone
|
||||
if(QDELETED(thrower))
|
||||
thrower = null //Let's not pass a qdeleting reference if any.
|
||||
else
|
||||
target_zone = thrower.zone_selected
|
||||
|
||||
var/datum/thrownthing/TT = new(src, target, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
|
||||
|
||||
var/dist_x = abs(target.x - src.x)
|
||||
var/dist_y = abs(target.y - src.y)
|
||||
@@ -359,7 +418,8 @@
|
||||
SSthrowing.processing[src] = TT
|
||||
if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun))
|
||||
SSthrowing.currentrun[src] = TT
|
||||
TT.tick()
|
||||
if (quickstart)
|
||||
TT.tick()
|
||||
|
||||
/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
|
||||
return FALSE
|
||||
@@ -382,13 +442,13 @@
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
|
||||
/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S)
|
||||
return
|
||||
/// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
|
||||
/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) // rename S to master_storage
|
||||
// SEND_SIGNAL(src, COMSIG_STORAGE_EXITED, master_storage)
|
||||
|
||||
// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
|
||||
/// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
|
||||
/atom/movable/proc/on_enter_storage(datum/component/storage/concrete/S)
|
||||
return
|
||||
// SEND_SIGNAL(src, COMSIG_STORAGE_ENTERED, master_storage)
|
||||
|
||||
/atom/movable/proc/get_spacemove_backup()
|
||||
var/atom/movable/dense_object_backup
|
||||
@@ -422,24 +482,26 @@
|
||||
return //don't do an animation if attacking self
|
||||
var/pixel_x_diff = 0
|
||||
var/pixel_y_diff = 0
|
||||
var/turn_dir = 1
|
||||
|
||||
var/direction = get_dir(src, A)
|
||||
if(direction & NORTH)
|
||||
pixel_y_diff = 8
|
||||
turn_dir = prob(50) ? -1 : 1
|
||||
else if(direction & SOUTH)
|
||||
pixel_y_diff = -8
|
||||
turn_dir = prob(50) ? -1 : 1
|
||||
|
||||
if(direction & EAST)
|
||||
pixel_x_diff = 8
|
||||
else if(direction & WEST)
|
||||
pixel_x_diff = -8
|
||||
turn_dir = -1
|
||||
|
||||
var/matrix/OM = matrix(transform)
|
||||
var/matrix/M = matrix(transform)
|
||||
M.Turn(pixel_x_diff ? pixel_x_diff*2 : pick(-16, 16))
|
||||
|
||||
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = M, time = 2)
|
||||
animate(src, pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform = OM, time = 2)
|
||||
var/matrix/initial_transform = matrix(transform)
|
||||
var/matrix/rotated_transform = transform.Turn(15 * turn_dir)
|
||||
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN)
|
||||
animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING)
|
||||
|
||||
/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item)
|
||||
var/image/I
|
||||
@@ -450,21 +512,21 @@
|
||||
I.plane = GAME_PLANE
|
||||
|
||||
// Scale the icon.
|
||||
I.transform *= 0.75
|
||||
I.transform *= 0.4
|
||||
// The icon should not rotate.
|
||||
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
|
||||
|
||||
// Set the direction of the icon animation.
|
||||
var/direction = get_dir(src, A)
|
||||
if(direction & NORTH)
|
||||
I.pixel_y = -16
|
||||
I.pixel_y = -12
|
||||
else if(direction & SOUTH)
|
||||
I.pixel_y = 16
|
||||
I.pixel_y = 12
|
||||
|
||||
if(direction & EAST)
|
||||
I.pixel_x = -16
|
||||
I.pixel_x = -14
|
||||
else if(direction & WEST)
|
||||
I.pixel_x = 16
|
||||
I.pixel_x = 14
|
||||
|
||||
if(!direction) // Attacked self?!
|
||||
I.pixel_z = 16
|
||||
@@ -472,10 +534,12 @@
|
||||
if(!I)
|
||||
return
|
||||
|
||||
flick_overlay(I, GLOB.clients, 5) // 5 ticks/half a second
|
||||
flick_overlay(I, GLOB.clients, 10)
|
||||
|
||||
// And animate the attack!
|
||||
animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
|
||||
animate(I, alpha = 175, transform = matrix() * 0.75, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
|
||||
animate(time = 1)
|
||||
animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT)
|
||||
|
||||
/atom/movable/vv_get_dropdown()
|
||||
. = ..()
|
||||
@@ -495,16 +559,14 @@
|
||||
/atom/movable/proc/float(on)
|
||||
if(throwing)
|
||||
return
|
||||
if(on && (!(movement_type & FLOATING) || floating_need_update))
|
||||
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
|
||||
sleep(10)
|
||||
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
|
||||
if(!(movement_type & FLOATING))
|
||||
setMovetype(movement_type | FLOATING)
|
||||
else if (!on && movement_type & FLOATING)
|
||||
if(on && !(movement_type & FLOATING))
|
||||
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
|
||||
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
|
||||
setMovetype(movement_type | FLOATING)
|
||||
else if (!on && (movement_type & FLOATING))
|
||||
animate(src, pixel_y = initial(pixel_y), time = 10)
|
||||
setMovetype(movement_type & ~FLOATING)
|
||||
floating_need_update = FALSE
|
||||
floating_need_update = FALSE // assume it's done
|
||||
|
||||
/* Language procs
|
||||
* Unless you are doing something very specific, these are the ones you want to use.
|
||||
@@ -611,10 +673,32 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/// Updates the grab state of the movable
|
||||
/// This exists to act as a hook for behaviour
|
||||
/**
|
||||
* Updates the grab state of the movable
|
||||
*
|
||||
* This exists to act as a hook for behaviour
|
||||
*/
|
||||
/atom/movable/proc/setGrabState(newstate)
|
||||
if(newstate == grab_state)
|
||||
return
|
||||
// SEND_SIGNAL(src, COMSIG_MOVABLE_SET_GRAB_STATE, newstate)
|
||||
. = grab_state
|
||||
grab_state = newstate
|
||||
// switch(grab_state) // Current state.
|
||||
// if(GRAB_PASSIVE)
|
||||
// REMOVE_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
|
||||
// REMOVE_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
|
||||
// if(. >= GRAB_NECK) // Previous state was a a neck-grab or higher.
|
||||
// REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
|
||||
// if(GRAB_AGGRESSIVE)
|
||||
// if(. >= GRAB_NECK) // Grab got downgraded.
|
||||
// REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
|
||||
// else // Grab got upgraded from a passive one.
|
||||
// ADD_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
|
||||
// ADD_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
|
||||
// if(GRAB_NECK, GRAB_KILL)
|
||||
// if(. <= GRAB_AGGRESSIVE)
|
||||
// ADD_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
|
||||
|
||||
/obj/item/proc/do_pickup_animation(atom/target)
|
||||
set waitfor = FALSE
|
||||
@@ -626,31 +710,24 @@
|
||||
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
|
||||
var/turf/T = get_turf(src)
|
||||
var/direction
|
||||
var/to_x = 0
|
||||
var/to_y = 0
|
||||
var/to_x = initial(target.pixel_x)
|
||||
var/to_y = initial(target.pixel_y)
|
||||
|
||||
if(!QDELETED(T) && !QDELETED(target))
|
||||
direction = get_dir(T, target)
|
||||
if(direction & NORTH)
|
||||
to_y = 32
|
||||
to_y += 32
|
||||
else if(direction & SOUTH)
|
||||
to_y = -32
|
||||
to_y -= 32
|
||||
if(direction & EAST)
|
||||
to_x = 32
|
||||
to_x += 32
|
||||
else if(direction & WEST)
|
||||
to_x = -32
|
||||
to_x -= 32
|
||||
if(!direction)
|
||||
to_y = 16
|
||||
to_y += 16
|
||||
flick_overlay(I, GLOB.clients, 6)
|
||||
var/matrix/M = new
|
||||
M.Turn(pick(-30, 30))
|
||||
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
|
||||
sleep(1)
|
||||
animate(I, alpha = 0, transform = matrix(), time = 1)
|
||||
|
||||
/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
if(anchored == anchorvalue)
|
||||
return
|
||||
. = anchored
|
||||
anchored = anchorvalue
|
||||
|
||||
+61
-40
@@ -5,8 +5,7 @@
|
||||
// Here's where we rewrite how byond handles movement except slightly different
|
||||
// To be removed on step_ conversion
|
||||
// All this work to prevent a second bump
|
||||
/atom/movable/Move(atom/newloc, direct=0)
|
||||
set waitfor = FALSE //n o
|
||||
/atom/movable/Move(atom/newloc, direct=0, glide_size_override = 0)
|
||||
. = FALSE
|
||||
if(!newloc || newloc == loc)
|
||||
return
|
||||
@@ -52,8 +51,7 @@
|
||||
//
|
||||
////////////////////////////////////////
|
||||
|
||||
/atom/movable/Move(atom/newloc, direct)
|
||||
set waitfor = FALSE //n o
|
||||
/atom/movable/Move(atom/newloc, direct, glide_size_override = 0)
|
||||
var/atom/movable/pullee = pulling
|
||||
var/turf/T = loc
|
||||
if(!moving_from_pull)
|
||||
@@ -61,6 +59,9 @@
|
||||
if(!loc || !newloc)
|
||||
return FALSE
|
||||
var/atom/oldloc = loc
|
||||
//Early override for some cases like diagonal movement
|
||||
if(glide_size_override)
|
||||
set_glide_size(glide_size_override)
|
||||
|
||||
if(loc != newloc)
|
||||
if (!(direct & (direct - 1))) //Cardinal move
|
||||
@@ -120,32 +121,38 @@
|
||||
return
|
||||
|
||||
if(!loc || (loc == oldloc && oldloc != newloc))
|
||||
last_move = NONE
|
||||
last_move = 0
|
||||
return
|
||||
|
||||
if(.)
|
||||
last_move = direct
|
||||
setDir(direct)
|
||||
|
||||
if(has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s)
|
||||
return FALSE
|
||||
|
||||
if(pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move.
|
||||
if(pulling.anchored)
|
||||
stop_pulling()
|
||||
else
|
||||
var/pull_dir = get_dir(src, pulling)
|
||||
//puller and pullee more than one tile away or in diagonal position
|
||||
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
|
||||
pulling.moving_from_pull = src
|
||||
pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position
|
||||
pulling.moving_from_pull = null
|
||||
Moved(oldloc, direct)
|
||||
if(. && pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move.
|
||||
if(pulling.anchored)
|
||||
stop_pulling()
|
||||
else
|
||||
var/pull_dir = get_dir(src, pulling)
|
||||
//puller and pullee more than one tile away or in diagonal position
|
||||
if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir)))
|
||||
pulling.moving_from_pull = src
|
||||
pulling.Move(T, get_dir(pulling, T), glide_size) //the pullee tries to reach our previous position
|
||||
pulling.moving_from_pull = null
|
||||
check_pulling()
|
||||
|
||||
/atom/movable/proc/handle_buckled_mob_movement(newloc,direct)
|
||||
|
||||
//glide_size strangely enough can change mid movement animation and update correctly while the animation is playing
|
||||
//This means that if you don't override it late like this, it will just be set back by the movement update that's called when you move turfs.
|
||||
if(glide_size_override)
|
||||
set_glide_size(glide_size_override)
|
||||
|
||||
last_move = direct
|
||||
setDir(direct)
|
||||
if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, glide_size_override)) //movement failed due to buckled mob(s)
|
||||
return FALSE
|
||||
|
||||
/atom/movable/proc/handle_buckled_mob_movement(newloc, direct, glide_size_override)
|
||||
for(var/m in buckled_mobs)
|
||||
var/mob/living/buckled_mob = m
|
||||
if(!buckled_mob.Move(newloc, direct))
|
||||
if(!buckled_mob.Move(newloc, direct, glide_size_override))
|
||||
forceMove(buckled_mob.loc)
|
||||
last_move = buckled_mob.last_move
|
||||
inertia_dir = last_move
|
||||
@@ -155,6 +162,7 @@
|
||||
|
||||
//Called after a successful Move(). By this point, we've already moved
|
||||
/atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced)
|
||||
if (!inertia_moving)
|
||||
inertia_next_move = world.time + inertia_move_delay
|
||||
@@ -174,6 +182,8 @@
|
||||
|
||||
//oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called!
|
||||
/atom/movable/Crossed(atom/movable/AM, oldloc)
|
||||
// SHOULD_CALL_PARENT(TRUE)
|
||||
. = ..()
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM)
|
||||
|
||||
/atom/movable/Uncross(atom/movable/AM, atom/newloc)
|
||||
@@ -204,7 +214,11 @@
|
||||
var/atom/movable/AM = item
|
||||
AM.onTransitZ(old_z,new_z)
|
||||
|
||||
///Proc to modify the movement_type and hook behavior associated with it changing.
|
||||
/atom/movable/proc/setMovetype(newval)
|
||||
if(movement_type == newval)
|
||||
return
|
||||
. = movement_type
|
||||
movement_type = newval
|
||||
|
||||
///////////// FORCED MOVEMENT /////////////
|
||||
@@ -268,37 +282,44 @@
|
||||
old_area.Exited(src, null)
|
||||
loc = null
|
||||
|
||||
//Called whenever an object moves and by mobs when they attempt to move themselves through space
|
||||
//And when an object or action applies a force on src, see newtonian_move() below
|
||||
//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
|
||||
//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm
|
||||
//movement_dir == 0 when stopping or any dir when trying to move
|
||||
/**
|
||||
* Called whenever an object moves and by mobs when they attempt to move themselves through space
|
||||
* And when an object or action applies a force on src, see [newtonian_move][/atom/movable/proc/newtonian_move]
|
||||
*
|
||||
* Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting
|
||||
*
|
||||
* Mobs should return 1 if they should be able to move of their own volition, see [/client/proc/Move]
|
||||
*
|
||||
* Arguments:
|
||||
* * movement_dir - 0 when stopping or any dir when trying to move
|
||||
*/
|
||||
/atom/movable/proc/Process_Spacemove(movement_dir = 0)
|
||||
if(has_gravity(src))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(pulledby)
|
||||
return 1
|
||||
if(pulledby && (pulledby.pulledby != src || moving_from_pull))
|
||||
return TRUE
|
||||
|
||||
if(throwing)
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(!isturf(loc))
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity
|
||||
if(!loc || Process_Spacemove(0))
|
||||
/// Only moves the object if it's under no gravity
|
||||
/atom/movable/proc/newtonian_move(direction)
|
||||
if(!isturf(loc) || Process_Spacemove(0))
|
||||
inertia_dir = 0
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
inertia_dir = direction
|
||||
if(!direction)
|
||||
return 1
|
||||
return TRUE
|
||||
inertia_last_loc = loc
|
||||
SSspacedrift.processing[src] = src
|
||||
return 1
|
||||
return TRUE
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
. = ..()
|
||||
SSradio.remove_object(src, air_frequency)
|
||||
air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM)
|
||||
open()
|
||||
INVOKE_ASYNC(src, .proc/open)
|
||||
|
||||
/obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal)
|
||||
..()
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#define SPIN_TIME 65 //As always, deciseconds.
|
||||
#define REEL_DEACTIVATE_DELAY 7
|
||||
#define SEVEN "<font color='red'>7</font>"
|
||||
#define HOLOCHIP 1
|
||||
#define COIN 2
|
||||
|
||||
/obj/machinery/computer/slot_machine
|
||||
name = "slot machine"
|
||||
@@ -21,40 +23,48 @@
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 50
|
||||
circuit = /obj/item/circuitboard/computer/slot_machine
|
||||
light_color = LIGHT_COLOR_BROWN
|
||||
var/money = 3000 //How much money it has CONSUMED
|
||||
var/plays = 0
|
||||
var/working = 0
|
||||
var/working = FALSE
|
||||
var/balance = 0 //How much money is in the machine, ready to be CONSUMED.
|
||||
var/jackpots = 0
|
||||
var/paymode = HOLOCHIP //toggles between HOLOCHIP/COIN, defined above
|
||||
var/cointype = /obj/item/coin/iron //default cointype
|
||||
var/list/coinvalues = list()
|
||||
var/list/reels = list(list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0)
|
||||
var/list/symbols = list(SEVEN = 1, "<font color='orange'>&</font>" = 2, "<font color='yellow'>@</font>" = 2, "<font color='green'>$</font>" = 2, "<font color='blue'>?</font>" = 2, "<font color='grey'>#</font>" = 2, "<font color='white'>!</font>" = 2, "<font color='fuchsia'>%</font>" = 2) //if people are winning too much, multiply every number in this list by 2 and see if they are still winning too much.
|
||||
|
||||
light_color = LIGHT_COLOR_BROWN
|
||||
|
||||
/obj/machinery/computer/slot_machine/Initialize()
|
||||
. = ..()
|
||||
jackpots = rand(1, 4) //false hope
|
||||
plays = rand(75, 200)
|
||||
|
||||
toggle_reel_spin(1) //The reels won't spin unless we activate them
|
||||
INVOKE_ASYNC(src, .proc/toggle_reel_spin, TRUE)//The reels won't spin unless we activate them
|
||||
|
||||
var/list/reel = reels[1]
|
||||
for(var/i = 0, i < reel.len, i++) //Populate the reels.
|
||||
randomize_reels()
|
||||
|
||||
toggle_reel_spin(0)
|
||||
INVOKE_ASYNC(src, .proc/toggle_reel_spin, FALSE)
|
||||
|
||||
for(cointype in typesof(/obj/item/coin))
|
||||
var/obj/item/coin/C = new cointype
|
||||
coinvalues["[cointype]"] = C.get_item_credit_value()
|
||||
qdel(C) //Sigh
|
||||
|
||||
/obj/machinery/computer/slot_machine/Destroy()
|
||||
if(balance)
|
||||
give_coins(balance)
|
||||
give_payout(balance)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/slot_machine/process()
|
||||
/obj/machinery/computer/slot_machine/process(delta_time)
|
||||
. = ..() //Sanity checks.
|
||||
if(!.)
|
||||
return .
|
||||
|
||||
money++ //SPESSH MAJICKS
|
||||
money += round(delta_time / 2) //SPESSH MAJICKS
|
||||
|
||||
/obj/machinery/computer/slot_machine/update_icon_state()
|
||||
if(stat & NOPOWER)
|
||||
@@ -69,27 +79,46 @@
|
||||
else
|
||||
icon_state = "slots1"
|
||||
|
||||
/obj/machinery/computer/slot_machine/power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/slot_machine/attackby(obj/item/I, mob/living/user, params)
|
||||
if(istype(I, /obj/item/coin))
|
||||
var/obj/item/coin/C = I
|
||||
if(prob(2))
|
||||
if(!user.transferItemToLoc(C, drop_location()))
|
||||
return
|
||||
C.throw_at(user, 3, 10)
|
||||
if(prob(10))
|
||||
balance = max(balance - SPIN_PRICE, 0)
|
||||
to_chat(user, "<span class='warning'>[src] spits your coin back out!</span>")
|
||||
if(paymode == COIN)
|
||||
if(prob(2))
|
||||
if(!user.transferItemToLoc(C, drop_location()))
|
||||
return
|
||||
C.throw_at(user, 3, 10)
|
||||
if(prob(10))
|
||||
balance = max(balance - SPIN_PRICE, 0)
|
||||
to_chat(user, "<span class='warning'>[src] spits your coin back out!</span>")
|
||||
|
||||
else
|
||||
if(!user.temporarilyRemoveItemFromInventory(C))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You insert [C] into [src]'s slot!</span>")
|
||||
balance += C.value
|
||||
qdel(C)
|
||||
else
|
||||
if(!user.temporarilyRemoveItemFromInventory(C))
|
||||
to_chat(user, "<span class='warning'>This machine is only accepting holochips!</span>")
|
||||
else if(istype(I, /obj/item/holochip))
|
||||
if(paymode == HOLOCHIP)
|
||||
var/obj/item/holochip/H = I
|
||||
if(!user.temporarilyRemoveItemFromInventory(H))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You insert [C] into [src]'s slot!</span>")
|
||||
balance += C.value
|
||||
qdel(C)
|
||||
to_chat(user, "<span class='notice'>You insert [H.credits] holocredits into [src]'s slot!</span>")
|
||||
balance += H.credits
|
||||
qdel(H)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>This machine is only accepting coins!</span>")
|
||||
else if(I.tool_behaviour == TOOL_MULTITOOL)
|
||||
if(balance > 0)
|
||||
visible_message("<b>[src]</b> says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa
|
||||
else
|
||||
if(paymode == HOLOCHIP)
|
||||
paymode = COIN
|
||||
visible_message("<b>[src]</b> says, 'This machine now works with COINS!'")
|
||||
else
|
||||
paymode = HOLOCHIP
|
||||
visible_message("<b>[src]</b> says, 'This machine now works with HOLOCHIPS!'")
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -101,8 +130,7 @@
|
||||
var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(4, 0, src.loc)
|
||||
spark_system.start()
|
||||
playsound(src, "sparks", 50, 1)
|
||||
return TRUE
|
||||
playsound(src, "sparks", 50, TRUE)
|
||||
|
||||
/obj/machinery/computer/slot_machine/ui_interact(mob/living/user)
|
||||
. = ..()
|
||||
@@ -127,8 +155,9 @@
|
||||
<A href='?src=[REF(src)];spin=1'>Play!</A><BR>
|
||||
<BR>
|
||||
[reeltext]
|
||||
<BR>
|
||||
<font size='1'><A href='?src=[REF(src)];refund=1'>Refund balance</A><BR>"}
|
||||
<BR>"}
|
||||
if(balance > 0)
|
||||
dat+="<font size='1'><A href='?src=[REF(src)];refund=1'>Refund balance</A><BR>"
|
||||
|
||||
var/datum/browser/popup = new(user, "slotmachine", "Slot Machine")
|
||||
popup.set_content(dat)
|
||||
@@ -143,21 +172,22 @@
|
||||
spin(usr)
|
||||
|
||||
else if(href_list["refund"])
|
||||
give_coins(balance)
|
||||
balance = 0
|
||||
if(balance > 0)
|
||||
give_payout(balance)
|
||||
balance = 0
|
||||
|
||||
/obj/machinery/computer/slot_machine/emp_act(severity)
|
||||
. = ..()
|
||||
if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF)
|
||||
return
|
||||
if(prob(1500 / severity))
|
||||
if(prob(15 * severity))
|
||||
return
|
||||
if(prob(1 * severity/100)) // :^)
|
||||
if(prob(1)) // :^)
|
||||
obj_flags |= EMAGGED
|
||||
var/severity_ascending = 4 - severity
|
||||
money = max(rand(money - (200 * severity_ascending), money + (200 * severity_ascending)), 0)
|
||||
balance = max(rand(balance - (50 * severity_ascending), balance + (50 * severity_ascending)), 0)
|
||||
money -= max(0, give_coins(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo
|
||||
money -= max(0, give_payout(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo
|
||||
spin()
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/spin(mob/user)
|
||||
@@ -174,37 +204,43 @@
|
||||
balance -= SPIN_PRICE
|
||||
money += SPIN_PRICE
|
||||
plays += 1
|
||||
working = 1
|
||||
working = TRUE
|
||||
|
||||
toggle_reel_spin(1)
|
||||
update_icon()
|
||||
updateDialog()
|
||||
|
||||
spawn(0)
|
||||
while(working)
|
||||
randomize_reels()
|
||||
updateDialog()
|
||||
sleep(2)
|
||||
var/spin_loop = addtimer(CALLBACK(src, .proc/do_spin), 2, TIMER_LOOP|TIMER_STOPPABLE)
|
||||
|
||||
spawn(SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len)) //WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code.
|
||||
toggle_reel_spin(0, REEL_DEACTIVATE_DELAY)
|
||||
working = 0
|
||||
give_prizes(the_name, user)
|
||||
update_icon()
|
||||
updateDialog()
|
||||
addtimer(CALLBACK(src, .proc/finish_spinning, spin_loop, user, the_name), SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len))
|
||||
//WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code.
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/do_spin()
|
||||
randomize_reels()
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/finish_spinning(spin_loop, mob/user, the_name)
|
||||
toggle_reel_spin(0, REEL_DEACTIVATE_DELAY)
|
||||
working = FALSE
|
||||
deltimer(spin_loop)
|
||||
give_prizes(the_name, user)
|
||||
update_icon()
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/can_spin(mob/user)
|
||||
if(stat & NOPOWER)
|
||||
to_chat(user, "<span class='warning'>The slot machine has no power!</span>")
|
||||
return FALSE
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='warning'>The slot machine is broken!</span>")
|
||||
return FALSE
|
||||
if(working)
|
||||
to_chat(user, "<span class='warning'>You need to wait until the machine stops spinning before you can play again!</span>")
|
||||
return 0
|
||||
return FALSE
|
||||
if(balance < SPIN_PRICE)
|
||||
to_chat(user, "<span class='warning'>Insufficient money to play!</span>")
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/toggle_reel_spin(value, delay = 0) //value is 1 or 0 aka on or off
|
||||
for(var/list/reel in reels)
|
||||
@@ -223,23 +259,25 @@
|
||||
var/linelength = get_lines()
|
||||
|
||||
if(reels[1][2] + reels[2][2] + reels[3][2] + reels[4][2] + reels[5][2] == "[SEVEN][SEVEN][SEVEN][SEVEN][SEVEN]")
|
||||
visible_message("<b>[src]</b> says, 'JACKPOT! You win [money] credits worth of coins!'")
|
||||
visible_message("<b>[src]</b> says, 'JACKPOT! You win [money] credits!'")
|
||||
priority_announce("Congratulations to [user ? user.real_name : usrname] for winning the jackpot at the slot machine in [get_area(src)]!")
|
||||
jackpots += 1
|
||||
balance += money - give_coins(JACKPOT)
|
||||
balance += money - give_payout(JACKPOT)
|
||||
money = 0
|
||||
|
||||
for(var/i = 0, i < 5, i++)
|
||||
var/cointype = pick(subtypesof(/obj/item/coin))
|
||||
var/obj/item/coin/C = new cointype(loc)
|
||||
random_step(C, 2, 50)
|
||||
if(paymode == HOLOCHIP)
|
||||
new /obj/item/holochip(loc,JACKPOT)
|
||||
else
|
||||
for(var/i = 0, i < 5, i++)
|
||||
cointype = pick(subtypesof(/obj/item/coin))
|
||||
var/obj/item/coin/C = new cointype(loc)
|
||||
random_step(C, 2, 50)
|
||||
|
||||
else if(linelength == 5)
|
||||
visible_message("<b>[src]</b> says, 'Big Winner! You win a thousand credits worth of coins!'")
|
||||
visible_message("<b>[src]</b> says, 'Big Winner! You win a thousand credits!'")
|
||||
give_money(BIG_PRIZE)
|
||||
|
||||
else if(linelength == 4)
|
||||
visible_message("<b>[src]</b> says, 'Winner! You win four hundred credits worth of coins!'")
|
||||
visible_message("<b>[src]</b> says, 'Winner! You win four hundred credits!'")
|
||||
give_money(SMALL_PRIZE)
|
||||
|
||||
else if(linelength == 3)
|
||||
@@ -271,12 +309,15 @@
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/give_money(amount)
|
||||
var/amount_to_give = money >= amount ? amount : money
|
||||
var/surplus = amount_to_give - give_coins(amount_to_give)
|
||||
var/surplus = amount_to_give - give_payout(amount_to_give)
|
||||
money = max(0, money - amount)
|
||||
balance += surplus
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/give_coins(amount)
|
||||
var/cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver
|
||||
/obj/machinery/computer/slot_machine/proc/give_payout(amount)
|
||||
if(paymode == HOLOCHIP)
|
||||
cointype = /obj/item/holochip
|
||||
else
|
||||
cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver
|
||||
|
||||
if(!(obj_flags & EMAGGED))
|
||||
amount = dispense(amount, cointype, null, 0)
|
||||
@@ -288,22 +329,25 @@
|
||||
|
||||
return amount
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/dispense(amount = 0, cointype = /obj/item/coin/silver, mob/living/target, throwit = FALSE)
|
||||
var/value = GLOB.coin_values[cointype] || GLOB.coin_values[/obj/item/coin/iron]
|
||||
INVOKE_ASYNC(src, .proc/become_rich, amount, value, cointype, target, throwit)
|
||||
return amount % value
|
||||
/obj/machinery/computer/slot_machine/proc/dispense(amount = 0, cointype = /obj/item/coin/silver, mob/living/target, throwit = 0)
|
||||
if(paymode == HOLOCHIP)
|
||||
var/obj/item/holochip/H = new /obj/item/holochip(loc,amount)
|
||||
|
||||
/obj/machinery/computer/slot_machine/proc/become_rich(amount, value, cointype = /obj/item/coin/silver, mob/living/target, throwit = FALSE)
|
||||
if(value <= 0)
|
||||
return
|
||||
while(amount >= value && !QDELETED(src))
|
||||
var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN
|
||||
amount -= value
|
||||
if(throwit && target)
|
||||
C.throw_at(target, 3, 10)
|
||||
else
|
||||
random_step(C, 2, 40)
|
||||
CHECK_TICK
|
||||
H.throw_at(target, 3, 10)
|
||||
else
|
||||
var/value = coinvalues["[cointype]"]
|
||||
if(value <= 0)
|
||||
CRASH("Coin value of zero, refusing to payout in dispenser")
|
||||
while(amount >= value)
|
||||
var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN
|
||||
amount -= value
|
||||
if(throwit && target)
|
||||
C.throw_at(target, 3, 10)
|
||||
else
|
||||
random_step(C, 2, 40)
|
||||
|
||||
return amount
|
||||
|
||||
#undef SEVEN
|
||||
#undef SPIN_TIME
|
||||
@@ -311,3 +355,5 @@
|
||||
#undef BIG_PRIZE
|
||||
#undef SMALL_PRIZE
|
||||
#undef SPIN_PRICE
|
||||
#undef HOLOCHIP
|
||||
#undef COIN
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
return 0
|
||||
|
||||
/obj/effect/acid/Crossed(AM as mob|obj)
|
||||
. = ..()
|
||||
if(isliving(AM))
|
||||
var/mob/living/L = AM
|
||||
if(L.movement_type & FLYING)
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
|
||||
/obj/effect/anomaly/grav/high/Initialize(mapload, new_lifespan)
|
||||
. = ..()
|
||||
setup_grav_field()
|
||||
INVOKE_ASYNC(src, .proc/setup_grav_field)
|
||||
|
||||
/obj/effect/anomaly/grav/high/proc/setup_grav_field()
|
||||
grav_field = make_field(/datum/proximity_monitor/advanced/gravity, list("current_range" = 7, "host" = src, "gravity_value" = rand(0,3)))
|
||||
|
||||
@@ -65,4 +65,5 @@
|
||||
/obj/effect/decal/cleanable/oil/slippery
|
||||
|
||||
/obj/effect/decal/cleanable/oil/slippery/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
var/list/checkers //list of /obj/effect/abstract/proximity_checkers
|
||||
var/current_range
|
||||
var/ignore_if_not_on_turf //don't check turfs in range if the host's loc isn't a turf
|
||||
var/wire = FALSE
|
||||
|
||||
/datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE)
|
||||
checkers = list()
|
||||
@@ -35,6 +36,8 @@
|
||||
return ..()
|
||||
|
||||
/datum/proximity_monitor/proc/HandleMove()
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/atom/_host = host
|
||||
var/atom/new_host_loc = _host.loc
|
||||
if(last_host_loc != new_host_loc)
|
||||
@@ -58,6 +61,8 @@
|
||||
var/atom/_host = host
|
||||
|
||||
var/atom/loc_to_use = ignore_if_not_on_turf ? _host.loc : get_turf(_host)
|
||||
if(wire && !isturf(loc_to_use)) //it makes assemblies attached on wires work
|
||||
loc_to_use = get_turf(loc_to_use)
|
||||
if(!isturf(loc_to_use)) //only check the host's loc
|
||||
if(range)
|
||||
var/obj/effect/abstract/proximity_checker/pc
|
||||
@@ -109,4 +114,5 @@
|
||||
|
||||
/obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM)
|
||||
set waitfor = FALSE
|
||||
monitor?.hasprox_receiver.HasProximity(AM)
|
||||
. = ..()
|
||||
monitor?.hasprox_receiver?.HasProximity(AM)
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
/obj/item/clothing/under/rank/civilian/mime/sexy)
|
||||
|
||||
/obj/effect/spawner/bundle/crate/Initialize(mapload)
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
if(items && items.len)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/structure/closet/LC = locate(/obj/structure/closet) in T
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
/obj/item/grenade/plastic/Crossed(atom/movable/AM)
|
||||
if(nadeassembly)
|
||||
nadeassembly.Crossed(AM)
|
||||
. = ..()
|
||||
|
||||
/obj/item/grenade/plastic/on_found(mob/finder)
|
||||
if(nadeassembly)
|
||||
|
||||
@@ -447,6 +447,7 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths())
|
||||
can_random_spawn = FALSE
|
||||
|
||||
/obj/item/toy/plush/random/Initialize()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
var/newtype
|
||||
var/list/snowflake_list = CONFIG_GET(keyed_list/snowflake_plushies)
|
||||
|
||||
|
||||
@@ -134,11 +134,10 @@
|
||||
/obj/item/pressure_plate/hologrid/Crossed(atom/movable/AM)
|
||||
. = ..()
|
||||
if(trigger_item && istype(AM, specific_item) && !claimed)
|
||||
AM.anchored = TRUE
|
||||
AM.set_anchored(TRUE)
|
||||
flick("laserbox_burn", AM)
|
||||
trigger()
|
||||
sleep(15)
|
||||
qdel(AM)
|
||||
QDEL_IN(AM, 15)
|
||||
|
||||
// snowflake code until undertile elements
|
||||
/obj/item/pressure_plate/hologrid/hide()
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
if(merge)
|
||||
for(var/obj/item/stack/S in loc)
|
||||
if(S.merge_type == merge_type)
|
||||
merge(S)
|
||||
INVOKE_ASYNC(src, .proc/merge, S)
|
||||
var/list/temp_recipes = get_main_recipes()
|
||||
recipes = temp_recipes.Copy()
|
||||
if(material_type)
|
||||
|
||||
@@ -531,6 +531,7 @@
|
||||
pop_burst()
|
||||
|
||||
/obj/item/toy/snappop/Crossed(H as mob|obj)
|
||||
. = ..()
|
||||
if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off
|
||||
var/mob/living/carbon/M = H
|
||||
if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN)
|
||||
|
||||
@@ -269,13 +269,13 @@
|
||||
UnregisterSignal(source, COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/obj/structure/table/rolling/Moved(atom/OldLoc, Dir)
|
||||
. = ..()
|
||||
for(var/mob/M in OldLoc.contents)//Kidnap everyone on top
|
||||
M.forceMove(loc)
|
||||
for(var/x in attached_items)
|
||||
var/atom/movable/AM = x
|
||||
if(!AM.Move(loc))
|
||||
RemoveItemFromTable(AM, AM.loc)
|
||||
return TRUE
|
||||
|
||||
/*
|
||||
* Glass tables
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
animate(src, alpha = initial(alpha), time = time_between_triggers)
|
||||
|
||||
/obj/structure/trap/Crossed(atom/movable/AM)
|
||||
. = ..()
|
||||
if(last_trigger + time_between_triggers > world.time)
|
||||
return
|
||||
// Don't want the traps triggered by sparks, ghosts or projectiles.
|
||||
@@ -67,6 +68,7 @@
|
||||
return
|
||||
if(M.anti_magic_check())
|
||||
flare()
|
||||
return
|
||||
if(charges <= 0)
|
||||
return
|
||||
flare()
|
||||
|
||||
@@ -24,7 +24,13 @@
|
||||
//This is used to optimize the map loader
|
||||
return
|
||||
|
||||
/**
|
||||
* Space Initialize
|
||||
*
|
||||
* Doesn't call parent, see [/atom/proc/Initialize]
|
||||
*/
|
||||
/turf/open/space/Initialize()
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
icon_state = SPACE_ICON_STATE
|
||||
air = space_gas
|
||||
update_air_ref()
|
||||
@@ -35,6 +41,15 @@
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
flags_1 |= INITIALIZED_1
|
||||
|
||||
// if (length(smoothing_groups))
|
||||
// sortTim(smoothing_groups) //In case it's not properly ordered, let's avoid duplicate entries with the same values.
|
||||
// SET_BITFLAG_LIST(smoothing_groups)
|
||||
// if (length(canSmoothWith))
|
||||
// sortTim(canSmoothWith)
|
||||
// if(canSmoothWith[length(canSmoothWith)] > MAX_S_TURF) //If the last element is higher than the maximum turf-only value, then it must scan turf contents for smoothing targets.
|
||||
// smoothing_flags |= SMOOTH_OBJ
|
||||
// SET_BITFLAG_LIST(canSmoothWith)
|
||||
|
||||
var/area/A = loc
|
||||
if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A))
|
||||
add_overlay(/obj/effect/fullbright)
|
||||
@@ -48,6 +63,13 @@
|
||||
if (opacity)
|
||||
has_opaque_atom = TRUE
|
||||
|
||||
var/turf/T = SSmapping.get_turf_above(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, DOWN)
|
||||
T = SSmapping.get_turf_below(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, UP)
|
||||
|
||||
ComponentInitialize()
|
||||
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
@@ -73,6 +95,10 @@
|
||||
/turf/open/space/Assimilate_Air()
|
||||
return
|
||||
|
||||
//IT SHOULD RETURN NULL YOU MONKEY, WHY IN TARNATION WHAT THE FUCKING FUCK
|
||||
/turf/open/space/remove_air(amount)
|
||||
return null
|
||||
|
||||
/turf/open/space/proc/update_starlight()
|
||||
if(CONFIG_GET(flag/starlight))
|
||||
for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm
|
||||
@@ -89,9 +115,8 @@
|
||||
/turf/open/space/proc/CanBuildHere()
|
||||
return TRUE
|
||||
|
||||
/turf/open/space/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube)
|
||||
if(lube & FLYING_DOESNT_HELP)
|
||||
return ..()
|
||||
/turf/open/space/handle_slip()
|
||||
return // no lube bullshit, this is space
|
||||
|
||||
/turf/open/space/attackby(obj/item/C, mob/user, params)
|
||||
..()
|
||||
@@ -106,15 +131,16 @@
|
||||
return
|
||||
if(L)
|
||||
if(R.use(1))
|
||||
qdel(L)
|
||||
to_chat(user, "<span class='notice'>You construct a catwalk.</span>")
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
new/obj/structure/lattice/catwalk(src)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need two rods to build a catwalk!</span>")
|
||||
return
|
||||
if(R.use(1))
|
||||
to_chat(user, "<span class='notice'>You construct a lattice.</span>")
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
ReplaceWithLattice()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need one rod to build a lattice.</span>")
|
||||
@@ -125,7 +151,7 @@
|
||||
var/obj/item/stack/tile/plasteel/S = C
|
||||
if(S.use(1))
|
||||
qdel(L)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, 1)
|
||||
playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE)
|
||||
to_chat(user, "<span class='notice'>You build a floor.</span>")
|
||||
PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
|
||||
+47
-37
@@ -1,8 +1,11 @@
|
||||
GLOBAL_LIST_EMPTY(station_turfs)
|
||||
|
||||
/// Any floor or wall. What makes up the station and the rest of the map.
|
||||
/turf
|
||||
icon = 'icons/turf/floors.dmi'
|
||||
level = 1
|
||||
vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_ID //when this be added to vis_contents of something it inherit something.plane and be associatet with something on clicking,
|
||||
//important for visualisation of turf in openspace and interraction with openspace that show you turf.
|
||||
flags_1 = CAN_BE_DIRTY_1
|
||||
vis_flags = VIS_INHERIT_ID|VIS_INHERIT_PLANE // Important for interaction with and visualization of openspace.
|
||||
luminosity = 1
|
||||
|
||||
var/intact = 1
|
||||
|
||||
@@ -19,8 +22,6 @@
|
||||
|
||||
var/blocks_air = FALSE
|
||||
|
||||
flags_1 = CAN_BE_DIRTY_1
|
||||
|
||||
var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes
|
||||
|
||||
var/explosion_level = 0 //for preventing explosion dodging
|
||||
@@ -41,7 +42,13 @@
|
||||
return FALSE
|
||||
. = ..()
|
||||
|
||||
/**
|
||||
* Turf Initialize
|
||||
*
|
||||
* Doesn't call parent, see [/atom/proc/Initialize]
|
||||
*/
|
||||
/turf/Initialize(mapload)
|
||||
SHOULD_CALL_PARENT(FALSE)
|
||||
if(flags_1 & INITIALIZED_1)
|
||||
stack_trace("Warning: [src]([type]) initialized multiple times!")
|
||||
flags_1 |= INITIALIZED_1
|
||||
@@ -49,7 +56,7 @@
|
||||
// by default, vis_contents is inherited from the turf that was here before
|
||||
vis_contents.Cut()
|
||||
|
||||
if(color)
|
||||
if(color) // is this being used? This is here because parent isn't being called
|
||||
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
|
||||
assemble_baseturfs()
|
||||
@@ -57,6 +64,7 @@
|
||||
levelupdate()
|
||||
if(smooth)
|
||||
queue_smooth(src)
|
||||
|
||||
visibilityChanged()
|
||||
|
||||
for(var/atom/movable/AM in src)
|
||||
@@ -76,11 +84,10 @@
|
||||
var/turf/T = SSmapping.get_turf_above(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, DOWN)
|
||||
SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, DOWN)
|
||||
T = SSmapping.get_turf_below(src)
|
||||
if(T)
|
||||
T.multiz_turf_new(src, UP)
|
||||
SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, UP)
|
||||
|
||||
|
||||
if (opacity)
|
||||
has_opaque_atom = TRUE
|
||||
@@ -112,8 +119,6 @@
|
||||
var/turf/B = new world.turf(src)
|
||||
for(var/A in B.contents)
|
||||
qdel(A)
|
||||
for(var/I in B.vars)
|
||||
B.vars[I] = null
|
||||
return
|
||||
SSair.remove_from_active(src)
|
||||
visibilityChanged()
|
||||
@@ -122,12 +127,14 @@
|
||||
requires_activation = FALSE
|
||||
..()
|
||||
|
||||
/turf/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
/turf/on_attack_hand(mob/user)
|
||||
user.Move_Pulled(src)
|
||||
|
||||
/turf/proc/multiz_turf_del(turf/T, dir)
|
||||
// SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_DEL, T, dir)
|
||||
|
||||
/turf/proc/multiz_turf_new(turf/T, dir)
|
||||
SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_NEW, T, dir)
|
||||
|
||||
//zPassIn doesn't necessarily pass an atom!
|
||||
//direction is direction of travel of air
|
||||
@@ -158,13 +165,14 @@
|
||||
prev_turf.visible_message("<span class='danger'>[mov_name] falls through [prev_turf]!</span>")
|
||||
if(flags & FALL_INTERCEPTED)
|
||||
return
|
||||
if(zFall(A, ++levels))
|
||||
if(zFall(A, levels + 1))
|
||||
return FALSE
|
||||
A.visible_message("<span class='danger'>[A] crashes into [src]!</span>")
|
||||
A.onZImpact(src, levels)
|
||||
return TRUE
|
||||
|
||||
/turf/proc/can_zFall(atom/movable/A, levels = 1, turf/target)
|
||||
SHOULD_BE_PURE(TRUE)
|
||||
return zPassOut(A, DOWN, target) && target.zPassIn(A, DOWN, src)
|
||||
|
||||
/turf/proc/zFall(atom/movable/A, levels = 1, force = FALSE)
|
||||
@@ -217,49 +225,54 @@
|
||||
stack_trace("Non movable passed to turf CanPass : [mover]")
|
||||
return FALSE
|
||||
|
||||
//There's a lot of QDELETED() calls here if someone can figure out how to optimize this but not runtime when something gets deleted by a Bump/CanPass/Cross call, lemme know or go ahead and fix this mess - kevinz000
|
||||
/turf/Enter(atom/movable/mover, atom/oldloc)
|
||||
// Do not call ..()
|
||||
// Byond's default turf/Enter() doesn't have the behaviour we want with Bump()
|
||||
// By default byond will call Bump() on the first dense object in contents
|
||||
// Here's hoping it doesn't stay like this for years before we finish conversion to step_
|
||||
var/atom/firstbump
|
||||
if(!CanPass(mover, src))
|
||||
firstbump = src
|
||||
else
|
||||
var/canPassSelf = CanPass(mover, src)
|
||||
if(canPassSelf || (mover.movement_type & UNSTOPPABLE))
|
||||
for(var/i in contents)
|
||||
if(QDELETED(mover))
|
||||
return FALSE //We were deleted, do not attempt to proceed with movement.
|
||||
if(i == mover || i == mover.loc) // Multi tile objects and moving out of other objects
|
||||
continue
|
||||
if(QDELETED(mover))
|
||||
break
|
||||
var/atom/movable/thing = i
|
||||
if(!thing.Cross(mover))
|
||||
if(CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE))
|
||||
if(QDELETED(mover)) //Mover deleted from Cross/CanPass, do not proceed.
|
||||
return FALSE
|
||||
if((mover.movement_type & UNSTOPPABLE))
|
||||
mover.Bump(thing)
|
||||
continue
|
||||
else
|
||||
if(!firstbump || ((thing.layer > firstbump.layer || thing.flags_1 & ON_BORDER_1) && !(firstbump.flags_1 & ON_BORDER_1)))
|
||||
firstbump = thing
|
||||
if(QDELETED(mover)) //Mover deleted from Cross/CanPass/Bump, do not proceed.
|
||||
return FALSE
|
||||
if(!canPassSelf) //Even if mover is unstoppable they need to bump us.
|
||||
firstbump = src
|
||||
if(firstbump)
|
||||
if(!QDELETED(mover))
|
||||
mover.Bump(firstbump)
|
||||
return CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE)
|
||||
mover.Bump(firstbump)
|
||||
return (mover.movement_type & UNSTOPPABLE)
|
||||
return TRUE
|
||||
|
||||
/turf/Exit(atom/movable/mover, atom/newloc)
|
||||
. = ..()
|
||||
if(!.)
|
||||
if(!. || QDELETED(mover))
|
||||
return FALSE
|
||||
for(var/i in contents)
|
||||
if(QDELETED(mover))
|
||||
break
|
||||
if(i == mover)
|
||||
continue
|
||||
var/atom/movable/thing = i
|
||||
if(!thing.Uncross(mover, newloc))
|
||||
if(thing.flags_1 & ON_BORDER_1)
|
||||
mover.Bump(thing)
|
||||
if(!CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE))
|
||||
if(!(mover.movement_type & UNSTOPPABLE))
|
||||
return FALSE
|
||||
if(QDELETED(mover))
|
||||
return FALSE //We were deleted.
|
||||
|
||||
/turf/Entered(atom/movable/AM)
|
||||
..()
|
||||
@@ -271,6 +284,7 @@
|
||||
has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
|
||||
reconsider_lights()
|
||||
|
||||
|
||||
/turf/open/Entered(atom/movable/AM)
|
||||
..()
|
||||
//melting
|
||||
@@ -278,7 +292,6 @@
|
||||
var/obj/O = AM
|
||||
if(O.obj_flags & FROZEN)
|
||||
O.make_unfrozen()
|
||||
|
||||
if(!AM.zfalling)
|
||||
zFall(AM)
|
||||
|
||||
@@ -336,14 +349,13 @@
|
||||
|
||||
/turf/proc/levelupdate()
|
||||
for(var/obj/O in src)
|
||||
if(O.level == 1 && (O.flags_1 & INITIALIZED_1))
|
||||
O.hide(src.intact)
|
||||
if(O.flags_1 & INITIALIZED_1)
|
||||
// SEND_SIGNAL(O, COMSIG_OBJ_HIDE, intact)
|
||||
O.hide(intact)
|
||||
|
||||
// override for space turfs, since they should never hide anything
|
||||
/turf/open/space/levelupdate()
|
||||
for(var/obj/O in src)
|
||||
if(O.level == 1 && (O.flags_1 & INITIALIZED_1))
|
||||
O.hide(0)
|
||||
return
|
||||
|
||||
// Removes all signs of lattice on the pos of the turf -Donkieyo
|
||||
/turf/proc/RemoveLattice()
|
||||
@@ -368,13 +380,13 @@
|
||||
if(.)
|
||||
return
|
||||
if(length(src_object.contents()))
|
||||
to_chat(user, "<span class='notice'>You start dumping out the contents...</span>")
|
||||
if(!do_after(user,20,target=src_object.parent))
|
||||
to_chat(usr, "<span class='notice'>You start dumping out the contents...</span>")
|
||||
if(!do_after(usr,20,target=src_object.parent))
|
||||
return FALSE
|
||||
|
||||
var/list/things = src_object.contents()
|
||||
var/datum/progressbar/progress = new(user, things.len, src)
|
||||
while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress)))
|
||||
while (do_after(usr, 1 SECONDS, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress)))
|
||||
stoplag(1)
|
||||
qdel(progress)
|
||||
|
||||
@@ -494,10 +506,8 @@
|
||||
I.loc = src
|
||||
I.setDir(AM.dir)
|
||||
I.alpha = 128
|
||||
|
||||
LAZYADD(blueprint_data, I)
|
||||
|
||||
|
||||
/turf/proc/add_blueprints_preround(atom/movable/AM)
|
||||
if(!SSticker.HasRoundStarted())
|
||||
add_blueprints(AM)
|
||||
@@ -531,7 +541,7 @@
|
||||
if(!forced)
|
||||
return
|
||||
if(has_gravity(src))
|
||||
playsound(src, "bodyfall", 50, 1)
|
||||
playsound(src, "bodyfall", 50, TRUE)
|
||||
faller.drop_all_held_items()
|
||||
|
||||
/turf/proc/photograph(limit=20)
|
||||
|
||||
Reference in New Issue
Block a user